bug 8821: Domain specific Direct Vlans

This commit is contained in:
alena 2011-03-04 22:40:30 -08:00
parent 1e31f1bd6c
commit 485733b9e7
16 changed files with 345 additions and 118 deletions

0
api.log Normal file
View File

View File

@ -206,6 +206,7 @@
<dao name="User configuration server" class="com.cloud.user.dao.UserDaoImpl">
</dao>
<dao name="Account configuration server" class="com.cloud.user.dao.AccountDaoImpl"/>
<dao name="Domain configuration server" class="com.cloud.domain.dao.DomainDaoImpl"/>
<dao name="IP Addresses configuration server" class="com.cloud.network.dao.IPAddressDaoImpl"/>
<dao name="Datacenter IP Addresses configuration server" class="com.cloud.dc.dao.DataCenterIpAddressDaoImpl"/>
<dao name="domain router" class="com.cloud.vm.dao.DomainRouterDaoImpl"/>

View File

@ -35,14 +35,18 @@ public class AccountVlanMapVO {
private Long id;
@Column(name="account_id")
private long accountId;
private Long accountId;
@Column(name="vlan_db_id")
private long vlanDbId;
public AccountVlanMapVO(long accountId, long vlanDbId) {
@Column(name="domain_id")
private Long domainId;
public AccountVlanMapVO(Long accountId, long vlanDbId, Long domainId) {
this.accountId = accountId;
this.vlanDbId = vlanDbId;
this.domainId = domainId;
}
public AccountVlanMapVO() {
@ -53,11 +57,15 @@ public class AccountVlanMapVO {
return id;
}
public long getAccountId() {
public Long getAccountId() {
return accountId;
}
public long getVlanDbId() {
return vlanDbId;
}
public Long getDomainId() {
return domainId;
}
}

View File

@ -69,6 +69,6 @@ public class AccountVlanMapDaoImpl extends GenericDaoBase<AccountVlanMapVO, Long
AccountVlanSearch.and("accountId", AccountVlanSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AccountVlanSearch.and("vlanDbId", AccountVlanSearch.entity().getVlanDbId(), SearchCriteria.Op.EQ);
AccountVlanSearch.done();
}
}
}

View File

@ -21,8 +21,8 @@ package com.cloud.dc.dao;
import java.util.List;
import com.cloud.dc.Vlan;
import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.GenericDao;
@ -49,5 +49,7 @@ public interface VlanDao extends GenericDao<VlanVO, Long> {
boolean zoneHasDirectAttachUntaggedVlans(long zoneId);
List<VlanVO> searchForZoneWideVlans(long dcId, String vlanType,String vlanId);
List<VlanVO> listVlansForDomainByTypeAndZone(Long zoneId, long domainId, VlanType vlanType);
}

View File

@ -28,13 +28,12 @@ import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentLocator;
@ -42,6 +41,7 @@ import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
@ -55,7 +55,8 @@ public class VlanDaoImpl extends GenericDaoBase<VlanVO, Long> implements VlanDao
protected SearchBuilder<VlanVO> ZoneTypeSearch;
protected SearchBuilder<VlanVO> ZoneTypeAllPodsSearch;
protected SearchBuilder<VlanVO> ZoneTypePodSearch;
protected SearchBuilder<VlanVO> DomainZoneVlanSearch;
protected SearchBuilder<VlanVO> DomainVlanSearch;
protected PodVlanMapDaoImpl _podVlanMapDao = new PodVlanMapDaoImpl();
protected AccountVlanMapDao _accountVlanMapDao = new AccountVlanMapDaoImpl();
@ -290,7 +291,42 @@ public class VlanDaoImpl extends GenericDaoBase<VlanVO, Long> implements VlanDao
} catch (SQLException e) {
throw new CloudRuntimeException("Unable to execute " + pstmt.toString(), e);
}
}
@Override
public List<VlanVO> listVlansForDomainByTypeAndZone(Long zoneId, long domainId, VlanType vlanType) {
if (DomainZoneVlanSearch == null) {
DataCenterDao _dcDao = ComponentLocator.getLocator("management-server").getDao(DataCenterDao.class);
AccountVlanMapDao _accountVlanMap = ComponentLocator.getLocator("management-server").getDao(AccountVlanMapDao.class);
SearchBuilder<DataCenterVO> ZoneSearch = _dcDao.createSearchBuilder();
ZoneSearch.and("id", ZoneSearch.entity().getId(), SearchCriteria.Op.EQ);
SearchBuilder<AccountVlanMapVO> DomainSearch = _accountVlanMap.createSearchBuilder();
DomainSearch.and("accountId", DomainSearch.entity().getAccountId(), Op.NULL);
DomainSearch.and("domainId", DomainSearch.entity().getDomainId(), Op.EQ);
DomainZoneVlanSearch = createSearchBuilder();
DomainZoneVlanSearch.and("vlanType", DomainZoneVlanSearch.entity().getVlanType(), Op.EQ);
DomainZoneVlanSearch.join("zoneSearch", ZoneSearch, DomainZoneVlanSearch.entity().getDataCenterId(), ZoneSearch.entity().getId());
DomainZoneVlanSearch.join("domainVlanSearch", DomainSearch, DomainZoneVlanSearch.entity().getId(), DomainSearch.entity().getVlanDbId());
DomainZoneVlanSearch.done();
ZoneSearch.done();
DomainSearch.done();
}
SearchCriteria sc = DomainZoneVlanSearch.create();
sc.setParameters("vlanType", vlanType);
if (zoneId != null) {
sc.setJoinParameters("zoneSearch", "id", zoneId);
}
sc.setJoinParameters("domainVlanSearch", "domainId", domainId);
return listBy(sc);
}
}

