enhance asociateIPAddr API to acquire a protable IP and associate with a

guest network or VPC
This commit is contained in:
Murali Reddy 2013-05-12 16:53:45 +05:30
parent f82c6a8431
commit 27504d9098
11 changed files with 170 additions and 75 deletions

View File

@ -52,7 +52,7 @@ public interface NetworkService {
IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException,
InsufficientAddressCapacityException, ConcurrentOperationException;
IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId) throws ResourceAllocationException,
IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException,
InsufficientAddressCapacityException, ConcurrentOperationException;
boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException;

View File

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

View File

@ -112,7 +112,7 @@ public class IPAddressVO implements IpAddress {
private String vmIp;
@Column(name="is_portable")
private boolean portable;
private boolean portable = false;
protected IPAddressVO() {
this.uuid = UUID.randomUUID().toString();
@ -136,6 +136,19 @@ public class IPAddressVO implements IpAddress {
this.uuid = UUID.randomUUID().toString();
}
public IPAddressVO(Ip address, long dataCenterId, Long networkId, Long vpcId, long physicalNetworkId, long sourceNetworkId,
long vlanDbId, boolean portable) {
this.address = address;
this.dataCenterId = dataCenterId;
this.associatedWithNetworkId = networkId;
this.vpcId = vpcId;
this.physicalNetworkId = physicalNetworkId;
this.sourceNetworkId = sourceNetworkId;
this.vlanId = vlanDbId;
this.portable = portable;
this.uuid = UUID.randomUUID().toString();
}
public long getMacAddress() {
return macAddress;
}

View File

@ -44,6 +44,7 @@ import com.cloud.dc.*;
import com.cloud.dc.dao.*;
import com.cloud.user.*;
import com.cloud.event.UsageEventUtils;
import com.cloud.utils.db.*;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.ApiConstants.LDAPParams;
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
@ -164,10 +165,6 @@ import com.cloud.utils.NumbersUtil;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.VirtualMachine;
@ -4523,6 +4520,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
throw new InvalidParameterValueException("Invalid vlan id " + vlanId);
}
}
GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange");
portableIpLock.lock(5);
Transaction txn = Transaction.currentTxn();
txn.start();
@ -4539,7 +4538,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
txn.commit();
portableIpLock.unlock();
return portableIpRange;
}

View File

