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 * Modifications Copyright (C) 2018 IBM.
9 * ================================================================================
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ============LICENSE_END=========================================================
24 package org.onap.so.adapters.network;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
30 import java.util.Optional;
32 import javax.jws.WebService;
33 import javax.xml.ws.Holder;
35 import org.onap.so.adapters.network.beans.ContrailPolicyRef;
36 import org.onap.so.adapters.network.beans.ContrailPolicyRefSeq;
37 import org.onap.so.adapters.network.beans.ContrailSubnet;
38 import org.onap.so.adapters.network.exceptions.NetworkException;
39 import org.onap.so.adapters.network.mappers.ContrailSubnetMapper;
40 import org.onap.so.cloud.CloudConfig;
41 import org.onap.so.db.catalog.beans.CloudSite;
42 import org.onap.so.db.catalog.beans.HeatTemplate;
43 import org.onap.so.db.catalog.beans.NetworkResource;
44 import org.onap.so.db.catalog.beans.NetworkResourceCustomization;
45 import org.onap.so.db.catalog.beans.CollectionNetworkResourceCustomization;
46 import org.onap.so.db.catalog.data.repository.CollectionNetworkResourceCustomizationRepository;
47 import org.onap.so.db.catalog.data.repository.NetworkResourceCustomizationRepository;
48 import org.onap.so.db.catalog.data.repository.NetworkResourceRepository;
49 import org.onap.so.db.catalog.utils.MavenLikeVersioning;
50 import org.onap.so.entity.MsoRequest;
51 import org.onap.so.logger.MessageEnum;
52 import org.onap.so.logger.MsoAlarmLogger;
53 import org.onap.so.logger.MsoLogger;
54 import org.onap.so.openstack.beans.HeatStatus;
55 import org.onap.so.openstack.beans.NetworkInfo;
56 import org.onap.so.openstack.beans.NetworkRollback;
57 import org.onap.so.openstack.beans.NetworkStatus;
58 import org.onap.so.openstack.beans.Pool;
59 import org.onap.so.openstack.beans.RouteTarget;
60 import org.onap.so.openstack.beans.StackInfo;
61 import org.onap.so.openstack.beans.Subnet;
62 import org.onap.so.openstack.exceptions.MsoAdapterException;
63 import org.onap.so.openstack.exceptions.MsoException;
64 import org.onap.so.openstack.exceptions.MsoExceptionCategory;
65 import org.onap.so.openstack.utils.MsoCommonUtils;
66 import org.onap.so.openstack.utils.MsoHeatUtils;
67 import org.onap.so.openstack.utils.MsoHeatUtilsWithUpdate;
68 import org.onap.so.openstack.utils.MsoNeutronUtils;
69 import org.onap.so.openstack.utils.MsoNeutronUtils.NetworkType;
70 import org.springframework.beans.factory.annotation.Autowired;
71 import org.springframework.core.env.Environment;
72 import org.springframework.stereotype.Component;
73 import org.springframework.transaction.annotation.Transactional;
75 import com.fasterxml.jackson.databind.JsonNode;
76 import com.fasterxml.jackson.databind.ObjectMapper;
80 @WebService(serviceName = "NetworkAdapter", endpointInterface = "org.onap.so.adapters.network.MsoNetworkAdapter", targetNamespace = "http://org.onap.so/network")
81 public class MsoNetworkAdapterImpl implements MsoNetworkAdapter {
83 private static final String AIC3_NW_PROPERTY= "org.onap.so.adapters.network.aic3nw";
84 private static final String AIC3_NW="OS::ContrailV2::VirtualNetwork";
85 private static final String VLANS = "vlans";
86 private static final String PHYSICAL_NETWORK = "physical_network";
87 private static final String UPDATE_NETWORK_CONTEXT = "UpdateNetwork";
88 private static final String NETWORK_ID = "network_id";
89 private static final String NETWORK_FQDN = "network_fqdn";
90 private static final String CREATE_NETWORK_CONTEXT = "CreateNetwork";
91 private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
92 private static final String NEUTRON_MODE = "NEUTRON";
94 private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,MsoNetworkAdapterImpl.class);
95 private static final MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
97 private CloudConfig cloudConfig;
99 private Environment environment;
101 private MsoNeutronUtils neutron;
103 private MsoHeatUtils heat;
105 private MsoHeatUtilsWithUpdate heatWithUpdate;
107 private MsoCommonUtils commonUtils;
110 private NetworkResourceCustomizationRepository networkCustomRepo;
113 private CollectionNetworkResourceCustomizationRepository collectionNetworkCustomRepo;
116 private NetworkResourceRepository networkResourceRepo;
118 * Health Check web method. Does nothing but return to show the adapter is deployed.
121 public void healthCheck () {
122 LOGGER.debug ("Health check call in Network Adapter");
126 * Do not use this constructor or the msoPropertiesFactory will be NULL.
128 * @see MsoNetworkAdapterImpl#MsoNetworkAdapterImpl(MsoPropertiesFactory)
130 public MsoNetworkAdapterImpl() {
134 public void createNetwork (String cloudSiteId,
137 String modelCustomizationUuid,
139 String physicalNetworkName,
140 List <Integer> vlans,
141 Boolean failIfExists,
143 List <Subnet> subnets,
144 MsoRequest msoRequest,
145 Holder <String> networkId,
146 Holder <String> neutronNetworkId,
147 Holder <Map <String, String>> subnetIdMap,
148 Holder <NetworkRollback> rollback) throws NetworkException {
149 Holder <String> networkFqdn = new Holder <> ();
150 createNetwork (cloudSiteId,
153 modelCustomizationUuid,
174 public void createNetworkContrail (String cloudSiteId,
177 String modelCustomizationUuid,
179 List <RouteTarget> routeTargets,
182 Boolean failIfExists,
184 List <Subnet> subnets,
185 List <String> policyFqdns,
186 List<String> routeTableFqdns,
187 MsoRequest msoRequest,
188 Holder <String> networkId,
189 Holder <String> neutronNetworkId,
190 Holder <String> networkFqdn,
191 Holder <Map <String, String>> subnetIdMap,
192 Holder <NetworkRollback> rollback) throws NetworkException {
193 createNetwork (cloudSiteId,
196 modelCustomizationUuid,
217 * This is the "Create Network" web service implementation.
218 * It will create a new Network of the requested type in the specified cloud
219 * and tenant. The tenant must exist at the time this service is called.
221 * If a network with the same name already exists, this can be considered a
222 * success or failure, depending on the value of the 'failIfExists' parameter.
224 * There will be a pre-defined set of network types defined in the MSO Catalog.
225 * All such networks will have a similar configuration, based on the allowable
226 * Openstack networking definitions. This includes basic networks, provider
227 * networks (with a single VLAN), and multi-provider networks (one or more VLANs)
229 * Initially, all provider networks must be "vlan" type, and multiple segments in
230 * a multi-provider network must be multiple VLANs on the same physical network.
232 * This service supports two modes of Network creation/update:
233 * - via Heat Templates
235 * The network orchestration mode for each network type is declared in its
236 * catalog definition. All Heat-based templates must support some subset of
237 * the same input parameters: network_name, physical_network, vlan(s).
239 * The method returns the network ID and a NetworkRollback object. This latter
240 * object can be passed as-is to the rollbackNetwork operation to undo everything
241 * that was created. This is useful if a network is successfully created but
242 * the orchestration fails on a subsequent operation.
245 private void createNetwork (String cloudSiteId,
248 String modelCustomizationUuid,
250 String physicalNetworkName,
251 List <Integer> vlans,
252 List <RouteTarget> routeTargets,
255 Boolean failIfExists,
257 List <Subnet> subnets,
258 List <String> policyFqdns,
259 List <String> routeTableFqdns,
260 MsoRequest msoRequest,
261 Holder <String> networkId,
262 Holder <String> neutronNetworkId,
263 Holder <String> networkFqdn,
264 Holder <Map <String, String>> subnetIdMap,
265 Holder <NetworkRollback> rollback) throws NetworkException {
266 MsoLogger.setLogContext (msoRequest);
267 MsoLogger.setServiceName (CREATE_NETWORK_CONTEXT);
269 LOGGER.debug ("*** CREATE Network: " + networkName
277 // Will capture execution time for metrics
278 long startTime = System.currentTimeMillis ();
280 // Build a default rollback object (no actions performed)
281 NetworkRollback networkRollback = new NetworkRollback ();
282 networkRollback.setCloudId (cloudSiteId);
283 networkRollback.setTenantId (tenantId);
284 networkRollback.setMsoRequest (msoRequest);
285 networkRollback.setModelCustomizationUuid(modelCustomizationUuid);
287 // tenant query is not required here.
288 // If the tenant doesn't exist, the Heat calls will fail anyway (when the HeatUtils try to obtain a token).
289 // So this is just catching that error in a bit more obvious way up front.
291 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
292 if (!cloudSiteOpt.isPresent())
294 String error = "Configuration Error. Stack " + networkName + " in "
299 + " CloudSite does not exist in MSO Configuration";
300 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
301 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
302 // Set the detailed error as the Exception 'message'
303 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
307 NetworkResource networkResource = networkCheck (startTime,
309 modelCustomizationUuid,
316 String mode = networkResource.getOrchestrationMode ();
317 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
319 if (NEUTRON_MODE.equals (mode)) {
321 // Use an MsoNeutronUtils for all neutron commands
323 // See if the Network already exists (by name)
324 NetworkInfo netInfo = null;
325 long queryNetworkStarttime = System.currentTimeMillis ();
327 netInfo = neutron.queryNetwork (networkName, tenantId, cloudSiteId);
328 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
329 } catch (MsoException me) {
330 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack", "OpenStack", "QueryNetwork", null);
331 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while querying network from OpenStack", me);
332 me.addContext (CREATE_NETWORK_CONTEXT);
333 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack");
334 throw new NetworkException (me);
337 if (netInfo != null) {
338 // Exists. If that's OK, return success with the network ID.
339 // Otherwise, return an exception.
340 if (failIfExists != null && failIfExists) {
341 String error = "Create Nework: Network " + networkName
342 + " already exists in "
346 + " with ID " + netInfo.getId();
347 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network already exists");
348 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
349 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
351 // Populate the outputs from the existing network.
352 networkId.value = netInfo.getId ();
353 neutronNetworkId.value = netInfo.getId ();
354 rollback.value = networkRollback; // Default rollback - no updates performed
355 String msg = "Found Existing network, status=" + netInfo.getStatus () + " for Neutron mode";
356 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", MsoLogger.ErrorCode.DataError, "Found Existing network, status=" + netInfo.getStatus ());
357 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, msg);
362 long createNetworkStarttime = System.currentTimeMillis ();
364 netInfo = neutron.createNetwork (cloudSiteId,
370 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "CreateNetwork", null);
371 } catch (MsoException me) {
372 me.addContext (CREATE_NETWORK_CONTEXT);
373 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with OpenStack", "OpenStack", "CreateNetwork", null);
374 String error = "Create Network: type " + neutronNetworkType
381 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while communicate with OpenStack", me);
382 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
384 throw new NetworkException (me);
387 // Note: ignoring MsoNetworkAlreadyExists because we already checked.
389 // If reach this point, network creation is successful.
390 // Since directly created via Neutron, networkId tracked by MSO is the same
391 // as the neutron network ID.
392 networkId.value = netInfo.getId ();
393 neutronNetworkId.value = netInfo.getId ();
395 networkRollback.setNetworkCreated (true);
396 networkRollback.setNetworkId (netInfo.getId ());
397 networkRollback.setNeutronNetworkId (netInfo.getId ());
398 networkRollback.setNetworkType (networkType);
400 LOGGER.debug ("Network " + networkName + " created, id = " + netInfo.getId ());
401 } else if ("HEAT".equals (mode)) {
403 HeatTemplate heatTemplate = networkResource.getHeatTemplate();
404 if (heatTemplate == null) {
405 String error = "Network error - undefined Heat Template. Network Type = " + networkType;
406 LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
407 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
411 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
412 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
415 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString());
417 // "Fix" the template if it has CR/LF (getting this from Oracle)
418 String template = heatTemplate.getHeatTemplate ();
419 template = template.replaceAll ("\r\n", "\n");
421 boolean aic3template=false;
422 String aic3nw = AIC3_NW;
424 aic3nw = environment.getProperty(AIC3_NW_PROPERTY, AIC3_NW);
426 if (template.contains(aic3nw))
429 // First, look up to see if the Network already exists (by name).
430 // For HEAT orchestration of networks, the stack name will always match the network name
431 StackInfo heatStack = null;
432 long queryNetworkStarttime = System.currentTimeMillis ();
434 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
435 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
436 } catch (MsoException me) {
437 me.addContext (CREATE_NETWORK_CONTEXT);
438 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
439 String error = "Create Network (heat): query network " + networkName
446 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
447 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
448 throw new NetworkException (me);
451 if (heatStack != null && (heatStack.getStatus () != HeatStatus.NOTFOUND)) {
452 // Stack exists. Return success or error depending on input directive
453 if (failIfExists != null && failIfExists) {
454 String error = "CreateNetwork: Stack " + networkName
455 + " already exists in "
459 + " as " + heatStack.getCanonicalName();
460 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
461 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
462 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
464 // Populate the outputs from the existing stack.
465 networkId.value = heatStack.getCanonicalName ();
466 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
467 rollback.value = networkRollback; // Default rollback - no updates performed
470 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
472 Map <String, Object> outputs = heatStack.getOutputs ();
473 Map <String, String> sMap = new HashMap <> ();
474 if (outputs != null) {
475 for (Map.Entry<String, Object> entry : outputs.entrySet()) {
476 String key=entry.getKey();
477 if (key != null && key.startsWith ("subnet")) {
478 if (aic3template) //one subnet_id output
480 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
483 else //multiples subnet_%aaid% outputs
485 String subnetUUId = (String) outputs.get(key);
486 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
491 subnetIdMap.value = sMap;
492 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", MsoLogger.ErrorCode.DataError, "Found Existing network stack, status=" + heatStack.getStatus ());
493 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Found Existing network stack");
498 // Ready to deploy the new Network
499 // Build the common set of HEAT template parameters
500 Map <String, Object> stackParams = populateNetworkParams (neutronNetworkType,
509 // Validate (and update) the input parameters against the DB definition
510 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
511 // and inputs were already validated.
513 stackParams = heat.validateStackParams (stackParams, heatTemplate);
514 } catch (IllegalArgumentException e) {
515 String error = "Create Network: Configuration Error: " + e.getMessage ();
516 LOGGER.error (MessageEnum.RA_CONFIG_EXC, e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - Create Network, Configuration Error", e);
517 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
521 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
522 // Input parameters were not valid
523 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
526 if (subnets != null) {
530 template = mergeSubnetsAIC3 (template, subnets, stackParams);
534 template = mergeSubnets (template, subnets);
536 } catch (MsoException me) {
537 me.addContext (CREATE_NETWORK_CONTEXT);
538 String error = "Create Network (heat): type " + neutronNetworkType
545 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging subnets", me);
546 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
547 throw new NetworkException (me);
551 if (policyFqdns != null && !policyFqdns.isEmpty() && aic3template) {
553 mergePolicyRefs (policyFqdns, stackParams);
554 } catch (MsoException me) {
555 me.addContext (CREATE_NETWORK_CONTEXT);
556 String error = "Create Network (heat) mergePolicyRefs type " + neutronNetworkType
563 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging policyRefs", me);
564 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
565 throw new NetworkException (me);
569 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
571 mergeRouteTableRefs (routeTableFqdns, stackParams);
572 } catch (MsoException me) {
573 me.addContext (CREATE_NETWORK_CONTEXT);
574 String error = "Create Network (heat) mergeRouteTableRefs type " + neutronNetworkType
581 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging routeTableRefs", me);
582 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
583 throw new NetworkException (me);
587 // Deploy the network stack
588 // Ignore MsoStackAlreadyExists exception because we already checked.
592 heatStack = heat.createStack (cloudSiteId,
598 heatTemplate.getTimeoutMinutes (),
602 backout.booleanValue());
603 } catch (MsoException me) {
604 me.addContext (CREATE_NETWORK_CONTEXT);
605 String error = "Create Network (heat): type " + neutronNetworkType
612 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
613 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
614 throw new NetworkException (me);
617 // Reach this point if createStack is successful.
619 // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
620 // and the neutronNetworkId is the network UUID returned in stack outputs.
621 networkId.value = heatStack.getCanonicalName ();
622 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
625 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
627 Map <String, Object> outputs = heatStack.getOutputs ();
628 Map <String, String> sMap = new HashMap <> ();
629 if (outputs != null) {
630 for (Map.Entry<String, Object> entry : outputs.entrySet()) {
631 String key = entry.getKey();
632 if (key != null && key.startsWith ("subnet")) {
633 if (aic3template) //one subnet output expected
635 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
638 else //multiples subnet_%aaid% outputs allowed
640 String subnetUUId = (String) outputs.get(key);
641 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
646 subnetIdMap.value = sMap;
648 rollback.value = networkRollback;
649 // Populate remaining rollback info and response parameters.
650 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
651 networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
652 networkRollback.setNetworkCreated (true);
653 networkRollback.setNetworkType (networkType);
655 LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
658 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
663 public void updateNetwork (String cloudSiteId,
666 String modelCustomizationUuid,
669 String physicalNetworkName,
670 List <Integer> vlans,
671 List <Subnet> subnets,
672 MsoRequest msoRequest,
673 Holder <Map <String, String>> subnetIdMap,
674 Holder <NetworkRollback> rollback) throws NetworkException {
675 updateNetwork (cloudSiteId,
678 modelCustomizationUuid,
696 public void updateNetworkContrail (String cloudSiteId,
699 String modelCustomizationUuid,
702 List <RouteTarget> routeTargets,
705 List <Subnet> subnets,
706 List <String> policyFqdns,
707 List<String> routeTableFqdns,
708 MsoRequest msoRequest,
709 Holder <Map <String, String>> subnetIdMap,
710 Holder <NetworkRollback> rollback) throws NetworkException {
711 updateNetwork (cloudSiteId,
714 modelCustomizationUuid,
731 * This is the "Update Network" web service implementation.
732 * It will update an existing Network of the requested type in the specified cloud
733 * and tenant. The typical use will be to replace the VLANs with the supplied
734 * list (to add or remove a VLAN), but other properties may be updated as well.
736 * There will be a pre-defined set of network types defined in the MSO Catalog.
737 * All such networks will have a similar configuration, based on the allowable
738 * Openstack networking definitions. This includes basic networks, provider
739 * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
741 * Initially, all provider networks must currently be "vlan" type, and multi-provider
742 * networks must be multiple VLANs on the same physical network.
744 * This service supports two modes of Network update:
745 * - via Heat Templates
747 * The network orchestration mode for each network type is declared in its
748 * catalog definition. All Heat-based templates must support some subset of
749 * the same input parameters: network_name, physical_network, vlan, segments.
751 * The method returns a NetworkRollback object. This object can be passed
752 * as-is to the rollbackNetwork operation to undo everything that was updated.
753 * This is useful if a network is successfully updated but orchestration
754 * fails on a subsequent operation.
756 private void updateNetwork (String cloudSiteId,
759 String modelCustomizationUuid,
762 String physicalNetworkName,
763 List <Integer> vlans,
764 List <RouteTarget> routeTargets,
767 List <Subnet> subnets,
768 List <String> policyFqdns,
769 List<String> routeTableFqdns,
770 MsoRequest msoRequest,
771 Holder <Map <String, String>> subnetIdMap,
772 Holder <NetworkRollback> rollback) throws NetworkException {
773 MsoLogger.setLogContext (msoRequest);
774 MsoLogger.setServiceName (UPDATE_NETWORK_CONTEXT);
775 LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
784 // Will capture execution time for metrics
785 long startTime = System.currentTimeMillis ();
787 // Build a default rollback object (no actions performed)
788 NetworkRollback networkRollback = new NetworkRollback ();
789 networkRollback.setCloudId (cloudSiteId);
790 networkRollback.setTenantId (tenantId);
791 networkRollback.setMsoRequest (msoRequest);
793 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite (cloudSiteId);
794 if (!cloudSiteOpt.isPresent()) {
795 String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
800 + " CloudSite does not exist in MSO Configuration";
801 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
802 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
803 // Set the detailed error as the Exception 'message'
804 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
810 NetworkResource networkResource = networkCheck(
813 modelCustomizationUuid,
820 String mode = networkResource.getOrchestrationMode();
821 NetworkType neutronNetworkType = NetworkType.valueOf(networkResource.getNeutronNetworkType());
823 // Use an MsoNeutronUtils for all Neutron commands
825 if (NEUTRON_MODE.equals(mode)) {
827 // Verify that the Network exists
828 // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
829 NetworkInfo netInfo = null;
830 long queryNetworkStarttime = System.currentTimeMillis();
832 netInfo = neutron.queryNetwork(networkId, tenantId, cloudSiteId);
833 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
834 } catch (MsoException me) {
835 me.addContext(UPDATE_NETWORK_CONTEXT);
836 String error = "Update Network (neutron): query " + networkId
843 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
844 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
845 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
846 throw new NetworkException(me);
849 if (netInfo == null) {
850 String error = "Update Nework: Network " + networkId
851 + " does not exist in "
855 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
856 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
857 // Does not exist. Throw an exception (can't update a non-existent network)
858 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
860 long updateNetworkStarttime = System.currentTimeMillis();
862 netInfo = neutron.updateNetwork(cloudSiteId,
868 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
869 } catch (MsoException me) {
870 me.addContext(UPDATE_NETWORK_CONTEXT);
871 String error = "Update Network (neutron): " + networkId
878 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
879 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
880 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
881 throw new NetworkException(me);
884 // Add the network ID and previously queried vlans to the rollback object
885 networkRollback.setNetworkId(netInfo.getId());
886 networkRollback.setNeutronNetworkId(netInfo.getId());
887 networkRollback.setNetworkType(networkType);
888 // Save previous parameters
889 networkRollback.setNetworkName(netInfo.getName());
890 networkRollback.setPhysicalNetwork(netInfo.getProvider());
891 networkRollback.setVlans(netInfo.getVlans());
893 LOGGER.debug("Network " + networkId + " updated, id = " + netInfo.getId());
894 } else if ("HEAT".equals(mode)) {
896 // First, look up to see that the Network already exists.
897 // For Heat-based orchestration, the networkId is the network Stack ID.
898 StackInfo heatStack = null;
899 long queryStackStarttime = System.currentTimeMillis();
901 heatStack = heat.queryStack(cloudSiteId, tenantId, networkName);
902 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
903 } catch (MsoException me) {
904 me.addContext(UPDATE_NETWORK_CONTEXT);
905 String error = "UpdateNetwork (heat): query " + networkName
912 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
913 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
914 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
915 throw new NetworkException(me);
918 if (heatStack == null || (heatStack.getStatus() == HeatStatus.NOTFOUND)) {
919 String error = "UpdateNetwork: Stack " + networkName
920 + " does not exist in "
924 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
925 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
926 // Network stack does not exist. Return an error
927 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
930 // Get the previous parameters for rollback
931 Map<String, Object> heatParams = heatStack.getParameters();
933 String previousNetworkName = (String) heatParams.get("network_name");
934 String previousPhysicalNetwork = (String) heatParams.get(PHYSICAL_NETWORK);
936 List<Integer> previousVlans = new ArrayList<>();
937 String vlansParam = (String) heatParams.get(VLANS);
938 if (vlansParam != null) {
939 for (String vlan : vlansParam.split(",")) {
941 previousVlans.add(Integer.parseInt(vlan));
942 } catch (NumberFormatException e) {
943 LOGGER.warn(MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
947 LOGGER.debug("Update Stack: Previous VLANS: " + previousVlans);
949 // Ready to deploy the updated Network via Heat
952 HeatTemplate heatTemplate = networkResource.getHeatTemplate();
953 if (heatTemplate == null) {
954 String error = "Network error - undefined Heat Template. Network Type=" + networkType;
955 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);
956 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
957 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
958 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
961 LOGGER.debug("Got HEAT Template from DB: " + heatTemplate.toString());
963 // "Fix" the template if it has CR/LF (getting this from Oracle)
964 String template = heatTemplate.getHeatTemplate();
965 template = template.replaceAll("\r\n", "\n");
967 boolean aic3template = false;
968 String aic3nw = AIC3_NW;
970 aic3nw = environment.getProperty(AIC3_NW_PROPERTY, AIC3_NW);
972 if (template.contains(aic3nw))
975 // Build the common set of HEAT template parameters
976 Map<String, Object> stackParams = populateNetworkParams(neutronNetworkType,
985 // Validate (and update) the input parameters against the DB definition
986 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
988 stackParams = heat.validateStackParams(stackParams, heatTemplate);
989 } catch (IllegalArgumentException e) {
990 String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
991 LOGGER.error(MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
992 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
993 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
994 throw new NetworkException(error, MsoExceptionCategory.INTERNAL, e);
997 if (subnets != null) {
1000 template = mergeSubnetsAIC3(template, subnets, stackParams);
1002 template = mergeSubnets(template, subnets);
1004 } catch (MsoException me) {
1005 me.addContext(UPDATE_NETWORK_CONTEXT);
1006 String error = "Update Network (heat): type " + neutronNetworkType
1013 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
1014 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1015 throw new NetworkException(me);
1019 if (policyFqdns != null && aic3template) {
1021 mergePolicyRefs(policyFqdns, stackParams);
1022 } catch (MsoException me) {
1023 me.addContext(UPDATE_NETWORK_CONTEXT);
1024 String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
1031 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
1032 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1033 throw new NetworkException(me);
1037 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
1039 mergeRouteTableRefs(routeTableFqdns, stackParams);
1040 } catch (MsoException me) {
1041 me.addContext(UPDATE_NETWORK_CONTEXT);
1042 String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
1049 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
1050 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1051 throw new NetworkException(me);
1055 // Update the network stack
1056 // Ignore MsoStackNotFound exception because we already checked.
1057 long updateStackStarttime = System.currentTimeMillis();
1059 heatStack = heatWithUpdate.updateStack(cloudSiteId,
1065 heatTemplate.getTimeoutMinutes());
1066 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
1067 } catch (MsoException me) {
1068 me.addContext(UPDATE_NETWORK_CONTEXT);
1069 String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1070 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
1071 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
1072 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1073 throw new NetworkException(me);
1076 Map<String, Object> outputs = heatStack.getOutputs();
1077 Map<String, String> sMap = new HashMap<>();
1078 if (outputs != null) {
1079 for (Map.Entry<String, Object> entry : outputs.entrySet()) {
1080 String key=entry.getKey();
1081 if (key != null && key.startsWith("subnet")) {
1082 if (aic3template) //one subnet output expected
1084 Map<String, String> map = getSubnetUUId(key, outputs, subnets);
1086 } else //multiples subnet_%aaid% outputs allowed
1088 String subnetUUId = (String) outputs.get(key);
1089 sMap.put(key.substring("subnet_id_".length()), subnetUUId);
1094 subnetIdMap.value = sMap;
1096 // Reach this point if createStack is successful.
1097 // Populate remaining rollback info and response parameters.
1098 networkRollback.setNetworkStackId(heatStack.getCanonicalName());
1099 if(null != outputs) {
1100 networkRollback.setNeutronNetworkId((String) outputs.get(NETWORK_ID));
1103 LOGGER.debug("outputs is NULL");
1105 networkRollback.setNetworkType(networkType);
1106 // Save previous parameters
1107 networkRollback.setNetworkName(previousNetworkName);
1108 networkRollback.setPhysicalNetwork(previousPhysicalNetwork);
1109 networkRollback.setVlans(previousVlans);
1111 rollback.value = networkRollback;
1113 LOGGER.debug("Network " + networkId + " successfully updated via HEAT");
1116 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
1120 private NetworkResource networkCheck (long startTime,
1122 String modelCustomizationUuid,
1124 String physicalNetworkName,
1125 List <Integer> vlans,
1126 List <RouteTarget> routeTargets,
1128 CloudSite cloudSite) throws NetworkException {
1129 // Retrieve the Network Resource definition
1130 NetworkResource networkResource = null;
1131 NetworkResourceCustomization networkCust = null;
1132 CollectionNetworkResourceCustomization collectionNetworkCust = null;
1133 if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
1134 if (!commonUtils.isNullOrEmpty(networkType)) {
1135 networkResource = networkResourceRepo.findFirstByModelNameOrderByModelVersionDesc(networkType);
1138 networkCust = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid);
1139 if (networkCust == null) {
1140 collectionNetworkCust = collectionNetworkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid);
1143 if(networkCust != null){
1144 LOGGER.debug("Got Network Customization definition from Catalog: "
1145 + networkCust.toString());
1147 networkResource = networkCust.getNetworkResource();
1148 } else if (collectionNetworkCust != null) {
1149 LOGGER.debug("Retrieved Collection Network Resource Customization from Catalog: "
1150 + collectionNetworkCust.toString());
1151 networkResource = collectionNetworkCust.getNetworkResource();
1153 if (networkResource == null) {
1154 String error = "Create/UpdateNetwork: Unable to get network resource with NetworkType:"
1156 + " or ModelCustomizationUUID:"
1157 + modelCustomizationUuid;
1158 LOGGER.error(MessageEnum.RA_UNKOWN_PARAM,
1159 "NetworkType/ModelCustomizationUUID", networkType + "/"
1160 + modelCustomizationUuid, "OpenStack", "",
1161 MsoLogger.ErrorCode.DataError,
1162 "Create/UpdateNetwork: Unknown NetworkType/ModelCustomizationUUID");
1164 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1166 LOGGER.debug("Got Network definition from Catalog: "
1167 + networkResource.toString());
1169 String mode = networkResource.getOrchestrationMode();
1170 NetworkType neutronNetworkType = NetworkType
1171 .valueOf(networkResource.getNeutronNetworkType());
1173 // All Networks are orchestrated via HEAT or Neutron
1174 if (!("HEAT".equals(mode) || NEUTRON_MODE.equals(mode))) {
1175 String error = "CreateNetwork: Configuration Error: Network Type = "
1177 LOGGER.error(MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT,
1178 mode, "OpenStack", "", MsoLogger.ErrorCode.DataError,
1179 "CreateNetwork: Configuration Error");
1180 // Alarm on this error, configuration must be fixed
1181 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
1182 MsoAlarmLogger.CRITICAL, error);
1184 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
1187 MavenLikeVersioning aicV = new MavenLikeVersioning();
1188 aicV.setVersion(cloudSite.getCloudVersion());
1189 if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV
1190 .isTheSameVersion(networkResource.getAicVersionMin())) // aic
1193 && (aicV.isTheSameVersion(networkResource
1194 .getAicVersionMax()) || !(aicV
1195 .isMoreRecentThan(networkResource
1196 .getAicVersionMax())))) // aic <= max
1198 LOGGER.debug("Network Type:" + networkType + " VersionMin:"
1199 + networkResource.getAicVersionMin() + " VersionMax:"
1200 + networkResource.getAicVersionMax()
1201 + " supported on Cloud:" + cloudSiteId
1202 + " with AIC_Version:" + cloudSite.getCloudVersion());
1204 String error = "Network Type:" + networkType + " Version_Min:"
1205 + networkResource.getAicVersionMin() + " Version_Max:"
1206 + networkResource.getAicVersionMax()
1207 + " not supported on Cloud:" + cloudSiteId
1208 + " with AIC_Version:" + cloudSite.getCloudVersion();
1209 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "",
1210 MsoLogger.ErrorCode.DataError,
1211 "Network Type not supported on Cloud");
1212 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
1213 MsoLogger.ResponseCode.DataError, error);
1214 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1217 // Validate the Network parameters.
1218 String missing = validateNetworkParams(neutronNetworkType,
1219 networkName, physicalNetworkName, vlans, routeTargets);
1220 if (!missing.isEmpty()) {
1221 String error = "Create Network: Missing parameters: " + missing;
1222 LOGGER.error(MessageEnum.RA_MISSING_PARAM, missing,
1223 "OpenStack", "", MsoLogger.ErrorCode.DataError,
1224 "Create Network: Missing parameters");
1226 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1229 return networkResource;
1233 public void queryNetwork (String cloudSiteId,
1235 String networkNameOrId,
1236 MsoRequest msoRequest,
1237 Holder <Boolean> networkExists,
1238 Holder <String> networkId,
1239 Holder <String> neutronNetworkId,
1240 Holder <NetworkStatus> status,
1241 Holder <List <Integer>> vlans,
1242 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1243 queryNetwork (cloudSiteId,
1257 public void queryNetworkContrail (String cloudSiteId,
1259 String networkNameOrId,
1260 MsoRequest msoRequest,
1261 Holder <Boolean> networkExists,
1262 Holder <String> networkId,
1263 Holder <String> neutronNetworkId,
1264 Holder <NetworkStatus> status,
1265 Holder <List <RouteTarget>> routeTargets,
1266 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1267 queryNetwork (cloudSiteId,
1281 * This is the queryNetwork method. It returns the existence and status of
1282 * the specified network, along with its Neutron UUID and list of VLANs.
1283 * This method attempts to find the network using both Heat and Neutron.
1284 * Heat stacks are first searched based on the provided network name/id.
1285 * If none is found, the Neutron is directly queried.
1287 private void queryNetwork (String cloudSiteId,
1289 String networkNameOrId,
1290 MsoRequest msoRequest,
1291 Holder <Boolean> networkExists,
1292 Holder <String> networkId,
1293 Holder <String> neutronNetworkId,
1294 Holder <NetworkStatus> status,
1295 Holder <List <Integer>> vlans,
1296 Holder <List <RouteTarget>> routeTargets,
1297 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1298 MsoLogger.setLogContext (msoRequest);
1299 MsoLogger.setServiceName ("QueryNetwork");
1300 LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
1306 // Will capture execution time for metrics
1307 long startTime = System.currentTimeMillis ();
1309 if (commonUtils.isNullOrEmpty (cloudSiteId)
1310 || commonUtils.isNullOrEmpty(tenantId)
1311 || commonUtils.isNullOrEmpty(networkNameOrId)) {
1313 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1314 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1315 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1316 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1319 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
1320 if (!cloudSiteOpt.isPresent())
1322 String error = "Configuration Error. Stack " + networkNameOrId + " in "
1327 + " CloudSite does not exist in MSO Configuration";
1328 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
1329 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1330 // Set the detailed error as the Exception 'message'
1331 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1334 // Use MsoNeutronUtils for all NEUTRON commands
1338 // Try Heat first, since networks may be named the same as the Heat stack
1339 StackInfo heatStack = null;
1340 long queryStackStarttime = System.currentTimeMillis ();
1342 heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
1343 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
1344 } catch (MsoException me) {
1345 me.addContext ("QueryNetwork");
1346 String error = "Query Network (heat): " + networkNameOrId
1353 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
1354 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
1355 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1356 throw new NetworkException (me);
1359 // Populate the outputs based on the returned Stack information
1360 if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
1361 // Found it. Get the neutronNetworkId for further query
1362 Map <String, Object> outputs = heatStack.getOutputs ();
1363 neutronId = (String) outputs.get (NETWORK_ID);
1366 Map <String, String> sMap = new HashMap <> ();
1367 if (outputs != null) {
1368 for (String key : outputs.keySet ()) {
1369 if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
1371 String subnetUUId = (String) outputs.get(key);
1372 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1374 else if (key != null && key.startsWith ("subnet")) //one subnet output expected
1376 Map <String, String> map = getSubnetUUId(key, outputs, null);
1382 subnetIdMap.value = sMap;
1384 // Input ID was not a Heat stack ID. Try it directly in Neutron
1385 neutronId = networkNameOrId;
1386 mode = NEUTRON_MODE;
1389 // Query directly against the Neutron Network for the details
1390 // no RouteTargets available for ContrailV2 in neutron net-show
1391 // networkId is heatStackId
1392 long queryNetworkStarttime = System.currentTimeMillis ();
1394 NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
1395 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
1396 if (netInfo != null) {
1397 // Found. Populate the output elements
1398 networkExists.value = Boolean.TRUE;
1399 if ("HEAT".equals (mode)) {
1400 networkId.value = heatStack.getCanonicalName ();
1402 networkId.value = netInfo.getId ();
1404 neutronNetworkId.value = netInfo.getId ();
1405 status.value = netInfo.getStatus ();
1407 vlans.value = netInfo.getVlans ();
1409 LOGGER.debug ("Network " + networkNameOrId
1414 + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
1416 // Not found. Populate the status fields, leave the rest null
1417 networkExists.value = Boolean.FALSE;
1418 status.value = NetworkStatus.NOTFOUND;
1419 neutronNetworkId.value = null;
1421 vlans.value = new ArrayList<>();
1423 LOGGER.debug ("Network " + networkNameOrId + " not found");
1425 } catch (MsoException me) {
1426 me.addContext ("QueryNetwork");
1427 String error = "Query Network (neutron): " + networkNameOrId
1434 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
1435 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
1436 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1437 throw new NetworkException (me);
1439 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
1444 * This is the "Delete Network" web service implementation.
1445 * It will delete a Network in the specified cloud and tenant.
1447 * If the network is not found, it is treated as a success.
1449 * This service supports two modes of Network creation/update/delete:
1450 * - via Heat Templates
1452 * The network orchestration mode for each network type is declared in its
1453 * catalog definition.
1455 * For Heat-based orchestration, the networkId should be the stack ID.
1456 * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
1458 * The method returns nothing on success. Rollback is not possible for delete
1459 * commands, so any failure on delete will require manual fallout in the client.
1462 public void deleteNetwork (String cloudSiteId,
1465 String modelCustomizationUuid,
1467 MsoRequest msoRequest,
1468 Holder <Boolean> networkDeleted) throws NetworkException {
1469 MsoLogger.setLogContext (msoRequest);
1470 MsoLogger.setServiceName ("DeleteNetwork");
1471 LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
1477 // Will capture execution time for metrics
1478 long startTime = System.currentTimeMillis ();
1481 if (commonUtils.isNullOrEmpty (cloudSiteId)
1482 || commonUtils.isNullOrEmpty(tenantId)
1483 || commonUtils.isNullOrEmpty(networkId)) {
1484 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1485 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1486 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1487 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1490 // Retrieve the Network Resource definition
1491 NetworkResource networkResource = null;
1493 if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
1494 if (!commonUtils.isNullOrEmpty(networkType)) {
1495 networkResource = networkResourceRepo.findFirstByModelNameOrderByModelVersionDesc(networkType);
1498 NetworkResourceCustomization nrc = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid);
1500 networkResource = nrc.getNetworkResource();
1505 if (networkResource != null) {
1506 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1508 mode = networkResource.getOrchestrationMode ();
1511 if (NEUTRON_MODE.equals (mode)) {
1513 // Use MsoNeutronUtils for all NEUTRON commands
1514 long deleteNetworkStarttime = System.currentTimeMillis ();
1516 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1517 // was not found. So don't bother to query first.
1518 boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1519 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1520 networkDeleted.value = deleted;
1521 } catch (MsoException me) {
1522 me.addContext ("DeleteNetwork");
1523 String error = "Delete Network (neutron): " + networkId
1530 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1531 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
1532 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1533 throw new NetworkException (me);
1535 } else { // DEFAULT to ("HEAT".equals (mode))
1536 long deleteStackStarttime = System.currentTimeMillis ();
1539 // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
1540 // So query first to report back if stack WAS deleted or just NOTOFUND
1541 StackInfo heatStack = null;
1542 heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
1543 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
1545 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1546 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1547 networkDeleted.value = true;
1551 networkDeleted.value = false;
1553 } catch (MsoException me) {
1554 me.addContext ("DeleteNetwork");
1555 String error = "Delete Network (heat): " + networkId
1562 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1563 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
1564 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1565 throw new NetworkException (me);
1570 // On success, nothing is returned.
1571 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
1576 * This web service endpoint will rollback a previous Create VNF operation.
1577 * A rollback object is returned to the client in a successful creation
1578 * response. The client can pass that object as-is back to the rollbackVnf
1579 * operation to undo the creation.
1581 * The rollback includes removing the VNF and deleting the tenant if the
1582 * tenant did not exist prior to the VNF creation.
1585 public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
1586 MsoLogger.setServiceName ("RollbackNetwork");
1587 // Will capture execution time for metrics
1588 long startTime = System.currentTimeMillis ();
1590 if (rollback == null) {
1591 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
1592 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
1596 MsoLogger.setLogContext (rollback.getMsoRequest());
1598 // Get the elements of the VnfRollback object for easier access
1599 String cloudSiteId = rollback.getCloudId ();
1600 String tenantId = rollback.getTenantId ();
1601 String networkId = rollback.getNetworkStackId ();
1602 String networkType = rollback.getNetworkType ();
1603 String modelCustomizationUuid = rollback.getModelCustomizationUuid();
1605 LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
1609 // Retrieve the Network Resource definition
1610 NetworkResource networkResource = null;
1611 if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
1612 networkResource = networkCustomRepo.findOneByNetworkType(networkType).getNetworkResource();
1614 networkResource = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid).getNetworkResource();
1617 if (networkResource != null) {
1619 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1621 mode = networkResource.getOrchestrationMode ();
1624 if (rollback.getNetworkCreated ()) {
1625 // Rolling back a newly created network, so delete it.
1626 if (NEUTRON_MODE.equals (mode)) {
1627 // Use MsoNeutronUtils for all NEUTRON commands
1628 long deleteNetworkStarttime = System.currentTimeMillis ();
1630 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1631 // was not found. So don't bother to query first.
1632 neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1633 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1634 } catch (MsoException me) {
1635 me.addContext ("RollbackNetwork");
1636 String error = "Rollback Network (neutron): " + networkId
1643 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1644 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
1645 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1646 throw new NetworkException (me);
1648 } else { // DEFAULT to if ("HEAT".equals (mode))
1649 long deleteStackStarttime = System.currentTimeMillis ();
1651 // The deleteStack function in MsoHeatUtils returns success if the stack
1652 // was not found. So don't bother to query first.
1653 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1654 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1655 } catch (MsoException me) {
1656 me.addContext ("RollbackNetwork");
1657 String error = "Rollback Network (heat): " + networkId
1664 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1665 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
1666 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1667 throw new NetworkException (me);
1672 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
1676 private String validateNetworkParams (NetworkType neutronNetworkType,
1678 String physicalNetwork,
1679 List <Integer> vlans,
1680 List <RouteTarget> routeTargets) {
1682 StringBuilder missing = new StringBuilder ();
1683 if (commonUtils.isNullOrEmpty(networkName)) {
1684 missing.append ("networkName");
1688 if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1689 if (commonUtils.isNullOrEmpty(physicalNetwork)) {
1690 missing.append (sep).append ("physicalNetworkName");
1693 if (vlans == null || vlans.isEmpty ()) {
1694 missing.append (sep).append (VLANS);
1698 return missing.toString ();
1701 private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
1703 String physicalNetwork,
1704 List <Integer> vlans,
1705 List <RouteTarget> routeTargets,
1708 boolean aic3template) {
1709 // Build the common set of HEAT template parameters
1710 Map <String, Object> stackParams = new HashMap <> ();
1711 stackParams.put ("network_name", networkName);
1713 if (neutronNetworkType == NetworkType.PROVIDER) {
1714 // For Provider type
1715 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1716 stackParams.put ("vlan", vlans.get (0).toString ());
1717 } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1718 // For Multi-provider, PO supports a custom resource extension of ProviderNet.
1719 // It supports all ProviderNet properties except segmentation_id, and adds a
1720 // comma-separated-list of VLANs as a "segments" property.
1721 // Note that this does not match the Neutron definition of Multi-Provider network,
1722 // which contains a list of 'segments', each having physical_network, network_type,
1723 // and segmentation_id.
1724 StringBuilder buf = new StringBuilder ();
1726 for (Integer vlan : vlans) {
1727 buf.append (sep).append (vlan.toString ());
1730 String csl = buf.toString ();
1732 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1733 stackParams.put (VLANS, csl);
1735 if (routeTargets != null) {
1737 String rtGlobal = "";
1738 String rtImport = "";
1739 String rtExport = "";
1741 for (RouteTarget rt : routeTargets) {
1742 boolean rtIsNull = false;
1745 String routeTarget = rt.getRouteTarget();
1746 String routeTargetRole = rt.getRouteTargetRole();
1747 LOGGER.debug("Checking for an actually null route target: " + rt.toString());
1748 if (routeTarget == null || routeTarget.equals("") || routeTarget.equalsIgnoreCase("null"))
1750 if (routeTargetRole == null || routeTargetRole.equals("") || routeTargetRole.equalsIgnoreCase("null"))
1756 LOGGER.debug("Input RT:" + rt.toString());
1757 String role = rt.getRouteTargetRole();
1758 String rtValue = rt.getRouteTarget();
1760 if ("IMPORT".equalsIgnoreCase(role))
1762 sep = rtImport.isEmpty() ? "" : ",";
1763 rtImport = aic3template ? rtImport + sep + "target:" + rtValue : rtImport + sep + rtValue ;
1765 else if ("EXPORT".equalsIgnoreCase(role))
1767 sep = rtExport.isEmpty() ? "" : ",";
1768 rtExport = aic3template ? rtExport + sep + "target:" + rtValue : rtExport + sep + rtValue ;
1770 else // covers BOTH, empty etc
1772 sep = rtGlobal.isEmpty() ? "" : ",";
1773 rtGlobal = aic3template ? rtGlobal + sep + "target:" + rtValue : rtGlobal + sep + rtValue ;
1779 if (!rtImport.isEmpty())
1781 stackParams.put ("route_targets_import", rtImport);
1783 if (!rtExport.isEmpty())
1785 stackParams.put ("route_targets_export", rtExport);
1787 if (!rtGlobal.isEmpty())
1789 stackParams.put ("route_targets", rtGlobal);
1792 if (commonUtils.isNullOrEmpty(shared)) {
1793 stackParams.put ("shared", "False");
1795 stackParams.put ("shared", shared);
1797 if (commonUtils.isNullOrEmpty(external)) {
1798 stackParams.put ("external", "False");
1800 stackParams.put ("external", external);
1807 /** policyRef_list structure in stackParams
1810 "network_policy_refs_data_sequence": {
1811 "network_policy_refs_data_sequence_major": "1",
1812 "network_policy_refs_data_sequence_minor": "0"
1816 "network_policy_refs_data_sequence": {
1817 "network_policy_refs_data_sequence_major": "2",
1818 "network_policy_refs_data_sequence_minor": "0"
1823 private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
1825 List<ContrailPolicyRef> prlist = new ArrayList <> ();
1827 for (String pf : pFqdns) {
1828 if (!commonUtils.isNullOrEmpty(pf))
1830 ContrailPolicyRef pr = new ContrailPolicyRef();
1831 ContrailPolicyRefSeq refSeq = new ContrailPolicyRefSeq(String.valueOf(index), "0");
1834 LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
1839 JsonNode node = null;
1842 ObjectMapper mapper = new ObjectMapper();
1843 node = mapper.convertValue(prlist, JsonNode.class);
1844 String jsonString = mapper.writeValueAsString(prlist);
1845 LOGGER.debug("Json PolicyRefs Data:" + jsonString);
1849 String error = "Error creating JsonNode for policyRefs Data";
1850 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
1851 throw new MsoAdapterException (error);
1854 if (pFqdns != null && node != null)
1856 StringBuilder buf = new StringBuilder ();
1858 for (String pf : pFqdns) {
1859 if (!commonUtils.isNullOrEmpty(pf))
1861 buf.append (sep).append (pf);
1865 String csl = buf.toString ();
1866 stackParams.put ("policy_refs", csl);
1867 stackParams.put ("policy_refsdata", node);
1870 LOGGER.debug ("StackParams updated with policy refs");
1874 private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
1877 if (rtFqdns != null)
1879 StringBuilder buf = new StringBuilder ();
1881 for (String rtf : rtFqdns) {
1882 if (!commonUtils.isNullOrEmpty(rtf))
1884 buf.append (sep).append (rtf);
1888 String csl = buf.toString ();
1889 stackParams.put ("route_table_refs", csl);
1892 LOGGER.debug ("StackParams updated with route_table refs");
1897 /*** Subnet Output structure from Juniper
1902 "ip_prefix": "10.100.1.0",
1905 "addr_from_start": null,
1906 "enable_dhcp": false,
1907 "default_gateway": "10.100.1.1",
1908 "dns_nameservers": [],
1909 "dhcp_option_list": null,
1910 "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
1911 "allocation_pools": [
1913 "start": "10.100.1.3",
1917 "start": "10.100.1.6",
1921 "host_routes": null,
1922 "dns_server_address": "10.100.1.13",
1923 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
1927 "ip_prefix": "10.100.2.16",
1930 "addr_from_start": null,
1931 "enable_dhcp": true,
1932 "default_gateway": "10.100.2.17",
1933 "dns_nameservers": [],
1934 "dhcp_option_list": null,
1935 "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
1936 "allocation_pools": [
1938 "start": "10.100.2.18",
1939 "end": "10.100.2.20"
1942 "host_routes": null,
1943 "dns_server_address": "10.100.2.29",
1944 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
1950 private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
1953 List<ContrailSubnet> cslist = new ArrayList <> ();
1954 for (Subnet subnet : subnets) {
1955 LOGGER.debug("Input Subnet:" + subnet.toString());
1956 ContrailSubnet cs = new ContrailSubnetMapper(subnet).map();
1957 LOGGER.debug("Contrail Subnet:" + cs.toString());
1961 JsonNode node = null;
1964 ObjectMapper mapper = new ObjectMapper();
1965 node = mapper.convertValue(cslist, JsonNode.class);
1966 String jsonString = mapper.writeValueAsString(cslist);
1967 LOGGER.debug("Json Subnet List:" + jsonString);
1971 String error = "Error creating JsonNode from input subnets";
1972 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
1973 throw new MsoAdapterException (error);
1978 stackParams.put ("subnet_list", node);
1980 //Outputs - All subnets are in one ipam_subnets structure
1981 String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
1982 + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
1984 // append outputs in heatTemplate
1985 int outputsIdx = heatTemplate.indexOf ("outputs:");
1986 heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
1987 LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
1988 return heatTemplate;
1992 private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
1994 String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
1997 + " network_id: { get_resource: network }\n"
1998 + " cidr: %cidr%\n";
2000 /* make these optional
2001 + " ip_version: %ipversion%\n"
2002 + " enable_dhcp: %enabledhcp%\n"
2003 + " gateway_ip: %gatewayip%\n"
2004 + " allocation_pools:\n"
2005 + " - start: %poolstart%\n"
2006 + " end: %poolend%\n";
2010 String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
2011 + " value: {get_resource: subnet_%subnetId%}\n";
2015 StringBuilder resourcesBuf = new StringBuilder ();
2016 StringBuilder outputsBuf = new StringBuilder ();
2017 for (Subnet subnet : subnets) {
2019 // build template for each subnet
2020 curR = resourceTempl;
2021 if (subnet.getSubnetId () != null) {
2022 curR = curR.replace ("%subnetId%", subnet.getSubnetId ());
2024 String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
2025 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
2026 throw new MsoAdapterException (error);
2029 if (subnet.getSubnetName () != null) {
2030 curR = curR.replace ("%name%", subnet.getSubnetName ());
2032 curR = curR.replace ("%name%", subnet.getSubnetId ());
2035 if (subnet.getCidr () != null) {
2036 curR = curR.replace ("%cidr%", subnet.getCidr ());
2038 String error = "Missing Required cidr for subnet in HEAT Template";
2039 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
2040 throw new MsoAdapterException (error);
2043 if (subnet.getIpVersion () != null) {
2044 curR = curR + " ip_version: " + subnet.getIpVersion () + "\n";
2046 if (subnet.getEnableDHCP () != null) {
2047 curR = curR + " enable_dhcp: " + Boolean.toString (subnet.getEnableDHCP ()) + "\n";
2049 if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
2050 curR = curR + " gateway_ip: " + subnet.getGatewayIp () + "\n";
2053 if (subnet.getAllocationPools() != null) {
2054 curR = curR + " allocation_pools:\n";
2055 for (Pool pool : subnet.getAllocationPools())
2057 if (!commonUtils.isNullOrEmpty(pool.getStart()) && !commonUtils.isNullOrEmpty(pool.getEnd()))
2059 curR = curR + " - start: " + pool.getStart () + "\n";
2060 curR = curR + " end: " + pool.getEnd () + "\n";
2065 resourcesBuf.append (curR);
2068 curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
2070 outputsBuf.append (curO);
2073 // append resources and outputs in heatTemplate
2074 LOGGER.debug ("Tempate initial:" + heatTemplate);
2075 int outputsIdx = heatTemplate.indexOf ("outputs:");
2076 heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
2077 int resourcesIdx = heatTemplate.indexOf ("resources:");
2078 heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
2080 LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
2081 return heatTemplate;
2084 private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
2086 Map <String, String> sMap = new HashMap <> ();
2089 Object obj = outputs.get(key);
2090 ObjectMapper mapper = new ObjectMapper();
2091 String jStr = mapper.writeValueAsString(obj);
2092 LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
2094 JsonNode rootNode = mapper.readTree(jStr);
2095 for (JsonNode sNode : rootNode.path("ipam_subnets"))
2097 LOGGER.debug("Output Subnet Node" + sNode.toString());
2098 String name = sNode.path("subnet_name").textValue();
2099 String uuid = sNode.path("subnet_uuid").textValue();
2100 String aaiId = name; // default
2101 // try to find aaiId for name in input subnetList
2102 if (subnets != null)
2104 for (Subnet subnet : subnets)
2106 if ( subnet != null && !commonUtils.isNullOrEmpty(subnet.getSubnetName()))
2108 if (subnet.getSubnetName().equals(name))
2110 aaiId = subnet.getSubnetId();
2116 sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
2121 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
2124 LOGGER.debug ("Return sMap" + sMap.toString());
2128 private static String insertStr (String template, String snippet, int index) {
2130 String updatedTemplate;
2132 LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
2134 String templateBeg = template.substring (0, index);
2135 String templateEnd = template.substring (index);
2137 updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
2139 LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
2140 return updatedTemplate;