View File

@ -17,33 +17,26 @@
*/
package com.cloud.server;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.rmi.ServerException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import netapp.manage.NaAPIFailedException;
import netapp.manage.NaAuthenticationException;
import netapp.manage.NaException;
import netapp.manage.NaProtocolException;
import com.cloud.alert.AlertVO;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.capacity.CapacityVO;
import com.cloud.configuration.ConfigurationVO;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.domain.DomainVO;
import com.cloud.event.EventVO;
import com.cloud.exception.ConcurrentOperationException;
@ -95,7 +88,6 @@ import com.cloud.user.UserAccount;
import com.cloud.user.UserAccountVO;
import com.cloud.user.UserStatisticsVO;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouter;
@ -420,19 +412,20 @@ public interface ManagementServer {
/**
* Adds a VLAN to the database, along with an IP address range. Can add three types of VLANs: (1) zone-wide VLANs on the virtual network (2) pod-wide direct attached VLANs (3) account-specific direct attached VLANs
* @param userId
* @param vlanType - either "DomR" (VLAN for a virtual network) or "DirectAttached" (VLAN for IPs that will be directly attached to UserVMs)
* @param zoneId
* @param accountId
* @param podId
* @param add
* @param vlanId
* @param gateway
* @param startIP
* @param endIP
* @param vlanType - either "DomR" (VLAN for a virtual network) or "DirectAttached" (VLAN for IPs that will be directly attached to UserVMs)
* @param zoneId
* @param accountId
* @param podId
* @param vlanId
* @param startIP
* @param endIP
* @param domainId TODO
* @param add
* @param gateway
* @return The new VlanVO object
* @throws Exception
*/
VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws Exception;
VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP, Long domainId) throws Exception;
/**
* Deletes a VLAN from the database, along with all of its IP addresses. Will not delete VLANs that have allocated IP addresses.
@ -2191,5 +2184,8 @@ public interface ManagementServer {
*/
String getHostTags(long hostId);
VolumeVO findVolumeByIdIncludingRemoved(long id);
Long getDomainIdForVlan(long vlanDbId);
}

