Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api/src/main/java/com/cloud/network/vpc/VpcOffering.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,6 @@ public enum State {
NetworkOffering.RoutingMode getRoutingMode();

Boolean isSpecifyAsNumber();

boolean isConserveMode();
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ VpcOffering createVpcOffering(String name, String displayText, List<String> supp
Map serviceCapabilitystList, NetUtils.InternetProtocol internetProtocol,
Long serviceOfferingId, String externalProvider, NetworkOffering.NetworkMode networkMode,
List<Long> domainIds, List<Long> zoneIds, VpcOffering.State state,
NetworkOffering.RoutingMode routingMode, boolean specifyAsNumber);
NetworkOffering.RoutingMode routingMode, boolean specifyAsNumber, boolean conserveMode);


Pair<List<? extends VpcOffering>,Integer> listVpcOfferings(ListVPCOfferingsCmd cmd);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,7 @@ public class ApiConstants {
public static final String REGION_ID = "regionid";
public static final String VPC_OFF_ID = "vpcofferingid";
public static final String VPC_OFF_NAME = "vpcofferingname";
public static final String VPC_OFFERING_CONSERVE_MODE = "vpcofferingconservemode";
public static final String NETWORK = "network";
public static final String VPC_ID = "vpcid";
public static final String VPC_NAME = "vpcname";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd {
description = "the routing mode for the VPC offering. Supported types are: Static or Dynamic.")
private String routingMode;

@Parameter(name = ApiConstants.CONSERVE_MODE, type = CommandType.BOOLEAN,
since = "4.23.0",
description = "True if the VPC offering is IP conserve mode enabled, allowing public IP services to be used across multiple VPC tiers")
private Boolean conserveMode;


/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -311,6 +317,10 @@ public String getRoutingMode() {
return routingMode;
}

public boolean isConserveMode() {
return BooleanUtils.toBoolean(conserveMode);
}

@Override
public void create() throws ResourceAllocationException {
VpcOffering vpcOff = _vpcProvSvc.createVpcOffering(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ public long getNetworkId() {
IpAddress ip = _entityMgr.findById(IpAddress.class, getIpAddressId());
Long ntwkId = null;

if (ip.getAssociatedWithNetworkId() != null) {
if (ip.getVpcId() == null && ip.getAssociatedWithNetworkId() != null) {
ntwkId = ip.getAssociatedWithNetworkId();
} else {
ntwkId = networkId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ public class VpcOfferingResponse extends BaseResponse {
@Param(description = "The routing mode for the network offering, supported types are Static or Dynamic.")
private String routingMode;

@SerializedName(ApiConstants.CONSERVE_MODE)
@Param(description = "True if the VPC offering is IP conserve mode enabled, allowing public IP services to be used across multiple VPC tiers.")
private Boolean conserveMode;

public void setId(String id) {
this.id = id;
}
Expand Down Expand Up @@ -201,4 +205,12 @@ public String getRoutingMode() {
public void setRoutingMode(String routingMode) {
this.routingMode = routingMode;
}

public Boolean getConserveMode() {
return conserveMode;
}

public void setConserveMode(Boolean conserveMode) {
this.conserveMode = conserveMode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ public class VpcResponse extends BaseResponseWithAnnotations implements Controll
@Param(description = "VPC offering name the VPC is created from", since = "4.13.2")
private String vpcOfferingName;

@SerializedName(ApiConstants.VPC_OFFERING_CONSERVE_MODE)
@Param(description = "true if VPC offering is ip conserve mode enabled", since = "4.23")
private Boolean vpcOfferingConserveMode;

@SerializedName(ApiConstants.CREATED)
@Param(description = "The date this VPC was created")
private Date created;
Expand Down Expand Up @@ -197,6 +201,10 @@ public void setDisplayText(final String displayText) {
this.displayText = displayText;
}

public void setVpcOfferingConserveMode(Boolean vpcOfferingConserveMode) {
this.vpcOfferingConserveMode = vpcOfferingConserveMode;
}

public void setCreated(final Date created) {
this.created = created;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
public interface LoadBalancingRulesManager {

LoadBalancer createPublicLoadBalancer(String xId, String name, String description, int srcPort, int destPort, long sourceIpId, String protocol, String algorithm,
boolean openFirewall, CallContext caller, String lbProtocol, Boolean forDisplay, String cidrList) throws NetworkRuleConflictException;
boolean openFirewall, CallContext caller, String lbProtocol, Boolean forDisplay, String cidrList, Long networkId) throws NetworkRuleConflictException;

boolean removeAllLoadBalanacersForIp(long ipId, Account caller, long callerUserId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public class VpcOfferingVO implements VpcOffering {
@Column(name = "specify_as_number")
private Boolean specifyAsNumber = false;

@Column(name = "conserve_mode")
private boolean conserveMode;

public VpcOfferingVO() {
this.uuid = UUID.randomUUID().toString();
}
Expand Down Expand Up @@ -242,4 +245,13 @@ public Boolean isSpecifyAsNumber() {
public void setSpecifyAsNumber(Boolean specifyAsNumber) {
this.specifyAsNumber = specifyAsNumber;
}

@Override
public boolean isConserveMode() {
return conserveMode;
}

public void setConserveMode(boolean conserveMode) {
this.conserveMode = conserveMode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@ CREATE TABLE IF NOT EXISTS `cloud`.`webhook_filter` (
INDEX `i_webhook_filter__webhook_id`(`webhook_id`),
CONSTRAINT `fk_webhook_filter__webhook_id` FOREIGN KEY(`webhook_id`) REFERENCES `webhook`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Add conserve mode for VPC offerings
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','conserve_mode', 'tinyint(1) unsigned NULL DEFAULT 0 COMMENT ''True if the VPC offering is IP conserve mode enabled, allowing public IP services to be used across multiple VPC tiers'' ');
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ select
`vpc_offerings`.`sort_key` AS `sort_key`,
`vpc_offerings`.`routing_mode` AS `routing_mode`,
`vpc_offerings`.`specify_as_number` AS `specify_as_number`,
`vpc_offerings`.`conserve_mode` AS `conserve_mode`,
group_concat(distinct `domain`.`id` separator ',') AS `domain_id`,
group_concat(distinct `domain`.`uuid` separator ',') AS `domain_uuid`,
group_concat(distinct `domain`.`name` separator ',') AS `domain_name`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ private LoadBalancer handleCreateLoadBalancerRuleWithLock(final CreateLoadBalanc
lb.setSourceIpAddressId(ipId);

result = _lbMgr.createPublicLoadBalancer(lb.getXid(), lb.getName(), lb.getDescription(), lb.getSourcePortStart(), lb.getDefaultPortStart(), ipId.longValue(),
lb.getProtocol(), lb.getAlgorithm(), false, CallContext.current(), lb.getLbProtocol(), true, null);
lb.getProtocol(), lb.getAlgorithm(), false, CallContext.current(), lb.getLbProtocol(), true, null, networkId);
} catch (final NetworkRuleConflictException e) {
logger.warn("Failed to create LB rule, not continuing with ELB deployment");
if (newIp) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ private VpcOffering locateVpcOffering() {
}
serviceProviderMap.put(svc, providerSet);
}
vpcOffer = _vpcProvSvc.createVpcOffering(juniperVPCOfferingName, juniperVPCOfferingDisplayText, services, serviceProviderMap, null, null, null, null, null, null, null, VpcOffering.State.Enabled, null, false);
vpcOffer = _vpcProvSvc.createVpcOffering(juniperVPCOfferingName, juniperVPCOfferingDisplayText, services, serviceProviderMap, null, null, null, null, null, null, null, VpcOffering.State.Enabled, null, false, false);
long id = vpcOffer.getId();
_vpcOffDao.update(id, (VpcOfferingVO)vpcOffer);
return _vpcOffDao.findById(id);
Expand Down
1 change: 1 addition & 0 deletions server/src/main/java/com/cloud/api/ApiResponseHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -3499,6 +3499,7 @@ public VpcResponse createVpcResponse(ResponseView view, Vpc vpc) {
if (voff != null) {
response.setVpcOfferingId(voff.getUuid());
response.setVpcOfferingName(voff.getName());
response.setVpcOfferingConserveMode(voff.isConserveMode());
}
response.setCidr(vpc.getCidr());
response.setRestartRequired(vpc.isRestartRequired());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public VpcOfferingResponse newVpcOfferingResponse(VpcOffering offering) {
if (offering.isSpecifyAsNumber() != null) {
offeringResponse.setSpecifyAsNumber(offering.isSpecifyAsNumber());
}
offeringResponse.setConserveMode(offering.isConserveMode());
if (offering instanceof VpcOfferingJoinVO) {
VpcOfferingJoinVO offeringJoinVO = (VpcOfferingJoinVO) offering;
offeringResponse.setDomainId(offeringJoinVO.getDomainUuid());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ public class VpcOfferingJoinVO implements VpcOffering {
@Column(name = "specify_as_number")
private Boolean specifyAsNumber = false;

@Column(name = "conserve_mode")
private boolean conserveMode;

public VpcOfferingJoinVO() {
}

Expand Down Expand Up @@ -178,6 +181,11 @@ public Boolean isSpecifyAsNumber() {
return specifyAsNumber;
}

@Override
public boolean isConserveMode() {
return conserveMode;
}

public void setSpecifyAsNumber(Boolean specifyAsNumber) {
this.specifyAsNumber = specifyAsNumber;
}
Expand Down
14 changes: 13 additions & 1 deletion server/src/main/java/com/cloud/network/IpAddressManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,14 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
return ipaddr;
}

protected IPAddressVO getExistingSourceNatInVPC(Long vpcId) {
List<IPAddressVO> ips = _ipAddressDao.listByAssociatedVpc(vpcId, true);
if (CollectionUtils.isEmpty(ips)) {
return null;
}
return ips.get(0);
}

protected IPAddressVO getExistingSourceNatInNetwork(long ownerId, Long networkId) {
List<? extends IpAddress> addrs;
Network guestNetwork = _networksDao.findById(networkId);
Expand Down Expand Up @@ -1723,7 +1731,11 @@ protected boolean isSourceNatAvailableForNetwork(Account owner, IPAddressVO ipTo
NetworkOffering offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
boolean sharedSourceNat = offering.isSharedSourceNat();
boolean isSourceNat = false;
if (!sharedSourceNat) {
if (network.getVpcId() != null) {
// For VPCs: Check if the VPC Source NAT IP address is the same we are associating
IPAddressVO vpcSourceNatIpAddress = getExistingSourceNatInVPC(network.getVpcId());
isSourceNat = vpcSourceNatIpAddress != null && vpcSourceNatIpAddress.getId() == ipToAssoc.getId();
} else if (!sharedSourceNat) {
if (getExistingSourceNatInNetwork(owner.getId(), network.getId()) == null) {
if (network.getGuestType() == GuestType.Isolated && network.getVpcId() == null && !ipToAssoc.isPortable()) {
isSourceNat = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import javax.inject.Inject;
import javax.naming.ConfigurationException;

import com.cloud.network.vpc.VpcOfferingVO;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;

Expand Down Expand Up @@ -159,6 +161,8 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
IpAddressManager _ipAddrMgr;
@Inject
RoutedIpv4Manager routedIpv4Manager;
@Inject
VpcOfferingDao vpcOfferingDao;

private boolean _elbEnabled = false;
static Boolean rulesContinueOnErrFlag = true;
Expand Down Expand Up @@ -395,6 +399,17 @@ public void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflict
assert (rules.size() >= 1);
}

NetworkVO newRuleNetwork = _networkDao.findById(newRule.getNetworkId());
if (newRuleNetwork == null) {
throw new InvalidParameterValueException("Unable to create firewall rule as cannot find network by id=" + newRule.getNetworkId());
}
boolean isNewRuleOnVpcNetwork = newRuleNetwork.getVpcId() != null;
boolean isVpcConserveModeEnabled = false;
if (isNewRuleOnVpcNetwork) {
VpcOfferingVO vpcOffering = vpcOfferingDao.findById(newRuleNetwork.getVpcId());
isVpcConserveModeEnabled = vpcOffering != null && vpcOffering.isConserveMode();
}

for (FirewallRuleVO rule : rules) {
if (rule.getId() == newRule.getId()) {
continue; // Skips my own rule.
Expand Down Expand Up @@ -443,8 +458,14 @@ public void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflict
}

// Checking if the rule applied is to the same network that is passed in the rule.
if (rule.getNetworkId() != newRule.getNetworkId() && rule.getState() != State.Revoke) {
throw new NetworkRuleConflictException("New rule is for a different network than what's specified in rule " + rule.getXid());
// (except for VPCs with conserve mode = true)
if ((!isNewRuleOnVpcNetwork || !isVpcConserveModeEnabled)
&& rule.getNetworkId() != newRule.getNetworkId() && rule.getState() != State.Revoke) {
String errMsg = String.format("New rule is for a different network than what's specified in rule %s", rule.getXid());
if (isNewRuleOnVpcNetwork) {
errMsg += String.format(" - VPC id=%s is not using conserve mode", newRuleNetwork.getVpcId());
}
throw new NetworkRuleConflictException(errMsg);
}

//Check for the ICMP protocol. This has to be done separately from other protocols as we need to check the ICMP codes and ICMP type also.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1761,7 +1761,7 @@ public LoadBalancer createPublicLoadBalancerRule(String xId, String name, String
}

result = createPublicLoadBalancer(xId, name, description, srcPortStart, defPortStart, ipVO.getId(), protocol, algorithm, openFirewall, CallContext.current(),
lbProtocol, forDisplay, cidrString);
lbProtocol, forDisplay, cidrString, networkId);
} catch (Exception ex) {
logger.warn("Failed to create load balancer due to ", ex);
if (ex instanceof NetworkRuleConflictException) {
Expand Down Expand Up @@ -1824,7 +1824,7 @@ private String validateCidr(String cidr) {
@Override
public LoadBalancer createPublicLoadBalancer(final String xId, final String name, final String description, final int srcPort, final int destPort, final long sourceIpId,
final String protocol, final String algorithm, final boolean openFirewall, final CallContext caller, final String lbProtocol,
final Boolean forDisplay, String cidrList) throws NetworkRuleConflictException {
final Boolean forDisplay, String cidrList, Long networkIdParam) throws NetworkRuleConflictException {
if (!NetUtils.isValidPort(destPort)) {
throw new InvalidParameterValueException("privatePort is an invalid value: " + destPort);
}
Expand Down Expand Up @@ -1853,7 +1853,7 @@ public LoadBalancer createPublicLoadBalancer(final String xId, final String name

_accountMgr.checkAccess(caller.getCallingAccount(), null, true, ipAddr);

final Long networkId = ipAddr.getAssociatedWithNetworkId();
final Long networkId = ipAddr.getVpcId() == null ? ipAddr.getAssociatedWithNetworkId() : networkIdParam;
if (networkId == null) {
InvalidParameterValueException ex =
new InvalidParameterValueException("Unable to create load balancer rule ; specified sourceip id is not associated with any network");
Expand Down
Loading
Loading