@ -58,6 +58,7 @@ import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.region.PortableIp;
/**
* NetworkManager manages the network for the different end users.
@ -323,6 +324,9 @@ public interface NetworkManager {
DataCenter zone) throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException;
IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID)
throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException;
Map<String, String> finalizeServicesAndProvidersForNetwork(NetworkOffering offering,
Long physicalNetworkId);

View File

@ -105,6 +105,10 @@ import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.dao.*;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.region.PortableIp;
import org.apache.cloudstack.region.PortableIpDao;
import org.apache.cloudstack.region.PortableIpVO;
import org.apache.cloudstack.region.Region;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -251,6 +255,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
UserIpv6AddressDao _ipv6Dao;
@Inject
Ipv6AddressManager _ipv6Mgr;
@Inject
PortableIpDao _portableIpDao;
protected StateMachine2<Network.State, Network.Event, Network> _stateMachine;
private final HashMap<String, NetworkOfferingVO> _systemNetworks = new HashMap<String, NetworkOfferingVO>(5);
@ -696,6 +702,62 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
return ip;
}
@Override
@DB
public IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID)
throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException {
Transaction txn = Transaction.currentTxn();
GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange");
PortableIpVO allocatedPortableIp;
IPAddressVO ipaddr;
try {
portableIpLock.lock(5);
txn.start();
//TODO: get the region ID corresponding to running management server
List<PortableIpVO> portableIpVOs = _portableIpDao.listByRegionIdAndState(1, PortableIp.State.Free);
if (portableIpVOs == null || portableIpVOs.isEmpty()) {
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException
("Unable to find available portable IP addresses", Region.class, new Long(1));
throw ex;
}
// allocate first portable IP to the user
allocatedPortableIp = portableIpVOs.get(0);
allocatedPortableIp.setAllocatedTime(new Date());
allocatedPortableIp.setAllocatedToAccountId(ipOwner.getAccountId());
allocatedPortableIp.setAllocatedInDomainId(ipOwner.getDomainId());
allocatedPortableIp.setState(PortableIp.State.Allocated);
_portableIpDao.update(allocatedPortableIp.getId(), allocatedPortableIp);
// provision portable IP range VLAN
long physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(dcId, TrafficType.Public).getId();
Network network = _networkModel.getNetwork(physicalNetworkId);
String range = allocatedPortableIp.getAddress() + "-" + allocatedPortableIp.getAddress();
VlanVO vlan = new VlanVO(VlanType.VirtualNetwork, allocatedPortableIp.getVlan(), allocatedPortableIp.getGateway(),
allocatedPortableIp.getNetmask(), dcId, range, network.getId(), network.getId(), null, null, null);
vlan = _vlanDao.persist(vlan);
// provision the portable IP in to user_ip_address table
ipaddr = new IPAddressVO(new Ip(allocatedPortableIp.getAddress()), dcId, networkId, vpcID, network.getId(),
network.getId(), vlan.getId(), true);
ipaddr.setState(State.Allocated);
ipaddr.setAllocatedTime(new Date());
ipaddr.setAllocatedInDomainId(ipOwner.getDomainId());
ipaddr.setAllocatedToAccountId(ipOwner.getId());
ipaddr= _ipAddressDao.persist(ipaddr);
txn.commit();
} finally {
portableIpLock.unlock();
}
return ipaddr;
}
protected IPAddressVO getExistingSourceNatInNetwork(long ownerId, Long networkId) {
List<? extends IpAddress> addrs = _networkModel.listPublicIpsAssignedToGuestNtwk(ownerId, networkId, true);

View File

@ -37,6 +37,7 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.vpc.dao.VpcDao;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@ -171,32 +172,6 @@ import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.NicSecondaryIpVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.*;
import com.cloud.vm.dao.*;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.InvalidParameterException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
/**
@ -301,6 +276,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
DataCenterVnetDao _datacneter_vnet;
@Inject
AccountGuestVlanMapDao _accountGuestVlanMapDao;
@Inject
VpcDao _vpcDao;
int _cidrLimit;
boolean _allowSubdomainNetworkAccess;
@ -512,22 +489,23 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId)
throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
Account caller = UserContext.current().getCaller();
long callerUserId = UserContext.current().getCallerUserId();
DataCenter zone = _configMgr.getZone(zoneId);
if (networkId != null) {
Network network = _networksDao.findById(networkId);
if (network == null) {
throw new InvalidParameterValueException("Invalid network id is given");
}
if (network.getGuestType() == Network.GuestType.Shared) {
DataCenter zone = _configMgr.getZone(zoneId);
if (zone == null) {
throw new InvalidParameterValueException("Invalid zone Id is given");
}
// if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork'
if (zone.getNetworkType() == NetworkType.Advanced) {
if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) {
Account caller = UserContext.current().getCaller();
long callerUserId = UserContext.current().getCallerUserId();
_accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
@ -539,27 +517,57 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
}
}
}
} else {
_accountMgr.checkAccess(caller, null, false, ipOwner);
}
return allocateIP(ipOwner, false, zoneId);
return _networkMgr.allocateIp(ipOwner, false, caller, callerUserId, zone);
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_ASSIGN, eventDescription = "allocating portable public Ip", create = true)
public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId)
throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
return null;
}
public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId)
public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId)
throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
Account caller = UserContext.current().getCaller();
// check permissions
_accountMgr.checkAccess(caller, null, false, ipOwner);
long callerUserId = UserContext.current().getCallerUserId();
DataCenter zone = _configMgr.getZone(zoneId);
return _networkMgr.allocateIp(ipOwner, isSystem, caller, callerUserId, zone);
if (networkId != null) {
Network network = _networksDao.findById(networkId);
if (network == null) {
throw new InvalidParameterValueException("Invalid network id is given");
}
if (network.getGuestType() == Network.GuestType.Shared) {
if (zone == null) {
throw new InvalidParameterValueException("Invalid zone Id is given");
}
// if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork'
if (zone.getNetworkType() == NetworkType.Advanced) {
if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) {
_accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
}
return _networkMgr.allocatePortableIp(ipOwner, caller, zoneId, networkId, null);
} else {
throw new InvalidParameterValueException("Associate IP address can only be called on the shared networks in the advanced zone" +
" with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled");
}
}
}
}
if (vpcId != null) {
Vpc vpc = _vpcDao.findById(vpcId);
if (vpc != null) {
throw new InvalidParameterValueException("Invalid vpc id is given");
}
}
_accountMgr.checkAccess(caller, null, false, ipOwner);
return _networkMgr.allocatePortableIp(ipOwner, caller, zoneId, null, null);
}
@Override

View File

@ -31,4 +31,5 @@ public interface PortableIpDao extends GenericDao<PortableIpVO, Long> {
List<PortableIpVO> listByRangeIdAndState(long rangeId, PortableIp.State state);
List<PortableIpVO> listByRegionIdAndState(int regionId, PortableIp.State state);
}

View File

@ -51,6 +51,7 @@ public class PortableIpDaoImpl extends GenericDaoBase<PortableIpVO, Long> implem
private final SearchBuilder<PortableIpVO> listByRegionIDSearch;
private final SearchBuilder<PortableIpVO> listByRangeIDSearch;
private final SearchBuilder<PortableIpVO> listByRangeIDAndStateSearch;
private final SearchBuilder<PortableIpVO> listByRegionIDAndStateSearch;
public PortableIpDaoImpl() {
listByRegionIDSearch = createSearchBuilder();
@ -65,6 +66,11 @@ public class PortableIpDaoImpl extends GenericDaoBase<PortableIpVO, Long> implem
listByRangeIDAndStateSearch.and("rangeId", listByRangeIDAndStateSearch.entity().getRangeId(), SearchCriteria.Op.EQ);
listByRangeIDAndStateSearch.and("state", listByRangeIDAndStateSearch.entity().getState(), SearchCriteria.Op.EQ);
listByRangeIDAndStateSearch.done();
listByRegionIDAndStateSearch = createSearchBuilder();
listByRegionIDAndStateSearch.and("regionId", listByRegionIDAndStateSearch.entity().getRangeId(), SearchCriteria.Op.EQ);
listByRegionIDAndStateSearch.and("state", listByRegionIDAndStateSearch.entity().getState(), SearchCriteria.Op.EQ);
listByRegionIDAndStateSearch.done();
}
@Override
@ -88,4 +94,12 @@ public class PortableIpDaoImpl extends GenericDaoBase<PortableIpVO, Long> implem
sc.setParameters("state", state);
return listBy(sc);
}
@Override
public List<PortableIpVO> listByRegionIdAndState(int regionId, PortableIp.State state) {
SearchCriteria<PortableIpVO> sc = listByRegionIDAndStateSearch.create();
sc.setParameters("regionId", regionId);
sc.setParameters("state", state);
return listBy(sc);
}
}

View File

@ -49,7 +49,6 @@ import com.cloud.network.Networks.TrafficType;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.GuestVlan;
import com.cloud.network.element.LoadBalancingServiceProvider;
import com.cloud.network.element.StaticNatServiceProvider;
import com.cloud.network.element.UserDataServiceProvider;
@ -68,21 +67,8 @@ import com.cloud.utils.component.ManagerBase;
import com.cloud.vm.*;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
import org.springframework.stereotype.Component;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
@ -859,10 +845,17 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage
}
@Override
public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
public IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID)
throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException {
return null;// TODO Auto-generated method stub
}
@Override
public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException,
InsufficientAddressCapacityException, ConcurrentOperationException {
return null;
}
@Override
public boolean isSecondaryIpSetForNic(long nicId) {
// TODO Auto-generated method stub

View File

@ -62,7 +62,6 @@ import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkTrafficType;
import com.cloud.network.PublicIpAddress;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.AccountGuestVlanMapVO;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.dao.NetworkVO;
@ -92,16 +91,6 @@ import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@Component
@ -208,10 +197,16 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage
}
@Override
public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
public IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID)
throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException {
return null;// TODO Auto-generated method stub
}
@Override
public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException,
InsufficientAddressCapacityException, ConcurrentOperationException {
return null;
}
/* (non-Javadoc)
* @see com.cloud.network.NetworkService#releaseIpAddress(long)