17
deps/.project vendored Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>deps</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -18,19 +18,19 @@
package com.cloud.api.commands;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.dc.VlanVO;
import com.cloud.domain.DomainVO;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Pair;
@ -99,14 +99,28 @@ public class CreateVlanIpRangeCmd extends BaseCmd {
} else {
accountId = account.getId();
}
}
}
//if only domain id is specified, create domain specific vlan
if (domainId != null) {
DomainVO domain = getManagementServer().findDomainIdById(domainId);
if (domain == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid domain");
}
}
//pass only accountId or domainId to createVlanIpRange command, but never both
Long domainIdForVlan = null;
if (accountId == null && domainId != null) {
domainIdForVlan = domainId;
}
VlanType vlanType = forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
// Create a VLAN and public IP addresses
VlanVO vlan = null;
try {
vlan = getManagementServer().createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIp, endIp);
vlan = getManagementServer().createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIp, endIp, domainIdForVlan);
} catch (Exception e) {
s_logger.error("Error adding VLAN: ", e);
throw new ServerApiException (BaseCmd.INTERNAL_ERROR, e.getMessage());

View File

@ -18,20 +18,19 @@
package com.cloud.api.commands;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.server.Criteria;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
import com.cloud.utils.Pair;
public class ListVlanIpRangesCmd extends BaseCmd {
@ -118,6 +117,7 @@ public class ListVlanIpRangesCmd extends BaseCmd {
for (VlanVO vlan : vlans) {
accountId = getManagementServer().getAccountIdForVlan(vlan.getId());
Long vlanDomainId = getManagementServer().getDomainIdForVlan(vlan.getId());
podId = getManagementServer().getPodIdForVlan(vlan.getId());
List<Pair<String, Object>> vlanData = new ArrayList<Pair<String, Object>>();
@ -132,6 +132,11 @@ public class ListVlanIpRangesCmd extends BaseCmd {
vlanData.add(new Pair<String, Object>(BaseCmd.Properties.DOMAIN_ID.getName(), account.getDomainId()));
vlanData.add(new Pair<String, Object>(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(account.getDomainId()).getName()));
}
if (vlanDomainId != null) {
vlanData.add(new Pair<String, Object>(BaseCmd.Properties.DOMAIN_ID.getName(), vlanDomainId));
vlanData.add(new Pair<String, Object>(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(vlanDomainId).getName()));
}
if (podId != null) {
HostPodVO pod = getManagementServer().findHostPodById(podId);

View File

@ -18,11 +18,12 @@
package com.cloud.configuration;
import java.util.List;
import java.util.Map;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.service.ServiceOfferingVO;
@ -175,15 +176,16 @@ public interface ConfigurationManager extends Manager {
* @param zoneId
* @param accountId
* @param podId
* @param add
* @param vlanId
* @param gateway
* @param startIP
* @param endIP
* @param domainId TODO
* @param add
* @param gateway
* @throws InvalidParameterValueException
* @return The new VlanVO object
*/
VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws InvalidParameterValueException, InternalErrorException;
VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP, Long domainId) throws InvalidParameterValueException, InternalErrorException;
/**
* Deletes a VLAN from the database, along with all of its IP addresses. Will not delete VLANs that have allocated IP addresses.
@ -209,5 +211,7 @@ public interface ConfigurationManager extends Manager {
* @return true for Premium, false for not
*/
boolean isPremium();
Map<Integer, List<VlanVO>> listDomainDirectVlans(long domainId, long zoneId);
}

View File

@ -45,6 +45,8 @@ import com.cloud.dc.dao.DataCenterIpAddressDaoImpl;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventTypes;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
@ -56,7 +58,6 @@ import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.user.AccountVO;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
@ -88,6 +89,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
@Inject DataCenterIpAddressDaoImpl _privateIpAddressDao;
@Inject VMInstanceDao _vmInstanceDao;
@Inject AccountDao _accountDao;
@Inject DomainDao _domainDao;
@Inject EventDao _eventDao;
@Inject UserDao _userDao;
public boolean _premium;
@ -973,8 +975,9 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
}
}
public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws InvalidParameterValueException, InternalErrorException {
public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP, Long domainId) throws InvalidParameterValueException, InternalErrorException {
//check for hypervisor type to be xenserver
String hypervisorType = _configDao.getValue("hypervisor.type");
@ -988,7 +991,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
throw new InternalErrorException("For adding an untagged vlan, please set up xen.public.network.device");
}
}
}
DataCenterVO zone;
@ -1015,8 +1017,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
}
// Check that the pod ID is valid
HostPodVO pod = null;
if (podId != null && ((pod = _podDao.findById(podId)) == null)) {
if (podId != null && ((_podDao.findById(podId)) == null)) {
throw new InvalidParameterValueException("Please specify a valid pod.");
}
@ -1032,19 +1033,22 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
}
else
{
// VLANs for an account must be tagged
// VLANs for an account/domain must be tagged
if (vlanId.equals(Vlan.UNTAGGED)) {
throw new InvalidParameterValueException("Direct Attached VLANs for an account must be tagged.");
}
if(accountId!=null)
{
if(accountId != null || domainId != null) {
// Check that the account ID is valid
AccountVO account;
if ((account = _accountDao.findById(accountId)) == null) {
if (accountId != null && _accountDao.findById(accountId) == null) {
throw new InvalidParameterValueException("Please specify a valid account.");
}
//Check that domainId is valid
if (domainId != null && _domainDao.findById(domainId) == null) {
throw new InvalidParameterValueException("Please specify a valid domain");
}
// Make sure there aren't any pod VLANs in this zone
List<HostPodVO> podsInZone = _podDao.listByDataCenterId(zone.getId());
for (HostPodVO pod : podsInZone) {
@ -1052,15 +1056,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
throw new InvalidParameterValueException("Zone " + zone.getName() + " already has pod VLANs. A zone may contain either pod VLANs or account VLANs, but not both.");
}
}
// Make sure the specified account isn't already assigned to a VLAN in this zone
// List<AccountVlanMapVO> accountVlanMaps = _accountVlanMapDao.listAccountVlanMapsByAccount(accountId);
// for (AccountVlanMapVO accountVlanMap : accountVlanMaps) {
// VlanVO vlan = _vlanDao.findById(accountVlanMap.getVlanDbId());
// if (vlan.getDataCenterId() == zone.getId().longValue()) {
// throw new InvalidParameterValueException("The account " + account.getAccountName() + " is already assigned to the VLAN with ID " + vlan.getVlanId() + " in zone " + zone.getName() + ".");
// }
// }
}
}
}
@ -1166,7 +1161,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
_vlanDao.delete(vlan.getId());
throw new InternalErrorException("Failed to save IP range. Please contact Cloud Support."); //It can be Direct IP or Public IP.
}
}else if (!savePublicIPRange(startIP, endIP, zoneId, vlan.getId())) {
} else if (!savePublicIPRange(startIP, endIP, zoneId, vlan.getId())) {
deletePublicIPRange(vlan.getId());
_vlanDao.delete(vlan.getId());
throw new InternalErrorException("Failed to save IP range. Please contact Cloud Support."); //It can be Direct IP or Public IP.
@ -1174,8 +1169,12 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
if (accountId != null) {
// This VLAN is account-specific, so create an AccountVlanMapVO entry
AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(accountId, vlan.getId());
AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(accountId, vlan.getId(), null);
_accountVlanMapDao.persist(accountVlanMapVO);
} else if (domainId != null) {
// This VLAN is domain-specific, so create an AccountVlanMapVO entry
AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(null, vlan.getId(), domainId);
_accountVlanMapDao.persist(accountVlanMapVO);
} else if (podId != null) {
// This VLAN is pod-wide, so create a PodVlanMapVO entry
PodVlanMapVO podVlanMapVO = new PodVlanMapVO(podId, vlan.getId());
@ -1191,7 +1190,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
"accountId=" + accountId, "podId=" + podId,
"vlanId=" + vlanId, "vlanGateway=" + vlanGateway,
"vlanNetmask=" + vlanNetmask, "startIP=" + startIP,
"endIP=" + endIP);
"endIP=" + endIP, "domainId=" + domainId);
return vlan;
}
@ -1690,4 +1689,32 @@ public class ConfigurationManagerImpl implements ConfigurationManager {
return ipRanges;
}
@Override
public Map<Integer, List<VlanVO>> listDomainDirectVlans(long domainId, long zoneId) {
Map<Integer, List<VlanVO>> vlansForDomain = new HashMap<Integer, List<VlanVO>>();
getDomainDirectVlans(vlansForDomain, domainId, zoneId);
return vlansForDomain;
}
private void getDomainDirectVlans(Map<Integer, List<VlanVO>> vlans, long domainId, long zoneId) {
//Domain level vlans include:
//* vlans belonging to this domain
//* vlans belonging to all domain
DomainVO domain = _domainDao.findById(domainId);
if (domain == null) {
return;
}
List<VlanVO> vlan = _vlanDao.listVlansForDomainByTypeAndZone(zoneId, domainId, VlanType.DirectAttached);
if (vlan != null && !vlan.isEmpty()) {
vlans.put(domain.getLevel(), vlan);
}
if (domain.getParent() != null) {
getDomainDirectVlans(vlans, domain.getParent(), zoneId);
} else {
return;
}
}
}

