re-merge optional public IP for EIP service feature

Squashed commit of the following:

commit 2dae394a42a364cd93a11b2c2f74b274b7c43315
Author: Murali Reddy <murali.reddy@citrix.com>
Date:   Tue Apr 16 17:35:28 2013 +0530

    CLOUDSTACK-265: provide option to turn-off automatic public IP association
    for each VM when using EIP service.

      - introduces Capability in the network offering, which decides when EIP
        service is used, by defualt public IP should be assigned to the VM or not

      - default network offering with EIP/ELB service will still work with old
        EIP semantics, i.e) assign a public IP to each VM on start
This commit is contained in:
Murali Reddy 2013-04-16 17:45:27 +05:30
parent 574e716352
commit 90e8158db5
9 changed files with 98 additions and 32 deletions

View File

@ -16,24 +16,11 @@
// under the License.
package com.cloud.network;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.utils.fsm.StateObject;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@ -183,6 +170,7 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
public static final Capability AllowDnsSuffixModification = new Capability("AllowDnsSuffixModification");
public static final Capability RedundantRouter = new Capability("RedundantRouter");
public static final Capability ElasticIp = new Capability("ElasticIp");
public static final Capability AssociatePublicIP = new Capability("AssociatePublicIP");
public static final Capability ElasticLb = new Capability("ElasticLb");
public static final Capability AutoScaleCounters = new Capability("AutoScaleCounters");
public static final Capability InlineMode = new Capability("InlineMode");

View File

@ -107,6 +107,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
boolean getElasticIp();
boolean getAssociatePublicIP();
boolean getElasticLb();
boolean getSpecifyIpRanges();

View File

