2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.so.adapters.network;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.Optional;
30 import javax.jws.WebService;
31 import javax.xml.ws.Holder;
33 import org.onap.so.adapters.network.beans.ContrailPolicyRef;
34 import org.onap.so.adapters.network.beans.ContrailPolicyRefSeq;
35 import org.onap.so.adapters.network.beans.ContrailSubnet;
36 import org.onap.so.adapters.network.exceptions.NetworkException;
37 import org.onap.so.adapters.network.mappers.ContrailSubnetMapper;
38 import org.onap.so.cloud.CloudConfig;
39 import org.onap.so.cloud.CloudSite;
40 import org.onap.so.db.catalog.beans.HeatTemplate;
41 import org.onap.so.db.catalog.beans.NetworkResource;
42 import org.onap.so.db.catalog.beans.NetworkResourceCustomization;
43 import org.onap.so.db.catalog.data.repository.NetworkResourceCustomizationRepository;
44 import org.onap.so.db.catalog.data.repository.NetworkResourceRepository;
45 import org.onap.so.db.catalog.utils.MavenLikeVersioning;
46 import org.onap.so.entity.MsoRequest;
47 import org.onap.so.logger.MessageEnum;
48 import org.onap.so.logger.MsoAlarmLogger;
49 import org.onap.so.logger.MsoLogger;
50 import org.onap.so.openstack.beans.HeatStatus;
51 import org.onap.so.openstack.beans.NetworkInfo;
52 import org.onap.so.openstack.beans.NetworkRollback;
53 import org.onap.so.openstack.beans.NetworkStatus;
54 import org.onap.so.openstack.beans.Pool;
55 import org.onap.so.openstack.beans.RouteTarget;
56 import org.onap.so.openstack.beans.StackInfo;
57 import org.onap.so.openstack.beans.Subnet;
58 import org.onap.so.openstack.exceptions.MsoAdapterException;
59 import org.onap.so.openstack.exceptions.MsoException;
60 import org.onap.so.openstack.exceptions.MsoExceptionCategory;
61 import org.onap.so.openstack.utils.MsoCommonUtils;
62 import org.onap.so.openstack.utils.MsoHeatUtils;
63 import org.onap.so.openstack.utils.MsoHeatUtilsWithUpdate;
64 import org.onap.so.openstack.utils.MsoNeutronUtils;
65 import org.onap.so.openstack.utils.MsoNeutronUtils.NetworkType;
66 import org.springframework.beans.factory.annotation.Autowired;
67 import org.springframework.core.env.Environment;
68 import org.springframework.stereotype.Component;
69 import org.springframework.transaction.annotation.Transactional;
71 import com.fasterxml.jackson.databind.JsonNode;
72 import com.fasterxml.jackson.databind.ObjectMapper;
76 @WebService(serviceName = "NetworkAdapter", endpointInterface = "org.onap.so.adapters.network.MsoNetworkAdapter", targetNamespace = "http://org.onap.so/network")
77 public class MsoNetworkAdapterImpl implements MsoNetworkAdapter {
79 private static final String AIC3_NW_PROPERTY= "org.onap.so.adapters.network.aic3nw";
80 private static final String AIC3_NW="OS::ContrailV2::VirtualNetwork";
81 private static final String VLANS = "vlans";
82 private static final String PHYSICAL_NETWORK = "physical_network";
83 private static final String UPDATE_NETWORK_CONTEXT = "UpdateNetwork";
84 private static final String NETWORK_ID = "network_id";
85 private static final String NETWORK_FQDN = "network_fqdn";
86 private static final String CREATE_NETWORK_CONTEXT = "CreateNetwork";
87 private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
88 private static final String NEUTRON_MODE = "NEUTRON";
90 private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,MsoNetworkAdapterImpl.class);
91 private static final MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
93 private CloudConfig cloudConfig;
95 private Environment environment;
97 private MsoNeutronUtils neutron;
99 private MsoHeatUtils heat;
101 private MsoHeatUtilsWithUpdate heatWithUpdate;
103 private MsoCommonUtils commonUtils;
106 private NetworkResourceCustomizationRepository networkCustomRepo;
109 private NetworkResourceRepository networkResourceRepo;
111 * Health Check web method. Does nothing but return to show the adapter is deployed.
114 public void healthCheck () {
115 LOGGER.debug ("Health check call in Network Adapter");
119 * Do not use this constructor or the msoPropertiesFactory will be NULL.
121 * @see MsoNetworkAdapterImpl#MsoNetworkAdapterImpl(MsoPropertiesFactory)
123 public MsoNetworkAdapterImpl() {
127 public void createNetwork (String cloudSiteId,
130 String modelCustomizationUuid,
132 String physicalNetworkName,
133 List <Integer> vlans,
134 Boolean failIfExists,
136 List <Subnet> subnets,
137 MsoRequest msoRequest,
138 Holder <String> networkId,
139 Holder <String> neutronNetworkId,
140 Holder <Map <String, String>> subnetIdMap,
141 Holder <NetworkRollback> rollback) throws NetworkException {
142 Holder <String> networkFqdn = new Holder <> ();
143 createNetwork (cloudSiteId,
146 modelCustomizationUuid,
167 public void createNetworkContrail (String cloudSiteId,
170 String modelCustomizationUuid,
172 List <RouteTarget> routeTargets,
175 Boolean failIfExists,
177 List <Subnet> subnets,
178 List <String> policyFqdns,
179 List<String> routeTableFqdns,
180 MsoRequest msoRequest,
181 Holder <String> networkId,
182 Holder <String> neutronNetworkId,
183 Holder <String> networkFqdn,
184 Holder <Map <String, String>> subnetIdMap,
185 Holder <NetworkRollback> rollback) throws NetworkException {
186 createNetwork (cloudSiteId,
189 modelCustomizationUuid,
210 * This is the "Create Network" web service implementation.
211 * It will create a new Network of the requested type in the specified cloud
212 * and tenant. The tenant must exist at the time this service is called.
214 * If a network with the same name already exists, this can be considered a
215 * success or failure, depending on the value of the 'failIfExists' parameter.
217 * There will be a pre-defined set of network types defined in the MSO Catalog.
218 * All such networks will have a similar configuration, based on the allowable
219 * Openstack networking definitions. This includes basic networks, provider
220 * networks (with a single VLAN), and multi-provider networks (one or more VLANs)
222 * Initially, all provider networks must be "vlan" type, and multiple segments in
223 * a multi-provider network must be multiple VLANs on the same physical network.
225 * This service supports two modes of Network creation/update:
226 * - via Heat Templates
228 * The network orchestration mode for each network type is declared in its
229 * catalog definition. All Heat-based templates must support some subset of
230 * the same input parameters: network_name, physical_network, vlan(s).
232 * The method returns the network ID and a NetworkRollback object. This latter
233 * object can be passed as-is to the rollbackNetwork operation to undo everything
234 * that was created. This is useful if a network is successfully created but
235 * the orchestration fails on a subsequent operation.
238 private void createNetwork (String cloudSiteId,
241 String modelCustomizationUuid,
243 String physicalNetworkName,
244 List <Integer> vlans,
245 List <RouteTarget> routeTargets,
248 Boolean failIfExists,
250 List <Subnet> subnets,
251 List <String> policyFqdns,
252 List <String> routeTableFqdns,
253 MsoRequest msoRequest,
254 Holder <String> networkId,
255 Holder <String> neutronNetworkId,
256 Holder <String> networkFqdn,
257 Holder <Map <String, String>> subnetIdMap,
258 Holder <NetworkRollback> rollback) throws NetworkException {
259 MsoLogger.setLogContext (msoRequest);
260 MsoLogger.setServiceName ("CreateNetwork");
262 LOGGER.debug ("*** CREATE Network: " + networkName
270 // Will capture execution time for metrics
271 long startTime = System.currentTimeMillis ();
273 // Build a default rollback object (no actions performed)
274 NetworkRollback networkRollback = new NetworkRollback ();
275 networkRollback.setCloudId (cloudSiteId);
276 networkRollback.setTenantId (tenantId);
277 networkRollback.setMsoRequest (msoRequest);
278 networkRollback.setModelCustomizationUuid(modelCustomizationUuid);
280 // tenant query is not required here.
281 // If the tenant doesn't exist, the Heat calls will fail anyway (when the HeatUtils try to obtain a token).
282 // So this is just catching that error in a bit more obvious way up front.
284 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
285 if (!cloudSiteOpt.isPresent())
287 String error = "Configuration Error. Stack " + networkName + " in "
292 + " CloudSite does not exist in MSO Configuration";
293 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
294 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
295 // Set the detailed error as the Exception 'message'
296 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
300 NetworkResource networkResource = networkCheck (startTime,
302 modelCustomizationUuid,
309 String mode = networkResource.getOrchestrationMode ();
310 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
312 if (NEUTRON_MODE.equals (mode)) {
314 // Use an MsoNeutronUtils for all neutron commands
316 // See if the Network already exists (by name)
317 NetworkInfo netInfo = null;
318 long queryNetworkStarttime = System.currentTimeMillis ();
320 netInfo = neutron.queryNetwork (networkName, tenantId, cloudSiteId);
321 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
322 } catch (MsoException me) {
323 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack", "OpenStack", "QueryNetwork", null);
324 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while querying network from OpenStack", me);
325 me.addContext (CREATE_NETWORK_CONTEXT);
326 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack");
327 throw new NetworkException (me);
330 if (netInfo != null) {
331 // Exists. If that's OK, return success with the network ID.
332 // Otherwise, return an exception.
333 if (failIfExists != null && failIfExists) {
334 String error = "Create Nework: Network " + networkName
335 + " already exists in "
339 + " with ID " + netInfo.getId();
340 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network already exists");
341 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
342 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
344 // Populate the outputs from the existing network.
345 networkId.value = netInfo.getId ();
346 neutronNetworkId.value = netInfo.getId ();
347 rollback.value = networkRollback; // Default rollback - no updates performed
348 String msg = "Found Existing network, status=" + netInfo.getStatus () + " for Neutron mode";
349 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", MsoLogger.ErrorCode.DataError, "Found Existing network, status=" + netInfo.getStatus ());
350 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, msg);
355 long createNetworkStarttime = System.currentTimeMillis ();
357 netInfo = neutron.createNetwork (cloudSiteId,
363 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "CreateNetwork", null);
364 } catch (MsoException me) {
365 me.addContext (CREATE_NETWORK_CONTEXT);
366 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with OpenStack", "OpenStack", "CreateNetwork", null);
367 String error = "Create Network: type " + neutronNetworkType
374 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while communicate with OpenStack", me);
375 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
377 throw new NetworkException (me);
380 // Note: ignoring MsoNetworkAlreadyExists because we already checked.
382 // If reach this point, network creation is successful.
383 // Since directly created via Neutron, networkId tracked by MSO is the same
384 // as the neutron network ID.
385 networkId.value = netInfo.getId ();
386 neutronNetworkId.value = netInfo.getId ();
388 networkRollback.setNetworkCreated (true);
389 networkRollback.setNetworkId (netInfo.getId ());
390 networkRollback.setNeutronNetworkId (netInfo.getId ());
391 networkRollback.setNetworkType (networkType);
393 LOGGER.debug ("Network " + networkName + " created, id = " + netInfo.getId ());
394 } else if ("HEAT".equals (mode)) {
396 HeatTemplate heatTemplate = networkResource.getHeatTemplate();
397 if (heatTemplate == null) {
398 String error = "Network error - undefined Heat Template. Network Type = " + networkType;
399 LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
400 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
404 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
405 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
408 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString());
410 // "Fix" the template if it has CR/LF (getting this from Oracle)
411 String template = heatTemplate.getHeatTemplate ();
412 template = template.replaceAll ("\r\n", "\n");
414 boolean aic3template=false;
415 String aic3nw = AIC3_NW;
417 aic3nw = environment.getProperty(AIC3_NW_PROPERTY, AIC3_NW);
419 if (template.contains(aic3nw))
422 // First, look up to see if the Network already exists (by name).
423 // For HEAT orchestration of networks, the stack name will always match the network name
424 StackInfo heatStack = null;
425 long queryNetworkStarttime = System.currentTimeMillis ();
427 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
428 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
429 } catch (MsoException me) {
430 me.addContext (CREATE_NETWORK_CONTEXT);
431 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
432 String error = "Create Network (heat): query network " + networkName
439 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
440 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
441 throw new NetworkException (me);
444 if (heatStack != null && (heatStack.getStatus () != HeatStatus.NOTFOUND)) {
445 // Stack exists. Return success or error depending on input directive
446 if (failIfExists != null && failIfExists) {
447 String error = "CreateNetwork: Stack " + networkName
448 + " already exists in "
452 + " as " + heatStack.getCanonicalName();
453 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
454 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
455 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
457 // Populate the outputs from the existing stack.
458 networkId.value = heatStack.getCanonicalName ();
459 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
460 rollback.value = networkRollback; // Default rollback - no updates performed
463 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
465 Map <String, Object> outputs = heatStack.getOutputs ();
466 Map <String, String> sMap = new HashMap <> ();
467 if (outputs != null) {
468 for (String key : outputs.keySet ()) {
469 if (key != null && key.startsWith ("subnet")) {
470 if (aic3template) //one subnet_id output
472 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
475 else //multiples subnet_%aaid% outputs
477 String subnetUUId = (String) outputs.get(key);
478 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
483 subnetIdMap.value = sMap;
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.
584 heatStack = heat.createStack (cloudSiteId,
590 heatTemplate.getTimeoutMinutes (),
594 backout.booleanValue());
595 } catch (MsoException me) {
596 me.addContext (CREATE_NETWORK_CONTEXT);
597 String error = "Create Network (heat): type " + neutronNetworkType
604 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
605 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
606 throw new NetworkException (me);
609 // Reach this point if createStack is successful.
611 // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
612 // and the neutronNetworkId is the network UUID returned in stack outputs.
613 networkId.value = heatStack.getCanonicalName ();
614 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
617 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
619 Map <String, Object> outputs = heatStack.getOutputs ();
620 Map <String, String> sMap = new HashMap <> ();
621 if (outputs != null) {
622 for (String key : outputs.keySet ()) {
623 if (key != null && key.startsWith ("subnet")) {
624 if (aic3template) //one subnet output expected
626 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
629 else //multiples subnet_%aaid% outputs allowed
631 String subnetUUId = (String) outputs.get(key);
632 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
637 subnetIdMap.value = sMap;
639 rollback.value = networkRollback;
640 // Populate remaining rollback info and response parameters.
641 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
642 networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
643 networkRollback.setNetworkCreated (true);
644 networkRollback.setNetworkType (networkType);
646 LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
649 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
654 public void updateNetwork (String cloudSiteId,
657 String modelCustomizationUuid,
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,
669 modelCustomizationUuid,
687 public void updateNetworkContrail (String cloudSiteId,
690 String modelCustomizationUuid,
693 List <RouteTarget> routeTargets,
696 List <Subnet> subnets,
697 List <String> policyFqdns,
698 List<String> routeTableFqdns,
699 MsoRequest msoRequest,
700 Holder <Map <String, String>> subnetIdMap,
701 Holder <NetworkRollback> rollback) throws NetworkException {
702 updateNetwork (cloudSiteId,
705 modelCustomizationUuid,
722 * This is the "Update Network" web service implementation.
723 * It will update an existing Network of the requested type in the specified cloud
724 * and tenant. The typical use will be to replace the VLANs with the supplied
725 * list (to add or remove a VLAN), but other properties may be updated as well.
727 * There will be a pre-defined set of network types defined in the MSO Catalog.
728 * All such networks will have a similar configuration, based on the allowable
729 * Openstack networking definitions. This includes basic networks, provider
730 * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
732 * Initially, all provider networks must currently be "vlan" type, and multi-provider
733 * networks must be multiple VLANs on the same physical network.
735 * This service supports two modes of Network update:
736 * - via Heat Templates
738 * The network orchestration mode for each network type is declared in its
739 * catalog definition. All Heat-based templates must support some subset of
740 * the same input parameters: network_name, physical_network, vlan, segments.
742 * The method returns a NetworkRollback object. This object can be passed
743 * as-is to the rollbackNetwork operation to undo everything that was updated.
744 * This is useful if a network is successfully updated but orchestration
745 * fails on a subsequent operation.
747 private void updateNetwork (String cloudSiteId,
750 String modelCustomizationUuid,
753 String physicalNetworkName,
754 List <Integer> vlans,
755 List <RouteTarget> routeTargets,
758 List <Subnet> subnets,
759 List <String> policyFqdns,
760 List<String> routeTableFqdns,
761 MsoRequest msoRequest,
762 Holder <Map <String, String>> subnetIdMap,
763 Holder <NetworkRollback> rollback) throws NetworkException {
764 MsoLogger.setLogContext (msoRequest);
765 MsoLogger.setServiceName ("UpdateNetwork");
766 LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
775 // Will capture execution time for metrics
776 long startTime = System.currentTimeMillis ();
778 // Build a default rollback object (no actions performed)
779 NetworkRollback networkRollback = new NetworkRollback ();
780 networkRollback.setCloudId (cloudSiteId);
781 networkRollback.setTenantId (tenantId);
782 networkRollback.setMsoRequest (msoRequest);
784 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite (cloudSiteId);
785 if (!cloudSiteOpt.isPresent()) {
786 String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
791 + " CloudSite does not exist in MSO Configuration";
792 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
793 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
794 // Set the detailed error as the Exception 'message'
795 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
801 NetworkResource networkResource = networkCheck(
804 modelCustomizationUuid,
811 String mode = networkResource.getOrchestrationMode();
812 NetworkType neutronNetworkType = NetworkType.valueOf(networkResource.getNeutronNetworkType());
814 // Use an MsoNeutronUtils for all Neutron commands
816 if (NEUTRON_MODE.equals(mode)) {
818 // Verify that the Network exists
819 // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
820 NetworkInfo netInfo = null;
821 long queryNetworkStarttime = System.currentTimeMillis();
823 netInfo = neutron.queryNetwork(networkId, tenantId, cloudSiteId);
824 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
825 } catch (MsoException me) {
826 me.addContext(UPDATE_NETWORK_CONTEXT);
827 String error = "Update Network (neutron): query " + networkId
834 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
835 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
836 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
837 throw new NetworkException(me);
840 if (netInfo == null) {
841 String error = "Update Nework: Network " + networkId
842 + " does not exist in "
846 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
847 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
848 // Does not exist. Throw an exception (can't update a non-existent network)
849 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
851 long updateNetworkStarttime = System.currentTimeMillis();
853 netInfo = neutron.updateNetwork(cloudSiteId,
859 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
860 } catch (MsoException me) {
861 me.addContext(UPDATE_NETWORK_CONTEXT);
862 String error = "Update Network (neutron): " + networkId
869 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
870 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
871 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
872 throw new NetworkException(me);
875 // Add the network ID and previously queried vlans to the rollback object
876 networkRollback.setNetworkId(netInfo.getId());
877 networkRollback.setNeutronNetworkId(netInfo.getId());
878 networkRollback.setNetworkType(networkType);
879 // Save previous parameters
880 networkRollback.setNetworkName(netInfo.getName());
881 networkRollback.setPhysicalNetwork(netInfo.getProvider());
882 networkRollback.setVlans(netInfo.getVlans());
884 LOGGER.debug("Network " + networkId + " updated, id = " + netInfo.getId());
885 } else if ("HEAT".equals(mode)) {
887 // First, look up to see that the Network already exists.
888 // For Heat-based orchestration, the networkId is the network Stack ID.
889 StackInfo heatStack = null;
890 long queryStackStarttime = System.currentTimeMillis();
892 heatStack = heat.queryStack(cloudSiteId, tenantId, networkName);
893 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
894 } catch (MsoException me) {
895 me.addContext(UPDATE_NETWORK_CONTEXT);
896 String error = "UpdateNetwork (heat): query " + networkName
903 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
904 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
905 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
906 throw new NetworkException(me);
909 if (heatStack == null || (heatStack.getStatus() == HeatStatus.NOTFOUND)) {
910 String error = "UpdateNetwork: Stack " + networkName
911 + " does not exist in "
915 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
916 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
917 // Network stack does not exist. Return an error
918 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
921 // Get the previous parameters for rollback
922 Map<String, Object> heatParams = heatStack.getParameters();
924 String previousNetworkName = (String) heatParams.get("network_name");
925 String previousPhysicalNetwork = (String) heatParams.get(PHYSICAL_NETWORK);
927 List<Integer> previousVlans = new ArrayList<>();
928 String vlansParam = (String) heatParams.get(VLANS);
929 if (vlansParam != null) {
930 for (String vlan : vlansParam.split(",")) {
932 previousVlans.add(Integer.parseInt(vlan));
933 } catch (NumberFormatException e) {
934 LOGGER.warn(MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
938 LOGGER.debug("Update Stack: Previous VLANS: " + previousVlans);
940 // Ready to deploy the updated Network via Heat
943 HeatTemplate heatTemplate = networkResource.getHeatTemplate();
944 if (heatTemplate == null) {
945 String error = "Network error - undefined Heat Template. Network Type=" + networkType;
946 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);
947 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
948 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
949 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
952 LOGGER.debug("Got HEAT Template from DB: " + heatTemplate.toString());
954 // "Fix" the template if it has CR/LF (getting this from Oracle)
955 String template = heatTemplate.getHeatTemplate();
956 template = template.replaceAll("\r\n", "\n");
958 boolean aic3template = false;
959 String aic3nw = AIC3_NW;
961 aic3nw = environment.getProperty(AIC3_NW_PROPERTY, AIC3_NW);
963 if (template.contains(aic3nw))
966 // Build the common set of HEAT template parameters
967 Map<String, Object> stackParams = populateNetworkParams(neutronNetworkType,
976 // Validate (and update) the input parameters against the DB definition
977 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
979 stackParams = heat.validateStackParams(stackParams, heatTemplate);
980 } catch (IllegalArgumentException e) {
981 String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
982 LOGGER.error(MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
983 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
984 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
985 throw new NetworkException(error, MsoExceptionCategory.INTERNAL, e);
988 if (subnets != null) {
991 template = mergeSubnetsAIC3(template, subnets, stackParams);
993 template = mergeSubnets(template, subnets);
995 } catch (MsoException me) {
996 me.addContext(UPDATE_NETWORK_CONTEXT);
997 String error = "Update Network (heat): type " + neutronNetworkType
1004 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
1005 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1006 throw new NetworkException(me);
1010 if (policyFqdns != null && aic3template) {
1012 mergePolicyRefs(policyFqdns, stackParams);
1013 } catch (MsoException me) {
1014 me.addContext(UPDATE_NETWORK_CONTEXT);
1015 String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
1022 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
1023 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1024 throw new NetworkException(me);
1028 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
1030 mergeRouteTableRefs(routeTableFqdns, stackParams);
1031 } catch (MsoException me) {
1032 me.addContext(UPDATE_NETWORK_CONTEXT);
1033 String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
1040 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
1041 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1042 throw new NetworkException(me);
1046 // Update the network stack
1047 // Ignore MsoStackNotFound exception because we already checked.
1048 long updateStackStarttime = System.currentTimeMillis();
1050 heatStack = heatWithUpdate.updateStack(cloudSiteId,
1056 heatTemplate.getTimeoutMinutes());
1057 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
1058 } catch (MsoException me) {
1059 me.addContext(UPDATE_NETWORK_CONTEXT);
1060 String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1061 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
1062 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
1063 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1064 throw new NetworkException(me);
1067 Map<String, Object> outputs = heatStack.getOutputs();
1068 Map<String, String> sMap = new HashMap<>();
1069 if (outputs != null) {
1070 for (String key : outputs.keySet()) {
1071 if (key != null && key.startsWith("subnet")) {
1072 if (aic3template) //one subnet output expected
1074 Map<String, String> map = getSubnetUUId(key, outputs, subnets);
1076 } else //multiples subnet_%aaid% outputs allowed
1078 String subnetUUId = (String) outputs.get(key);
1079 sMap.put(key.substring("subnet_id_".length()), subnetUUId);
1084 subnetIdMap.value = sMap;
1086 // Reach this point if createStack is successful.
1087 // Populate remaining rollback info and response parameters.
1088 networkRollback.setNetworkStackId(heatStack.getCanonicalName());
1089 if(null != outputs) {
1090 networkRollback.setNeutronNetworkId((String) outputs.get(NETWORK_ID));
1093 LOGGER.debug("outputs is NULL");
1095 networkRollback.setNetworkType(networkType);
1096 // Save previous parameters
1097 networkRollback.setNetworkName(previousNetworkName);
1098 networkRollback.setPhysicalNetwork(previousPhysicalNetwork);
1099 networkRollback.setVlans(previousVlans);
1101 rollback.value = networkRollback;
1103 LOGGER.debug("Network " + networkId + " successfully updated via HEAT");
1106 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
1110 private NetworkResource networkCheck (long startTime,
1112 String modelCustomizationUuid,
1114 String physicalNetworkName,
1115 List <Integer> vlans,
1116 List <RouteTarget> routeTargets,
1118 CloudSite cloudSite) throws NetworkException {
1119 // Retrieve the Network Resource definition
1120 NetworkResource networkResource = null;
1121 NetworkResourceCustomization networkCust = null;
1122 if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
1123 if (!commonUtils.isNullOrEmpty(networkType)) {
1124 networkResource = networkResourceRepo.findOneByModelName(networkType);
1127 networkCust = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid);
1129 if(networkCust != null){
1130 LOGGER.debug("Got Network Customization definition from Catalog: "
1131 + networkCust.toString());
1133 networkResource = networkCust.getNetworkResource();
1135 if (networkResource == null) {
1136 String error = "Create/UpdateNetwork: Unable to get network resource with NetworkType:"
1138 + " or ModelCustomizationUUID:"
1139 + modelCustomizationUuid;
1140 LOGGER.error(MessageEnum.RA_UNKOWN_PARAM,
1141 "NetworkType/ModelCustomizationUUID", networkType + "/"
1142 + modelCustomizationUuid, "OpenStack", "",
1143 MsoLogger.ErrorCode.DataError,
1144 "Create/UpdateNetwork: Unknown NetworkType/ModelCustomizationUUID");
1146 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1148 LOGGER.debug("Got Network definition from Catalog: "
1149 + networkResource.toString());
1151 String mode = networkResource.getOrchestrationMode();
1152 NetworkType neutronNetworkType = NetworkType
1153 .valueOf(networkResource.getNeutronNetworkType());
1155 // All Networks are orchestrated via HEAT or Neutron
1156 if (!("HEAT".equals(mode) || NEUTRON_MODE.equals(mode))) {
1157 String error = "CreateNetwork: Configuration Error: Network Type = "
1159 LOGGER.error(MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT,
1160 mode, "OpenStack", "", MsoLogger.ErrorCode.DataError,
1161 "CreateNetwork: Configuration Error");
1162 // Alarm on this error, configuration must be fixed
1163 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
1164 MsoAlarmLogger.CRITICAL, error);
1166 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
1169 MavenLikeVersioning aicV = new MavenLikeVersioning();
1170 aicV.setVersion(cloudSite.getAicVersion());
1171 if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV
1172 .isTheSameVersion(networkResource.getAicVersionMin())) // aic
1175 && (aicV.isTheSameVersion(networkResource
1176 .getAicVersionMax()) || !(aicV
1177 .isMoreRecentThan(networkResource
1178 .getAicVersionMax())))) // aic <= max
1180 LOGGER.debug("Network Type:" + networkType + " VersionMin:"
1181 + networkResource.getAicVersionMin() + " VersionMax:"
1182 + networkResource.getAicVersionMax()
1183 + " supported on Cloud:" + cloudSiteId
1184 + " with AIC_Version:" + cloudSite.getAicVersion());
1186 String error = "Network Type:" + networkType + " Version_Min:"
1187 + networkResource.getAicVersionMin() + " Version_Max:"
1188 + networkResource.getAicVersionMax()
1189 + " not supported on Cloud:" + cloudSiteId
1190 + " with AIC_Version:" + cloudSite.getAicVersion();
1191 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "",
1192 MsoLogger.ErrorCode.DataError,
1193 "Network Type not supported on Cloud");
1194 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
1195 MsoLogger.ResponseCode.DataError, error);
1196 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1199 // Validate the Network parameters.
1200 String missing = validateNetworkParams(neutronNetworkType,
1201 networkName, physicalNetworkName, vlans, routeTargets);
1202 if (!missing.isEmpty()) {
1203 String error = "Create Network: Missing parameters: " + missing;
1204 LOGGER.error(MessageEnum.RA_MISSING_PARAM, missing,
1205 "OpenStack", "", MsoLogger.ErrorCode.DataError,
1206 "Create Network: Missing parameters");
1208 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1211 return networkResource;
1215 public void queryNetwork (String cloudSiteId,
1217 String networkNameOrId,
1218 MsoRequest msoRequest,
1219 Holder <Boolean> networkExists,
1220 Holder <String> networkId,
1221 Holder <String> neutronNetworkId,
1222 Holder <NetworkStatus> status,
1223 Holder <List <Integer>> vlans,
1224 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1225 queryNetwork (cloudSiteId,
1239 public void queryNetworkContrail (String cloudSiteId,
1241 String networkNameOrId,
1242 MsoRequest msoRequest,
1243 Holder <Boolean> networkExists,
1244 Holder <String> networkId,
1245 Holder <String> neutronNetworkId,
1246 Holder <NetworkStatus> status,
1247 Holder <List <RouteTarget>> routeTargets,
1248 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1249 queryNetwork (cloudSiteId,
1263 * This is the queryNetwork method. It returns the existence and status of
1264 * the specified network, along with its Neutron UUID and list of VLANs.
1265 * This method attempts to find the network using both Heat and Neutron.
1266 * Heat stacks are first searched based on the provided network name/id.
1267 * If none is found, the Neutron is directly queried.
1269 private void queryNetwork (String cloudSiteId,
1271 String networkNameOrId,
1272 MsoRequest msoRequest,
1273 Holder <Boolean> networkExists,
1274 Holder <String> networkId,
1275 Holder <String> neutronNetworkId,
1276 Holder <NetworkStatus> status,
1277 Holder <List <Integer>> vlans,
1278 Holder <List <RouteTarget>> routeTargets,
1279 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1280 MsoLogger.setLogContext (msoRequest);
1281 MsoLogger.setServiceName ("QueryNetwork");
1282 LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
1288 // Will capture execution time for metrics
1289 long startTime = System.currentTimeMillis ();
1291 if (commonUtils.isNullOrEmpty (cloudSiteId)
1292 || commonUtils.isNullOrEmpty(tenantId)
1293 || commonUtils.isNullOrEmpty(networkNameOrId)) {
1295 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1296 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1297 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1298 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1301 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
1302 if (!cloudSiteOpt.isPresent())
1304 String error = "Configuration Error. Stack " + networkNameOrId + " in "
1309 + " CloudSite does not exist in MSO Configuration";
1310 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
1311 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1312 // Set the detailed error as the Exception 'message'
1313 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1316 // Use MsoNeutronUtils for all NEUTRON commands
1320 // Try Heat first, since networks may be named the same as the Heat stack
1321 StackInfo heatStack = null;
1322 long queryStackStarttime = System.currentTimeMillis ();
1324 heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
1325 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
1326 } catch (MsoException me) {
1327 me.addContext ("QueryNetwork");
1328 String error = "Query Network (heat): " + networkNameOrId
1335 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
1336 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
1337 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1338 throw new NetworkException (me);
1341 // Populate the outputs based on the returned Stack information
1342 if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
1343 // Found it. Get the neutronNetworkId for further query
1344 Map <String, Object> outputs = heatStack.getOutputs ();
1345 neutronId = (String) outputs.get (NETWORK_ID);
1348 Map <String, String> sMap = new HashMap <> ();
1349 if (outputs != null) {
1350 for (String key : outputs.keySet ()) {
1351 if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
1353 String subnetUUId = (String) outputs.get(key);
1354 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1356 else if (key != null && key.startsWith ("subnet")) //one subnet output expected
1358 Map <String, String> map = getSubnetUUId(key, outputs, null);
1364 subnetIdMap.value = sMap;
1366 // Input ID was not a Heat stack ID. Try it directly in Neutron
1367 neutronId = networkNameOrId;
1368 mode = NEUTRON_MODE;
1371 // Query directly against the Neutron Network for the details
1372 // no RouteTargets available for ContrailV2 in neutron net-show
1373 // networkId is heatStackId
1374 long queryNetworkStarttime = System.currentTimeMillis ();
1376 NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
1377 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
1378 if (netInfo != null) {
1379 // Found. Populate the output elements
1380 networkExists.value = Boolean.TRUE;
1381 if ("HEAT".equals (mode)) {
1382 networkId.value = heatStack.getCanonicalName ();
1384 networkId.value = netInfo.getId ();
1386 neutronNetworkId.value = netInfo.getId ();
1387 status.value = netInfo.getStatus ();
1389 vlans.value = netInfo.getVlans ();
1391 LOGGER.debug ("Network " + networkNameOrId
1396 + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
1398 // Not found. Populate the status fields, leave the rest null
1399 networkExists.value = Boolean.FALSE;
1400 status.value = NetworkStatus.NOTFOUND;
1401 neutronNetworkId.value = null;
1403 vlans.value = new ArrayList<>();
1405 LOGGER.debug ("Network " + networkNameOrId + " not found");
1407 } catch (MsoException me) {
1408 me.addContext ("QueryNetwork");
1409 String error = "Query Network (neutron): " + networkNameOrId
1416 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
1417 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
1418 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1419 throw new NetworkException (me);
1421 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
1426 * This is the "Delete Network" web service implementation.
1427 * It will delete a Network in the specified cloud and tenant.
1429 * If the network is not found, it is treated as a success.
1431 * This service supports two modes of Network creation/update/delete:
1432 * - via Heat Templates
1434 * The network orchestration mode for each network type is declared in its
1435 * catalog definition.
1437 * For Heat-based orchestration, the networkId should be the stack ID.
1438 * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
1440 * The method returns nothing on success. Rollback is not possible for delete
1441 * commands, so any failure on delete will require manual fallout in the client.
1444 public void deleteNetwork (String cloudSiteId,
1447 String modelCustomizationUuid,
1449 MsoRequest msoRequest,
1450 Holder <Boolean> networkDeleted) throws NetworkException {
1451 MsoLogger.setLogContext (msoRequest);
1452 MsoLogger.setServiceName ("DeleteNetwork");
1453 LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
1459 // Will capture execution time for metrics
1460 long startTime = System.currentTimeMillis ();
1463 if (commonUtils.isNullOrEmpty (cloudSiteId)
1464 || commonUtils.isNullOrEmpty(tenantId)
1465 || commonUtils.isNullOrEmpty(networkId)) {
1466 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1467 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1468 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1469 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1472 // Retrieve the Network Resource definition
1473 NetworkResource networkResource = null;
1475 if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
1476 if (!commonUtils.isNullOrEmpty(networkType)) {
1477 networkResource = networkResourceRepo.findFirstByModelNameOrderByModelVersionDesc(networkType);
1480 NetworkResourceCustomization nrc = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid);
1482 networkResource = nrc.getNetworkResource();
1487 if (networkResource != null) {
1488 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1490 mode = networkResource.getOrchestrationMode ();
1493 if (NEUTRON_MODE.equals (mode)) {
1495 // Use MsoNeutronUtils for all NEUTRON commands
1496 long deleteNetworkStarttime = System.currentTimeMillis ();
1498 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1499 // was not found. So don't bother to query first.
1500 boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1501 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1502 networkDeleted.value = deleted;
1503 } catch (MsoException me) {
1504 me.addContext ("DeleteNetwork");
1505 String error = "Delete Network (neutron): " + networkId
1512 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1513 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
1514 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1515 throw new NetworkException (me);
1517 } else { // DEFAULT to ("HEAT".equals (mode))
1518 long deleteStackStarttime = System.currentTimeMillis ();
1521 // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
1522 // So query first to report back if stack WAS deleted or just NOTOFUND
1523 StackInfo heatStack = null;
1524 heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
1525 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
1527 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1528 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1529 networkDeleted.value = true;
1533 networkDeleted.value = false;
1535 } catch (MsoException me) {
1536 me.addContext ("DeleteNetwork");
1537 String error = "Delete Network (heat): " + networkId
1544 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1545 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
1546 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1547 throw new NetworkException (me);
1552 // On success, nothing is returned.
1553 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
1558 * This web service endpoint will rollback a previous Create VNF operation.
1559 * A rollback object is returned to the client in a successful creation
1560 * response. The client can pass that object as-is back to the rollbackVnf
1561 * operation to undo the creation.
1563 * The rollback includes removing the VNF and deleting the tenant if the
1564 * tenant did not exist prior to the VNF creation.
1567 public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
1568 MsoLogger.setServiceName ("RollbackNetwork");
1569 // Will capture execution time for metrics
1570 long startTime = System.currentTimeMillis ();
1572 if (rollback == null) {
1573 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
1574 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
1578 MsoLogger.setLogContext (rollback.getMsoRequest());
1580 // Get the elements of the VnfRollback object for easier access
1581 String cloudSiteId = rollback.getCloudId ();
1582 String tenantId = rollback.getTenantId ();
1583 String networkId = rollback.getNetworkStackId ();
1584 String networkType = rollback.getNetworkType ();
1585 String modelCustomizationUuid = rollback.getModelCustomizationUuid();
1587 LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
1591 // Retrieve the Network Resource definition
1592 NetworkResource networkResource = null;
1593 if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
1594 networkResource = networkCustomRepo.findOneByNetworkType(networkType).getNetworkResource();
1596 networkResource = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid).getNetworkResource();
1599 if (networkResource != null) {
1601 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1603 mode = networkResource.getOrchestrationMode ();
1606 if (rollback.getNetworkCreated ()) {
1607 // Rolling back a newly created network, so delete it.
1608 if (NEUTRON_MODE.equals (mode)) {
1609 // Use MsoNeutronUtils for all NEUTRON commands
1610 long deleteNetworkStarttime = System.currentTimeMillis ();
1612 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1613 // was not found. So don't bother to query first.
1614 neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1615 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1616 } catch (MsoException me) {
1617 me.addContext ("RollbackNetwork");
1618 String error = "Rollback Network (neutron): " + networkId
1625 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1626 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
1627 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1628 throw new NetworkException (me);
1630 } else { // DEFAULT to if ("HEAT".equals (mode))
1631 long deleteStackStarttime = System.currentTimeMillis ();
1633 // The deleteStack function in MsoHeatUtils returns success if the stack
1634 // was not found. So don't bother to query first.
1635 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1636 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1637 } catch (MsoException me) {
1638 me.addContext ("RollbackNetwork");
1639 String error = "Rollback Network (heat): " + networkId
1646 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1647 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
1648 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1649 throw new NetworkException (me);
1654 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
1658 private String validateNetworkParams (NetworkType neutronNetworkType,
1660 String physicalNetwork,
1661 List <Integer> vlans,
1662 List <RouteTarget> routeTargets) {
1664 StringBuilder missing = new StringBuilder ();
1665 if (commonUtils.isNullOrEmpty(networkName)) {
1666 missing.append ("networkName");
1670 if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1671 if (commonUtils.isNullOrEmpty(physicalNetwork)) {
1672 missing.append (sep).append ("physicalNetworkName");
1675 if (vlans == null || vlans.isEmpty ()) {
1676 missing.append (sep).append (VLANS);
1680 return missing.toString ();
1683 private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
1685 String physicalNetwork,
1686 List <Integer> vlans,
1687 List <RouteTarget> routeTargets,
1690 boolean aic3template) {
1691 // Build the common set of HEAT template parameters
1692 Map <String, Object> stackParams = new HashMap <> ();
1693 stackParams.put ("network_name", networkName);
1695 if (neutronNetworkType == NetworkType.PROVIDER) {
1696 // For Provider type
1697 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1698 stackParams.put ("vlan", vlans.get (0).toString ());
1699 } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1700 // For Multi-provider, PO supports a custom resource extension of ProviderNet.
1701 // It supports all ProviderNet properties except segmentation_id, and adds a
1702 // comma-separated-list of VLANs as a "segments" property.
1703 // Note that this does not match the Neutron definition of Multi-Provider network,
1704 // which contains a list of 'segments', each having physical_network, network_type,
1705 // and segmentation_id.
1706 StringBuilder buf = new StringBuilder ();
1708 for (Integer vlan : vlans) {
1709 buf.append (sep).append (vlan.toString ());
1712 String csl = buf.toString ();
1714 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1715 stackParams.put (VLANS, csl);
1717 if (routeTargets != null) {
1719 String rtGlobal = "";
1720 String rtImport = "";
1721 String rtExport = "";
1723 for (RouteTarget rt : routeTargets) {
1724 boolean rtIsNull = false;
1727 String routeTarget = rt.getRouteTarget();
1728 String routeTargetRole = rt.getRouteTargetRole();
1729 LOGGER.debug("Checking for an actually null route target: " + rt.toString());
1730 if (routeTarget == null || routeTarget.equals("") || routeTarget.equalsIgnoreCase("null"))
1732 if (routeTargetRole == null || routeTargetRole.equals("") || routeTargetRole.equalsIgnoreCase("null"))
1738 LOGGER.debug("Input RT:" + rt.toString());
1739 String role = rt.getRouteTargetRole();
1740 String rtValue = rt.getRouteTarget();
1742 if ("IMPORT".equalsIgnoreCase(role))
1744 sep = rtImport.isEmpty() ? "" : ",";
1745 rtImport = aic3template ? rtImport + sep + "target:" + rtValue : rtImport + sep + rtValue ;
1747 else if ("EXPORT".equalsIgnoreCase(role))
1749 sep = rtExport.isEmpty() ? "" : ",";
1750 rtExport = aic3template ? rtExport + sep + "target:" + rtValue : rtExport + sep + rtValue ;
1752 else // covers BOTH, empty etc
1754 sep = rtGlobal.isEmpty() ? "" : ",";
1755 rtGlobal = aic3template ? rtGlobal + sep + "target:" + rtValue : rtGlobal + sep + rtValue ;
1761 if (!rtImport.isEmpty())
1763 stackParams.put ("route_targets_import", rtImport);
1765 if (!rtExport.isEmpty())
1767 stackParams.put ("route_targets_export", rtExport);
1769 if (!rtGlobal.isEmpty())
1771 stackParams.put ("route_targets", rtGlobal);
1774 if (commonUtils.isNullOrEmpty(shared)) {
1775 stackParams.put ("shared", "False");
1777 stackParams.put ("shared", shared);
1779 if (commonUtils.isNullOrEmpty(external)) {
1780 stackParams.put ("external", "False");
1782 stackParams.put ("external", external);
1789 /** policyRef_list structure in stackParams
1792 "network_policy_refs_data_sequence": {
1793 "network_policy_refs_data_sequence_major": "1",
1794 "network_policy_refs_data_sequence_minor": "0"
1798 "network_policy_refs_data_sequence": {
1799 "network_policy_refs_data_sequence_major": "2",
1800 "network_policy_refs_data_sequence_minor": "0"
1805 private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
1807 List<ContrailPolicyRef> prlist = new ArrayList <> ();
1809 for (String pf : pFqdns) {
1810 if (!commonUtils.isNullOrEmpty(pf))
1812 ContrailPolicyRef pr = new ContrailPolicyRef();
1813 ContrailPolicyRefSeq refSeq = new ContrailPolicyRefSeq(String.valueOf(index), "0");
1816 LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
1821 JsonNode node = null;
1824 ObjectMapper mapper = new ObjectMapper();
1825 node = mapper.convertValue(prlist, JsonNode.class);
1826 String jsonString = mapper.writeValueAsString(prlist);
1827 LOGGER.debug("Json PolicyRefs Data:" + jsonString);
1831 String error = "Error creating JsonNode for policyRefs Data";
1832 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
1833 throw new MsoAdapterException (error);
1836 if (pFqdns != null && node != null)
1838 StringBuilder buf = new StringBuilder ();
1840 for (String pf : pFqdns) {
1841 if (!commonUtils.isNullOrEmpty(pf))
1843 buf.append (sep).append (pf);
1847 String csl = buf.toString ();
1848 stackParams.put ("policy_refs", csl);
1849 stackParams.put ("policy_refsdata", node);
1852 LOGGER.debug ("StackParams updated with policy refs");
1856 private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
1859 if (rtFqdns != null)
1861 StringBuilder buf = new StringBuilder ();
1863 for (String rtf : rtFqdns) {
1864 if (!commonUtils.isNullOrEmpty(rtf))
1866 buf.append (sep).append (rtf);
1870 String csl = buf.toString ();
1871 stackParams.put ("route_table_refs", csl);
1874 LOGGER.debug ("StackParams updated with route_table refs");
1879 /*** Subnet Output structure from Juniper
1884 "ip_prefix": "10.100.1.0",
1887 "addr_from_start": null,
1888 "enable_dhcp": false,
1889 "default_gateway": "10.100.1.1",
1890 "dns_nameservers": [],
1891 "dhcp_option_list": null,
1892 "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
1893 "allocation_pools": [
1895 "start": "10.100.1.3",
1899 "start": "10.100.1.6",
1903 "host_routes": null,
1904 "dns_server_address": "10.100.1.13",
1905 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
1909 "ip_prefix": "10.100.2.16",
1912 "addr_from_start": null,
1913 "enable_dhcp": true,
1914 "default_gateway": "10.100.2.17",
1915 "dns_nameservers": [],
1916 "dhcp_option_list": null,
1917 "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
1918 "allocation_pools": [
1920 "start": "10.100.2.18",
1921 "end": "10.100.2.20"
1924 "host_routes": null,
1925 "dns_server_address": "10.100.2.29",
1926 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
1932 private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
1935 List<ContrailSubnet> cslist = new ArrayList <> ();
1936 for (Subnet subnet : subnets) {
1937 LOGGER.debug("Input Subnet:" + subnet.toString());
1938 ContrailSubnet cs = new ContrailSubnetMapper(subnet).map();
1939 LOGGER.debug("Contrail Subnet:" + cs.toString());
1943 JsonNode node = null;
1946 ObjectMapper mapper = new ObjectMapper();
1947 node = mapper.convertValue(cslist, JsonNode.class);
1948 String jsonString = mapper.writeValueAsString(cslist);
1949 LOGGER.debug("Json Subnet List:" + jsonString);
1953 String error = "Error creating JsonNode from input subnets";
1954 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
1955 throw new MsoAdapterException (error);
1960 stackParams.put ("subnet_list", node);
1962 //Outputs - All subnets are in one ipam_subnets structure
1963 String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
1964 + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
1966 // append outputs in heatTemplate
1967 int outputsIdx = heatTemplate.indexOf ("outputs:");
1968 heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
1969 LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
1970 return heatTemplate;
1974 private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
1976 String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
1979 + " network_id: { get_resource: network }\n"
1980 + " cidr: %cidr%\n";
1982 /* make these optional
1983 + " ip_version: %ipversion%\n"
1984 + " enable_dhcp: %enabledhcp%\n"
1985 + " gateway_ip: %gatewayip%\n"
1986 + " allocation_pools:\n"
1987 + " - start: %poolstart%\n"
1988 + " end: %poolend%\n";
1992 String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
1993 + " value: {get_resource: subnet_%subnetId%}\n";
1997 StringBuilder resourcesBuf = new StringBuilder ();
1998 StringBuilder outputsBuf = new StringBuilder ();
1999 for (Subnet subnet : subnets) {
2001 // build template for each subnet
2002 curR = resourceTempl;
2003 if (subnet.getSubnetId () != null) {
2004 curR = curR.replace ("%subnetId%", subnet.getSubnetId ());
2006 String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
2007 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
2008 throw new MsoAdapterException (error);
2011 if (subnet.getSubnetName () != null) {
2012 curR = curR.replace ("%name%", subnet.getSubnetName ());
2014 curR = curR.replace ("%name%", subnet.getSubnetId ());
2017 if (subnet.getCidr () != null) {
2018 curR = curR.replace ("%cidr%", subnet.getCidr ());
2020 String error = "Missing Required cidr for subnet in HEAT Template";
2021 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
2022 throw new MsoAdapterException (error);
2025 if (subnet.getIpVersion () != null) {
2026 curR = curR + " ip_version: " + subnet.getIpVersion () + "\n";
2028 if (subnet.getEnableDHCP () != null) {
2029 curR = curR + " enable_dhcp: " + Boolean.toString (subnet.getEnableDHCP ()) + "\n";
2031 if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
2032 curR = curR + " gateway_ip: " + subnet.getGatewayIp () + "\n";
2035 if (subnet.getAllocationPools() != null) {
2036 curR = curR + " allocation_pools:\n";
2037 for (Pool pool : subnet.getAllocationPools())
2039 if (!commonUtils.isNullOrEmpty(pool.getStart()) && !commonUtils.isNullOrEmpty(pool.getEnd()))
2041 curR = curR + " - start: " + pool.getStart () + "\n";
2042 curR = curR + " end: " + pool.getEnd () + "\n";
2047 resourcesBuf.append (curR);
2050 curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
2052 outputsBuf.append (curO);
2055 // append resources and outputs in heatTemplate
2056 LOGGER.debug ("Tempate initial:" + heatTemplate);
2057 int outputsIdx = heatTemplate.indexOf ("outputs:");
2058 heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
2059 int resourcesIdx = heatTemplate.indexOf ("resources:");
2060 heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
2062 LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
2063 return heatTemplate;
2066 private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
2068 Map <String, String> sMap = new HashMap <> ();
2071 Object obj = outputs.get(key);
2072 ObjectMapper mapper = new ObjectMapper();
2073 String jStr = mapper.writeValueAsString(obj);
2074 LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
2076 JsonNode rootNode = mapper.readTree(jStr);
2077 for (JsonNode sNode : rootNode.path("ipam_subnets"))
2079 LOGGER.debug("Output Subnet Node" + sNode.toString());
2080 String name = sNode.path("subnet_name").textValue();
2081 String uuid = sNode.path("subnet_uuid").textValue();
2082 String aaiId = name; // default
2083 // try to find aaiId for name in input subnetList
2084 if (subnets != null)
2086 for (Subnet subnet : subnets)
2088 if ( subnet != null && !commonUtils.isNullOrEmpty(subnet.getSubnetName()))
2090 if (subnet.getSubnetName().equals(name))
2092 aaiId = subnet.getSubnetId();
2098 sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
2103 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
2106 LOGGER.debug ("Return sMap" + sMap.toString());
2110 private static String insertStr (String template, String snippet, int index) {
2112 String updatedTemplate;
2114 LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
2116 String templateBeg = template.substring (0, index);
2117 String templateEnd = template.substring (index);
2119 updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
2121 LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
2122 return updatedTemplate;