View File

@ -1716,7 +1716,7 @@ public class ManagementServerImpl implements ManagementServer {
@DB
@Override
public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws Exception{
public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP, Long domainId) throws Exception{
if(accountId != null && vlanType == VlanType.VirtualNetwork){
long ipResourceLimit = _accountMgr.findCorrectResourceLimit( _accountDao.findById(accountId), ResourceType.public_ip);
@ -1729,7 +1729,7 @@ public class ManagementServerImpl implements ManagementServer {
Transaction txn = Transaction.currentTxn();
try{
txn.start();
VlanVO vlan = _configMgr.createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIP, endIP);
VlanVO vlan = _configMgr.createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIP, endIP, null);
associateIpAddressListToAccount(userId, accountId, zoneId, vlan.getId());
txn.commit();
return vlan;
@ -1744,7 +1744,7 @@ public class ManagementServerImpl implements ManagementServer {
throw new Exception(e.getMessage());
}
}
return _configMgr.createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIP, endIP);
return _configMgr.createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIP, endIP, domainId);
}
@Override
@ -3820,6 +3820,7 @@ public class ManagementServerImpl implements ManagementServer {
//if account doesn't have direct ip addresses and there are no direct Zone wide vlans, return virtual service offerings only
//If untagged network is enabled, return only direct service offerings
List<VlanVO> accountDirectVlans = new ArrayList<VlanVO>();
Map<Integer, List<VlanVO>> domainDirectVlans = new HashMap<Integer, List<VlanVO>>();
List<VlanVO> zoneDirectVlans = new ArrayList<VlanVO>();
boolean isDirectUntaggedNetworkEnabled = new Boolean(_configDao.getValue("direct.attach.untagged.vlan.enabled"));
@ -3828,9 +3829,11 @@ public class ManagementServerImpl implements ManagementServer {
sc.addAnd("guestIpType", SearchCriteria.Op.EQ, GuestIpType.DirectSingle);
} else {
if (accountId != null && zoneId != null) {
accountDirectVlans = _vlanDao.listVlansForAccountByType(null, ((Long)accountId).longValue(), VlanType.DirectAttached);
AccountVO account = _accountDao.findById((Long)accountId);
accountDirectVlans = _vlanDao.listVlansForAccountByType((Long)zoneId, ((Long)accountId).longValue(), VlanType.DirectAttached);
domainDirectVlans = _configMgr.listDomainDirectVlans(account.getDomainId(), (Long)zoneId);
zoneDirectVlans = listZoneWideVlansByType(VlanType.DirectAttached, (Long)zoneId);
if (accountDirectVlans.isEmpty() && zoneDirectVlans.isEmpty()) {
if (accountDirectVlans.isEmpty() && domainDirectVlans.isEmpty() && zoneDirectVlans.isEmpty()) {
sc.addAnd("guestIpType", SearchCriteria.Op.EQ, GuestIpType.Virtualized);
}
} else if (zoneId != null) {
@ -6243,6 +6246,26 @@ public class ManagementServerImpl implements ManagementServer {
}
}
}
//delete domain specific vlans
List<VlanVO> domainVlans = _vlanDao.listVlansForDomainByTypeAndZone(null, domainId, VlanType.DirectAttached);
s_logger.debug("Found " + domainVlans.size() + " vlans to cleanup as a part of domain id=" + domainId + " cleanup.");
boolean allVlansDeleted = true;
for (VlanVO vlan : domainVlans) {
try {
allVlansDeleted = _configMgr.deleteVlanAndPublicIpRange(User.UID_SYSTEM, vlan.getId());
} catch (Exception e) {
s_logger.warn("Failed to delete vlan id=" + vlan.getId() + " as a part of domain cleanup due to exception: ", e);
allVlansDeleted = false;
}
}
if (!allVlansDeleted) {
s_logger.warn("Failed to cleanup domain specific vlans as a part of domain cleanup");
success = false;
} else {
s_logger.debug("Successfully deleted vlans as a part of domain id=" + domainId + " cleanup.");
}
// delete the domain itself
boolean deleteDomainSuccess = _domainDao.remove(domainId);
@ -8433,5 +8456,15 @@ public class ManagementServerImpl implements ManagementServer {
}
return _hashKey;
}
@Override
public Long getDomainIdForVlan(long vlanDbId) {
List<AccountVlanMapVO> accountVlanMaps = _accountVlanMapDao.listAccountVlanMapsByVlan(vlanDbId);
if (accountVlanMaps.isEmpty()) {
return null;
} else {
return accountVlanMaps.get(0).getDomainId();
}
}
}

