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.WebService;
29 import javax.xml.ws.Holder;
31 import org.codehaus.jackson.JsonNode;
32 import org.codehaus.jackson.map.ObjectMapper;
34 import org.openecomp.mso.adapters.network.exceptions.NetworkException;
35 import org.openecomp.mso.cloud.CloudConfig;
36 import org.openecomp.mso.cloud.CloudConfigFactory;
37 import org.openecomp.mso.cloud.CloudSite;
38 import org.openecomp.mso.db.catalog.CatalogDatabase;
39 import org.openecomp.mso.db.catalog.beans.HeatTemplate;
40 import org.openecomp.mso.db.catalog.beans.NetworkResource;
41 import org.openecomp.mso.db.catalog.utils.MavenLikeVersioning;
42 import org.openecomp.mso.entity.MsoRequest;
43 import org.openecomp.mso.logger.MessageEnum;
44 import org.openecomp.mso.logger.MsoAlarmLogger;
45 import org.openecomp.mso.logger.MsoLogger;
46 import org.openecomp.mso.openstack.beans.HeatStatus;
47 import org.openecomp.mso.openstack.beans.NetworkInfo;
48 import org.openecomp.mso.openstack.beans.NetworkRollback;
49 import org.openecomp.mso.openstack.beans.NetworkStatus;
50 import org.openecomp.mso.openstack.beans.Pool;
51 import org.openecomp.mso.openstack.beans.StackInfo;
52 import org.openecomp.mso.openstack.beans.Subnet;
53 import org.openecomp.mso.openstack.exceptions.MsoAdapterException;
54 import org.openecomp.mso.openstack.exceptions.MsoException;
55 import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
56 import org.openecomp.mso.openstack.utils.MsoHeatUtils;
57 import org.openecomp.mso.openstack.utils.MsoHeatUtilsWithUpdate;
58 import org.openecomp.mso.openstack.utils.MsoNeutronUtils;
59 import org.openecomp.mso.openstack.utils.MsoNeutronUtils.NetworkType;
60 import org.openecomp.mso.properties.MsoPropertiesException;
61 import org.openecomp.mso.properties.MsoPropertiesFactory;
63 import static org.openecomp.mso.openstack.utils.MsoCommonUtils.isNullOrEmpty;
65 @WebService(serviceName = "NetworkAdapter", endpointInterface = "org.openecomp.mso.adapters.network.MsoNetworkAdapter", targetNamespace = "http://org.openecomp.mso/network")
66 public class MsoNetworkAdapterImpl implements MsoNetworkAdapter {
68 MsoPropertiesFactory msoPropertiesFactory=new MsoPropertiesFactory();
70 CloudConfigFactory cloudConfigFactory=new CloudConfigFactory();
72 private static final String AIC3_NW_PROPERTY= "org.openecomp.mso.adapters.network.aic3nw";
73 private static final String AIC3_NW="OS::ContrailV2::VirtualNetwork";
74 public static final String MSO_PROP_NETWORK_ADAPTER="MSO_PROP_NETWORK_ADAPTER";
75 private static final String VLANS = "vlans";
76 private static final String PHYSICAL_NETWORK = "physical_network";
77 private static final String UPDATE_NETWORK_CONTEXT = "UpdateNetwork";
78 private static final String NETWORK_ID = "network_id";
79 private static final String NETWORK_FQDN = "network_fqdn";
80 private static final String CREATE_NETWORK_CONTEXT = "CreateNetwork";
81 private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
82 private static final String NEUTRON_MODE = "NEUTRON";
83 private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
84 private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
85 protected CloudConfig cloudConfig;
88 * Health Check web method. Does nothing but return to show the adapter is deployed.
91 public void healthCheck () {
92 LOGGER.debug ("Health check call in Network Adapter");
96 * Do not use this constructor or the msoPropertiesFactory will be NULL.
98 * @see MsoNetworkAdapterImpl#MsoNetworkAdapterImpl(MsoPropertiesFactory)
100 public MsoNetworkAdapterImpl() {
104 * This constructor MUST be used if this class if called with the new operator.
105 * @param msoPropFactory
108 public MsoNetworkAdapterImpl(MsoPropertiesFactory msoPropFactory,CloudConfigFactory cloudConfigFact) {
109 this.msoPropertiesFactory = msoPropFactory;
110 this.cloudConfigFactory=cloudConfigFact;
111 cloudConfig = cloudConfigFactory.getCloudConfig ();
115 public void createNetwork (String cloudSiteId,
118 String modelCustomizationUuid,
120 String physicalNetworkName,
121 List <Integer> vlans,
122 Boolean failIfExists,
124 List <Subnet> subnets,
125 MsoRequest msoRequest,
126 Holder <String> networkId,
127 Holder <String> neutronNetworkId,
128 Holder <Map <String, String>> subnetIdMap,
129 Holder <NetworkRollback> rollback) throws NetworkException {
130 Holder <String> networkFqdn = new Holder <String> ();
131 createNetwork (cloudSiteId,
134 modelCustomizationUuid,
155 public void createNetworkContrail (String cloudSiteId,
158 String modelCustomizationUuid,
160 List <String> routeTargets,
163 Boolean failIfExists,
165 List <Subnet> subnets,
166 List <String> policyFqdns,
167 List<String> routeTableFqdns,
168 MsoRequest msoRequest,
169 Holder <String> networkId,
170 Holder <String> neutronNetworkId,
171 Holder <String> networkFqdn,
172 Holder <Map <String, String>> subnetIdMap,
173 Holder <NetworkRollback> rollback) throws NetworkException {
174 createNetwork (cloudSiteId,
177 modelCustomizationUuid,
198 * This is the "Create Network" web service implementation.
199 * It will create a new Network of the requested type in the specified cloud
200 * and tenant. The tenant must exist at the time this service is called.
202 * If a network with the same name already exists, this can be considered a
203 * success or failure, depending on the value of the 'failIfExists' parameter.
205 * There will be a pre-defined set of network types defined in the MSO Catalog.
206 * All such networks will have a similar configuration, based on the allowable
207 * Openstack networking definitions. This includes basic networks, provider
208 * networks (with a single VLAN), and multi-provider networks (one or more VLANs)
210 * Initially, all provider networks must be "vlan" type, and multiple segments in
211 * a multi-provider network must be multiple VLANs on the same physical network.
213 * This service supports two modes of Network creation/update:
214 * - via Heat Templates
216 * The network orchestration mode for each network type is declared in its
217 * catalog definition. All Heat-based templates must support some subset of
218 * the same input parameters: network_name, physical_network, vlan(s).
220 * The method returns the network ID and a NetworkRollback object. This latter
221 * object can be passed as-is to the rollbackNetwork operation to undo everything
222 * that was created. This is useful if a network is successfully created but
223 * the orchestration fails on a subsequent operation.
226 private void createNetwork (String cloudSiteId,
229 String modelCustomizationUuid,
231 String physicalNetworkName,
232 List <Integer> vlans,
233 List <String> routeTargets,
236 Boolean failIfExists,
238 List <Subnet> subnets,
239 List <String> policyFqdns,
240 List <String> routeTableFqdns,
241 MsoRequest msoRequest,
242 Holder <String> networkId,
243 Holder <String> neutronNetworkId,
244 Holder <String> networkFqdn,
245 Holder <Map <String, String>> subnetIdMap,
246 Holder <NetworkRollback> rollback) throws NetworkException {
247 MsoLogger.setLogContext (msoRequest);
248 MsoLogger.setServiceName ("CreateNetwork");
250 LOGGER.debug ("*** CREATE Network: " + networkName
258 // Will capture execution time for metrics
259 long startTime = System.currentTimeMillis ();
261 // Build a default rollback object (no actions performed)
262 NetworkRollback networkRollback = new NetworkRollback ();
263 networkRollback.setCloudId (cloudSiteId);
264 networkRollback.setTenantId (tenantId);
265 networkRollback.setMsoRequest (msoRequest);
266 networkRollback.setModelCustomizationUuid(modelCustomizationUuid);
268 // tenant query is not required here.
269 // If the tenant doesn’t exist, the Heat calls will fail anyway (when the HeatUtils try to obtain a token).
270 // So this is just catching that error in a bit more obvious way up front.
272 cloudConfig = cloudConfigFactory.getCloudConfig ();
273 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
274 if (cloudSite == null)
276 String error = "Configuration Error. Stack " + networkName + " in "
281 + " CloudSite does not exist in MSO Configuration";
282 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
283 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
284 // Set the detailed error as the Exception 'message'
285 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
288 // Get a handle to the Catalog Database
289 CatalogDatabase db = getCatalogDB ();
291 // Make sure DB connection is always closed
293 NetworkResource networkResource = networkCheck (db,
296 modelCustomizationUuid,
302 String mode = networkResource.getOrchestrationMode ();
303 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
305 if (NEUTRON_MODE.equals (mode)) {
307 // Use an MsoNeutronUtils for all neutron commands
308 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
310 // See if the Network already exists (by name)
311 NetworkInfo netInfo = null;
312 long queryNetworkStarttime = System.currentTimeMillis ();
314 netInfo = neutron.queryNetwork (networkName, tenantId, cloudSiteId);
315 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
316 } catch (MsoException me) {
317 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack", "OpenStack", "QueryNetwork", null);
318 String error = "Create Network (neutron): query network " + networkName
325 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while querying network from OpenStack", me);
326 me.addContext (CREATE_NETWORK_CONTEXT);
327 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack");
328 throw new NetworkException (me);
331 if (netInfo != null) {
332 // Exists. If that's OK, return success with the network ID.
333 // Otherwise, return an exception.
334 if (failIfExists != null && failIfExists) {
335 String error = "Create Nework: Network " + networkName
336 + " already exists in "
340 + " with ID " + netInfo.getId();
341 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network already exists");
342 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
343 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
345 // Populate the outputs from the existing network.
346 networkId.value = netInfo.getId ();
347 neutronNetworkId.value = netInfo.getId ();
348 rollback.value = networkRollback; // Default rollback - no updates performed
349 String msg = "Found Existing network, status=" + netInfo.getStatus () + " for Neutron mode";
350 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network, status=" + netInfo.getStatus ());
351 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, msg);
356 long createNetworkStarttime = System.currentTimeMillis ();
358 netInfo = neutron.createNetwork (cloudSiteId,
364 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "CreateNetwork", null);
365 } catch (MsoException me) {
366 me.addContext (CREATE_NETWORK_CONTEXT);
367 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with OpenStack", "OpenStack", "CreateNetwork", null);
368 String error = "Create Network: type " + neutronNetworkType
375 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while communicate with OpenStack", me);
376 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
378 throw new NetworkException (me);
381 // Note: ignoring MsoNetworkAlreadyExists because we already checked.
383 // If reach this point, network creation is successful.
384 // Since directly created via Neutron, networkId tracked by MSO is the same
385 // as the neutron network ID.
386 networkId.value = netInfo.getId ();
387 neutronNetworkId.value = netInfo.getId ();
389 networkRollback.setNetworkCreated (true);
390 networkRollback.setNetworkId (netInfo.getId ());
391 networkRollback.setNeutronNetworkId (netInfo.getId ());
392 networkRollback.setNetworkType (networkType);
394 LOGGER.debug ("Network " + networkName + " created, id = " + netInfo.getId ());
395 } else if ("HEAT".equals (mode)) {
397 // Use an MsoHeatUtils for all Heat commands
398 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
400 //HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
401 HeatTemplate heatTemplate = db.getHeatTemplateByArtifactUuidRegularQuery (networkResource.getHeatTemplateArtifactUUID());
402 if (heatTemplate == null) {
403 String error = "Network error - undefined Heat Template. Network Type = " + networkType;
404 LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
405 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
409 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
410 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
413 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
415 // "Fix" the template if it has CR/LF (getting this from Oracle)
416 String template = heatTemplate.getHeatTemplate ();
417 template = template.replaceAll ("\r\n", "\n");
419 boolean aic3template=false;
420 String aic3nw = AIC3_NW;
422 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
423 } catch (MsoPropertiesException e) {
424 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
425 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
428 if (template.contains(aic3nw))
431 // First, look up to see if the Network already exists (by name).
432 // For HEAT orchestration of networks, the stack name will always match the network name
433 StackInfo heatStack = null;
434 long queryNetworkStarttime = System.currentTimeMillis ();
436 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
437 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
438 } catch (MsoException me) {
439 me.addContext (CREATE_NETWORK_CONTEXT);
440 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
441 String error = "Create Network (heat): query network " + networkName
448 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
449 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
450 throw new NetworkException (me);
453 if (heatStack != null && !(heatStack.getStatus () == HeatStatus.NOTFOUND)) {
454 // Stack exists. Return success or error depending on input directive
455 if (failIfExists != null && failIfExists) {
456 String error = "CreateNetwork: Stack " + networkName
457 + " already exists in "
461 + " as " + heatStack.getCanonicalName();
462 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
463 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
464 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
466 // Populate the outputs from the existing stack.
467 networkId.value = heatStack.getCanonicalName ();
468 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
469 rollback.value = networkRollback; // Default rollback - no updates performed
472 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
474 Map <String, Object> outputs = heatStack.getOutputs ();
475 Map <String, String> sMap = new HashMap <String, String> ();
476 if (outputs != null) {
477 for (String key : outputs.keySet ()) {
478 if (key != null && key.startsWith ("subnet")) {
479 if (aic3template) //one subnet_id output
481 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
484 else //multiples subnet_%aaid% outputs
486 String subnetUUId = (String) outputs.get(key);
487 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
492 subnetIdMap.value = sMap;
493 String msg = "Found Existing network stack, status=" + heatStack.getStatus () + " for Heat mode";
494 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network stack, status=" + heatStack.getStatus ());
495 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Found Existing network stack");
500 // Ready to deploy the new Network
501 // Build the common set of HEAT template parameters
502 Map <String, Object> stackParams = populateNetworkParams (neutronNetworkType,
511 // Validate (and update) the input parameters against the DB definition
512 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
513 // and inputs were already validated.
515 stackParams = heat.validateStackParams (stackParams, heatTemplate);
516 } catch (IllegalArgumentException e) {
517 String error = "Create Network: Configuration Error: " + e.getMessage ();
518 LOGGER.error (MessageEnum.RA_CONFIG_EXC, e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - Create Network, Configuration Error", e);
519 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
523 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
524 // Input parameters were not valid
525 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
528 if (subnets != null) {
532 template = mergeSubnetsAIC3 (template, subnets, stackParams);
536 template = mergeSubnets (template, subnets);
538 } catch (MsoException me) {
539 me.addContext (CREATE_NETWORK_CONTEXT);
540 String error = "Create Network (heat): type " + neutronNetworkType
547 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging subnets", me);
548 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
549 throw new NetworkException (me);
553 if (policyFqdns != null && !policyFqdns.isEmpty() && aic3template) {
555 mergePolicyRefs (policyFqdns, stackParams);
556 } catch (MsoException me) {
557 me.addContext (CREATE_NETWORK_CONTEXT);
558 String error = "Create Network (heat) mergePolicyRefs type " + neutronNetworkType
565 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging policyRefs", me);
566 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
567 throw new NetworkException (me);
571 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
573 mergeRouteTableRefs (routeTableFqdns, stackParams);
574 } catch (MsoException me) {
575 me.addContext (CREATE_NETWORK_CONTEXT);
576 String error = "Create Network (heat) mergeRouteTableRefs type " + neutronNetworkType
583 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging routeTableRefs", me);
584 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
585 throw new NetworkException (me);
589 // Deploy the network stack
590 // Ignore MsoStackAlreadyExists exception because we already checked.
591 long createStackStartTime = System.currentTimeMillis ();
595 heatStack = heat.createStack (cloudSiteId,
601 heatTemplate.getTimeoutMinutes (),
605 backout.booleanValue());
606 } catch (MsoException me) {
607 me.addContext (CREATE_NETWORK_CONTEXT);
608 String error = "Create Network (heat): type " + neutronNetworkType
615 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
616 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
617 throw new NetworkException (me);
620 // Reach this point if createStack is successful.
622 // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
623 // and the neutronNetworkId is the network UUID returned in stack outputs.
624 networkId.value = heatStack.getCanonicalName ();
625 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
628 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
630 Map <String, Object> outputs = heatStack.getOutputs ();
631 Map <String, String> sMap = new HashMap <String, String> ();
632 if (outputs != null) {
633 for (String key : outputs.keySet ()) {
634 if (key != null && key.startsWith ("subnet")) {
635 if (aic3template) //one subnet output expected
637 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
640 else //multiples subnet_%aaid% outputs allowed
642 String subnetUUId = (String) outputs.get(key);
643 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
648 subnetIdMap.value = sMap;
650 rollback.value = networkRollback;
651 // Populate remaining rollback info and response parameters.
652 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
653 networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
654 networkRollback.setNetworkCreated (true);
655 networkRollback.setNetworkType (networkType);
657 LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
662 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
667 public void updateNetwork (String cloudSiteId,
670 String modelCustomizationUuid,
673 String physicalNetworkName,
674 List <Integer> vlans,
675 List <Subnet> subnets,
676 MsoRequest msoRequest,
677 Holder <Map <String, String>> subnetIdMap,
678 Holder <NetworkRollback> rollback) throws NetworkException {
679 updateNetwork (cloudSiteId,
682 modelCustomizationUuid,
700 public void updateNetworkContrail (String cloudSiteId,
703 String modelCustomizationUuid,
706 List <String> routeTargets,
709 List <Subnet> subnets,
710 List <String> policyFqdns,
711 List<String> routeTableFqdns,
712 MsoRequest msoRequest,
713 Holder <Map <String, String>> subnetIdMap,
714 Holder <NetworkRollback> rollback) throws NetworkException {
715 updateNetwork (cloudSiteId,
718 modelCustomizationUuid,
735 * This is the "Update Network" web service implementation.
736 * It will update an existing Network of the requested type in the specified cloud
737 * and tenant. The typical use will be to replace the VLANs with the supplied
738 * list (to add or remove a VLAN), but other properties may be updated as well.
740 * There will be a pre-defined set of network types defined in the MSO Catalog.
741 * All such networks will have a similar configuration, based on the allowable
742 * Openstack networking definitions. This includes basic networks, provider
743 * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
745 * Initially, all provider networks must currently be "vlan" type, and multi-provider
746 * networks must be multiple VLANs on the same physical network.
748 * This service supports two modes of Network update:
749 * - via Heat Templates
751 * The network orchestration mode for each network type is declared in its
752 * catalog definition. All Heat-based templates must support some subset of
753 * the same input parameters: network_name, physical_network, vlan, segments.
755 * The method returns a NetworkRollback object. This object can be passed
756 * as-is to the rollbackNetwork operation to undo everything that was updated.
757 * This is useful if a network is successfully updated but orchestration
758 * fails on a subsequent operation.
760 private void updateNetwork (String cloudSiteId,
763 String modelCustomizationUuid,
766 String physicalNetworkName,
767 List <Integer> vlans,
768 List <String> routeTargets,
771 List <Subnet> subnets,
772 List <String> policyFqdns,
773 List<String> routeTableFqdns,
774 MsoRequest msoRequest,
775 Holder <Map <String, String>> subnetIdMap,
776 Holder <NetworkRollback> rollback) throws NetworkException {
777 MsoLogger.setLogContext (msoRequest);
778 MsoLogger.setServiceName ("UpdateNetwork");
779 LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
788 // Will capture execution time for metrics
789 long startTime = System.currentTimeMillis ();
791 // Build a default rollback object (no actions performed)
792 NetworkRollback networkRollback = new NetworkRollback ();
793 networkRollback.setCloudId (cloudSiteId);
794 networkRollback.setTenantId (tenantId);
795 networkRollback.setMsoRequest (msoRequest);
797 cloudConfig = cloudConfigFactory.getCloudConfig ();
798 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
799 if (cloudSite == null) {
800 String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
805 + " CloudSite does not exist in MSO Configuration";
806 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
807 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
808 // Set the detailed error as the Exception 'message'
809 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
812 // Get a handle to the Catalog Database
813 CatalogDatabase db = getCatalogDB ();
815 // Make sure DB connection is always closed
817 NetworkResource networkResource = networkCheck(db,
820 modelCustomizationUuid,
826 String mode = networkResource.getOrchestrationMode();
827 NetworkType neutronNetworkType = NetworkType.valueOf(networkResource.getNeutronNetworkType());
829 // Use an MsoNeutronUtils for all Neutron commands
830 MsoNeutronUtils neutron = new MsoNeutronUtils(MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
832 if (NEUTRON_MODE.equals(mode)) {
834 // Verify that the Network exists
835 // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
836 NetworkInfo netInfo = null;
837 long queryNetworkStarttime = System.currentTimeMillis();
839 netInfo = neutron.queryNetwork(networkId, tenantId, cloudSiteId);
840 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
841 } catch (MsoException me) {
842 me.addContext(UPDATE_NETWORK_CONTEXT);
843 String error = "Update Network (neutron): query " + networkId
850 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
851 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
852 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
853 throw new NetworkException(me);
856 if (netInfo == null) {
857 String error = "Update Nework: Network " + networkId
858 + " does not exist in "
862 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
863 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
864 // Does not exist. Throw an exception (can't update a non-existent network)
865 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
867 long updateNetworkStarttime = System.currentTimeMillis();
869 netInfo = neutron.updateNetwork(cloudSiteId,
875 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
876 } catch (MsoException me) {
877 me.addContext(UPDATE_NETWORK_CONTEXT);
878 String error = "Update Network (neutron): " + networkId
885 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
886 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
887 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
888 throw new NetworkException(me);
891 // Add the network ID and previously queried vlans to the rollback object
892 networkRollback.setNetworkId(netInfo.getId());
893 networkRollback.setNeutronNetworkId(netInfo.getId());
894 networkRollback.setNetworkType(networkType);
895 // Save previous parameters
896 networkRollback.setNetworkName(netInfo.getName());
897 networkRollback.setPhysicalNetwork(netInfo.getProvider());
898 networkRollback.setVlans(netInfo.getVlans());
900 LOGGER.debug("Network " + networkId + " updated, id = " + netInfo.getId());
901 } else if ("HEAT".equals(mode)) {
903 // Use an MsoHeatUtils for all Heat commands
904 MsoHeatUtilsWithUpdate heat = new MsoHeatUtilsWithUpdate(MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory, cloudConfigFactory);
906 // First, look up to see that the Network already exists.
907 // For Heat-based orchestration, the networkId is the network Stack ID.
908 StackInfo heatStack = null;
909 long queryStackStarttime = System.currentTimeMillis();
911 heatStack = heat.queryStack(cloudSiteId, tenantId, networkName);
912 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
913 } catch (MsoException me) {
914 me.addContext(UPDATE_NETWORK_CONTEXT);
915 String error = "UpdateNetwork (heat): query " + networkName
922 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
923 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
924 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
925 throw new NetworkException(me);
928 if (heatStack == null || (heatStack.getStatus() == HeatStatus.NOTFOUND)) {
929 String error = "UpdateNetwork: Stack " + networkName
930 + " does not exist in "
934 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
935 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
936 // Network stack does not exist. Return an error
937 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
940 // Get the previous parameters for rollback
941 Map<String, Object> heatParams = heatStack.getParameters();
943 String previousNetworkName = (String) heatParams.get("network_name");
944 String previousPhysicalNetwork = (String) heatParams.get(PHYSICAL_NETWORK);
946 List<Integer> previousVlans = new ArrayList<Integer>();
947 String vlansParam = (String) heatParams.get(VLANS);
948 if (vlansParam != null) {
949 for (String vlan : vlansParam.split(",")) {
951 previousVlans.add(Integer.parseInt(vlan));
952 } catch (NumberFormatException e) {
953 LOGGER.warn(MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
957 LOGGER.debug("Update Stack: Previous VLANS: " + previousVlans);
959 // Ready to deploy the updated Network via Heat
961 //HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
962 HeatTemplate heatTemplate = db.getHeatTemplateByArtifactUuidRegularQuery (networkResource.getHeatTemplateArtifactUUID());
963 if (heatTemplate == null) {
964 String error = "Network error - undefined Heat Template. Network Type=" + networkType;
965 LOGGER.error(MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "OpenStack", "getHeatTemplate", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type=" + networkType);
966 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
967 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
968 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
971 LOGGER.debug("Got HEAT Template from DB: " + heatTemplate.toString());
973 // "Fix" the template if it has CR/LF (getting this from Oracle)
974 String template = heatTemplate.getHeatTemplate();
975 template = template.replaceAll("\r\n", "\n");
977 boolean aic3template = false;
978 String aic3nw = AIC3_NW;
980 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
981 } catch (MsoPropertiesException e) {
982 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
983 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
985 if (template.contains(aic3nw))
988 // Build the common set of HEAT template parameters
989 Map<String, Object> stackParams = populateNetworkParams(neutronNetworkType,
998 // Validate (and update) the input parameters against the DB definition
999 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
1001 stackParams = heat.validateStackParams(stackParams, heatTemplate);
1002 } catch (IllegalArgumentException e) {
1003 String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
1004 LOGGER.error(MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
1005 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
1006 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
1007 throw new NetworkException(error, MsoExceptionCategory.INTERNAL, e);
1010 if (subnets != null) {
1013 template = mergeSubnetsAIC3(template, subnets, stackParams);
1015 template = mergeSubnets(template, subnets);
1017 } catch (MsoException me) {
1018 me.addContext(UPDATE_NETWORK_CONTEXT);
1019 String error = "Update Network (heat): type " + neutronNetworkType
1026 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
1027 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1028 throw new NetworkException(me);
1032 if (policyFqdns != null && aic3template) {
1034 mergePolicyRefs(policyFqdns, stackParams);
1035 } catch (MsoException me) {
1036 me.addContext(UPDATE_NETWORK_CONTEXT);
1037 String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
1044 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
1045 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1046 throw new NetworkException(me);
1050 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
1052 mergeRouteTableRefs(routeTableFqdns, stackParams);
1053 } catch (MsoException me) {
1054 me.addContext(UPDATE_NETWORK_CONTEXT);
1055 String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
1062 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
1063 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1064 throw new NetworkException(me);
1068 // Update the network stack
1069 // Ignore MsoStackNotFound exception because we already checked.
1070 long updateStackStarttime = System.currentTimeMillis();
1072 heatStack = heat.updateStack(cloudSiteId,
1078 heatTemplate.getTimeoutMinutes());
1079 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
1080 } catch (MsoException me) {
1081 me.addContext(UPDATE_NETWORK_CONTEXT);
1082 String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1083 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
1084 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
1085 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1086 throw new NetworkException(me);
1089 Map<String, Object> outputs = heatStack.getOutputs();
1090 Map<String, String> sMap = new HashMap<String, String>();
1091 if (outputs != null) {
1092 for (String key : outputs.keySet()) {
1093 if (key != null && key.startsWith("subnet")) {
1094 if (aic3template) //one subnet output expected
1096 Map<String, String> map = getSubnetUUId(key, outputs, subnets);
1098 } else //multiples subnet_%aaid% outputs allowed
1100 String subnetUUId = (String) outputs.get(key);
1101 sMap.put(key.substring("subnet_id_".length()), subnetUUId);
1106 subnetIdMap.value = sMap;
1108 // Reach this point if createStack is successful.
1109 // Populate remaining rollback info and response parameters.
1110 networkRollback.setNetworkStackId(heatStack.getCanonicalName());
1111 networkRollback.setNeutronNetworkId((String) outputs.get(NETWORK_ID));
1112 networkRollback.setNetworkType(networkType);
1113 // Save previous parameters
1114 networkRollback.setNetworkName(previousNetworkName);
1115 networkRollback.setPhysicalNetwork(previousPhysicalNetwork);
1116 networkRollback.setVlans(previousVlans);
1118 rollback.value = networkRollback;
1120 LOGGER.debug("Network " + networkId + " successfully updated via HEAT");
1125 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
1129 private NetworkResource networkCheck (CatalogDatabase db,
1132 String modelCustomizationUuid,
1134 String physicalNetworkName,
1135 List <Integer> vlans,
1136 List <String> routeTargets,
1137 CloudSite cloudSite) throws NetworkException {
1138 // Retrieve the Network Resource definition
1139 NetworkResource networkResource = null;
1141 if (isNullOrEmpty(modelCustomizationUuid)) {
1142 networkResource = db.getNetworkResource(networkType);
1144 networkResource = db
1145 .getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1147 if (networkResource == null) {
1148 String error = "Create/UpdateNetwork: Unable to get network resource with NetworkType:"
1150 + " or ModelCustomizationUUID:"
1151 + modelCustomizationUuid;
1152 LOGGER.error(MessageEnum.RA_UNKOWN_PARAM,
1153 "NetworkType/ModelCustomizationUUID", networkType + "/"
1154 + modelCustomizationUuid, "OpenStack", "",
1155 MsoLogger.ErrorCode.DataError,
1156 "Create/UpdateNetwork: Unknown NetworkType/ModelCustomizationUUID");
1158 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1160 LOGGER.debug("Got Network definition from Catalog: "
1161 + networkResource.toString());
1163 String mode = networkResource.getOrchestrationMode();
1164 NetworkType neutronNetworkType = NetworkType
1165 .valueOf(networkResource.getNeutronNetworkType());
1167 // All Networks are orchestrated via HEAT or Neutron
1168 if (!("HEAT".equals(mode) || NEUTRON_MODE.equals(mode))) {
1169 String error = "CreateNetwork: Configuration Error: Network Type = "
1171 LOGGER.error(MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT,
1172 mode, "OpenStack", "", MsoLogger.ErrorCode.DataError,
1173 "CreateNetwork: Configuration Error");
1174 // Alarm on this error, configuration must be fixed
1175 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
1176 MsoAlarmLogger.CRITICAL, error);
1178 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
1181 MavenLikeVersioning aicV = new MavenLikeVersioning();
1182 aicV.setVersion(cloudSite.getAic_version());
1183 if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV
1184 .isTheSameVersion(networkResource.getAicVersionMin())) // aic
1187 && (aicV.isTheSameVersion(networkResource
1188 .getAicVersionMax()) || !(aicV
1189 .isMoreRecentThan(networkResource
1190 .getAicVersionMax())))) // aic <= max
1192 LOGGER.debug("Network Type:" + networkType + " VersionMin:"
1193 + networkResource.getAicVersionMin() + " VersionMax:"
1194 + networkResource.getAicVersionMax()
1195 + " supported on Cloud:" + cloudSite.getId()
1196 + " with AIC_Version:" + cloudSite.getAic_version());
1198 String error = "Network Type:" + networkType + " Version_Min:"
1199 + networkResource.getAicVersionMin() + " Version_Max:"
1200 + networkResource.getAicVersionMax()
1201 + " not supported on Cloud:" + cloudSite.getId()
1202 + " with AIC_Version:" + cloudSite.getAic_version();
1203 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "",
1204 MsoLogger.ErrorCode.DataError,
1205 "Network Type not supported on Cloud");
1206 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
1207 MsoLogger.ResponseCode.DataError, error);
1208 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1211 // Validate the Network parameters.
1212 String missing = validateNetworkParams(neutronNetworkType,
1213 networkName, physicalNetworkName, vlans, routeTargets);
1214 if (!missing.isEmpty()) {
1215 String error = "Create Network: Missing parameters: " + missing;
1216 LOGGER.error(MessageEnum.RA_MISSING_PARAM, missing,
1217 "OpenStack", "", MsoLogger.ErrorCode.DataError,
1218 "Create Network: Missing parameters");
1220 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1225 return networkResource;
1229 public void queryNetwork (String cloudSiteId,
1231 String networkNameOrId,
1232 MsoRequest msoRequest,
1233 Holder <Boolean> networkExists,
1234 Holder <String> networkId,
1235 Holder <String> neutronNetworkId,
1236 Holder <NetworkStatus> status,
1237 Holder <List <Integer>> vlans,
1238 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1239 queryNetwork (cloudSiteId,
1253 public void queryNetworkContrail (String cloudSiteId,
1255 String networkNameOrId,
1256 MsoRequest msoRequest,
1257 Holder <Boolean> networkExists,
1258 Holder <String> networkId,
1259 Holder <String> neutronNetworkId,
1260 Holder <NetworkStatus> status,
1261 Holder <List <String>> routeTargets,
1262 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1263 queryNetwork (cloudSiteId,
1277 * This is the queryNetwork method. It returns the existence and status of
1278 * the specified network, along with its Neutron UUID and list of VLANs.
1279 * This method attempts to find the network using both Heat and Neutron.
1280 * Heat stacks are first searched based on the provided network name/id.
1281 * If none is found, the Neutron is directly queried.
1283 private void queryNetwork (String cloudSiteId,
1285 String networkNameOrId,
1286 MsoRequest msoRequest,
1287 Holder <Boolean> networkExists,
1288 Holder <String> networkId,
1289 Holder <String> neutronNetworkId,
1290 Holder <NetworkStatus> status,
1291 Holder <List <Integer>> vlans,
1292 Holder <List <String>> routeTargets,
1293 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1294 MsoLogger.setLogContext (msoRequest);
1295 MsoLogger.setServiceName ("QueryNetwork");
1296 LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
1302 // Will capture execution time for metrics
1303 long startTime = System.currentTimeMillis ();
1305 if (isNullOrEmpty (cloudSiteId)
1306 || isNullOrEmpty(tenantId)
1307 || isNullOrEmpty(networkNameOrId)) {
1309 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1310 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1311 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1312 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1315 cloudConfig = cloudConfigFactory.getCloudConfig ();
1316 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
1317 if (cloudSite == null)
1319 String error = "Configuration Error. Stack " + networkNameOrId + " in "
1324 + " CloudSite does not exist in MSO Configuration";
1325 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
1326 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1327 // Set the detailed error as the Exception 'message'
1328 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1331 // Use MsoNeutronUtils for all NEUTRON commands
1332 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER,msoPropertiesFactory,cloudConfigFactory);
1333 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1336 String neutronId = null;
1337 // Try Heat first, since networks may be named the same as the Heat stack
1338 StackInfo heatStack = null;
1339 long queryStackStarttime = System.currentTimeMillis ();
1341 heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
1342 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
1343 } catch (MsoException me) {
1344 me.addContext ("QueryNetwork");
1345 String error = "Query Network (heat): " + networkNameOrId
1352 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
1353 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
1354 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1355 throw new NetworkException (me);
1358 // Populate the outputs based on the returned Stack information
1359 if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
1360 // Found it. Get the neutronNetworkId for further query
1361 Map <String, Object> outputs = heatStack.getOutputs ();
1362 neutronId = (String) outputs.get (NETWORK_ID);
1365 Map <String, String> sMap = new HashMap <String, String> ();
1366 if (outputs != null) {
1367 for (String key : outputs.keySet ()) {
1368 if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
1370 String subnetUUId = (String) outputs.get(key);
1371 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1373 else if (key != null && key.startsWith ("subnet")) //one subnet output expected
1375 Map <String, String> map = getSubnetUUId(key, outputs, null);
1381 subnetIdMap.value = sMap;
1383 // Input ID was not a Heat stack ID. Try it directly in Neutron
1384 neutronId = networkNameOrId;
1385 mode = NEUTRON_MODE;
1388 // Query directly against the Neutron Network for the details
1389 // no RouteTargets available for ContrailV2 in neutron net-show
1390 // networkId is heatStackId
1391 long queryNetworkStarttime = System.currentTimeMillis ();
1393 NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
1394 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
1395 if (netInfo != null) {
1396 // Found. Populate the output elements
1397 networkExists.value = Boolean.TRUE;
1398 if ("HEAT".equals (mode)) {
1399 networkId.value = heatStack.getCanonicalName ();
1401 networkId.value = netInfo.getId ();
1403 neutronNetworkId.value = netInfo.getId ();
1404 status.value = netInfo.getStatus ();
1406 vlans.value = netInfo.getVlans ();
1408 LOGGER.debug ("Network " + networkNameOrId
1413 + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
1415 // Not found. Populate the status fields, leave the rest null
1416 networkExists.value = Boolean.FALSE;
1417 status.value = NetworkStatus.NOTFOUND;
1418 neutronNetworkId.value = null;
1420 vlans.value = new ArrayList <Integer> ();
1422 LOGGER.debug ("Network " + networkNameOrId + " not found");
1424 } catch (MsoException me) {
1425 me.addContext ("QueryNetwork");
1426 String error = "Query Network (neutron): " + networkNameOrId
1433 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
1434 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
1435 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1436 throw new NetworkException (me);
1438 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
1443 * This is the "Delete Network" web service implementation.
1444 * It will delete a Network in the specified cloud and tenant.
1446 * If the network is not found, it is treated as a success.
1448 * This service supports two modes of Network creation/update/delete:
1449 * - via Heat Templates
1451 * The network orchestration mode for each network type is declared in its
1452 * catalog definition.
1454 * For Heat-based orchestration, the networkId should be the stack ID.
1455 * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
1457 * The method returns nothing on success. Rollback is not possible for delete
1458 * commands, so any failure on delete will require manual fallout in the client.
1461 public void deleteNetwork (String cloudSiteId,
1464 String modelCustomizationUuid,
1466 MsoRequest msoRequest,
1467 Holder <Boolean> networkDeleted) throws NetworkException {
1468 MsoLogger.setLogContext (msoRequest);
1469 MsoLogger.setServiceName ("DeleteNetwork");
1470 LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
1476 // Will capture execution time for metrics
1477 long startTime = System.currentTimeMillis ();
1479 // Get a handle to the Catalog Database
1480 CatalogDatabase db = getCatalogDB ();
1482 // Make sure DB connection is always closed
1484 if (isNullOrEmpty (cloudSiteId)
1485 || isNullOrEmpty(tenantId)
1486 || isNullOrEmpty(networkId)) {
1487 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1488 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1489 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1490 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1493 // Retrieve the Network Resource definition
1494 NetworkResource networkResource = null;
1495 if (isNullOrEmpty(modelCustomizationUuid)) {
1496 networkResource = db.getNetworkResource (networkType);
1498 else if (!isNullOrEmpty(networkType))
1500 networkResource = db.getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1503 if (networkResource != null) {
1504 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1506 mode = networkResource.getOrchestrationMode ();
1509 if (NEUTRON_MODE.equals (mode)) {
1511 // Use MsoNeutronUtils for all NEUTRON commands
1512 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1513 long deleteNetworkStarttime = System.currentTimeMillis ();
1515 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1516 // was not found. So don't bother to query first.
1517 boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1518 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1519 networkDeleted.value = deleted;
1520 } catch (MsoException me) {
1521 me.addContext ("DeleteNetwork");
1522 String error = "Delete Network (neutron): " + networkId
1529 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1530 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
1531 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1532 throw new NetworkException (me);
1534 } else { // DEFAULT to ("HEAT".equals (mode))
1535 long deleteStackStarttime = System.currentTimeMillis ();
1536 // Use MsoHeatUtils for all HEAT commands
1537 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1540 // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
1541 // So query first to report back if stack WAS deleted or just NOTOFUND
1542 StackInfo heatStack = null;
1543 heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
1544 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
1546 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1547 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1548 networkDeleted.value = true;
1552 networkDeleted.value = false;
1554 } catch (MsoException me) {
1555 me.addContext ("DeleteNetwork");
1556 String error = "Delete Network (heat): " + networkId
1563 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1564 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
1565 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1566 throw new NetworkException (me);
1573 // On success, nothing is returned.
1574 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
1578 public CatalogDatabase getCatalogDB() {
1579 return CatalogDatabase.getInstance();
1583 * This web service endpoint will rollback a previous Create VNF operation.
1584 * A rollback object is returned to the client in a successful creation
1585 * response. The client can pass that object as-is back to the rollbackVnf
1586 * operation to undo the creation.
1588 * The rollback includes removing the VNF and deleting the tenant if the
1589 * tenant did not exist prior to the VNF creation.
1592 public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
1593 MsoLogger.setServiceName ("RollbackNetwork");
1594 // Will capture execution time for metrics
1595 long startTime = System.currentTimeMillis ();
1597 if (rollback == null) {
1598 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
1599 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
1603 MsoLogger.setLogContext (rollback.getMsoRequest());
1605 // Get the elements of the VnfRollback object for easier access
1606 String cloudSiteId = rollback.getCloudId ();
1607 String tenantId = rollback.getTenantId ();
1608 String networkId = rollback.getNetworkStackId ();
1609 String networkType = rollback.getNetworkType ();
1610 String modelCustomizationUuid = rollback.getModelCustomizationUuid();
1612 LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
1614 // rollback may be null (e.g. if network already existed when Create was called)
1615 // Get a handle to the Catalog Database
1616 CatalogDatabase db = getCatalogDB ();
1618 // Make sure DB connection is always closed
1621 // Retrieve the Network Resource definition
1622 NetworkResource networkResource = null;
1623 if (isNullOrEmpty(modelCustomizationUuid)) {
1624 networkResource = db.getNetworkResource (networkType);
1628 networkResource = db.getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1631 if (networkResource != null) {
1633 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1635 mode = networkResource.getOrchestrationMode ();
1638 if (rollback.getNetworkCreated ()) {
1639 // Rolling back a newly created network, so delete it.
1640 if (NEUTRON_MODE.equals (mode)) {
1641 // Use MsoNeutronUtils for all NEUTRON commands
1642 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1643 long deleteNetworkStarttime = System.currentTimeMillis ();
1645 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1646 // was not found. So don't bother to query first.
1647 neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1648 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1649 } catch (MsoException me) {
1650 me.addContext ("RollbackNetwork");
1651 String error = "Rollback Network (neutron): " + networkId
1658 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1659 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
1660 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1661 throw new NetworkException (me);
1663 } else { // DEFAULT to if ("HEAT".equals (mode))
1664 // Use MsoHeatUtils for all HEAT commands
1665 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1666 long deleteStackStarttime = System.currentTimeMillis ();
1668 // The deleteStack function in MsoHeatUtils returns success if the stack
1669 // was not found. So don't bother to query first.
1670 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1671 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1672 } catch (MsoException me) {
1673 me.addContext ("RollbackNetwork");
1674 String error = "Rollback Network (heat): " + networkId
1681 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1682 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
1683 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1684 throw new NetworkException (me);
1691 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
1695 private String validateNetworkParams (NetworkType neutronNetworkType,
1697 String physicalNetwork,
1698 List <Integer> vlans,
1699 List <String> routeTargets) {
1701 StringBuilder missing = new StringBuilder ();
1702 if (isNullOrEmpty(networkName)) {
1703 missing.append ("networkName");
1707 if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1708 if (isNullOrEmpty(physicalNetwork)) {
1709 missing.append (sep).append ("physicalNetworkName");
1712 if (vlans == null || vlans.isEmpty ()) {
1713 missing.append (sep).append (VLANS);
1717 return missing.toString ();
1720 private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
1722 String physicalNetwork,
1723 List <Integer> vlans,
1724 List <String> routeTargets,
1727 boolean aic3template) {
1728 // Build the common set of HEAT template parameters
1729 Map <String, Object> stackParams = new HashMap <String, Object> ();
1730 stackParams.put ("network_name", networkName);
1732 if (neutronNetworkType == NetworkType.PROVIDER) {
1733 // For Provider type
1734 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1735 stackParams.put ("vlan", vlans.get (0).toString ());
1736 } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1737 // For Multi-provider, PO supports a custom resource extension of ProviderNet.
1738 // It supports all ProviderNet properties except segmentation_id, and adds a
1739 // comma-separated-list of VLANs as a "segments" property.
1740 // Note that this does not match the Neutron definition of Multi-Provider network,
1741 // which contains a list of 'segments', each having physical_network, network_type,
1742 // and segmentation_id.
1743 StringBuilder buf = new StringBuilder ();
1745 for (Integer vlan : vlans) {
1746 buf.append (sep).append (vlan.toString ());
1749 String csl = buf.toString ();
1751 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1752 stackParams.put (VLANS, csl);
1754 if (routeTargets != null && !routeTargets.isEmpty()) {
1755 StringBuilder buf = new StringBuilder ();
1757 for (String rt : routeTargets) {
1758 if (!isNullOrEmpty(rt))
1761 buf.append (sep).append ("target:" + rt.toString ());
1763 buf.append (sep).append (rt.toString ());
1768 String csl = buf.toString ();
1770 stackParams.put ("route_targets", csl);
1772 if (isNullOrEmpty(shared)) {
1773 stackParams.put ("shared", "False");
1775 stackParams.put ("shared", shared);
1777 if (isNullOrEmpty(external)) {
1778 stackParams.put ("external", "False");
1780 stackParams.put ("external", external);
1787 /** policyRef_list structure in stackParams
1790 "network_policy_refs_data_sequence": {
1791 "network_policy_refs_data_sequence_major": "1",
1792 "network_policy_refs_data_sequence_minor": "0"
1796 "network_policy_refs_data_sequence": {
1797 "network_policy_refs_data_sequence_major": "2",
1798 "network_policy_refs_data_sequence_minor": "0"
1803 private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
1805 List<ContrailPolicyRef> prlist = new ArrayList <ContrailPolicyRef> ();
1807 for (String pf : pFqdns) {
1808 if (!isNullOrEmpty(pf))
1810 ContrailPolicyRef pr = new ContrailPolicyRef();
1811 pr.populate(String.valueOf(index), "0");
1813 LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
1818 JsonNode node = null;
1821 ObjectMapper mapper = new ObjectMapper();
1822 node = mapper.convertValue(prlist, JsonNode.class);
1823 String jsonString = mapper.writeValueAsString(prlist);
1824 LOGGER.debug("Json PolicyRefs Data:" + jsonString);
1828 String error = "Error creating JsonNode for policyRefs Data";
1829 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
1830 throw new MsoAdapterException (error);
1833 if (pFqdns != null && node != null)
1835 StringBuilder buf = new StringBuilder ();
1837 for (String pf : pFqdns) {
1838 if (!isNullOrEmpty(pf))
1840 buf.append (sep).append (pf.toString ());
1844 String csl = buf.toString ();
1845 stackParams.put ("policy_refs", csl);
1846 stackParams.put ("policy_refsdata", node);
1849 LOGGER.debug ("StackParams updated with policy refs");
1853 private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
1856 if (rtFqdns != null)
1858 StringBuilder buf = new StringBuilder ();
1860 for (String rtf : rtFqdns) {
1861 if (!isNullOrEmpty(rtf))
1863 buf.append (sep).append (rtf.toString ());
1867 String csl = buf.toString ();
1868 stackParams.put ("route_table_refs", csl);
1871 LOGGER.debug ("StackParams updated with route_table refs");
1876 /*** Subnet Output structure from Juniper
1881 "ip_prefix": "10.100.1.0",
1884 "addr_from_start": null,
1885 "enable_dhcp": false,
1886 "default_gateway": "10.100.1.1",
1887 "dns_nameservers": [],
1888 "dhcp_option_list": null,
1889 "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
1890 "allocation_pools": [
1892 "start": "10.100.1.3",
1896 "start": "10.100.1.6",
1900 "host_routes": null,
1901 "dns_server_address": "10.100.1.13",
1902 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
1906 "ip_prefix": "10.100.2.16",
1909 "addr_from_start": null,
1910 "enable_dhcp": true,
1911 "default_gateway": "10.100.2.17",
1912 "dns_nameservers": [],
1913 "dhcp_option_list": null,
1914 "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
1915 "allocation_pools": [
1917 "start": "10.100.2.18",
1918 "end": "10.100.2.20"
1921 "host_routes": null,
1922 "dns_server_address": "10.100.2.29",
1923 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
1929 private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
1932 List<ContrailSubnet> cslist = new ArrayList <ContrailSubnet> ();
1933 for (Subnet subnet : subnets) {
1934 ContrailSubnet cs = new ContrailSubnet();
1935 LOGGER.debug("Input Subnet:" + subnet.toString());
1936 cs.populateWith(subnet);
1937 LOGGER.debug("Contrail Subnet:" + cs.toString());
1941 JsonNode node = null;
1944 ObjectMapper mapper = new ObjectMapper();
1945 node = mapper.convertValue(cslist, JsonNode.class);
1946 String jsonString = mapper.writeValueAsString(cslist);
1947 LOGGER.debug("Json Subnet List:" + jsonString);
1951 String error = "Error creating JsonNode from input subnets";
1952 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
1953 throw new MsoAdapterException (error);
1958 stackParams.put ("subnet_list", node);
1960 //Outputs - All subnets are in one ipam_subnets structure
1961 String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
1962 + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
1964 // append outputs in heatTemplate
1965 int outputsIdx = heatTemplate.indexOf ("outputs:");
1966 heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
1967 LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
1968 return heatTemplate;
1972 private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
1974 String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
1977 + " network_id: { get_resource: network }\n"
1978 + " cidr: %cidr%\n";
1980 /* make these optional
1981 + " ip_version: %ipversion%\n"
1982 + " enable_dhcp: %enabledhcp%\n"
1983 + " gateway_ip: %gatewayip%\n"
1984 + " allocation_pools:\n"
1985 + " - start: %poolstart%\n"
1986 + " end: %poolend%\n";
1990 String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
1991 + " value: {get_resource: subnet_%subnetId%}\n";
1995 StringBuilder resourcesBuf = new StringBuilder ();
1996 StringBuilder outputsBuf = new StringBuilder ();
1997 for (Subnet subnet : subnets) {
1999 // build template for each subnet
2000 curR = resourceTempl;
2001 if (subnet.getSubnetId () != null) {
2002 curR = curR.replace ("%subnetId%", subnet.getSubnetId ());
2004 String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
2005 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
2006 throw new MsoAdapterException (error);
2009 if (subnet.getSubnetName () != null) {
2010 curR = curR.replace ("%name%", subnet.getSubnetName ());
2012 curR = curR.replace ("%name%", subnet.getSubnetId ());
2015 if (subnet.getCidr () != null) {
2016 curR = curR.replace ("%cidr%", subnet.getCidr ());
2018 String error = "Missing Required cidr for subnet in HEAT Template";
2019 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
2020 throw new MsoAdapterException (error);
2023 if (subnet.getIpVersion () != null) {
2024 curR = curR + " ip_version: " + subnet.getIpVersion () + "\n";
2026 if (subnet.getEnableDHCP () != null) {
2027 curR = curR + " enable_dhcp: " + Boolean.toString (subnet.getEnableDHCP ()) + "\n";
2029 if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
2030 curR = curR + " gateway_ip: " + subnet.getGatewayIp () + "\n";
2033 if (subnet.getAllocationPools() != null) {
2034 curR = curR + " allocation_pools:\n";
2035 for (Pool pool : subnet.getAllocationPools())
2037 if (!isNullOrEmpty(pool.getStart()) && !isNullOrEmpty(pool.getEnd()))
2039 curR = curR + " - start: " + pool.getStart () + "\n";
2040 curR = curR + " end: " + pool.getEnd () + "\n";
2045 resourcesBuf.append (curR);
2048 curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
2050 outputsBuf.append (curO);
2053 // append resources and outputs in heatTemplate
2054 LOGGER.debug ("Tempate initial:" + heatTemplate);
2055 int outputsIdx = heatTemplate.indexOf ("outputs:");
2056 heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
2057 int resourcesIdx = heatTemplate.indexOf ("resources:");
2058 heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
2060 LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
2061 return heatTemplate;
2064 private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
2066 Map <String, String> sMap = new HashMap <String, String> ();
2069 Object obj = outputs.get(key);
2070 ObjectMapper mapper = new ObjectMapper();
2071 String jStr = mapper.writeValueAsString(obj);
2072 LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
2074 JsonNode rootNode = mapper.readTree(jStr);
2075 for (JsonNode sNode : rootNode.path("ipam_subnets"))
2077 LOGGER.debug("Output Subnet Node" + sNode.toString());
2078 String name = sNode.path("subnet_name").getTextValue();
2079 String uuid = sNode.path("subnet_uuid").getTextValue();
2080 String aaiId = name; // default
2081 // try to find aaiId for name in input subnetList
2082 if (subnets != null)
2084 for (Subnet subnet : subnets)
2086 if ( subnet != null && !isNullOrEmpty(subnet.getSubnetName()))
2088 if (subnet.getSubnetName().equals(name))
2090 aaiId = subnet.getSubnetId();
2096 sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
2101 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
2104 LOGGER.debug ("Return sMap" + sMap.toString());
2108 private static String insertStr (String template, String snippet, int index) {
2110 String updatedTemplate = "";
2112 LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
2114 String templateBeg = template.substring (0, index);
2115 String templateEnd = template.substring (index);
2117 updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
2119 LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
2120 return updatedTemplate;