Support for IPAssoc inside VPC

This commit is contained in:
Alena Prokharchyk 2012-05-29 11:27:26 -07:00
parent a7c8354c7b
commit 6a097ad3b6
12 changed files with 141 additions and 86 deletions

View File

@ -106,7 +106,8 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd {
DataCenter zone = _configService.getZone(zoneId);
if (zone.getNetworkType() == NetworkType.Advanced) {
List<? extends Network> networks = _networkService.getIsolatedNetworksOwnedByAccountInZone(getZoneId(), _accountService.getAccount(getEntityOwnerId()));
List<? extends Network> networks = _networkService.getIsolatedNetworksOwnedByAccountInZone(getZoneId(),
_accountService.getAccount(getEntityOwnerId()));
if (networks.size() == 0) {
String domain = _domainService.getDomain(getDomainId()).getName();
throw new InvalidParameterValueException("Account name=" + getAccountName() + " domain=" + domain + " doesn't have virtual networks in zone=" + zone.getName());

View File

@ -74,6 +74,10 @@ public class ListPublicIpAddressesCmd extends BaseListProjectAndAccountResources
@Parameter(name=ApiConstants.IS_STATIC_NAT, type=CommandType.BOOLEAN, description="list only static nat ip addresses")
private Boolean isStaticNat;
@IdentityMapper(entityTableName="vpc")
@Parameter(name=ApiConstants.VPC_ID, type=CommandType.LONG, description="List ips belonging to the VPC")
private Long vpcId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -118,6 +122,10 @@ public class ListPublicIpAddressesCmd extends BaseListProjectAndAccountResources
return isStaticNat;
}
public Long getVpcId() {
return vpcId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -92,16 +92,10 @@ public class IPAddressResponse extends BaseResponse implements ControlledEntityR
@SerializedName(ApiConstants.PURPOSE) @Param(description="purpose of the IP address. In Acton this value is not null for Ips with isSystem=true, and can have either StaticNat or LB value")
private String purpose;
@SerializedName(ApiConstants.VPC_ID) @Param(description="VPC the ip belongs to")
private IdentityProxy vpcId = new IdentityProxy("vpc");
/*
@SerializedName(ApiConstants.JOB_ID) @Param(description="shows the current pending asynchronous job ID. This tag is not returned if no current pending jobs are acting on the volume")
private IdentityProxy jobId = new IdentityProxy("async_job");
*/
/*
@SerializedName(ApiConstants.JOB_STATUS) @Param(description="shows the current pending asynchronous job status")
private Integer jobStatus;
*/
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
@ -212,4 +206,8 @@ public class IPAddressResponse extends BaseResponse implements ControlledEntityR
public void setPurpose(String purpose) {
this.purpose = purpose;
}
public void setVpcId(Long vpcId) {
this.vpcId.setValue(vpcId);
}
}

View File

@ -730,30 +730,30 @@ public class ApiResponseHelper implements ResponseGenerator {
}
@Override
public IPAddressResponse createIPAddressResponse(IpAddress ipAddress) {
VlanVO vlan = ApiDBUtils.findVlanById(ipAddress.getVlanId());
public IPAddressResponse createIPAddressResponse(IpAddress ipAddr) {
VlanVO vlan = ApiDBUtils.findVlanById(ipAddr.getVlanId());
boolean forVirtualNetworks = vlan.getVlanType().equals(VlanType.VirtualNetwork);
long zoneId = ipAddress.getDataCenterId();
long zoneId = ipAddr.getDataCenterId();
IPAddressResponse ipResponse = new IPAddressResponse();
ipResponse.setId(ipAddress.getId());
ipResponse.setIpAddress(ipAddress.getAddress().toString());
if (ipAddress.getAllocatedTime() != null) {
ipResponse.setAllocated(ipAddress.getAllocatedTime());
ipResponse.setId(ipAddr.getId());
ipResponse.setIpAddress(ipAddr.getAddress().toString());
if (ipAddr.getAllocatedTime() != null) {
ipResponse.setAllocated(ipAddr.getAllocatedTime());
}
ipResponse.setZoneId(zoneId);
ipResponse.setZoneName(ApiDBUtils.findZoneById(ipAddress.getDataCenterId()).getName());
ipResponse.setSourceNat(ipAddress.isSourceNat());
ipResponse.setIsSystem(ipAddress.getSystem());
ipResponse.setZoneName(ApiDBUtils.findZoneById(ipAddr.getDataCenterId()).getName());
ipResponse.setSourceNat(ipAddr.isSourceNat());
ipResponse.setIsSystem(ipAddr.getSystem());
// get account information
populateOwner(ipResponse, ipAddress);
populateOwner(ipResponse, ipAddr);
ipResponse.setForVirtualNetwork(forVirtualNetworks);
ipResponse.setStaticNat(ipAddress.isOneToOneNat());
ipResponse.setStaticNat(ipAddr.isOneToOneNat());
if (ipAddress.getAssociatedWithVmId() != null) {
UserVm vm = ApiDBUtils.findUserVmById(ipAddress.getAssociatedWithVmId());
if (ipAddr.getAssociatedWithVmId() != null) {
UserVm vm = ApiDBUtils.findUserVmById(ipAddr.getAssociatedWithVmId());
ipResponse.setVirtualMachineId(vm.getId());
ipResponse.setVirtualMachineName(vm.getHostName());
if (vm.getDisplayName() != null) {
@ -763,11 +763,12 @@ public class ApiResponseHelper implements ResponseGenerator {
}
}
ipResponse.setAssociatedNetworkId(ipAddress.getAssociatedWithNetworkId());
ipResponse.setAssociatedNetworkId(ipAddr.getAssociatedWithNetworkId());
ipResponse.setVpcId(ipAddr.getVpcId());
// Network id the ip is associated withif associated networkId is null, try to get this information from vlan
Long associatedNetworkId = ipAddress.getAssociatedWithNetworkId();
Long vlanNetworkId = ApiDBUtils.getVlanNetworkId(ipAddress.getVlanId());
Long associatedNetworkId = ipAddr.getAssociatedWithNetworkId();
Long vlanNetworkId = ApiDBUtils.getVlanNetworkId(ipAddr.getVlanId());
if (associatedNetworkId == null) {
associatedNetworkId = vlanNetworkId;
}
@ -783,18 +784,18 @@ public class ApiResponseHelper implements ResponseGenerator {
}
ipResponse.setNetworkId(networkId);
ipResponse.setState(ipAddress.getState().toString());
ipResponse.setPhysicalNetworkId(ipAddress.getPhysicalNetworkId());
ipResponse.setState(ipAddr.getState().toString());
ipResponse.setPhysicalNetworkId(ipAddr.getPhysicalNetworkId());
// show this info to admin only
Account account = UserContext.current().getCaller();
if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
ipResponse.setVlanId(ipAddress.getVlanId());
ipResponse.setVlanName(ApiDBUtils.findVlanById(ipAddress.getVlanId()).getVlanTag());
ipResponse.setVlanId(ipAddr.getVlanId());
ipResponse.setVlanName(ApiDBUtils.findVlanById(ipAddr.getVlanId()).getVlanTag());
}
if (ipAddress.getSystem()) {
if (ipAddress.isOneToOneNat()) {
if (ipAddr.getSystem()) {
if (ipAddr.isOneToOneNat()) {
ipResponse.setPurpose(IpAddress.Purpose.StaticNat.toString());
} else {
ipResponse.setPurpose(IpAddress.Purpose.Lb.toString());

View File

@ -379,11 +379,13 @@ public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase impl
IPAddressVO sourceNatIp = null;
if (!sharedSourceNat) {
// Get the source NAT IP address for this network
List<IPAddressVO> sourceNatIps = _networkMgr.listPublicIpsAssignedToGuestNtwk(network.getAccountId(), zoneId, true, null);
// Get the source NAT IP address for this account
List<IPAddressVO> sourceNatIps = _networkMgr.listPublicIpsAssignedToAccount(network.getAccountId(),
zoneId, true);
if (sourceNatIps.size() != 1) {
String errorMsg = "External firewall was unable to find the source NAT IP address for account " + account.getAccountName();
String errorMsg = "External firewall was unable to find the source NAT IP address for account "
+ account.getAccountName();
s_logger.error(errorMsg);
return true;
} else {

View File

@ -96,15 +96,13 @@ public interface NetworkManager extends NetworkService {
*
* @param accountId
* - account that the IP address should belong to
* @param dcId
* - zone that the IP address should belong to
* @param sourceNat
* - (optional) true if the IP address should be a source NAT address
* @param associatedNetworkId
* TODO
* @param sourceNat
* - (optional) true if the IP address should be a source NAT address
* @return - list of IP addresses
*/
List<IPAddressVO> listPublicIpsAssignedToGuestNtwk(long accountId, long dcId, Boolean sourceNat, Long associatedNetworkId);
List<IPAddressVO> listPublicIpsAssignedToGuestNtwk(long accountId, long associatedNetworkId, Boolean sourceNat);
List<NetworkVO> setupNetwork(Account owner, NetworkOfferingVO offering, DeploymentPlan plan, String name, String displayText, boolean isDefault)
throws ConcurrentOperationException;
@ -391,4 +389,13 @@ public interface NetworkManager extends NetworkService {
*/
void removeNic(VirtualMachineProfile<? extends VMInstanceVO> vm, Network network);
/**
* @param accountId
* @param dcId
* @param sourceNat
* @return
*/
List<IPAddressVO> listPublicIpsAssignedToAccount(long accountId, long dcId, Boolean sourceNat);
}

View File

@ -432,7 +432,9 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
addr.setState(assign ? IpAddress.State.Allocated : IpAddress.State.Allocating);
if (vlanUse != VlanType.DirectAttached || zone.getNetworkType() == NetworkType.Basic) {
Network guestNtwk = getNetwork(guestNetworkId);
addr.setAssociatedWithNetworkId(guestNetworkId);
addr.setVpcId(guestNtwk.getVpcId());
addr.setVpcId(vpcId);
}
@ -484,21 +486,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
public PublicIp assignSourceNatIpAddressToVpc(Account owner, Vpc vpc) throws InsufficientAddressCapacityException, ConcurrentOperationException {
long dcId = vpc.getZoneId();
List<IPAddressVO> addrs = listPublicIpsAssignedToVpc(owner.getId(), true, vpc.getId());
IPAddressVO sourceNatIp = getExistingSourceNat(owner.getId(), null, vpc.getId());
PublicIp ipToReturn = null;
if (!addrs.isEmpty()) {
IPAddressVO sourceNatIp = null;
// Account already has ip addresses
for (IPAddressVO addr : addrs) {
if (addr.isSourceNat()) {
sourceNatIp = addr;
break;
}
}
assert (sourceNatIp != null) : "How do we get a bunch of ip addresses but none of them are source nat? " +
"account=" + owner.getId() + "; vpc=" + vpc;
if (sourceNatIp != null) {
ipToReturn = new PublicIp(sourceNatIp, _vlanDao.findById(sourceNatIp.getVlanId()),
NetUtils.createSequenceBasedMacAddress(sourceNatIp.getMacAddress()));
} else {
@ -509,25 +501,16 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override
public PublicIp assignSourceNatIpAddressToGuestNetwork(Account owner, Network guestNetwork) throws InsufficientAddressCapacityException, ConcurrentOperationException {
public PublicIp assignSourceNatIpAddressToGuestNetwork(Account owner, Network guestNetwork)
throws InsufficientAddressCapacityException, ConcurrentOperationException {
assert (guestNetwork.getTrafficType() != null) : "You're asking for a source nat but your network " +
"can't participate in source nat. What do you have to say for yourself?";
long dcId = guestNetwork.getDataCenterId();
List<IPAddressVO> addrs = listPublicIpsAssignedToGuestNtwk(owner.getId(), dcId, null, guestNetwork.getId());
IPAddressVO sourceNatIp = getExistingSourceNat(owner.getId(), guestNetwork.getId(), guestNetwork.getVpcId());
PublicIp ipToReturn = null;
if (!addrs.isEmpty()) {
IPAddressVO sourceNatIp = null;
// Account already has ip addresses
for (IPAddressVO addr : addrs) {
if (addr.isSourceNat()) {
sourceNatIp = addr;
break;
}
}
assert (sourceNatIp != null) : "How do we get a bunch of ip addresses but none of them are source nat? " +
"account=" + owner.getId() + "; guestNetwork=" + guestNetwork;
if (sourceNatIp != null) {
ipToReturn = new PublicIp(sourceNatIp, _vlanDao.findById(sourceNatIp.getVlanId()),
NetUtils.createSequenceBasedMacAddress(sourceNatIp.getMacAddress()));
} else {
@ -729,7 +712,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
ipToServices.put(ip, services);
// if IP in allocating state then it will not have any rules attached so skip IPAssoc to network service
// provider
// provider
if (ip.getState() == State.Allocating) {
continue;
}
@ -1045,8 +1028,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
// In Advance zone only allow to do IP assoc for Isolated networks with source nat service enabled
if (zone.getNetworkType() == NetworkType.Advanced && !(network.getGuestType() == GuestType.Isolated && areServicesSupportedInNetwork(network.getId(), Service.SourceNat))) {
throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced + " ip address can be associated only to the network of guest type " + GuestType.Isolated + " with the "
if (zone.getNetworkType() == NetworkType.Advanced &&
!(network.getGuestType() == GuestType.Isolated && areServicesSupportedInNetwork(network.getId(), Service.SourceNat))) {
throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced +
" ip address can be associated only to the network of guest type " + GuestType.Isolated + " with the "
+ Service.SourceNat.getName() + " enabled");
}
@ -1096,11 +1081,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
boolean sharedSourceNat = offering.getSharedSourceNat();
if (!sharedSourceNat) {
// First IP address should be source nat when it's being associated with Guest Virtual network
List<IPAddressVO> addrs = listPublicIpsAssignedToGuestNtwk(ownerId, zone.getId(), true, networkId);
if (addrs.isEmpty() && network.getGuestType() == Network.GuestType.Isolated) {
isSourceNat = true;
if (getExistingSourceNat(ownerId, network.getId(), network.getVpcId()) == null) {
if (network.getGuestType() == GuestType.Isolated) {
isSourceNat = true;
}
}
}
@ -1128,6 +1112,34 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return ip;
}
protected IPAddressVO getExistingSourceNat(long ownerId, Long networkId, Long vpcId) {
List<IPAddressVO> addrs = null;
if (vpcId != null) {
addrs = listPublicIpsAssignedToVpc(ownerId, true, vpcId);
} else if (networkId != null) {
addrs = listPublicIpsAssignedToGuestNtwk(ownerId, networkId, true);
}
IPAddressVO sourceNatIp = null;
if (addrs.isEmpty()) {
return null;
} else {
// Account already has ip addresses
for (IPAddressVO addr : addrs) {
if (addr.isSourceNat()) {
sourceNatIp = addr;
return sourceNatIp;
}
}
assert (sourceNatIp != null) : "How do we get a bunch of ip addresses but none of them are source nat? " +
"account=" + ownerId + "; networkId=" + networkId + "; vpcId=" + vpcId;
}
return sourceNatIp;
}
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "associating Ip", async = true)
@ -1481,13 +1493,24 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override
public List<IPAddressVO> listPublicIpsAssignedToGuestNtwk(long accountId, long dcId, Boolean sourceNat, Long associatedNetworkId) {
public List<IPAddressVO> listPublicIpsAssignedToGuestNtwk(long accountId, long associatedNetworkId, Boolean sourceNat) {
SearchCriteria<IPAddressVO> sc = IpAddressSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("associatedWithNetworkId", associatedNetworkId);
if (sourceNat != null) {
sc.addAnd("sourceNat", SearchCriteria.Op.EQ, sourceNat);
}
sc.setJoinParameters("virtualNetworkVlanSB", "vlanType", VlanType.VirtualNetwork);
return _ipAddressDao.search(sc, null);
}
@Override
public List<IPAddressVO> listPublicIpsAssignedToAccount(long accountId, long dcId, Boolean sourceNat) {
SearchCriteria<IPAddressVO> sc = IpAddressSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("dataCenterId", dcId);
if (associatedNetworkId != null) {
sc.setParameters("associatedWithNetworkId", associatedNetworkId);
}
if (sourceNat != null) {
sc.addAnd("sourceNat", SearchCriteria.Op.EQ, sourceNat);
@ -2164,7 +2187,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
Integer networkRate = getNetworkRate(network.getId(), vm.getId());
NetworkGuru guru = _networkGurus.get(network.getGuruName());
NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), networkRate, isSecurityGroupSupportedInNetwork(network), getNetworkTag(vm.getHypervisorType(), network));
NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
networkRate, isSecurityGroupSupportedInNetwork(network), getNetworkTag(vm.getHypervisorType(), network));
guru.updateNicProfile(profile, network);
profiles.add(profile);
}
@ -2196,6 +2220,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
if (ipVO.getAllocatedToAccountId() != null) {
_accountMgr.checkAccess(caller, null, true, ipVO);
}
//if ip address is a source nat ip in vpc, fail to disassociate
if (ipVO.getVpcId() != null && ipVO.isSourceNat()) {
throw new InvalidParameterValueException("IP address id=" + ipAddressId + " is a source nat for VPC id=" +
ipVO.getVpcId() + " and can't be released");
}
Network associatedNetwork = getNetwork(ipVO.getAssociatedWithNetworkId());
@ -3981,6 +4011,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
addr.setSourceNat(false);
}
addr.setAssociatedWithNetworkId(guestNetwork.getId());
addr.setVpcId(guestNetwork.getVpcId());
addr.setAllocatedTime(new Date());
addr.setAllocatedInDomainId(owner.getDomainId());
addr.setAllocatedToAccountId(owner.getId());

View File

@ -141,6 +141,7 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
address.setAssociatedWithVmId(null);
address.setState(State.Free);
address.setAssociatedWithNetworkId(null);
address.setVpcId(null);
address.setSystem(false);
update(ipAddressId, address);
}

View File

@ -1850,13 +1850,13 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
if (reprogramGuestNtwks) {
s_logger.debug("Resending ipAssoc, port forwarding, load balancing rules as a part of Virtual router start");
long ownerId = router.getAccountId();
long zoneId = router.getDataCenterIdToDeployIn();
final List<IPAddressVO> userIps = _networkMgr.listPublicIpsAssignedToGuestNtwk(ownerId, zoneId, null, guestNetworkId);
final List<IPAddressVO> userIps = _networkMgr.listPublicIpsAssignedToGuestNtwk(ownerId, guestNetworkId, null);
List<PublicIp> allPublicIps = new ArrayList<PublicIp>();
if (userIps != null && !userIps.isEmpty()) {
for (IPAddressVO userIp : userIps) {
PublicIp publicIp = new PublicIp(userIp, _vlanDao.findById(userIp.getVlanId()), NetUtils.createSequenceBasedMacAddress(userIp.getMacAddress()));
PublicIp publicIp = new PublicIp(userIp, _vlanDao.findById(userIp.getVlanId()),
NetUtils.createSequenceBasedMacAddress(userIp.getMacAddress()));
allPublicIps.add(publicIp);
}
}

View File

@ -1644,6 +1644,7 @@ public class ManagementServerImpl implements ManagementServer {
Long ipId = cmd.getId();
Boolean sourceNat = cmd.getIsSourceNat();
Boolean staticNat = cmd.getIsStaticNat();
Long vpcId = cmd.getVpcId();
Account caller = UserContext.current().getCaller();
List<Long> permittedAccounts = new ArrayList<Long>();
@ -1671,6 +1672,7 @@ public class ManagementServerImpl implements ManagementServer {
sb.and("associatedNetworkIdEq", sb.entity().getAssociatedWithNetworkId(), SearchCriteria.Op.EQ);
sb.and("isSourceNat", sb.entity().isSourceNat(), SearchCriteria.Op.EQ);
sb.and("isStaticNat", sb.entity().isOneToOneNat(), SearchCriteria.Op.EQ);
sb.and("vpcId", sb.entity().getVpcId(), SearchCriteria.Op.EQ);
if (forLoadBalancing != null && (Boolean) forLoadBalancing) {
SearchBuilder<LoadBalancerVO> lbSearch = _loadbalancerDao.createSearchBuilder();
@ -1713,6 +1715,10 @@ public class ManagementServerImpl implements ManagementServer {
sc.setParameters("dataCenterId", zone);
}
if (vpcId != null) {
sc.setParameters("vpcId", vpcId);
}
if (ipId != null) {
sc.setParameters("id", ipId);
}

View File

@ -187,7 +187,7 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS
}
@Override
public List<IPAddressVO> listPublicIpsAssignedToGuestNtwk(long accountId, long dcId, Boolean sourceNat, Long associatedNetworkId) {
public List<IPAddressVO> listPublicIpsAssignedToGuestNtwk(long accountId, long associatedNetworkId, Boolean sourceNat) {
// TODO Auto-generated method stub
return null;
}

View File

@ -3,7 +3,7 @@
# the following two variables are used by the target "waf dist"
# if you change 'em here, you need to change it also in cloud.spec, add a %changelog entry there, and add an entry in debian/changelog
VERSION = '3.0.3.2012-05-29T17:33:07Z'
VERSION = '3.0.3.2012-05-29T18:21:13Z'
APPNAME = 'cloud'
import shutil,os