@ -3433,20 +3433,34 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
void validateStaticNatServiceCapablities(Map<Capability, String> staticNatServiceCapabilityMap) {
if (staticNatServiceCapabilityMap != null && !staticNatServiceCapabilityMap.isEmpty()) {
if (staticNatServiceCapabilityMap.keySet().size() > 1) {
throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " capability can be specified for static nat service");
if (staticNatServiceCapabilityMap.keySet().size() > 2) {
throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service");
}
boolean eipEnabled = false;
boolean eipDisabled = false;
boolean associatePublicIP = true;
for (Capability capability : staticNatServiceCapabilityMap.keySet()) {
String value = staticNatServiceCapabilityMap.get(capability);
if (capability == Capability.ElasticIp) {
boolean enabled = value.contains("true");
boolean disabled = value.contains("false");
if (!enabled && !disabled) {
eipEnabled = value.contains("true");
eipDisabled = value.contains("false");
if (!eipEnabled && !eipDisabled) {
throw new InvalidParameterValueException("Unknown specified value for " + Capability.ElasticIp.getName());
}
} else if (capability == Capability.AssociatePublicIP) {
if (value.contains("true")) {
associatePublicIP = true;
} else if (value.contains("false")) {
associatePublicIP = false;
} else {
throw new InvalidParameterValueException("Unknown specified value for " + Capability.AssociatePublicIP.getName());
}
} else {
throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " capability can be specified for static nat service");
throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service");
}
if (eipDisabled && associatePublicIP) {
throw new InvalidParameterValueException("Capability " + Capability.AssociatePublicIP.getName() + " can only be set when capability " + Capability.ElasticIp.getName() + " is true");
}
}
}
@ -3508,6 +3522,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
boolean sharedSourceNat = false;
boolean redundantRouter = false;
boolean elasticIp = false;
boolean associatePublicIp = false;
boolean inline = false;
if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) {
Map<Capability, String> lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb);
@ -3557,13 +3572,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
String param = staticNatServiceCapabilityMap.get(Capability.ElasticIp);
if (param != null) {
elasticIp = param.contains("true");
String associatePublicIP = staticNatServiceCapabilityMap.get(Capability.AssociatePublicIP);
if (associatePublicIP != null) {
associatePublicIp = associatePublicIP.contains("true");
}
}
}
}
NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan,
networkRate, multicastRate, isDefault, availability, tags, type, conserveMode, dedicatedLb,
sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent);
sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp);
if (serviceOfferingId != null) {
offering.setServiceOfferingId(serviceOfferingId);

View File

@ -1215,11 +1215,13 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
Network guestNetwork = _networkModel.getNetwork(ipAddress.getAssociatedWithNetworkId());
NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
if (offering.getElasticIp()) {
getSystemIpAndEnableStaticNatForVm(_vmDao.findById(vmId), true);
return true;
} else {
return disableStaticNat(ipId, caller, ctx.getCallerUserId(), false);
if (offering.getAssociatePublicIP()) {
getSystemIpAndEnableStaticNatForVm(_vmDao.findById(vmId), true);
return true;
}
}
return disableStaticNat(ipId, caller, ctx.getCallerUserId(), false);
}
@Override
@ -1410,6 +1412,11 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
Network guestNetwork = _networkModel.getNetwork(nic.getNetworkId());
NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
if (offering.getElasticIp()) {
boolean isSystemVM = (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm);
// for user VM's associate public IP only if offering is marked to associate a public IP by default on start of VM
if (!isSystemVM && !offering.getAssociatePublicIP()) {
continue;
}
// check if there is already static nat enabled
if (_ipAddressDao.findByAssociatedVmId(vm.getId()) != null && !getNewIp) {
s_logger.debug("Vm " + vm + " already has ip associated with it in guest network " + guestNetwork);
@ -1424,7 +1431,6 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
s_logger.debug("Allocated system ip " + ip + ", now enabling static nat on it for vm " + vm);
boolean isSystemVM = (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm);
try {
success = enableStaticNat(ip.getId(), vm.getId(), guestNetwork.getId(), isSystemVM, null);
} catch (NetworkRuleConflictException ex) {

View File

@ -110,6 +110,9 @@ public class NetworkOfferingVO implements NetworkOffering {
@Column(name = "elastic_ip_service")
boolean elasticIp;
@Column(name = "eip_associate_public_ip")
boolean eipAssociatePublicIp;
@Column(name = "elastic_lb_service")
boolean elasticLb;
@ -278,6 +281,7 @@ public class NetworkOfferingVO implements NetworkOffering {
this.sharedSourceNat = false;
this.redundantRouter = false;
this.elasticIp = false;
this.eipAssociatePublicIp = true;
this.elasticLb = false;
this.inline = false;
this.specifyIpRanges = specifyIpRanges;
@ -286,7 +290,7 @@ public class NetworkOfferingVO implements NetworkOffering {
public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, boolean isDefault,
Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb, boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb,
boolean specifyIpRanges, boolean inline, boolean isPersistent) {
boolean specifyIpRanges, boolean inline, boolean isPersistent, boolean associatePublicIP) {
this(name, displayText, trafficType, systemOnly, specifyVlan, rateMbps, multicastRateMbps, isDefault, availability, tags, guestType, conserveMode, specifyIpRanges, isPersistent);
this.dedicatedLB = dedicatedLb;
this.sharedSourceNat = sharedSourceNat;
@ -294,6 +298,7 @@ public class NetworkOfferingVO implements NetworkOffering {
this.elasticIp = elasticIp;
this.elasticLb = elasticLb;
this.inline = inline;
this.eipAssociatePublicIp = associatePublicIP;
}
public NetworkOfferingVO() {
@ -355,6 +360,11 @@ public class NetworkOfferingVO implements NetworkOffering {
return elasticIp;
}
@Override
public boolean getAssociatePublicIP() {
return eipAssociatePublicIp;
}
@Override
public boolean getElasticLb() {
return elasticLb;

View File

@ -1008,7 +1008,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
"Offering for Shared networks with Elastic IP and Elastic LB capabilities",
TrafficType.Guest,
false, true, null, null, true, Availability.Optional,
null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false);
null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true);
defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled);
defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering);

View File

@ -17,6 +17,10 @@
package com.cloud.upgrade.dao;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import org.apache.log4j.Logger;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
@ -24,11 +28,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
import org.apache.log4j.Logger;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
public class Upgrade410to420 implements DbUpgrade {
final static Logger s_logger = Logger.getLogger(Upgrade410to420.class);
@ -66,6 +65,7 @@ public class Upgrade410to420 implements DbUpgrade {
updateCluster_details(conn);
updatePrimaryStore(conn);
addEgressFwRulesForSRXGuestNw(conn);
upgradeEIPNetworkOfferings(conn);
}
private void updateSystemVmTemplates(Connection conn) {
@ -365,4 +365,38 @@ public class Upgrade410to420 implements DbUpgrade {
}
}
}
private void upgradeEIPNetworkOfferings(Connection conn) {
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement("select id, elastic_ip_service from `cloud`.`network_offerings` where traffic_type='Guest'");
rs = pstmt.executeQuery();
while (rs.next()) {
long id = rs.getLong(1);
// check if elastic IP service is enabled for network offering
if (rs.getLong(2) != 0) {
//update network offering with eip_associate_public_ip set to true
pstmt = conn.prepareStatement("UPDATE `cloud`.`network_offerings` set eip_associate_public_ip=? where id=?");
pstmt.setBoolean(1, true);
pstmt.setLong(2, id);
pstmt.executeUpdate();
}
}
} catch (SQLException e) {
throw new CloudRuntimeException("Unable to set elastic_ip_service for network offerings with EIP service enabled.", e);
} finally {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
}
}
}
}

View File

@ -2890,6 +2890,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
if (ip != null && ip.getSystem()) {
UserContext ctx = UserContext.current();
try {
long networkId = ip.getAssociatedWithNetworkId();
Network guestNetwork = _networkDao.findById(networkId);
NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId());
assert (offering.getAssociatePublicIP() == true) : "User VM should not have system owned public IP associated with it when offering configured not to associate public IP.";
_rulesMgr.disableStaticNat(ip.getId(), ctx.getCaller(), ctx.getCallerUserId(), true);
} catch (Exception ex) {
s_logger.warn(

View File

@ -715,6 +715,9 @@ CREATE TABLE `cloud`.`network_asa1000v_map` (
CONSTRAINT `fk_network_asa1000v_map__asa1000v_id` FOREIGN KEY (`asa1000v_id`) REFERENCES `external_cisco_asa1000v_devices`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `eip_associate_public_ip` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if public IP is associated with user VM creation by default when EIP service is enabled.' AFTER `elastic_ip_service`;
-- Re-enable foreign key checking, at the end of the upgrade path
SET foreign_key_checks = 1;