bug CS-14862: EIP/ELB - SSVM and CPVM should be given an ip address from the public ip address range.

With this fix  both SSVM and CPVM will get public IP's in case of basic zone with EIP service.
A static NAT rule is implicitly configured on the EIP service provider to map public IP to a
guest IP address associated with SSVM/CPVM
This commit is contained in:
Murali reddy 2012-05-21 20:08:46 +05:30
parent ed0b98ee75
commit a4b0759c52
10 changed files with 119 additions and 36 deletions

View File

@ -168,7 +168,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
@Override
public void create() throws ResourceAllocationException{
try {
IpAddress ip = _networkService.allocateIP(getNetworkId(), _accountService.getAccount(getEntityOwnerId()), false);
IpAddress ip = _networkService.allocateIP(getNetworkId(), _accountService.getAccount(getEntityOwnerId()));
if (ip != null) {
this.setEntityId(ip.getId());
} else {

View File

@ -78,7 +78,7 @@ public class EnableStaticNatCmd extends BaseCmd{
@Override
public void execute() throws ResourceUnavailableException{
try {
boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId);
boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId, false);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);

View File

@ -37,7 +37,7 @@ public interface NetworkService {
List<? extends Network> getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner);
IpAddress allocateIP(long networkId, Account ipOwner, boolean isSystem) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException;
IpAddress allocateIP(long networkId, Account ipOwner) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException;
/**
* Associates a public IP address for a router.

View File

@ -60,7 +60,7 @@ public interface RulesService {
boolean applyPortForwardingRules(long ipAdddressId, Account caller) throws ResourceUnavailableException;
boolean enableStaticNat(long ipAddressId, long vmId) throws NetworkRuleConflictException, ResourceUnavailableException;
boolean enableStaticNat(long ipAddressId, long vmId, boolean isSystemVm) throws NetworkRuleConflictException, ResourceUnavailableException;
PortForwardingRule getPortForwardigRule(long ruleId);

View File

@ -81,10 +81,13 @@ import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo;
import com.cloud.keystore.KeystoreDao;
import com.cloud.keystore.KeystoreManager;
import com.cloud.keystore.KeystoreVO;
import com.cloud.network.IPAddressVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.rules.RulesManager;
import com.cloud.offering.ServiceOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
@ -108,6 +111,7 @@ import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.User;
import com.cloud.user.UserContext;
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@ -129,6 +133,7 @@ import com.cloud.uuididentity.dao.IdentityDao;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.SystemVmLoadScanHandler;
import com.cloud.vm.SystemVmLoadScanner;
import com.cloud.vm.SystemVmLoadScanner.AfterScanAction;
@ -214,7 +219,11 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
IdentityDao _identityDao;
@Inject
NetworkDao _networkDao;
@Inject
RulesManager _rulesMgr;
@Inject
IPAddressDao _ipAddressDao;
private ConsoleProxyListener _listener;
private ServiceOfferingVO _serviceOffering;
@ -1677,6 +1686,21 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
return false;
}
try {
//get system ip and create static nat rule for the vm in case of basic networking with EIP/ELB
_rulesMgr.getSystemIpAndEnableStaticNatForVm(profile.getVirtualMachine(), false);
IPAddressVO ipaddr = _ipAddressDao.findByAssociatedVmId(profile.getVirtualMachine().getId());
if (ipaddr != null && ipaddr.getSystem()) {
ConsoleProxyVO consoleVm = profile.getVirtualMachine();
// override CPVM guest IP with EIP, so that console url's will be prepared with EIP
consoleVm.setPublicIpAddress(ipaddr.getAddress().addr());
_consoleProxyDao.update(consoleVm.getId(), consoleVm);
}
} catch (Exception ex) {
s_logger.warn("Failed to get system ip and enable static nat for the vm " + profile.getVirtualMachine() + " due to exception ", ex);
return false;
}
return true;
}
@ -1757,6 +1781,16 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
@Override
public void finalizeStop(VirtualMachineProfile<ConsoleProxyVO> profile, StopAnswer answer) {
//release elastic IP here if assigned
IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(profile.getId());
if (ip != null && ip.getSystem()) {
UserContext ctx = UserContext.current();
try {
_rulesMgr.disableStaticNat(ip.getId(), ctx.getCaller(), ctx.getCallerUserId(), true);
} catch (Exception ex) {
s_logger.warn("Failed to disable static nat and release system ip " + ip + " as a part of vm " + profile.getVirtualMachine() + " stop due to exception ", ex);
}
}
}
@Override

View File

@ -972,8 +972,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true)
public IpAddress allocateIP(long networkId, Account ipOwner) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
return allocateIP(networkId, ipOwner, false);
}
@DB
public IpAddress allocateIP(long networkId, Account ipOwner, boolean isSystem) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
Account caller = UserContext.current().getCaller();
long userId = UserContext.current().getCallerUserId();
@ -1080,9 +1084,13 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "associating Ip", async = true)
public IpAddress associateIP(long ipId) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException {
return associateIP(ipId, false);
}
@DB
private IpAddress associateIP(long ipId, boolean isSystem) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException {
Account caller = UserContext.current().getCaller();
Account owner = null;

View File

@ -20,6 +20,7 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.vm.VirtualMachine;
/**
* Rules Manager manages the network rules created for different networks.
@ -69,7 +70,7 @@ public interface RulesManager extends RulesService {
boolean applyStaticNatsForNetwork(long networkId, boolean continueOnError, Account caller);
void getSystemIpAndEnableStaticNatForVm(UserVm vm, boolean getNewIp) throws InsufficientAddressCapacityException;
void getSystemIpAndEnableStaticNatForVm(VirtualMachine vm, boolean getNewIp) throws InsufficientAddressCapacityException;
boolean disableStaticNat(long ipAddressId, Account caller, long callerUserId, boolean releaseIpIfElastic) throws ResourceUnavailableException;

View File

@ -69,6 +69,7 @@ import com.cloud.utils.AnnotationHelper;
import com.cloud.vm.Nic;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@ -322,23 +323,24 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
@Override
public boolean enableStaticNat(long ipId, long vmId) throws NetworkRuleConflictException, ResourceUnavailableException {
public boolean enableStaticNat(long ipId, long vmId, boolean isSystemVm) throws NetworkRuleConflictException, ResourceUnavailableException {
UserContext ctx = UserContext.current();
Account caller = ctx.getCaller();
// Verify input parameters
UserVmVO vm = _vmDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("Can't enable static nat for the address id=" + ipId + ", invalid virtual machine id specified (" + vmId + ").");
}
IPAddressVO ipAddress = _ipAddressDao.findById(ipId);
if (ipAddress == null) {
throw new InvalidParameterValueException("Unable to find ip address by id " + ipId);
}
// Check permissions
checkIpAndUserVm(ipAddress, vm, caller);
// Verify input parameters
if (!isSystemVm) {
UserVmVO vm = _vmDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("Can't enable static nat for the address id=" + ipId + ", invalid virtual machine id specified (" + vmId + ").");
}
// Check permissions
checkIpAndUserVm(ipAddress, vm, caller);
}
// Verify that the ip is associated with the network and static nat service is supported for the network
Long networkId = ipAddress.getAssociatedWithNetworkId();
@ -1188,7 +1190,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
@Override
public void getSystemIpAndEnableStaticNatForVm(UserVm vm, boolean getNewIp) throws InsufficientAddressCapacityException {
public void getSystemIpAndEnableStaticNatForVm(VirtualMachine vm, boolean getNewIp) throws InsufficientAddressCapacityException {
boolean success = true;
// enable static nat if eIp capability is supported
@ -1212,8 +1214,9 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
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());
success = enableStaticNat(ip.getId(), vm.getId(), isSystemVM);
} catch (NetworkRuleConflictException ex) {
s_logger.warn("Failed to enable static nat as a part of enabling elasticIp and staticNat for vm " + vm + " in guest network " + guestNetwork + " due to exception ", ex);
success = false;

View File

@ -68,10 +68,13 @@ import com.cloud.info.RunningHostCountInfo;
import com.cloud.info.RunningHostInfoAgregator;
import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo;
import com.cloud.keystore.KeystoreManager;
import com.cloud.network.IPAddressVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.rules.RulesManager;
import com.cloud.offering.ServiceOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
@ -96,6 +99,7 @@ import com.cloud.storage.template.TemplateConstants;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.User;
import com.cloud.user.UserContext;
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@ -215,8 +219,11 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
NetworkDao _networkDao;
@Inject
NetworkOfferingDao _networkOfferingDao;
@Inject
protected IPAddressDao _ipAddressDao = null;
@Inject
protected RulesManager _rulesMgr;
@Inject
KeystoreManager _keystoreMgr;
private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL;
@ -1181,11 +1188,36 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
return false;
}
try {
//get system ip and create static nat rule for the vm in case of basic networking with EIP/ELB
_rulesMgr.getSystemIpAndEnableStaticNatForVm(profile.getVirtualMachine(), false);
IPAddressVO ipaddr = _ipAddressDao.findByAssociatedVmId(profile.getVirtualMachine().getId());
if (ipaddr != null && ipaddr.getSystem()) {
SecondaryStorageVmVO secVm = profile.getVirtualMachine();
// override SSVM guest IP with EIP, so that download url's with be prepared with EIP
secVm.setPublicIpAddress(ipaddr.getAddress().addr());
_secStorageVmDao.update(secVm.getId(), secVm);
}
} catch (Exception ex) {
s_logger.warn("Failed to get system ip and enable static nat for the vm " + profile.getVirtualMachine() + " due to exception ", ex);
return false;
}
return true;
}
@Override
public void finalizeStop(VirtualMachineProfile<SecondaryStorageVmVO> profile, StopAnswer answer) {
//release elastic IP here
IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(profile.getId());
if (ip != null && ip.getSystem()) {
UserContext ctx = UserContext.current();
try {
_rulesMgr.disableStaticNat(ip.getId(), ctx.getCaller(), ctx.getCallerUserId(), true);
} catch (Exception ex) {
s_logger.warn("Failed to disable static nat and release system ip " + ip + " as a part of vm " + profile.getVirtualMachine() + " stop due to exception ", ex);
}
}
}
@Override

View File

@ -279,12 +279,7 @@ public class UploadMonitorImpl implements UploadMonitor {
uploadJob.setUploadState(Status.DOWNLOAD_URL_NOT_CREATED);
uploadJob.setLastUpdated(new Date());
_uploadDao.update(uploadJob.getId(), uploadJob);
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running);
if (ssVms.size() == 0){
errorString = "Couldnt find a running SSVM in the zone" + dataCenterId+ ". Couldnt create the extraction URL.";
throw new CloudRuntimeException(errorString);
}
// Create Symlink at ssvm
String uuid = UUID.randomUUID().toString() + path.substring(path.length() - 4) ; // last 4 characters of the path specify the format like .vhd
HostVO secStorage = ApiDBUtils.findHostById(ApiDBUtils.findUploadById(uploadId).getHostId());
@ -303,16 +298,26 @@ public class UploadMonitorImpl implements UploadMonitor {
throw new CloudRuntimeException(errorString);
}
//Construct actual URL locally now that the symlink exists at SSVM
String extractURL = generateCopyUrl(ssvm.getPublicIpAddress(), uuid);
UploadVO vo = _uploadDao.createForUpdate();
vo.setLastUpdated(new Date());
vo.setUploadUrl(extractURL);
vo.setUploadState(Status.DOWNLOAD_URL_CREATED);
_uploadDao.update(uploadId, vo);
success = true;
return;
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running);
if (ssVms.size() > 0) {
SecondaryStorageVmVO ssVm = ssVms.get(0);
if (ssVm.getPublicIpAddress() == null) {
errorString = "A running secondary storage vm has a null public ip?";
s_logger.error(errorString);
throw new CloudRuntimeException(errorString);
}
//Construct actual URL locally now that the symlink exists at SSVM
String extractURL = generateCopyUrl(ssVm.getPublicIpAddress(), uuid);
UploadVO vo = _uploadDao.createForUpdate();
vo.setLastUpdated(new Date());
vo.setUploadUrl(extractURL);
vo.setUploadState(Status.DOWNLOAD_URL_CREATED);
_uploadDao.update(uploadId, vo);
success = true;
return;
}
errorString = "Couldnt find a running SSVM in the zone" + dataCenterId+ ". Couldnt create the extraction URL.";
throw new CloudRuntimeException(errorString);
}finally{
if(!success){
UploadVO uploadJob = _uploadDao.createForUpdate(uploadId);