bug 12911, 12912, 11417: netscaler SDX based dynamiac load balancer provisioning

status 12911, 12912, 11417: resolved fixed
This commit is contained in:
Murali reddy 2012-01-06 20:46:31 +05:30
parent c46591f814
commit a4cabad669
4 changed files with 83 additions and 31 deletions

View File

@ -256,9 +256,7 @@ public class NetscalerResource implements ServerResource {
private void validateInterfaces(String publicInterface, String privateInterface) throws ExecutionException {
try {
if (_isSdx) {
return;
} else {
if (!_isSdx && !_cloudManaged) {
Interface publicIf = Interface.get(_netscalerService, publicInterface);
Interface privateIf = Interface.get(_netscalerService, privateInterface);
if (publicIf != null || privateIf != null) {
@ -266,7 +264,7 @@ public class NetscalerResource implements ServerResource {
} else {
throw new ExecutionException("Invalid interface name specified for public/private interfaces.");
}
}
}
} catch (nitro_exception e) {
if (e.getErrorCode() == NitroError.NS_RESOURCE_NOT_EXISTS) {
throw new ExecutionException("Invalid interface name specified for public and private interfaces.");
@ -280,7 +278,7 @@ public class NetscalerResource implements ServerResource {
private void validateDeviceType(String deviceType) throws ExecutionException {
try {
if (!_isSdx) {
if (!_isSdx && !_cloudManaged) {
nshardware nsHw = com.citrix.netscaler.nitro.resource.config.ns.nshardware.get(_netscalerService);
if (nsHw == null) {
throw new ExecutionException("Failed to get the hardware description of the Netscaler device at " + _ip);
@ -291,7 +289,7 @@ public class NetscalerResource implements ServerResource {
}
throw new ExecutionException("Netscalar device type specified does not match with the actuall device type.");
}
} else {
} else if (_isSdx) {
mps serviceVM = mps.get(_netscalerSdxService);
if (serviceVM != null) {
if (serviceVM.get_platform().contains("SDX") || serviceVM.get_product().contains("SDX")) {
@ -656,10 +654,10 @@ public class NetscalerResource implements ServerResource {
// wait for VPX instance to start-up
long startTick = System.currentTimeMillis();
long startWaitMins = 200000;
while(!newVpx.get_ns_state().equalsIgnoreCase("up") && System.currentTimeMillis() - startTick < startWaitMins) {
long startWaitMilliSeconds = 600000;
while(!newVpx.get_ns_state().equalsIgnoreCase("up") && System.currentTimeMillis() - startTick < startWaitMilliSeconds) {
try {
Thread.sleep(1000);
Thread.sleep(10000);
} catch(InterruptedException e) {
}
ns refreshNsObj = new ns();
@ -669,16 +667,36 @@ public class NetscalerResource implements ServerResource {
// if vpx instance never came up then error out
if (!newVpx.get_ns_state().equalsIgnoreCase("up")) {
new Answer(cmd, new ExecutionException("Failed to start VPX instance " + vpxName + " created on the netscaler SDX device " + _ip));
return new Answer(cmd, new ExecutionException("Failed to start VPX instance " + vpxName + " created on the netscaler SDX device " + _ip));
}
// wait till NS service in side VPX is actually ready
startTick = System.currentTimeMillis();
boolean nsServiceUp = false;
long nsServiceWaitMilliSeconds = 60000;
while (System.currentTimeMillis() - startTick < nsServiceWaitMilliSeconds) {
try {
nitro_service _netscalerService = new nitro_service(cmd.getLoadBalancerIP(), "https");
_netscalerService.set_credential(username, password);
_netscalerService.set_timeout(_timeout);
apiCallResult = _netscalerService.login();
if (apiCallResult.errorcode == 0) {
nsServiceUp = true;
break;
}
} catch (Exception e) {
continue;
}
}
if (!nsServiceUp) {
return new Answer(cmd, new ExecutionException("Failed to create VPX instance " + vpxName + " on the netscaler SDX device " + _ip));
}
if (s_logger.isInfoEnabled()) {
s_logger.info("Successfully provisioned VPX instance " + vpxName + " on the Netscaler SDX device " + _ip);
}
// FIXME: once VPX comes up there is time lag before we can actually login to VPX, so wait
Thread.sleep(20000);
// physical interfaces on the SDX range from 10/1 to 10/8 of which two different port or same port can be used for public and private interfaces
// However the VPX instances created will have interface range start from 10/1 but will only have as many interfaces enabled while creating the VPX instance
@ -816,8 +834,6 @@ public class NetscalerResource implements ServerResource {
String vlanInterface = guestVlan ? _privateInterface : _publicInterface;
throw new ExecutionException("Failed to bind vlan with tag:" + vlanTag + " with the interface " + vlanInterface + " due to " + apiCallResult.message);
}
} else {
throw new ExecutionException("Failed to configure Netscaler device for vlan with tag " + vlanTag + " as vlan already exisits");
}
} catch (nitro_exception e) {
throw new ExecutionException("Failed to implement guest network on the Netscaler device due to " + e.getMessage());

View File

@ -69,6 +69,7 @@ import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceAllocationState;
import com.cloud.network.ExternalLoadBalancerDeviceVO.LBDeviceState;
import com.cloud.network.ExternalNetworkDeviceManager.NetworkDevice;
@ -103,6 +104,7 @@ import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.resource.ResourceStateAdapter.DeleteHostAnswer;
import com.cloud.server.api.response.ExternalLoadBalancerResponse;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
@ -469,27 +471,44 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
//we have provisioned load balancer so add the appliance as cloudstack provisioned external load balancer
String dedicatedLb = offering.getDedicatedLB()?"true":"false";
// acquire a public IP to associate with lb appliance (used as subnet IP to make the appliance part of private network)
//acquire a public IP to associate with lb appliance (used as subnet IP to make the appliance part of private network)
PublicIp publicIp = _networkMgr.assignPublicIpAddress(guestConfig.getDataCenterId(), null, _accountMgr.getSystemAccount(), VlanType.VirtualNetwork, null, null);
IPAddressVO ipvo = _ipAddressDao.findById(publicIp.getId());
String publicIPNetmask = publicIp.getVlanNetmask();
String publicIPgateway = publicIp.getVlanGateway();
String publicIPVlanTag = publicIp.getVlanTag();
String publicIP = publicIp.getAddress().toString();
String url = "https://" + lbIP + "?publicinterface=" + publicIf + "&privateinterface=" + privateIf + "&lbdevicededicated=" + dedicatedLb +
"&cloudmanaged=true" + "&publicip=" + publicIP + "&publicipnetmask=" + publicIPNetmask + "&publicipvlan="+ publicIPVlanTag + "&publicipgateway=" + publicIPgateway;
ExternalLoadBalancerDeviceVO lbAppliance = addExternalLoadBalancer(physicalNetworkId, url, username, password, createLbAnswer.getDeviceName(), createLbAnswer.getServerResource());
"&cloudmanaged=true" + "&publicip=" + publicIP + "&publicipnetmask=" + publicIPNetmask + "&publicipvlan="+ publicIPVlanTag + "&publicipgateway=" + publicIPgateway;
ExternalLoadBalancerDeviceVO lbAppliance = null;
try {
lbAppliance = addExternalLoadBalancer(physicalNetworkId, url, username, password, createLbAnswer.getDeviceName(), createLbAnswer.getServerResource());
} catch (Exception e) {
s_logger.error("Failed to add load balancer appliance in to cloudstack due to " + e.getMessage() + ". So provisioned load balancer appliance will be destroyed.");
}
if (lbAppliance != null) {
// mark the load balancer as cloudstack managed
// mark the load balancer as cloudstack managed and set parent host id on which lb appliance is provisioned
ExternalLoadBalancerDeviceVO managedLb = _externalLoadBalancerDeviceDao.findById(lbAppliance.getId());
managedLb.setIsManagedDevice(true);
// set parent host id on which lb appliance is provisioned
managedLb.setParentHostId(lbProviderDevice.getHostId());
_externalLoadBalancerDeviceDao.update(lbAppliance.getId(), managedLb);
} else {
_networkMgr.releasePublicIpAddress(publicIp.getId(), _accountMgr.getSystemUser().getId(), _accountMgr.getSystemAccount());
// failed to add the provisioned load balancer into cloudstack so destroy the appliance
DestroyLoadBalancerApplianceCommand lbDeleteCmd = new DestroyLoadBalancerApplianceCommand(lbIP);
DestroyLoadBalancerApplianceAnswer answer = null;
try {
answer = (DestroyLoadBalancerApplianceAnswer) _agentMgr.easySend(lbProviderDevice.getHostId(), lbDeleteCmd);
if (answer == null || !answer.getResult()) {
s_logger.warn("Failed to destroy load balancer appliance created");
} else {
// release the public & private IP back to dc pool, as the load balancer appliance is now destroyed
_dcDao.releasePrivateIpAddress(lbIP, guestConfig.getDataCenterId(), null);
_networkMgr.releasePublicIpAddress(publicIp.getId(), _accountMgr.getSystemUser().getId(), _accountMgr.getSystemAccount());
}
} catch (Exception e) {
s_logger.warn("Failed to destroy load balancer appliance created for the network" + guestConfig.getId() + " due to " + e.getMessage());
}
}
}
}
@ -607,8 +626,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
txn.commit();
if (!lbInUse && lbCloudManaged) {
// send DestroyLoadBalancerApplianceCommand to the host where load balancer appliance
// is provisioned as this is the last network using it
// send DestroyLoadBalancerApplianceCommand to the host where load balancer appliance is provisioned
Host lbHost = _hostDao.findById(lbDevice.getHostId());
String lbIP = lbHost.getPrivateIpAddress();
DestroyLoadBalancerApplianceCommand lbDeleteCmd = new DestroyLoadBalancerApplianceCommand(lbIP);
@ -627,10 +645,16 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
}
deviceMapLock.unlock();
// remove the provisioned load balancer appliance from cloudstack
deleteExternalLoadBalancer(lbHost.getId());
// release the private IP back to dc pool, as the load balancer appliance is now destroyed
_dcDao.releasePrivateIpAddress(lbHost.getPrivateIpAddress(), guestConfig.getDataCenterId(), null);
//FIXME : release the public IP allocated for this LB appliance
// release the public IP allocated for this LB appliance
DetailVO publicIpDetail = _hostDetailDao.findDetail(lbHost.getId(), "publicip");
IPAddressVO ipVo = _ipAddressDao.findByIpAndDcId(guestConfig.getDataCenterId(), publicIpDetail.toString());
_networkMgr.releasePublicIpAddress(ipVo.getId(), _accountMgr.getSystemUser().getId(), _accountMgr.getSystemAccount());
} else {
deviceMapLock.unlock();
}
@ -1213,7 +1237,9 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
// TODO Auto-generated method stub
return null;
if (host.getType() != com.cloud.host.Host.Type.ExternalLoadBalancer) {
return null;
}
return new DeleteHostAnswer(true);
}
}

View File

@ -56,7 +56,9 @@ public interface IPAddressDao extends GenericDao<IPAddressVO, Long> {
IPAddressVO findByAssociatedVmId(long vmId);
IPAddressVO findByIpAndSourceNetworkId(long networkId, String ipAddress);
public IPAddressVO findByIpAndDcId(long dcId, String ipAddress);
List<IPAddressVO> listByPhysicalNetworkId(long physicalNetworkId);
long countFreeIPs();

View File

@ -208,7 +208,15 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
sc.setParameters("ipAddress", ipAddress);
return findOneBy(sc);
}
@Override
public IPAddressVO findByIpAndDcId(long dcId, String ipAddress) {
SearchCriteria<IPAddressVO> sc = AllFieldsSearch.create();
sc.setParameters("dataCenterId", dcId);
sc.setParameters("ipAddress", ipAddress);
return findOneBy(sc);
}
@Override
public List<IPAddressVO> listByDcId(long dcId) {
SearchCriteria<IPAddressVO> sc = AllFieldsSearch.create();