View File

@ -77,6 +77,7 @@ import com.cloud.async.executor.VMOperationListener;
import com.cloud.async.executor.VMOperationParam;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.configuration.dao.ResourceLimitDao;
@ -88,6 +89,7 @@ import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventState;
import com.cloud.event.EventTypes;
@ -227,6 +229,7 @@ public class UserVmManagerImpl implements UserVmManager {
@Inject StoragePoolDao _storagePoolDao;
@Inject VMTemplateHostDao _vmTemplateHostDao;
@Inject NetworkGroupManager _networkGroupManager;
@Inject ConfigurationManager _configMgr;
@Inject ServiceOfferingDao _serviceOfferingDao;
@Inject EventDao _eventDao = null;
private IpAddrAllocator _IpAllocator;
@ -2485,28 +2488,37 @@ public class UserVmManagerImpl implements UserVmManager {
Set<Long> avoids = new HashSet<Long>();
VlanVO guestVlan = null;
List<VlanVO> vlansForAccount = _vlanDao.listVlansForAccountByType(dc.getId(), account.getId(), VlanType.DirectAttached);
Map<Integer, List<VlanVO>> vlansForDomain = _configMgr.listDomainDirectVlans(account.getDomainId(), dc.getId());
List<VlanVO> vlansForPod = null;
List<VlanVO> zoneWideVlans = null;
int freeIpCount = 0;
boolean forAccount = false;
boolean forDomain = false;
if (vlansForAccount.size() > 0) {
//iterate over the vlan to see if there are actually addresses available
for(VlanVO vlan:vlansForAccount)
{
for(VlanVO vlan : vlansForAccount) {
freeIpCount = (_ipAddressDao.countIPs(dc.getId(), vlan.getId(), false) - _ipAddressDao.countIPs(dc.getId(), vlan.getId(), true));
if(freeIpCount>0)
{
if(freeIpCount>0) {
forAccount = true;
guestVlan = vlan;
s_logger.debug("Found account specific guest vlan id=" + guestVlan.getId() + " for vm deployment");
break;
}
}
}
if (!forAccount && vlansForDomain != null && !vlansForDomain.isEmpty()) {
guestVlan = getDomainDirectVlan(account.getDomainId(), dc);
if (guestVlan != null) {
s_logger.debug("Found domain level vlan id=" + guestVlan.getId() + " for vm deployment");
forDomain = true;
}
}
if(!forAccount)
if(!forAccount && !forDomain)
{
//list zone wide vlans that are direct attached and tagged
//if exists pick random one
@ -2537,7 +2549,7 @@ public class UserVmManagerImpl implements UserVmManager {
s_logger.debug("Attempting to create direct attached vm in pod " + pod.first().getName());
}
avoids.add(pod.first().getId());
if (!forAccount && !forZone) {
if (!forAccount && !forDomain && !forZone) {
vlansForPod = _vlanDao.listVlansForPodByType(pod.first().getId(), VlanType.DirectAttached);
if (vlansForPod.size() < 1) {
if (s_logger.isDebugEnabled()) {
@ -2548,6 +2560,11 @@ public class UserVmManagerImpl implements UserVmManager {
guestVlan = vlansForPod.get(0);//FIXME: iterate over all vlans
}
if (guestVlan == null) {
s_logger.debug("Unable to find Direct IP address in the pod id=" + pod.first().getId() + " to use for vm deployment for account id=" + account.getId() + "; checking other pods");
continue;
}
List<DomainRouterVO> rtrs = _routerDao.listByVlanDbId(guestVlan.getId());
assert rtrs.size() < 2 : "How did we get more than one router per vlan?";
if (rtrs.size() > 0) {
@ -2564,43 +2581,56 @@ public class UserVmManagerImpl implements UserVmManager {
routerId = router.getId();
}
String guestIp = null;
if(forAccount)
{
for(VlanVO vlanForAcc : vlansForAccount)
{
guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForAcc.getId(), false);
if(guestIp!=null)
break; //got an ip
}
}
else if(!forAccount && !forZone)
{
//i.e. for pod
for(VlanVO vlanForPod : vlansForPod)
{
guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForPod.getId(), false);
if(guestIp!=null)
break;//got an ip
}
}
else
{
//for zone
for(VlanVO vlanForZone : zoneWideVlans)
{
guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId().longValue(), vlanForZone.getId(), false);
if(guestIp!=null)
break;//found an ip
}
//First try to get guest ip address from the guest vlan; if the operation fails, go through account/domain/pod/zone specific vlans again
guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), guestVlan.getId(), false);
if (guestIp == null) {
if (forAccount) {
for(VlanVO vlanForAcc : vlansForAccount) {
guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForAcc.getId(), false);
if(guestIp != null)
break; //got an ip
}
} else if (forDomain) {
if (vlansForDomain != null && !vlansForDomain.isEmpty()) {
guestIp = getDomainDirectIp(account.getDomainId(), dc, account);
if(guestIp != null) {
break; //got an ip
}
}
} else if(!forAccount && !forDomain && !forZone) {
//i.e. for pod
for(VlanVO vlanForPod : vlansForPod)
{
guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId(), vlanForPod.getId(), false);
if(guestIp!=null)
break;//got an ip
}
} else {
//for zone
for(VlanVO vlanForZone : zoneWideVlans)
{
guestIp = _ipAddressDao.assignIpAddress(accountId, account.getDomainId().longValue(), vlanForZone.getId(), false);
if(guestIp!=null)
break;//found an ip
}
}
}
VlanVO guestIpVlan = null;
if (guestIp == null) {
s_logger.debug("No guest IP available in pod id=" + pod.first().getId());
continue;
} else {
IPAddressVO ip = _ipAddressDao.findById(guestIp);
guestIpVlan = _vlanDao.findById(ip.getVlanDbId());
}
s_logger.debug("Acquired a guest IP, ip=" + guestIp);
String guestMacAddress = macAddresses[0];
String externalMacAddress = macAddresses[1];
@ -2621,7 +2651,7 @@ public class UserVmManagerImpl implements UserVmManager {
vm = _vmDao.persist(vm);
*/
vm.setDomainRouterId(routerId);
vm.setGuestNetmask(guestVlan.getVlanNetmask());
vm.setGuestNetmask(guestIpVlan.getVlanNetmask());
vm.setGuestIpAddress(guestIp);
vm.setGuestMacAddress(guestMacAddress);
vm.setPodId(pod.first().getId());
@ -3010,6 +3040,56 @@ public class UserVmManagerImpl implements UserVmManager {
return usedCapacity;
}
protected VlanVO getDomainDirectVlan(long domainId, DataCenterVO dc) {
//Domain level vlans include:
//* vlans belonging to this domain
//* vlans belonging to all parent domains
DomainVO domain = _domainDao.findById(domainId);
VlanVO guestVlan = null;
List<VlanVO> vlansForDomain = _vlanDao.listVlansForDomainByTypeAndZone(dc.getId(), domainId, VlanType.DirectAttached);
for(VlanVO vlan : vlansForDomain) {
long freeIpCount = (_ipAddressDao.countIPs(dc.getId(), vlan.getId(), false) - _ipAddressDao.countIPs(dc.getId(), vlan.getId(), true));
if(freeIpCount>0) {
guestVlan = vlan;
break;
}
}
if (guestVlan == null && domain.getParent() != null) {
guestVlan = getDomainDirectVlan(domain.getParent(), dc);
}
return guestVlan;
}
protected String getDomainDirectIp(long domainId, DataCenterVO dc, AccountVO account) {
//Domain level ips include:
//* ips belonging to vlans of this domain
//* ips belonging to vlans belonging to all parent domains
DomainVO domain = _domainDao.findById(domainId);
String guestIp = null;
List<VlanVO> vlansForDomain = _vlanDao.listVlansForDomainByTypeAndZone(dc.getId(), domainId, VlanType.DirectAttached);
for(VlanVO vlan : vlansForDomain) {
guestIp = _ipAddressDao.assignIpAddress(account.getId(), account.getDomainId(), vlan.getId(), false);
if(guestIp != null) {
s_logger.debug("Got direct ip address " + guestIp + " from domain level vlan id=" + vlan.getId() + " for vm deployment");
break; //got an ip
}
}
if (guestIp == null && domain.getParent() != null) {
guestIp = getDomainDirectIp(domain.getParent(), dc, account);
}
return guestIp;
}
}

View File

@ -167,6 +167,9 @@ ALTER TABLE `cloud`.`pod_vlan_map` ADD INDEX `i_pod_vlan_map__vlan_id`(`vlan_db_
ALTER TABLE `cloud`.`account_vlan_map` ADD CONSTRAINT `fk_account_vlan_map__account_id` FOREIGN KEY `fk_account_vlan_map__account_id` (`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`account_vlan_map` ADD INDEX `i_account_vlan_map__account_id`(`account_id`);
ALTER TABLE `cloud`.`account_vlan_map` ADD CONSTRAINT `fk_account_vlan_map__domain_id` FOREIGN KEY `fk_account_vlan_map__domain_id` (`domain_id`) REFERENCES `domain` (`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`account_vlan_map` ADD INDEX `i_account_vlan_map__domain_id`(`domain_id`);
ALTER TABLE `cloud`.`account_vlan_map` ADD CONSTRAINT `fk_account_vlan_map__vlan_id` FOREIGN KEY `fk_account_vlan_map__vlan_id` (`vlan_db_id`) REFERENCES `vlan` (`id`) ON DELETE CASCADE;
ALTER TABLE `cloud`.`account_vlan_map` ADD INDEX `i_account_vlan_map__vlan_id`(`vlan_db_id`);

View File

@ -242,8 +242,9 @@ CREATE TABLE `cloud`.`pod_vlan_map` (
CREATE TABLE `cloud`.`account_vlan_map` (
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
`account_id` bigint unsigned NOT NULL COMMENT 'account id. foreign key to account table',
`account_id` bigint unsigned COMMENT 'account id. foreign key to account table',
`vlan_db_id` bigint unsigned NOT NULL COMMENT 'database id of vlan. foreign key to vlan table',
`domain_id` bigint unsigned COMMENT 'domain id. foreign key to domain table',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;