in server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java [4947:5150]
public Vlan createVlanAndPublicIpRange(final long zoneId, final long networkId, final long physicalNetworkId, final boolean forVirtualNetwork, final boolean forSystemVms, final Long podId, final String startIP, final String endIP,
final String vlanGateway, final String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, final Account vlanOwner, final String startIPv6, final String endIPv6, final String vlanIp6Gateway, final String vlanIp6Cidr, boolean forNsx) {
final Network network = _networkModel.getNetwork(networkId);
boolean ipv4 = false, ipv6 = false;
if (startIP != null) {
ipv4 = true;
}
if (vlanIp6Cidr != null) {
ipv6 = true;
}
if (!ipv4 && !ipv6) {
throw new InvalidParameterValueException("Please specify IPv4 or IPv6 address.");
}
// Validate the zone
final DataCenterVO zone = _zoneDao.findById(zoneId);
if (zone == null) {
throw new InvalidParameterValueException("Please specify a valid zone.");
}
// ACL check
checkZoneAccess(CallContext.current().getCallingAccount(), zone);
// Validate the physical network
if (_physicalNetworkDao.findById(physicalNetworkId) == null) {
throw new InvalidParameterValueException("Please specify a valid physical network id");
}
// Validate the pod
if (podId != null) {
final Pod pod = _podDao.findById(podId);
if (pod == null) {
throw new InvalidParameterValueException("Please specify a valid pod.");
}
if (pod.getDataCenterId() != zoneId) {
throw new InvalidParameterValueException(String.format("Pod %s doesn't belong to zone id=%d", pod, zoneId));
}
// pod vlans can be created in basic zone only
if (zone.getNetworkType() != NetworkType.Basic || network.getTrafficType() != TrafficType.Guest) {
throw new InvalidParameterValueException("Pod id can be specified only for the networks of type " + TrafficType.Guest + " in zone of type " + NetworkType.Basic);
}
}
// 1) if vlan is specified for the guest network range, it should be the
// same as network's vlan
// 2) if vlan is missing, default it to the guest network's vlan
if (network.getTrafficType() == TrafficType.Guest) {
String networkVlanId = null;
boolean connectivityWithoutVlan = false;
if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Connectivity)) {
Map<Capability, String> connectivityCapabilities = _networkModel.getNetworkServiceCapabilities(network.getId(), Service.Connectivity);
connectivityWithoutVlan = MapUtils.isNotEmpty(connectivityCapabilities) && connectivityCapabilities.containsKey(Capability.NoVlan);
}
final URI uri = network.getBroadcastUri();
if (connectivityWithoutVlan) {
networkVlanId = network.getBroadcastDomainType().toUri(network.getUuid()).toString();
} else if (uri != null) {
// Do not search for the VLAN tag when the network doesn't support VLAN
if (uri.toString().startsWith("vlan")) {
final String[] vlan = uri.toString().split("vlan:\\/\\/");
networkVlanId = vlan[1];
// For pvlan
if (network.getBroadcastDomainType() != BroadcastDomainType.Vlan) {
networkVlanId = networkVlanId.split("-")[0];
}
}
}
if (vlanId != null && !connectivityWithoutVlan) {
// if vlan is specified, throw an error if it's not equal to
// network's vlanId
if (networkVlanId != null && !NetUtils.isSameIsolationId(networkVlanId, vlanId)) {
throw new InvalidParameterValueException("Vlan doesn't match vlan of the network");
}
} else {
vlanId = networkVlanId;
}
} else if (network.getTrafficType() == TrafficType.Public && vlanId == null && !forNsx) {
throw new InvalidParameterValueException("Unable to determine vlan id or untagged vlan for public network");
}
if (vlanId == null && !forNsx) {
vlanId = Vlan.UNTAGGED;
}
final VlanType vlanType = forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
if ((domain != null || vlanOwner != null) && zone.getNetworkType() != NetworkType.Advanced) {
throw new InvalidParameterValueException("Vlan owner can be defined only in the zone of type " + NetworkType.Advanced);
}
if (ipv4) {
// Make sure the gateway is valid
if (!NetUtils.isValidIp4(vlanGateway)) {
throw new InvalidParameterValueException("Please specify a valid gateway");
}
// Make sure the netmask is valid
if (!NetUtils.isValidIp4Netmask(vlanNetmask)) {
throw new InvalidParameterValueException("Please specify a valid netmask");
}
}
if (ipv6) {
if (!NetUtils.isValidIp6(vlanIp6Gateway)) {
throw new InvalidParameterValueException("Please specify a valid IPv6 gateway");
}
if (!NetUtils.isValidIp6Cidr(vlanIp6Cidr)) {
throw new InvalidParameterValueException("Please specify a valid IPv6 CIDR");
}
}
boolean isSharedNetworkWithoutSpecifyVlan = _networkMgr.isSharedNetworkWithoutSpecifyVlan(_networkOfferingDao.findById(network.getNetworkOfferingId()));
if (ipv4) {
final String newCidr = NetUtils.getCidrFromGatewayAndNetmask(vlanGateway, vlanNetmask);
//Make sure start and end ips are with in the range of cidr calculated for this gateway and netmask {
if (!NetUtils.isIpWithInCidrRange(vlanGateway, newCidr) || !NetUtils.isIpWithInCidrRange(startIP, newCidr) || !NetUtils.isIpWithInCidrRange(endIP, newCidr)) {
throw new InvalidParameterValueException("Please specify a valid IP range or valid netmask or valid gateway");
}
// Check if the new VLAN's subnet conflicts with the guest network
// in
// the specified zone (guestCidr is null for basic zone)
// when adding shared network with same cidr of zone guest cidr,
// if the specified vlan is not present in zone, physical network, allow to create the network as the isolation is based on VLAN.
final String guestNetworkCidr = zone.getGuestNetworkCidr();
if (guestNetworkCidr != null && NetUtils.isNetworksOverlap(newCidr, guestNetworkCidr) && _zoneDao.findVnet(zoneId, physicalNetworkId, vlanId).isEmpty() != true) {
throw new InvalidParameterValueException("The new IP range you have specified has overlapped with the guest network in zone: " + zone.getName()
+ "along with existing Vlan also. Please specify a different gateway/netmask");
}
// Check if there are any errors with the IP range
checkPublicIpRangeErrors(zoneId, vlanId, vlanGateway, vlanNetmask, startIP, endIP);
checkConflictsWithPortableIpRange(zoneId, vlanId, vlanGateway, vlanNetmask, startIP, endIP);
if (!isSharedNetworkWithoutSpecifyVlan) {
checkZoneVlanIpOverlap(zone, network, newCidr, vlanId, vlanGateway, vlanNetmask, startIP, endIP);
}
}
String ipv6Range = null;
if (ipv6) {
ipv6Range = startIPv6;
if (StringUtils.isNotEmpty(ipv6Range) && StringUtils.isNotEmpty(endIPv6)) {
ipv6Range += "-" + endIPv6;
}
final List<VlanVO> vlans = _vlanDao.listByZone(zone.getId());
for (final VlanVO vlan : vlans) {
if (vlan.getIp6Gateway() == null) {
continue;
}
if ((StringUtils.isAllEmpty(ipv6Range, vlan.getIp6Range())) &&
NetUtils.ipv6NetworksOverlap(IPv6Network.fromString(vlanIp6Cidr), IPv6Network.fromString(vlan.getIp6Cidr()))) {
throw new InvalidParameterValueException(String.format("The IPv6 range with tag: %s already has IPs that overlap with the new range.",
vlan.getVlanTag()));
}
if (!StringUtils.isAllEmpty(ipv6Range, vlan.getIp6Range())) {
String r1 = StringUtils.isEmpty(ipv6Range) ? NetUtils.getIpv6RangeFromCidr(vlanIp6Cidr) : ipv6Range;
String r2 = StringUtils.isEmpty(vlan.getIp6Range()) ? NetUtils.getIpv6RangeFromCidr(vlan.getIp6Cidr()) : vlan.getIp6Range();
if(NetUtils.isIp6RangeOverlap(r1, r2)) {
throw new InvalidParameterValueException(String.format("The IPv6 range with tag: %s already has IPs that overlap with the new range.",
vlan.getVlanTag()));
}
}
if (NetUtils.isSameIsolationId(vlanId, vlan.getVlanTag()) && !vlanIp6Gateway.equals(vlan.getIp6Gateway())) {
throw new InvalidParameterValueException(String.format("The IP range with tag: %s has already been added with gateway %s. Please specify a different tag.",
vlan.getVlanTag(), vlan.getIp6Gateway()));
}
}
}
// Check if the vlan is being used
if (isSharedNetworkWithoutSpecifyVlan) {
bypassVlanOverlapCheck = true;
}
if (!bypassVlanOverlapCheck && !forNsx && !_zoneDao.findVnet(zoneId, physicalNetworkId, BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlanId))).isEmpty()) {
throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone "
+ zone.getName());
}
String ipRange = null;
if (ipv4) {
ipRange = startIP;
if (endIP != null) {
ipRange += "-" + endIP;
}
}
// Everything was fine, so persist the VLAN
final VlanVO vlan = commitVlanAndIpRange(zoneId, networkId, physicalNetworkId, podId, startIP, endIP, vlanGateway, vlanNetmask, vlanId, domain, vlanOwner, vlanIp6Gateway, vlanIp6Cidr,
ipv4, zone, vlanType, ipv6Range, ipRange, forSystemVms, forNsx);
return vlan;
}