public NetworkOfferingVO createNetworkOffering()

in server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java [6694:7037]


    public NetworkOfferingVO createNetworkOffering(final String name, final String displayText, final TrafficType trafficType, String tags, final boolean specifyVlan,
                                                   final Availability availability,
                                                   final Integer networkRate, final Map<Service, Set<Provider>> serviceProviderMap, final boolean isDefault, final GuestType type, final boolean systemOnly,
                                                   final Long serviceOfferingId,
                                                   final boolean conserveMode, final Map<Service, Map<Capability, String>> serviceCapabilityMap, final boolean specifyIpRanges, final boolean isPersistent,
                                                   final Map<Detail, String> details, final boolean egressDefaultPolicy, final Integer maxconn, final boolean enableKeepAlive, Boolean forVpc,
                                                   Boolean forTungsten, boolean forNsx, NetworkOffering.NetworkMode networkMode, final List<Long> domainIds, final List<Long> zoneIds, final boolean enableOffering, final NetUtils.InternetProtocol internetProtocol,
                                                   final NetworkOffering.RoutingMode routingMode, final boolean specifyAsNumber) {

        String servicePackageUuid;
        String spDescription = null;
        if (details == null) {
            servicePackageUuid = null;
        } else {
            servicePackageUuid = details.get(NetworkOffering.Detail.servicepackageuuid);
            spDescription = details.get(NetworkOffering.Detail.servicepackagedescription);
        }


        final String multicastRateStr = _configDao.getValue("multicast.throttling.rate");
        final int multicastRate = multicastRateStr == null ? 10 : Integer.parseInt(multicastRateStr);
        tags = com.cloud.utils.StringUtils.cleanupTags(tags);

        // specifyIpRanges should always be true for Shared networks
        // specifyIpRanges can only be true for Isolated networks with no Source
        // Nat service
        if (specifyIpRanges) {
            if (type == GuestType.Isolated) {
                if (serviceProviderMap.containsKey(Service.SourceNat)) {
                    throw new InvalidParameterValueException("SpecifyIpRanges can only be true for Shared network offerings and Isolated with no SourceNat service");
                }
            }
        } else {
            if (type == GuestType.Shared) {
                throw new InvalidParameterValueException("SpecifyIpRanges should always be true for Shared network offerings");
            }
        }

        if (specifyAsNumber && !forNsx) {
            String msg = "SpecifyAsNumber can only be true for network offerings for NSX";
            logger.error(msg);
            throw new InvalidParameterValueException(msg);
        }

        if (specifyAsNumber && !Dynamic.equals(routingMode)) {
            String msg = "SpecifyAsNumber can only be true for Dynamic Route Mode network offerings";
            logger.error(msg);
            throw new InvalidParameterValueException(msg);
        }

        if (specifyAsNumber && Boolean.TRUE.equals(forVpc)) {
            String msg = "SpecifyAsNumber cannot be set for VPC network tiers. It needs to be defined at VPC level";
            logger.error(msg);
            throw new InvalidParameterValueException(msg);
        }

        // isPersistent should always be false for Shared network Offerings
        if (isPersistent && type == GuestType.Shared) {
            throw new InvalidParameterValueException("isPersistent should be false if network offering's type is " + type);
        }

        // Validate network mode
        if (networkMode != null) {
            if (type != GuestType.Isolated) {
                throw new InvalidParameterValueException("networkMode should be set only for Isolated network offerings");
            }
            if (NetworkOffering.NetworkMode.ROUTED.equals(networkMode)) {
                if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.value()) {
                    throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed networks", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key()));
                }
                if (zoneIds != null) {
                    for (Long zoneId: zoneIds) {
                        if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.valueIn(zoneId)) {
                            throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed networks in zone (ID: %s)", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key(), zoneId));
                        }
                    }
                }
                boolean useVirtualRouterOnly = true;
                for (Service service : serviceProviderMap.keySet()) {
                    Set<Provider> providers = serviceProviderMap.get(service);
                    if (Arrays.asList(Service.SourceNat, Service.StaticNat, Service.Lb, Service.PortForwarding, Service.Vpn).contains(service)) {
                        if (providers != null) {
                            throw new InvalidParameterValueException("SourceNat/StaticNat/Lb/PortForwarding/Vpn service are not supported in ROUTED mode");
                        }
                    }
                    if (useVirtualRouterOnly && Arrays.asList(Service.Firewall, Service.NetworkACL).contains(service)) {
                        for (Provider provider : providers) {
                            if (!Provider.VirtualRouter.equals(provider) && !Provider.VPCVirtualRouter.equals(provider)) {
                                useVirtualRouterOnly = false;
                                break;
                            }
                        }
                    }
                }
                if (useVirtualRouterOnly) {
                    // Add VirtualRouter/VPCVirtualRouter as provider of Gateway service
                    if (forVpc) {
                        serviceProviderMap.put(Service.Gateway, Sets.newHashSet(Provider.VPCVirtualRouter));
                    } else {
                        serviceProviderMap.put(Service.Gateway, Sets.newHashSet(Provider.VirtualRouter));
                    }
                }
            }
        }

        // validate availability value
        if (availability == NetworkOffering.Availability.Required) {
            final boolean canOffBeRequired = type == GuestType.Isolated && serviceProviderMap.containsKey(Service.SourceNat);
            if (!canOffBeRequired) {
                throw new InvalidParameterValueException("Availability can be " + NetworkOffering.Availability.Required + " only for networkOfferings of type "
                        + GuestType.Isolated + " and with " + Service.SourceNat.getName() + " enabled");
            }

            // only one network offering in the system can be Required
            final List<NetworkOfferingVO> offerings = _networkOfferingDao.listByAvailability(Availability.Required, false);
            if (!offerings.isEmpty()) {
                throw new InvalidParameterValueException("System already has network offering id=" + offerings.get(0).getId() + " with availability " + Availability.Required);
            }
        }

        boolean dedicatedLb = false;
        boolean elasticLb = false;
        boolean sharedSourceNat = false;
        boolean redundantRouter = false;
        boolean elasticIp = false;
        boolean associatePublicIp = false;
        boolean inline = false;
        boolean publicLb = false;
        boolean internalLb = false;
        boolean strechedL2Subnet = false;
        boolean publicAccess = false;
        boolean vmAutoScaling = false;

        if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) {
            final Map<Capability, String> lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb);

            if (lbServiceCapabilityMap != null && !lbServiceCapabilityMap.isEmpty()) {
                final String isolationCapability = lbServiceCapabilityMap.get(Capability.SupportedLBIsolation);
                if (isolationCapability != null) {
                    _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, Capability.SupportedLBIsolation, isolationCapability);
                    dedicatedLb = isolationCapability.contains("dedicated");
                } else {
                    dedicatedLb = true;
                }

                final String param = lbServiceCapabilityMap.get(Capability.ElasticLb);
                if (param != null) {
                    elasticLb = param.contains("true");
                }

                final String inlineMode = lbServiceCapabilityMap.get(Capability.InlineMode);
                if (inlineMode != null) {
                    _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, Capability.InlineMode, inlineMode);
                    inline = inlineMode.contains("true");
                } else {
                    inline = false;
                }

                final String publicLbStr = lbServiceCapabilityMap.get(Capability.LbSchemes);
                if (serviceProviderMap.containsKey(Service.Lb)) {
                    if (publicLbStr != null) {
                        _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, Capability.LbSchemes, publicLbStr);
                        internalLb = publicLbStr.contains("internal");
                        publicLb = publicLbStr.contains("public");
                    }
                }

                final String vmAutoScalingStr = lbServiceCapabilityMap.get(Capability.VmAutoScaling);
                if (vmAutoScalingStr != null) {
                    _networkModel.checkCapabilityForProvider(serviceProviderMap.get(Service.Lb), Service.Lb, Capability.VmAutoScaling, vmAutoScalingStr);
                    vmAutoScaling = vmAutoScalingStr.contains("true");
                }
            }

            // in the current version of the code, publicLb and specificLb can't
            // both be set to true for the same network offering
            if (publicLb && internalLb) {
                throw new InvalidParameterValueException("Public lb and internal lb can't be enabled at the same time on the offering");
            }

            final Map<Capability, String> sourceNatServiceCapabilityMap = serviceCapabilityMap.get(Service.SourceNat);
            if (MapUtils.isNotEmpty(sourceNatServiceCapabilityMap)) {
                sharedSourceNat = isSharedSourceNat(serviceProviderMap, sourceNatServiceCapabilityMap);
                redundantRouter = isRedundantRouter(serviceProviderMap.get(Service.SourceNat), Service.SourceNat, sourceNatServiceCapabilityMap);
            }

            final Map<Capability, String> gatewayServiceCapabilityMap = serviceCapabilityMap.get(Service.Gateway);
            if (MapUtils.isNotEmpty(gatewayServiceCapabilityMap)) {
                redundantRouter = redundantRouter || isRedundantRouter(serviceProviderMap.get(Service.Gateway), Service.Gateway, gatewayServiceCapabilityMap);
            }

            final Map<Capability, String> staticNatServiceCapabilityMap = serviceCapabilityMap.get(Service.StaticNat);
            if (staticNatServiceCapabilityMap != null && !staticNatServiceCapabilityMap.isEmpty()) {
                final String param = staticNatServiceCapabilityMap.get(Capability.ElasticIp);
                if (param != null) {
                    elasticIp = param.contains("true");
                    final String associatePublicIP = staticNatServiceCapabilityMap.get(Capability.AssociatePublicIP);
                    if (associatePublicIP != null) {
                        associatePublicIp = associatePublicIP.contains("true");
                    }
                }
            }

            final Map<Capability, String> connectivityServiceCapabilityMap = serviceCapabilityMap.get(Service.Connectivity);
            if (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()) {
                if (connectivityServiceCapabilityMap.containsKey(Capability.StretchedL2Subnet)) {
                    final String value = connectivityServiceCapabilityMap.get(Capability.StretchedL2Subnet);
                    if ("true".equalsIgnoreCase(value)) {
                        strechedL2Subnet = true;
                    }
                }

                if (connectivityServiceCapabilityMap.containsKey(Capability.PublicAccess)) {
                    final String value = connectivityServiceCapabilityMap.get(Capability.PublicAccess);
                    if ("true".equalsIgnoreCase(value)) {
                        publicAccess = true;
                    }
                }
            }
        }

        if (serviceProviderMap != null && serviceProviderMap.containsKey(Service.Lb) && !internalLb && !publicLb) {
            //if not specified, default public lb to true
            publicLb = true;
        }

        final NetworkOfferingVO offeringFinal = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability,
                tags, type, conserveMode, dedicatedLb, sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp, publicLb,
                internalLb, forVpc, egressDefaultPolicy, strechedL2Subnet, publicAccess);

        if (serviceOfferingId != null) {
            offeringFinal.setServiceOfferingId(serviceOfferingId);
        }

        offeringFinal.setForTungsten(Objects.requireNonNullElse(forTungsten, false));
        offeringFinal.setForNsx(Objects.requireNonNullElse(forNsx, false));
        offeringFinal.setNetworkMode(networkMode);

        if (enableOffering) {
            offeringFinal.setState(NetworkOffering.State.Enabled);
        }

        offeringFinal.setSpecifyAsNumber(specifyAsNumber);
        if (routingMode != null) {
            offeringFinal.setRoutingMode(routingMode);
        }

        // Set VM AutoScaling capability
        offeringFinal.setSupportsVmAutoScaling(vmAutoScaling);

        //Set Service package id
        offeringFinal.setServicePackage(servicePackageUuid);
        // validate the details
        if (details != null) {
            validateNtwkOffDetails(details, serviceProviderMap);
        }

        boolean vpcOff = false;
        boolean nsOff = false;

        if (serviceProviderMap != null && spDescription != null) {
            for (final Network.Service service : serviceProviderMap.keySet()) {
                final Set<Provider> providers = serviceProviderMap.get(service);
                if (providers != null && !providers.isEmpty()) {
                    for (final Network.Provider provider : providers) {
                        if (provider == Provider.VPCVirtualRouter) {
                            vpcOff = true;
                        }
                        if (provider == Provider.Netscaler) {
                            nsOff = true;
                        }
                    }
                }
            }
            if(vpcOff && nsOff) {
                if(!(spDescription.equalsIgnoreCase("A NetScalerVPX is dedicated per network.") || spDescription.contains("dedicated NetScaler"))) {
                    throw new InvalidParameterValueException("Only NetScaler Service Package with Dedicated Device Mode is Supported in VPC Type Guest Network");
                }
            }
        }

        return Transaction.execute(new TransactionCallback<NetworkOfferingVO>() {
            @Override
            public NetworkOfferingVO doInTransaction(final TransactionStatus status) {
                NetworkOfferingVO offering = offeringFinal;

                // 1) create network offering object
                logger.debug("Adding network offering " + offering);
                offering.setConcurrentConnections(maxconn);
                offering.setKeepAliveEnabled(enableKeepAlive);
                offering = _networkOfferingDao.persist(offering, details);
                // 2) populate services and providers
                if (serviceProviderMap != null) {
                    for (final Network.Service service : serviceProviderMap.keySet()) {
                        final Set<Provider> providers = serviceProviderMap.get(service);
                        if (providers != null && !providers.isEmpty()) {
                            boolean vpcOff = false;
                            for (final Network.Provider provider : providers) {
                                if (provider == Provider.VPCVirtualRouter) {
                                    vpcOff = true;
                                }
                                final NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(offering.getId(), service, provider);
                                _ntwkOffServiceMapDao.persist(offService);
                                logger.trace("Added service for the network offering: " + offService + " with provider " + provider.getName());
                            }

                            if (vpcOff && !forNsx) {
                                final List<Service> supportedSvcs = new ArrayList<Service>();
                                supportedSvcs.addAll(serviceProviderMap.keySet());
                                _vpcMgr.validateNtwkOffForVpc(offering, supportedSvcs);
                            }
                        } else {
                            final NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(offering.getId(), service, null);
                            _ntwkOffServiceMapDao.persist(offService);
                            logger.trace("Added service for the network offering: " + offService + " with null provider");
                        }
                    }
                    if (offering != null) {
                        // Filter child domains when both parent and child domains are present
                        List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
                        List<NetworkOfferingDetailsVO> detailsVO = new ArrayList<>();
                        for (Long domainId : filteredDomainIds) {
                            detailsVO.add(new NetworkOfferingDetailsVO(offering.getId(), Detail.domainid, String.valueOf(domainId), false));
                        }
                        if (CollectionUtils.isNotEmpty(zoneIds)) {
                            for (Long zoneId : zoneIds) {
                                detailsVO.add(new NetworkOfferingDetailsVO(offering.getId(), Detail.zoneid, String.valueOf(zoneId), false));
                            }
                        }
                        if (internetProtocol != null) {
                            detailsVO.add(new NetworkOfferingDetailsVO(offering.getId(), Detail.internetProtocol, String.valueOf(internetProtocol), true));
                        }
                        if (!detailsVO.isEmpty()) {
                            for (NetworkOfferingDetailsVO detail : detailsVO) {
                                networkOfferingDetailsDao.persist(detail);
                            }
                        }
                    }
                }

                return offering;
            }
        });
    }