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.data.repository.NetworkResourceCustomizationRepository;
46 import org.onap.so.db.catalog.data.repository.NetworkResourceRepository;
47 import org.onap.so.db.catalog.utils.MavenLikeVersioning;
48 import org.onap.so.entity.MsoRequest;
49 import org.onap.so.logger.MessageEnum;
50 import org.onap.so.logger.MsoAlarmLogger;
51 import org.onap.so.logger.MsoLogger;
52 import org.onap.so.openstack.beans.HeatStatus;
53 import org.onap.so.openstack.beans.NetworkInfo;
54 import org.onap.so.openstack.beans.NetworkRollback;
55 import org.onap.so.openstack.beans.NetworkStatus;
56 import org.onap.so.openstack.beans.Pool;
57 import org.onap.so.openstack.beans.RouteTarget;
58 import org.onap.so.openstack.beans.StackInfo;
59 import org.onap.so.openstack.beans.Subnet;
60 import org.onap.so.openstack.exceptions.MsoAdapterException;
61 import org.onap.so.openstack.exceptions.MsoException;
62 import org.onap.so.openstack.exceptions.MsoExceptionCategory;
63 import org.onap.so.openstack.utils.MsoCommonUtils;
64 import org.onap.so.openstack.utils.MsoHeatUtils;
65 import org.onap.so.openstack.utils.MsoHeatUtilsWithUpdate;
66 import org.onap.so.openstack.utils.MsoNeutronUtils;
67 import org.onap.so.openstack.utils.MsoNeutronUtils.NetworkType;
68 import org.springframework.beans.factory.annotation.Autowired;
69 import org.springframework.core.env.Environment;
70 import org.springframework.stereotype.Component;
71 import org.springframework.transaction.annotation.Transactional;
73 import com.fasterxml.jackson.databind.JsonNode;
74 import com.fasterxml.jackson.databind.ObjectMapper;
78 @WebService(serviceName = "NetworkAdapter", endpointInterface = "org.onap.so.adapters.network.MsoNetworkAdapter", targetNamespace = "http://org.onap.so/network")
79 public class MsoNetworkAdapterImpl implements MsoNetworkAdapter {
81 private static final String AIC3_NW_PROPERTY= "org.onap.so.adapters.network.aic3nw";
82 private static final String AIC3_NW="OS::ContrailV2::VirtualNetwork";
83 private static final String VLANS = "vlans";
84 private static final String PHYSICAL_NETWORK = "physical_network";
85 private static final String UPDATE_NETWORK_CONTEXT = "UpdateNetwork";
86 private static final String NETWORK_ID = "network_id";
87 private static final String NETWORK_FQDN = "network_fqdn";
88 private static final String CREATE_NETWORK_CONTEXT = "CreateNetwork";
89 private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
90 private static final String NEUTRON_MODE = "NEUTRON";
92 private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,MsoNetworkAdapterImpl.class);
93 private static final MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
95 private CloudConfig cloudConfig;
97 private Environment environment;
99 private MsoNeutronUtils neutron;
101 private MsoHeatUtils heat;
103 private MsoHeatUtilsWithUpdate heatWithUpdate;
105 private MsoCommonUtils commonUtils;
108 private NetworkResourceCustomizationRepository networkCustomRepo;
111 private NetworkResourceRepository networkResourceRepo;
113 * Health Check web method. Does nothing but return to show the adapter is deployed.
116 public void healthCheck () {
117 LOGGER.debug ("Health check call in Network Adapter");
121 * Do not use this constructor or the msoPropertiesFactory will be NULL.
123 * @see MsoNetworkAdapterImpl#MsoNetworkAdapterImpl(MsoPropertiesFactory)
125 public MsoNetworkAdapterImpl() {
129 public void createNetwork (String cloudSiteId,
132 String modelCustomizationUuid,
134 String physicalNetworkName,
135 List <Integer> vlans,
136 Boolean failIfExists,
138 List <Subnet> subnets,
139 MsoRequest msoRequest,
140 Holder <String> networkId,
141 Holder <String> neutronNetworkId,
142 Holder <Map <String, String>> subnetIdMap,
143 Holder <NetworkRollback> rollback) throws NetworkException {
144 Holder <String> networkFqdn = new Holder <> ();
145 createNetwork (cloudSiteId,
148 modelCustomizationUuid,
169 public void createNetworkContrail (String cloudSiteId,
172 String modelCustomizationUuid,
174 List <RouteTarget> routeTargets,
177 Boolean failIfExists,
179 List <Subnet> subnets,
180 List <String> policyFqdns,
181 List<String> routeTableFqdns,
182 MsoRequest msoRequest,
183 Holder <String> networkId,
184 Holder <String> neutronNetworkId,
185 Holder <String> networkFqdn,
186 Holder <Map <String, String>> subnetIdMap,
187 Holder <NetworkRollback> rollback) throws NetworkException {
188 createNetwork (cloudSiteId,
191 modelCustomizationUuid,
212 * This is the "Create Network" web service implementation.
213 * It will create a new Network of the requested type in the specified cloud
214 * and tenant. The tenant must exist at the time this service is called.
216 * If a network with the same name already exists, this can be considered a
217 * success or failure, depending on the value of the 'failIfExists' parameter.
219 * There will be a pre-defined set of network types defined in the MSO Catalog.
220 * All such networks will have a similar configuration, based on the allowable
221 * Openstack networking definitions. This includes basic networks, provider
222 * networks (with a single VLAN), and multi-provider networks (one or more VLANs)
224 * Initially, all provider networks must be "vlan" type, and multiple segments in
225 * a multi-provider network must be multiple VLANs on the same physical network.
227 * This service supports two modes of Network creation/update:
228 * - via Heat Templates
230 * The network orchestration mode for each network type is declared in its
231 * catalog definition. All Heat-based templates must support some subset of
232 * the same input parameters: network_name, physical_network, vlan(s).
234 * The method returns the network ID and a NetworkRollback object. This latter
235 * object can be passed as-is to the rollbackNetwork operation to undo everything
236 * that was created. This is useful if a network is successfully created but
237 * the orchestration fails on a subsequent operation.
240 private void createNetwork (String cloudSiteId,
243 String modelCustomizationUuid,
245 String physicalNetworkName,
246 List <Integer> vlans,
247 List <RouteTarget> routeTargets,
250 Boolean failIfExists,
252 List <Subnet> subnets,
253 List <String> policyFqdns,
254 List <String> routeTableFqdns,
255 MsoRequest msoRequest,
256 Holder <String> networkId,
257 Holder <String> neutronNetworkId,
258 Holder <String> networkFqdn,
259 Holder <Map <String, String>> subnetIdMap,
260 Holder <NetworkRollback> rollback) throws NetworkException {
261 MsoLogger.setLogContext (msoRequest);
262 MsoLogger.setServiceName (CREATE_NETWORK_CONTEXT);
264 LOGGER.debug ("*** CREATE Network: " + networkName
272 // Will capture execution time for metrics
273 long startTime = System.currentTimeMillis ();
275 // Build a default rollback object (no actions performed)
276 NetworkRollback networkRollback = new NetworkRollback ();
277 networkRollback.setCloudId (cloudSiteId);
278 networkRollback.setTenantId (tenantId);
279 networkRollback.setMsoRequest (msoRequest);
280 networkRollback.setModelCustomizationUuid(modelCustomizationUuid);
282 // tenant query is not required here.
283 // If the tenant doesn't exist, the Heat calls will fail anyway (when the HeatUtils try to obtain a token).
284 // So this is just catching that error in a bit more obvious way up front.
286 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
287 if (!cloudSiteOpt.isPresent())
289 String error = "Configuration Error. Stack " + networkName + " in "
294 + " CloudSite does not exist in MSO Configuration";
295 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
296 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
297 // Set the detailed error as the Exception 'message'
298 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
302 NetworkResource networkResource = networkCheck (startTime,
304 modelCustomizationUuid,
311 String mode = networkResource.getOrchestrationMode ();
312 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
314 if (NEUTRON_MODE.equals (mode)) {
316 // Use an MsoNeutronUtils for all neutron commands
318 // See if the Network already exists (by name)
319 NetworkInfo netInfo = null;
320 long queryNetworkStarttime = System.currentTimeMillis ();
322 netInfo = neutron.queryNetwork (networkName, tenantId, cloudSiteId);
323 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
324 } catch (MsoException me) {
325 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack", "OpenStack", "QueryNetwork", null);
326 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while querying network from OpenStack", me);
327 me.addContext (CREATE_NETWORK_CONTEXT);
328 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack");
329 throw new NetworkException (me);
332 if (netInfo != null) {
333 // Exists. If that's OK, return success with the network ID.
334 // Otherwise, return an exception.
335 if (failIfExists != null && failIfExists) {
336 String error = "Create Nework: Network " + networkName
337 + " already exists in "
341 + " with ID " + netInfo.getId();
342 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network already exists");
343 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
344 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
346 // Populate the outputs from the existing network.
347 networkId.value = netInfo.getId ();
348 neutronNetworkId.value = netInfo.getId ();
349 rollback.value = networkRollback; // Default rollback - no updates performed
350 String msg = "Found Existing network, status=" + netInfo.getStatus () + " for Neutron mode";
351 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", MsoLogger.ErrorCode.DataError, "Found Existing network, status=" + netInfo.getStatus ());
352 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, msg);
357 long createNetworkStarttime = System.currentTimeMillis ();
359 netInfo = neutron.createNetwork (cloudSiteId,
365 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "CreateNetwork", null);
366 } catch (MsoException me) {
367 me.addContext (CREATE_NETWORK_CONTEXT);
368 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with OpenStack", "OpenStack", "CreateNetwork", null);
369 String error = "Create Network: type " + neutronNetworkType
376 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while communicate with OpenStack", me);
377 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
379 throw new NetworkException (me);
382 // Note: ignoring MsoNetworkAlreadyExists because we already checked.
384 // If reach this point, network creation is successful.
385 // Since directly created via Neutron, networkId tracked by MSO is the same
386 // as the neutron network ID.
387 networkId.value = netInfo.getId ();
388 neutronNetworkId.value = netInfo.getId ();
390 networkRollback.setNetworkCreated (true);
391 networkRollback.setNetworkId (netInfo.getId ());
392 networkRollback.setNeutronNetworkId (netInfo.getId ());
393 networkRollback.setNetworkType (networkType);
395 LOGGER.debug ("Network " + networkName + " created, id = " + netInfo.getId ());
396 } else if ("HEAT".equals (mode)) {
398 HeatTemplate heatTemplate = networkResource.getHeatTemplate();
399 if (heatTemplate == null) {
400 String error = "Network error - undefined Heat Template. Network Type = " + networkType;
401 LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
402 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
406 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
407 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
410 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString());
412 // "Fix" the template if it has CR/LF (getting this from Oracle)
413 String template = heatTemplate.getHeatTemplate ();
414 template = template.replaceAll ("\r\n", "\n");
416 boolean aic3template=false;
417 String aic3nw = AIC3_NW;
419 aic3nw = environment.getProperty(AIC3_NW_PROPERTY, AIC3_NW);
421 if (template.contains(aic3nw))
424 // First, look up to see if the Network already exists (by name).
425 // For HEAT orchestration of networks, the stack name will always match the network name
426 StackInfo heatStack = null;
427 long queryNetworkStarttime = System.currentTimeMillis ();
429 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
430 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
431 } catch (MsoException me) {
432 me.addContext (CREATE_NETWORK_CONTEXT);
433 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
434 String error = "Create Network (heat): query network " + networkName
441 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
442 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
443 throw new NetworkException (me);
446 if (heatStack != null && (heatStack.getStatus () != HeatStatus.NOTFOUND)) {
447 // Stack exists. Return success or error depending on input directive
448 if (failIfExists != null && failIfExists) {
449 String error = "CreateNetwork: Stack " + networkName
450 + " already exists in "
454 + " as " + heatStack.getCanonicalName();
455 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
456 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
457 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
459 // Populate the outputs from the existing stack.
460 networkId.value = heatStack.getCanonicalName ();
461 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
462 rollback.value = networkRollback; // Default rollback - no updates performed
465 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
467 Map <String, Object> outputs = heatStack.getOutputs ();
468 Map <String, String> sMap = new HashMap <> ();
469 if (outputs != null) {
470 for (Map.Entry<String, Object> entry : outputs.entrySet()) {
471 String key=entry.getKey();
472 if (key != null && key.startsWith ("subnet")) {
473 if (aic3template) //one subnet_id output
475 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
478 else //multiples subnet_%aaid% outputs
480 String subnetUUId = (String) outputs.get(key);
481 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
486 subnetIdMap.value = sMap;
487 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", MsoLogger.ErrorCode.DataError, "Found Existing network stack, status=" + heatStack.getStatus ());
488 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Found Existing network stack");
493 // Ready to deploy the new Network
494 // Build the common set of HEAT template parameters
495 Map <String, Object> stackParams = populateNetworkParams (neutronNetworkType,
504 // Validate (and update) the input parameters against the DB definition
505 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
506 // and inputs were already validated.
508 stackParams = heat.validateStackParams (stackParams, heatTemplate);
509 } catch (IllegalArgumentException e) {
510 String error = "Create Network: Configuration Error: " + e.getMessage ();
511 LOGGER.error (MessageEnum.RA_CONFIG_EXC, e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - Create Network, Configuration Error", e);
512 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
516 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
517 // Input parameters were not valid
518 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
521 if (subnets != null) {
525 template = mergeSubnetsAIC3 (template, subnets, stackParams);
529 template = mergeSubnets (template, subnets);
531 } catch (MsoException me) {
532 me.addContext (CREATE_NETWORK_CONTEXT);
533 String error = "Create Network (heat): type " + neutronNetworkType
540 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging subnets", me);
541 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
542 throw new NetworkException (me);
546 if (policyFqdns != null && !policyFqdns.isEmpty() && aic3template) {
548 mergePolicyRefs (policyFqdns, stackParams);
549 } catch (MsoException me) {
550 me.addContext (CREATE_NETWORK_CONTEXT);
551 String error = "Create Network (heat) mergePolicyRefs type " + neutronNetworkType
558 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging policyRefs", me);
559 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
560 throw new NetworkException (me);
564 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
566 mergeRouteTableRefs (routeTableFqdns, stackParams);
567 } catch (MsoException me) {
568 me.addContext (CREATE_NETWORK_CONTEXT);
569 String error = "Create Network (heat) mergeRouteTableRefs type " + neutronNetworkType
576 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging routeTableRefs", me);
577 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
578 throw new NetworkException (me);
582 // Deploy the network stack
583 // Ignore MsoStackAlreadyExists exception because we already checked.
587 heatStack = heat.createStack (cloudSiteId,
593 heatTemplate.getTimeoutMinutes (),
597 backout.booleanValue());
598 } catch (MsoException me) {
599 me.addContext (CREATE_NETWORK_CONTEXT);
600 String error = "Create Network (heat): type " + neutronNetworkType
607 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
608 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
609 throw new NetworkException (me);
612 // Reach this point if createStack is successful.
614 // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
615 // and the neutronNetworkId is the network UUID returned in stack outputs.
616 networkId.value = heatStack.getCanonicalName ();
617 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
620 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
622 Map <String, Object> outputs = heatStack.getOutputs ();
623 Map <String, String> sMap = new HashMap <> ();
624 if (outputs != null) {
625 for (Map.Entry<String, Object> entry : outputs.entrySet()) {
626 String key = entry.getKey();
627 if (key != null && key.startsWith ("subnet")) {
628 if (aic3template) //one subnet output expected
630 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
633 else //multiples subnet_%aaid% outputs allowed
635 String subnetUUId = (String) outputs.get(key);
636 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
641 subnetIdMap.value = sMap;
643 rollback.value = networkRollback;
644 // Populate remaining rollback info and response parameters.
645 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
646 networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
647 networkRollback.setNetworkCreated (true);
648 networkRollback.setNetworkType (networkType);
650 LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
653 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
658 public void updateNetwork (String cloudSiteId,
661 String modelCustomizationUuid,
664 String physicalNetworkName,
665 List <Integer> vlans,
666 List <Subnet> subnets,
667 MsoRequest msoRequest,
668 Holder <Map <String, String>> subnetIdMap,
669 Holder <NetworkRollback> rollback) throws NetworkException {
670 updateNetwork (cloudSiteId,
673 modelCustomizationUuid,
691 public void updateNetworkContrail (String cloudSiteId,
694 String modelCustomizationUuid,
697 List <RouteTarget> routeTargets,
700 List <Subnet> subnets,
701 List <String> policyFqdns,
702 List<String> routeTableFqdns,
703 MsoRequest msoRequest,
704 Holder <Map <String, String>> subnetIdMap,
705 Holder <NetworkRollback> rollback) throws NetworkException {
706 updateNetwork (cloudSiteId,
709 modelCustomizationUuid,
726 * This is the "Update Network" web service implementation.
727 * It will update an existing Network of the requested type in the specified cloud
728 * and tenant. The typical use will be to replace the VLANs with the supplied
729 * list (to add or remove a VLAN), but other properties may be updated as well.
731 * There will be a pre-defined set of network types defined in the MSO Catalog.
732 * All such networks will have a similar configuration, based on the allowable
733 * Openstack networking definitions. This includes basic networks, provider
734 * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
736 * Initially, all provider networks must currently be "vlan" type, and multi-provider
737 * networks must be multiple VLANs on the same physical network.
739 * This service supports two modes of Network update:
740 * - via Heat Templates
742 * The network orchestration mode for each network type is declared in its
743 * catalog definition. All Heat-based templates must support some subset of
744 * the same input parameters: network_name, physical_network, vlan, segments.
746 * The method returns a NetworkRollback object. This object can be passed
747 * as-is to the rollbackNetwork operation to undo everything that was updated.
748 * This is useful if a network is successfully updated but orchestration
749 * fails on a subsequent operation.
751 private void updateNetwork (String cloudSiteId,
754 String modelCustomizationUuid,
757 String physicalNetworkName,
758 List <Integer> vlans,
759 List <RouteTarget> routeTargets,
762 List <Subnet> subnets,
763 List <String> policyFqdns,
764 List<String> routeTableFqdns,
765 MsoRequest msoRequest,
766 Holder <Map <String, String>> subnetIdMap,
767 Holder <NetworkRollback> rollback) throws NetworkException {
768 MsoLogger.setLogContext (msoRequest);
769 MsoLogger.setServiceName (UPDATE_NETWORK_CONTEXT);
770 LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
779 // Will capture execution time for metrics
780 long startTime = System.currentTimeMillis ();
782 // Build a default rollback object (no actions performed)
783 NetworkRollback networkRollback = new NetworkRollback ();
784 networkRollback.setCloudId (cloudSiteId);
785 networkRollback.setTenantId (tenantId);
786 networkRollback.setMsoRequest (msoRequest);
788 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite (cloudSiteId);
789 if (!cloudSiteOpt.isPresent()) {
790 String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
795 + " CloudSite does not exist in MSO Configuration";
796 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
797 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
798 // Set the detailed error as the Exception 'message'
799 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
805 NetworkResource networkResource = networkCheck(
808 modelCustomizationUuid,
815 String mode = networkResource.getOrchestrationMode();
816 NetworkType neutronNetworkType = NetworkType.valueOf(networkResource.getNeutronNetworkType());
818 // Use an MsoNeutronUtils for all Neutron commands
820 if (NEUTRON_MODE.equals(mode)) {
822 // Verify that the Network exists
823 // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
824 NetworkInfo netInfo = null;
825 long queryNetworkStarttime = System.currentTimeMillis();
827 netInfo = neutron.queryNetwork(networkId, tenantId, cloudSiteId);
828 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
829 } catch (MsoException me) {
830 me.addContext(UPDATE_NETWORK_CONTEXT);
831 String error = "Update Network (neutron): query " + networkId
838 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
839 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
840 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
841 throw new NetworkException(me);
844 if (netInfo == null) {
845 String error = "Update Nework: Network " + networkId
846 + " does not exist in "
850 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
851 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
852 // Does not exist. Throw an exception (can't update a non-existent network)
853 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
855 long updateNetworkStarttime = System.currentTimeMillis();
857 netInfo = neutron.updateNetwork(cloudSiteId,
863 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
864 } catch (MsoException me) {
865 me.addContext(UPDATE_NETWORK_CONTEXT);
866 String error = "Update Network (neutron): " + networkId
873 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
874 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
875 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
876 throw new NetworkException(me);
879 // Add the network ID and previously queried vlans to the rollback object
880 networkRollback.setNetworkId(netInfo.getId());
881 networkRollback.setNeutronNetworkId(netInfo.getId());
882 networkRollback.setNetworkType(networkType);
883 // Save previous parameters
884 networkRollback.setNetworkName(netInfo.getName());
885 networkRollback.setPhysicalNetwork(netInfo.getProvider());
886 networkRollback.setVlans(netInfo.getVlans());
888 LOGGER.debug("Network " + networkId + " updated, id = " + netInfo.getId());
889 } else if ("HEAT".equals(mode)) {
891 // First, look up to see that the Network already exists.
892 // For Heat-based orchestration, the networkId is the network Stack ID.
893 StackInfo heatStack = null;
894 long queryStackStarttime = System.currentTimeMillis();
896 heatStack = heat.queryStack(cloudSiteId, tenantId, networkName);
897 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
898 } catch (MsoException me) {
899 me.addContext(UPDATE_NETWORK_CONTEXT);
900 String error = "UpdateNetwork (heat): query " + networkName
907 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
908 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
909 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
910 throw new NetworkException(me);
913 if (heatStack == null || (heatStack.getStatus() == HeatStatus.NOTFOUND)) {
914 String error = "UpdateNetwork: Stack " + networkName
915 + " does not exist in "
919 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
920 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
921 // Network stack does not exist. Return an error
922 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
925 // Get the previous parameters for rollback
926 Map<String, Object> heatParams = heatStack.getParameters();
928 String previousNetworkName = (String) heatParams.get("network_name");
929 String previousPhysicalNetwork = (String) heatParams.get(PHYSICAL_NETWORK);
931 List<Integer> previousVlans = new ArrayList<>();
932 String vlansParam = (String) heatParams.get(VLANS);
933 if (vlansParam != null) {
934 for (String vlan : vlansParam.split(",")) {
936 previousVlans.add(Integer.parseInt(vlan));
937 } catch (NumberFormatException e) {
938 LOGGER.warn(MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
942 LOGGER.debug("Update Stack: Previous VLANS: " + previousVlans);
944 // Ready to deploy the updated Network via Heat
947 HeatTemplate heatTemplate = networkResource.getHeatTemplate();
948 if (heatTemplate == null) {
949 String error = "Network error - undefined Heat Template. Network Type=" + networkType;
950 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);
951 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
952 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
953 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
956 LOGGER.debug("Got HEAT Template from DB: " + heatTemplate.toString());
958 // "Fix" the template if it has CR/LF (getting this from Oracle)
959 String template = heatTemplate.getHeatTemplate();
960 template = template.replaceAll("\r\n", "\n");
962 boolean aic3template = false;
963 String aic3nw = AIC3_NW;
965 aic3nw = environment.getProperty(AIC3_NW_PROPERTY, AIC3_NW);
967 if (template.contains(aic3nw))
970 // Build the common set of HEAT template parameters
971 Map<String, Object> stackParams = populateNetworkParams(neutronNetworkType,
980 // Validate (and update) the input parameters against the DB definition
981 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
983 stackParams = heat.validateStackParams(stackParams, heatTemplate);
984 } catch (IllegalArgumentException e) {
985 String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
986 LOGGER.error(MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
987 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
988 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
989 throw new NetworkException(error, MsoExceptionCategory.INTERNAL, e);
992 if (subnets != null) {
995 template = mergeSubnetsAIC3(template, subnets, stackParams);
997 template = mergeSubnets(template, subnets);
999 } catch (MsoException me) {
1000 me.addContext(UPDATE_NETWORK_CONTEXT);
1001 String error = "Update Network (heat): type " + neutronNetworkType
1008 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
1009 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1010 throw new NetworkException(me);
1014 if (policyFqdns != null && aic3template) {
1016 mergePolicyRefs(policyFqdns, stackParams);
1017 } catch (MsoException me) {
1018 me.addContext(UPDATE_NETWORK_CONTEXT);
1019 String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
1026 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
1027 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1028 throw new NetworkException(me);
1032 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
1034 mergeRouteTableRefs(routeTableFqdns, stackParams);
1035 } catch (MsoException me) {
1036 me.addContext(UPDATE_NETWORK_CONTEXT);
1037 String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
1044 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
1045 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1046 throw new NetworkException(me);
1050 // Update the network stack
1051 // Ignore MsoStackNotFound exception because we already checked.
1052 long updateStackStarttime = System.currentTimeMillis();
1054 heatStack = heatWithUpdate.updateStack(cloudSiteId,
1060 heatTemplate.getTimeoutMinutes());
1061 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
1062 } catch (MsoException me) {
1063 me.addContext(UPDATE_NETWORK_CONTEXT);
1064 String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1065 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
1066 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
1067 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1068 throw new NetworkException(me);
1071 Map<String, Object> outputs = heatStack.getOutputs();
1072 Map<String, String> sMap = new HashMap<>();
1073 if (outputs != null) {
1074 for (Map.Entry<String, Object> entry : outputs.entrySet()) {
1075 String key=entry.getKey();
1076 if (key != null && key.startsWith("subnet")) {
1077 if (aic3template) //one subnet output expected
1079 Map<String, String> map = getSubnetUUId(key, outputs, subnets);
1081 } else //multiples subnet_%aaid% outputs allowed
1083 String subnetUUId = (String) outputs.get(key);
1084 sMap.put(key.substring("subnet_id_".length()), subnetUUId);
1089 subnetIdMap.value = sMap;
1091 // Reach this point if createStack is successful.
1092 // Populate remaining rollback info and response parameters.
1093 networkRollback.setNetworkStackId(heatStack.getCanonicalName());
1094 if(null != outputs) {
1095 networkRollback.setNeutronNetworkId((String) outputs.get(NETWORK_ID));
1098 LOGGER.debug("outputs is NULL");
1100 networkRollback.setNetworkType(networkType);
1101 // Save previous parameters
1102 networkRollback.setNetworkName(previousNetworkName);
1103 networkRollback.setPhysicalNetwork(previousPhysicalNetwork);
1104 networkRollback.setVlans(previousVlans);
1106 rollback.value = networkRollback;
1108 LOGGER.debug("Network " + networkId + " successfully updated via HEAT");
1111 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
1115 private NetworkResource networkCheck (long startTime,
1117 String modelCustomizationUuid,
1119 String physicalNetworkName,
1120 List <Integer> vlans,
1121 List <RouteTarget> routeTargets,
1123 CloudSite cloudSite) throws NetworkException {
1124 // Retrieve the Network Resource definition
1125 NetworkResource networkResource = null;
1126 NetworkResourceCustomization networkCust = null;
1127 if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
1128 if (!commonUtils.isNullOrEmpty(networkType)) {
1129 networkResource = networkResourceRepo.findOneByModelName(networkType);
1132 networkCust = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid);
1134 if(networkCust != null){
1135 LOGGER.debug("Got Network Customization definition from Catalog: "
1136 + networkCust.toString());
1138 networkResource = networkCust.getNetworkResource();
1140 if (networkResource == null) {
1141 String error = "Create/UpdateNetwork: Unable to get network resource with NetworkType:"
1143 + " or ModelCustomizationUUID:"
1144 + modelCustomizationUuid;
1145 LOGGER.error(MessageEnum.RA_UNKOWN_PARAM,
1146 "NetworkType/ModelCustomizationUUID", networkType + "/"
1147 + modelCustomizationUuid, "OpenStack", "",
1148 MsoLogger.ErrorCode.DataError,
1149 "Create/UpdateNetwork: Unknown NetworkType/ModelCustomizationUUID");
1151 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1153 LOGGER.debug("Got Network definition from Catalog: "
1154 + networkResource.toString());
1156 String mode = networkResource.getOrchestrationMode();
1157 NetworkType neutronNetworkType = NetworkType
1158 .valueOf(networkResource.getNeutronNetworkType());
1160 // All Networks are orchestrated via HEAT or Neutron
1161 if (!("HEAT".equals(mode) || NEUTRON_MODE.equals(mode))) {
1162 String error = "CreateNetwork: Configuration Error: Network Type = "
1164 LOGGER.error(MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT,
1165 mode, "OpenStack", "", MsoLogger.ErrorCode.DataError,
1166 "CreateNetwork: Configuration Error");
1167 // Alarm on this error, configuration must be fixed
1168 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
1169 MsoAlarmLogger.CRITICAL, error);
1171 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
1174 MavenLikeVersioning aicV = new MavenLikeVersioning();
1175 aicV.setVersion(cloudSite.getCloudVersion());
1176 if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV
1177 .isTheSameVersion(networkResource.getAicVersionMin())) // aic
1180 && (aicV.isTheSameVersion(networkResource
1181 .getAicVersionMax()) || !(aicV
1182 .isMoreRecentThan(networkResource
1183 .getAicVersionMax())))) // aic <= max
1185 LOGGER.debug("Network Type:" + networkType + " VersionMin:"
1186 + networkResource.getAicVersionMin() + " VersionMax:"
1187 + networkResource.getAicVersionMax()
1188 + " supported on Cloud:" + cloudSiteId
1189 + " with AIC_Version:" + cloudSite.getCloudVersion());
1191 String error = "Network Type:" + networkType + " Version_Min:"
1192 + networkResource.getAicVersionMin() + " Version_Max:"
1193 + networkResource.getAicVersionMax()
1194 + " not supported on Cloud:" + cloudSiteId
1195 + " with AIC_Version:" + cloudSite.getCloudVersion();
1196 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "",
1197 MsoLogger.ErrorCode.DataError,
1198 "Network Type not supported on Cloud");
1199 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
1200 MsoLogger.ResponseCode.DataError, error);
1201 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1204 // Validate the Network parameters.
1205 String missing = validateNetworkParams(neutronNetworkType,
1206 networkName, physicalNetworkName, vlans, routeTargets);
1207 if (!missing.isEmpty()) {
1208 String error = "Create Network: Missing parameters: " + missing;
1209 LOGGER.error(MessageEnum.RA_MISSING_PARAM, missing,
1210 "OpenStack", "", MsoLogger.ErrorCode.DataError,
1211 "Create Network: Missing parameters");
1213 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1216 return networkResource;
1220 public void queryNetwork (String cloudSiteId,
1222 String networkNameOrId,
1223 MsoRequest msoRequest,
1224 Holder <Boolean> networkExists,
1225 Holder <String> networkId,
1226 Holder <String> neutronNetworkId,
1227 Holder <NetworkStatus> status,
1228 Holder <List <Integer>> vlans,
1229 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1230 queryNetwork (cloudSiteId,
1244 public void queryNetworkContrail (String cloudSiteId,
1246 String networkNameOrId,
1247 MsoRequest msoRequest,
1248 Holder <Boolean> networkExists,
1249 Holder <String> networkId,
1250 Holder <String> neutronNetworkId,
1251 Holder <NetworkStatus> status,
1252 Holder <List <RouteTarget>> routeTargets,
1253 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1254 queryNetwork (cloudSiteId,
1268 * This is the queryNetwork method. It returns the existence and status of
1269 * the specified network, along with its Neutron UUID and list of VLANs.
1270 * This method attempts to find the network using both Heat and Neutron.
1271 * Heat stacks are first searched based on the provided network name/id.
1272 * If none is found, the Neutron is directly queried.
1274 private void queryNetwork (String cloudSiteId,
1276 String networkNameOrId,
1277 MsoRequest msoRequest,
1278 Holder <Boolean> networkExists,
1279 Holder <String> networkId,
1280 Holder <String> neutronNetworkId,
1281 Holder <NetworkStatus> status,
1282 Holder <List <Integer>> vlans,
1283 Holder <List <RouteTarget>> routeTargets,
1284 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1285 MsoLogger.setLogContext (msoRequest);
1286 MsoLogger.setServiceName ("QueryNetwork");
1287 LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
1293 // Will capture execution time for metrics
1294 long startTime = System.currentTimeMillis ();
1296 if (commonUtils.isNullOrEmpty (cloudSiteId)
1297 || commonUtils.isNullOrEmpty(tenantId)
1298 || commonUtils.isNullOrEmpty(networkNameOrId)) {
1300 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1301 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1302 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1303 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1306 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
1307 if (!cloudSiteOpt.isPresent())
1309 String error = "Configuration Error. Stack " + networkNameOrId + " in "
1314 + " CloudSite does not exist in MSO Configuration";
1315 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
1316 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1317 // Set the detailed error as the Exception 'message'
1318 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1321 // Use MsoNeutronUtils for all NEUTRON commands
1325 // Try Heat first, since networks may be named the same as the Heat stack
1326 StackInfo heatStack = null;
1327 long queryStackStarttime = System.currentTimeMillis ();
1329 heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
1330 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
1331 } catch (MsoException me) {
1332 me.addContext ("QueryNetwork");
1333 String error = "Query Network (heat): " + networkNameOrId
1340 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
1341 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
1342 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1343 throw new NetworkException (me);
1346 // Populate the outputs based on the returned Stack information
1347 if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
1348 // Found it. Get the neutronNetworkId for further query
1349 Map <String, Object> outputs = heatStack.getOutputs ();
1350 neutronId = (String) outputs.get (NETWORK_ID);
1353 Map <String, String> sMap = new HashMap <> ();
1354 if (outputs != null) {
1355 for (String key : outputs.keySet ()) {
1356 if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
1358 String subnetUUId = (String) outputs.get(key);
1359 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1361 else if (key != null && key.startsWith ("subnet")) //one subnet output expected
1363 Map <String, String> map = getSubnetUUId(key, outputs, null);
1369 subnetIdMap.value = sMap;
1371 // Input ID was not a Heat stack ID. Try it directly in Neutron
1372 neutronId = networkNameOrId;
1373 mode = NEUTRON_MODE;
1376 // Query directly against the Neutron Network for the details
1377 // no RouteTargets available for ContrailV2 in neutron net-show
1378 // networkId is heatStackId
1379 long queryNetworkStarttime = System.currentTimeMillis ();
1381 NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
1382 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
1383 if (netInfo != null) {
1384 // Found. Populate the output elements
1385 networkExists.value = Boolean.TRUE;
1386 if ("HEAT".equals (mode)) {
1387 networkId.value = heatStack.getCanonicalName ();
1389 networkId.value = netInfo.getId ();
1391 neutronNetworkId.value = netInfo.getId ();
1392 status.value = netInfo.getStatus ();
1394 vlans.value = netInfo.getVlans ();
1396 LOGGER.debug ("Network " + networkNameOrId
1401 + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
1403 // Not found. Populate the status fields, leave the rest null
1404 networkExists.value = Boolean.FALSE;
1405 status.value = NetworkStatus.NOTFOUND;
1406 neutronNetworkId.value = null;
1408 vlans.value = new ArrayList<>();
1410 LOGGER.debug ("Network " + networkNameOrId + " not found");
1412 } catch (MsoException me) {
1413 me.addContext ("QueryNetwork");
1414 String error = "Query Network (neutron): " + networkNameOrId
1421 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
1422 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
1423 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1424 throw new NetworkException (me);
1426 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
1431 * This is the "Delete Network" web service implementation.
1432 * It will delete a Network in the specified cloud and tenant.
1434 * If the network is not found, it is treated as a success.
1436 * This service supports two modes of Network creation/update/delete:
1437 * - via Heat Templates
1439 * The network orchestration mode for each network type is declared in its
1440 * catalog definition.
1442 * For Heat-based orchestration, the networkId should be the stack ID.
1443 * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
1445 * The method returns nothing on success. Rollback is not possible for delete
1446 * commands, so any failure on delete will require manual fallout in the client.
1449 public void deleteNetwork (String cloudSiteId,
1452 String modelCustomizationUuid,
1454 MsoRequest msoRequest,
1455 Holder <Boolean> networkDeleted) throws NetworkException {
1456 MsoLogger.setLogContext (msoRequest);
1457 MsoLogger.setServiceName ("DeleteNetwork");
1458 LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
1464 // Will capture execution time for metrics
1465 long startTime = System.currentTimeMillis ();
1468 if (commonUtils.isNullOrEmpty (cloudSiteId)
1469 || commonUtils.isNullOrEmpty(tenantId)
1470 || commonUtils.isNullOrEmpty(networkId)) {
1471 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1472 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1473 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1474 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1477 // Retrieve the Network Resource definition
1478 NetworkResource networkResource = null;
1480 if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
1481 if (!commonUtils.isNullOrEmpty(networkType)) {
1482 networkResource = networkResourceRepo.findFirstByModelNameOrderByModelVersionDesc(networkType);
1485 NetworkResourceCustomization nrc = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid);
1487 networkResource = nrc.getNetworkResource();
1492 if (networkResource != null) {
1493 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1495 mode = networkResource.getOrchestrationMode ();
1498 if (NEUTRON_MODE.equals (mode)) {
1500 // Use MsoNeutronUtils for all NEUTRON commands
1501 long deleteNetworkStarttime = System.currentTimeMillis ();
1503 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1504 // was not found. So don't bother to query first.
1505 boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1506 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1507 networkDeleted.value = deleted;
1508 } catch (MsoException me) {
1509 me.addContext ("DeleteNetwork");
1510 String error = "Delete Network (neutron): " + networkId
1517 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1518 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
1519 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1520 throw new NetworkException (me);
1522 } else { // DEFAULT to ("HEAT".equals (mode))
1523 long deleteStackStarttime = System.currentTimeMillis ();
1526 // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
1527 // So query first to report back if stack WAS deleted or just NOTOFUND
1528 StackInfo heatStack = null;
1529 heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
1530 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
1532 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1533 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1534 networkDeleted.value = true;
1538 networkDeleted.value = false;
1540 } catch (MsoException me) {
1541 me.addContext ("DeleteNetwork");
1542 String error = "Delete Network (heat): " + networkId
1549 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1550 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
1551 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1552 throw new NetworkException (me);
1557 // On success, nothing is returned.
1558 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
1563 * This web service endpoint will rollback a previous Create VNF operation.
1564 * A rollback object is returned to the client in a successful creation
1565 * response. The client can pass that object as-is back to the rollbackVnf
1566 * operation to undo the creation.
1568 * The rollback includes removing the VNF and deleting the tenant if the
1569 * tenant did not exist prior to the VNF creation.
1572 public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
1573 MsoLogger.setServiceName ("RollbackNetwork");
1574 // Will capture execution time for metrics
1575 long startTime = System.currentTimeMillis ();
1577 if (rollback == null) {
1578 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
1579 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
1583 MsoLogger.setLogContext (rollback.getMsoRequest());
1585 // Get the elements of the VnfRollback object for easier access
1586 String cloudSiteId = rollback.getCloudId ();
1587 String tenantId = rollback.getTenantId ();
1588 String networkId = rollback.getNetworkStackId ();
1589 String networkType = rollback.getNetworkType ();
1590 String modelCustomizationUuid = rollback.getModelCustomizationUuid();
1592 LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
1596 // Retrieve the Network Resource definition
1597 NetworkResource networkResource = null;
1598 if (commonUtils.isNullOrEmpty(modelCustomizationUuid)) {
1599 networkResource = networkCustomRepo.findOneByNetworkType(networkType).getNetworkResource();
1601 networkResource = networkCustomRepo.findOneByModelCustomizationUUID(modelCustomizationUuid).getNetworkResource();
1604 if (networkResource != null) {
1606 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1608 mode = networkResource.getOrchestrationMode ();
1611 if (rollback.getNetworkCreated ()) {
1612 // Rolling back a newly created network, so delete it.
1613 if (NEUTRON_MODE.equals (mode)) {
1614 // Use MsoNeutronUtils for all NEUTRON commands
1615 long deleteNetworkStarttime = System.currentTimeMillis ();
1617 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1618 // was not found. So don't bother to query first.
1619 neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1620 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1621 } catch (MsoException me) {
1622 me.addContext ("RollbackNetwork");
1623 String error = "Rollback Network (neutron): " + networkId
1630 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1631 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
1632 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1633 throw new NetworkException (me);
1635 } else { // DEFAULT to if ("HEAT".equals (mode))
1636 long deleteStackStarttime = System.currentTimeMillis ();
1638 // The deleteStack function in MsoHeatUtils returns success if the stack
1639 // was not found. So don't bother to query first.
1640 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1641 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1642 } catch (MsoException me) {
1643 me.addContext ("RollbackNetwork");
1644 String error = "Rollback Network (heat): " + networkId
1651 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1652 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
1653 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1654 throw new NetworkException (me);
1659 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
1663 private String validateNetworkParams (NetworkType neutronNetworkType,
1665 String physicalNetwork,
1666 List <Integer> vlans,
1667 List <RouteTarget> routeTargets) {
1669 StringBuilder missing = new StringBuilder ();
1670 if (commonUtils.isNullOrEmpty(networkName)) {
1671 missing.append ("networkName");
1675 if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1676 if (commonUtils.isNullOrEmpty(physicalNetwork)) {
1677 missing.append (sep).append ("physicalNetworkName");
1680 if (vlans == null || vlans.isEmpty ()) {
1681 missing.append (sep).append (VLANS);
1685 return missing.toString ();
1688 private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
1690 String physicalNetwork,
1691 List <Integer> vlans,
1692 List <RouteTarget> routeTargets,
1695 boolean aic3template) {
1696 // Build the common set of HEAT template parameters
1697 Map <String, Object> stackParams = new HashMap <> ();
1698 stackParams.put ("network_name", networkName);
1700 if (neutronNetworkType == NetworkType.PROVIDER) {
1701 // For Provider type
1702 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1703 stackParams.put ("vlan", vlans.get (0).toString ());
1704 } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1705 // For Multi-provider, PO supports a custom resource extension of ProviderNet.
1706 // It supports all ProviderNet properties except segmentation_id, and adds a
1707 // comma-separated-list of VLANs as a "segments" property.
1708 // Note that this does not match the Neutron definition of Multi-Provider network,
1709 // which contains a list of 'segments', each having physical_network, network_type,
1710 // and segmentation_id.
1711 StringBuilder buf = new StringBuilder ();
1713 for (Integer vlan : vlans) {
1714 buf.append (sep).append (vlan.toString ());
1717 String csl = buf.toString ();
1719 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1720 stackParams.put (VLANS, csl);
1722 if (routeTargets != null) {
1724 String rtGlobal = "";
1725 String rtImport = "";
1726 String rtExport = "";
1728 for (RouteTarget rt : routeTargets) {
1729 boolean rtIsNull = false;
1732 String routeTarget = rt.getRouteTarget();
1733 String routeTargetRole = rt.getRouteTargetRole();
1734 LOGGER.debug("Checking for an actually null route target: " + rt.toString());
1735 if (routeTarget == null || routeTarget.equals("") || routeTarget.equalsIgnoreCase("null"))
1737 if (routeTargetRole == null || routeTargetRole.equals("") || routeTargetRole.equalsIgnoreCase("null"))
1743 LOGGER.debug("Input RT:" + rt.toString());
1744 String role = rt.getRouteTargetRole();
1745 String rtValue = rt.getRouteTarget();
1747 if ("IMPORT".equalsIgnoreCase(role))
1749 sep = rtImport.isEmpty() ? "" : ",";
1750 rtImport = aic3template ? rtImport + sep + "target:" + rtValue : rtImport + sep + rtValue ;
1752 else if ("EXPORT".equalsIgnoreCase(role))
1754 sep = rtExport.isEmpty() ? "" : ",";
1755 rtExport = aic3template ? rtExport + sep + "target:" + rtValue : rtExport + sep + rtValue ;
1757 else // covers BOTH, empty etc
1759 sep = rtGlobal.isEmpty() ? "" : ",";
1760 rtGlobal = aic3template ? rtGlobal + sep + "target:" + rtValue : rtGlobal + sep + rtValue ;
1766 if (!rtImport.isEmpty())
1768 stackParams.put ("route_targets_import", rtImport);
1770 if (!rtExport.isEmpty())
1772 stackParams.put ("route_targets_export", rtExport);
1774 if (!rtGlobal.isEmpty())
1776 stackParams.put ("route_targets", rtGlobal);
1779 if (commonUtils.isNullOrEmpty(shared)) {
1780 stackParams.put ("shared", "False");
1782 stackParams.put ("shared", shared);
1784 if (commonUtils.isNullOrEmpty(external)) {
1785 stackParams.put ("external", "False");
1787 stackParams.put ("external", external);
1794 /** policyRef_list structure in stackParams
1797 "network_policy_refs_data_sequence": {
1798 "network_policy_refs_data_sequence_major": "1",
1799 "network_policy_refs_data_sequence_minor": "0"
1803 "network_policy_refs_data_sequence": {
1804 "network_policy_refs_data_sequence_major": "2",
1805 "network_policy_refs_data_sequence_minor": "0"
1810 private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
1812 List<ContrailPolicyRef> prlist = new ArrayList <> ();
1814 for (String pf : pFqdns) {
1815 if (!commonUtils.isNullOrEmpty(pf))
1817 ContrailPolicyRef pr = new ContrailPolicyRef();
1818 ContrailPolicyRefSeq refSeq = new ContrailPolicyRefSeq(String.valueOf(index), "0");
1821 LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
1826 JsonNode node = null;
1829 ObjectMapper mapper = new ObjectMapper();
1830 node = mapper.convertValue(prlist, JsonNode.class);
1831 String jsonString = mapper.writeValueAsString(prlist);
1832 LOGGER.debug("Json PolicyRefs Data:" + jsonString);
1836 String error = "Error creating JsonNode for policyRefs Data";
1837 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
1838 throw new MsoAdapterException (error);
1841 if (pFqdns != null && node != null)
1843 StringBuilder buf = new StringBuilder ();
1845 for (String pf : pFqdns) {
1846 if (!commonUtils.isNullOrEmpty(pf))
1848 buf.append (sep).append (pf);
1852 String csl = buf.toString ();
1853 stackParams.put ("policy_refs", csl);
1854 stackParams.put ("policy_refsdata", node);
1857 LOGGER.debug ("StackParams updated with policy refs");
1861 private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
1864 if (rtFqdns != null)
1866 StringBuilder buf = new StringBuilder ();
1868 for (String rtf : rtFqdns) {
1869 if (!commonUtils.isNullOrEmpty(rtf))
1871 buf.append (sep).append (rtf);
1875 String csl = buf.toString ();
1876 stackParams.put ("route_table_refs", csl);
1879 LOGGER.debug ("StackParams updated with route_table refs");
1884 /*** Subnet Output structure from Juniper
1889 "ip_prefix": "10.100.1.0",
1892 "addr_from_start": null,
1893 "enable_dhcp": false,
1894 "default_gateway": "10.100.1.1",
1895 "dns_nameservers": [],
1896 "dhcp_option_list": null,
1897 "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
1898 "allocation_pools": [
1900 "start": "10.100.1.3",
1904 "start": "10.100.1.6",
1908 "host_routes": null,
1909 "dns_server_address": "10.100.1.13",
1910 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
1914 "ip_prefix": "10.100.2.16",
1917 "addr_from_start": null,
1918 "enable_dhcp": true,
1919 "default_gateway": "10.100.2.17",
1920 "dns_nameservers": [],
1921 "dhcp_option_list": null,
1922 "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
1923 "allocation_pools": [
1925 "start": "10.100.2.18",
1926 "end": "10.100.2.20"
1929 "host_routes": null,
1930 "dns_server_address": "10.100.2.29",
1931 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
1937 private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
1940 List<ContrailSubnet> cslist = new ArrayList <> ();
1941 for (Subnet subnet : subnets) {
1942 LOGGER.debug("Input Subnet:" + subnet.toString());
1943 ContrailSubnet cs = new ContrailSubnetMapper(subnet).map();
1944 LOGGER.debug("Contrail Subnet:" + cs.toString());
1948 JsonNode node = null;
1951 ObjectMapper mapper = new ObjectMapper();
1952 node = mapper.convertValue(cslist, JsonNode.class);
1953 String jsonString = mapper.writeValueAsString(cslist);
1954 LOGGER.debug("Json Subnet List:" + jsonString);
1958 String error = "Error creating JsonNode from input subnets";
1959 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
1960 throw new MsoAdapterException (error);
1965 stackParams.put ("subnet_list", node);
1967 //Outputs - All subnets are in one ipam_subnets structure
1968 String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
1969 + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
1971 // append outputs in heatTemplate
1972 int outputsIdx = heatTemplate.indexOf ("outputs:");
1973 heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
1974 LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
1975 return heatTemplate;
1979 private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
1981 String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
1984 + " network_id: { get_resource: network }\n"
1985 + " cidr: %cidr%\n";
1987 /* make these optional
1988 + " ip_version: %ipversion%\n"
1989 + " enable_dhcp: %enabledhcp%\n"
1990 + " gateway_ip: %gatewayip%\n"
1991 + " allocation_pools:\n"
1992 + " - start: %poolstart%\n"
1993 + " end: %poolend%\n";
1997 String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
1998 + " value: {get_resource: subnet_%subnetId%}\n";
2002 StringBuilder resourcesBuf = new StringBuilder ();
2003 StringBuilder outputsBuf = new StringBuilder ();
2004 for (Subnet subnet : subnets) {
2006 // build template for each subnet
2007 curR = resourceTempl;
2008 if (subnet.getSubnetId () != null) {
2009 curR = curR.replace ("%subnetId%", subnet.getSubnetId ());
2011 String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
2012 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
2013 throw new MsoAdapterException (error);
2016 if (subnet.getSubnetName () != null) {
2017 curR = curR.replace ("%name%", subnet.getSubnetName ());
2019 curR = curR.replace ("%name%", subnet.getSubnetId ());
2022 if (subnet.getCidr () != null) {
2023 curR = curR.replace ("%cidr%", subnet.getCidr ());
2025 String error = "Missing Required cidr for subnet in HEAT Template";
2026 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
2027 throw new MsoAdapterException (error);
2030 if (subnet.getIpVersion () != null) {
2031 curR = curR + " ip_version: " + subnet.getIpVersion () + "\n";
2033 if (subnet.getEnableDHCP () != null) {
2034 curR = curR + " enable_dhcp: " + Boolean.toString (subnet.getEnableDHCP ()) + "\n";
2036 if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
2037 curR = curR + " gateway_ip: " + subnet.getGatewayIp () + "\n";
2040 if (subnet.getAllocationPools() != null) {
2041 curR = curR + " allocation_pools:\n";
2042 for (Pool pool : subnet.getAllocationPools())
2044 if (!commonUtils.isNullOrEmpty(pool.getStart()) && !commonUtils.isNullOrEmpty(pool.getEnd()))
2046 curR = curR + " - start: " + pool.getStart () + "\n";
2047 curR = curR + " end: " + pool.getEnd () + "\n";
2052 resourcesBuf.append (curR);
2055 curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
2057 outputsBuf.append (curO);
2060 // append resources and outputs in heatTemplate
2061 LOGGER.debug ("Tempate initial:" + heatTemplate);
2062 int outputsIdx = heatTemplate.indexOf ("outputs:");
2063 heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
2064 int resourcesIdx = heatTemplate.indexOf ("resources:");
2065 heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
2067 LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
2068 return heatTemplate;
2071 private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
2073 Map <String, String> sMap = new HashMap <> ();
2076 Object obj = outputs.get(key);
2077 ObjectMapper mapper = new ObjectMapper();
2078 String jStr = mapper.writeValueAsString(obj);
2079 LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
2081 JsonNode rootNode = mapper.readTree(jStr);
2082 for (JsonNode sNode : rootNode.path("ipam_subnets"))
2084 LOGGER.debug("Output Subnet Node" + sNode.toString());
2085 String name = sNode.path("subnet_name").textValue();
2086 String uuid = sNode.path("subnet_uuid").textValue();
2087 String aaiId = name; // default
2088 // try to find aaiId for name in input subnetList
2089 if (subnets != null)
2091 for (Subnet subnet : subnets)
2093 if ( subnet != null && !commonUtils.isNullOrEmpty(subnet.getSubnetName()))
2095 if (subnet.getSubnetName().equals(name))
2097 aaiId = subnet.getSubnetId();
2103 sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
2108 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
2111 LOGGER.debug ("Return sMap" + sMap.toString());
2115 private static String insertStr (String template, String snippet, int index) {
2117 String updatedTemplate;
2119 LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
2121 String templateBeg = template.substring (0, index);
2122 String templateEnd = template.substring (index);
2124 updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
2126 LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
2127 return updatedTemplate;