diff --git a/api/src/com/cloud/exception/PermissionDeniedException.java b/api/src/com/cloud/exception/PermissionDeniedException.java index 0dba3039654..70d3971885d 100644 --- a/api/src/com/cloud/exception/PermissionDeniedException.java +++ b/api/src/com/cloud/exception/PermissionDeniedException.java @@ -17,6 +17,10 @@ */ package com.cloud.exception; +import java.util.List; + +import com.cloud.acl.ControlledEntity; +import com.cloud.user.Account; import com.cloud.utils.SerialVersionUID; import com.cloud.utils.exception.CloudRuntimeException; @@ -35,5 +39,30 @@ public class PermissionDeniedException extends CloudRuntimeException { protected PermissionDeniedException() { super(); } - + + List violations; + Account account; + + public PermissionDeniedException(String message, Account account, List violations) { + super(message); + this.violations = violations; + this.account = account; + } + + public Account getAccount() { + return account; + } + + public List getEntitiesInViolation() { + return violations; + } + + public void addDetails(Account account, List violations) { + this.account = account; + this.violations = violations; + } + + public void addViolations(List violations) { + this.violations = violations; + } } diff --git a/core/src/com/cloud/dc/DataCenterVnetVO.java b/core/src/com/cloud/dc/DataCenterVnetVO.java index 40da1097200..6b926f5baf7 100755 --- a/core/src/com/cloud/dc/DataCenterVnetVO.java +++ b/core/src/com/cloud/dc/DataCenterVnetVO.java @@ -35,7 +35,7 @@ public class DataCenterVnetVO { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id") - Long id; + long id; @Column(name="taken", nullable=true) @Temporal(value=TemporalType.TIMESTAMP) @@ -50,6 +50,9 @@ public class DataCenterVnetVO { @Column(name="account_id") protected Long accountId; + @Column(name="reservation_id") + protected String reservationId; + public Date getTakenAt() { return takenAt; } @@ -64,7 +67,7 @@ public class DataCenterVnetVO { this.takenAt = null; } - public Long getId() { + public long getId() { return id; } @@ -72,6 +75,14 @@ public class DataCenterVnetVO { return vnet; } + public String getReservationId() { + return reservationId; + } + + public void setReservationId(String reservationId) { + this.reservationId = reservationId; + } + public Long getAccountId() { return accountId; } diff --git a/core/src/com/cloud/dc/dao/DataCenterDao.java b/core/src/com/cloud/dc/dao/DataCenterDao.java index a55dfcb8ee3..66a21d0b727 100644 --- a/core/src/com/cloud/dc/dao/DataCenterDao.java +++ b/core/src/com/cloud/dc/dao/DataCenterDao.java @@ -35,9 +35,9 @@ public interface DataCenterDao extends GenericDao { String[] getNextAvailableMacAddressPair(long id, long mask); String allocatePrivateIpAddress(long id, long podId, long instanceId, String reservationId); String allocateLinkLocalIpAddress(long id, long podId, long instanceId, String reservationId); - String allocateVnet(long dcId, long accountId); + String allocateVnet(long dcId, long accountId, String reservationId); - void releaseVnet(String vnet, long dcId, long accountId); + void releaseVnet(String vnet, long dcId, long accountId, String reservationId); void releasePrivateIpAddress(String ipAddress, long dcId, Long instanceId); void releasePrivateIpAddress(long nicId, String reservationId); void releaseLinkLocalIpAddress(String ipAddress, long dcId, Long instanceId); diff --git a/core/src/com/cloud/dc/dao/DataCenterDaoImpl.java b/core/src/com/cloud/dc/dao/DataCenterDaoImpl.java index 43c817eaf2f..8745ed96484 100644 --- a/core/src/com/cloud/dc/dao/DataCenterDaoImpl.java +++ b/core/src/com/cloud/dc/dao/DataCenterDaoImpl.java @@ -94,8 +94,8 @@ public class DataCenterDaoImpl extends GenericDaoBase implem } @Override - public void releaseVnet(String vnet, long dcId, long accountId) { - _vnetAllocDao.release(vnet, dcId, accountId); + public void releaseVnet(String vnet, long dcId, long accountId, String reservationId) { + _vnetAllocDao.release(vnet, dcId, accountId, reservationId); } @Override @@ -134,8 +134,8 @@ public class DataCenterDaoImpl extends GenericDaoBase implem } @Override - public String allocateVnet(long dataCenterId, long accountId) { - DataCenterVnetVO vo = _vnetAllocDao.take(dataCenterId, accountId); + public String allocateVnet(long dataCenterId, long accountId, String reservationId) { + DataCenterVnetVO vo = _vnetAllocDao.take(dataCenterId, accountId, reservationId); if (vo == null) { return null; } diff --git a/core/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java b/core/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java index da628ac55f4..efd1248b5f8 100755 --- a/core/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java +++ b/core/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java @@ -23,6 +23,7 @@ import java.util.Date; import java.util.List; import com.cloud.dc.DataCenterVnetVO; +import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; @@ -34,6 +35,7 @@ import com.cloud.utils.exception.CloudRuntimeException; * DataCenterVnetDaoImpl maintains the one-to-many relationship between * data center and the vnet that appears within its network. */ +@DB(txn=false) public class DataCenterVnetDaoImpl extends GenericDaoBase implements GenericDao { private final SearchBuilder FreeVnetSearch; private final SearchBuilder VnetDcSearch; @@ -53,6 +55,7 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase sc = VnetDcSearch.create(); + sc.setParameters("dc", dcId); + + remove(sc); } - public DataCenterVnetVO take(long dcId, long accountId) { + @DB + public DataCenterVnetVO take(long dcId, long accountId, String reservationId) { SearchCriteria sc = FreeVnetSearch.create(); sc.setParameters("dc", dcId); Date now = new Date(); Transaction txn = Transaction.currentTxn(); - try { - txn.start(); - DataCenterVnetVO vo = lockOneRandomRow(sc, true); - if (vo == null) { - return null; - } - - vo.setTakenAt(now); - vo.setAccountId(accountId); - update(vo.getId(), vo); - txn.commit(); - return vo; - - } catch (Exception e) { - throw new CloudRuntimeException("Caught Exception ", e); + txn.start(); + DataCenterVnetVO vo = lockOneRandomRow(sc, true); + if (vo == null) { + return null; } + + vo.setTakenAt(now); + vo.setAccountId(accountId); + vo.setReservationId(reservationId); + update(vo.getId(), vo); + txn.commit(); + return vo; } - public void release(String vnet, long dcId, long accountId) { + public void release(String vnet, long dcId, long accountId, String reservationId) { SearchCriteria sc = VnetDcSearchAllocated.create(); sc.setParameters("vnet", vnet); sc.setParameters("dc", dcId); sc.setParameters("account", accountId); + sc.setParameters("reservation", reservationId); DataCenterVnetVO vo = findOneIncludingRemovedBy(sc); if (vo == null) { @@ -121,6 +116,7 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase> domains = new HashMap>(); + for (ControlledEntity entity : entities) { + List toBeChecked = domains.get(entity.getDomainId()); + if (toBeChecked == null) { + toBeChecked = new ArrayList(); + } + toBeChecked.add(entity); boolean granted = false; for (SecurityChecker checker : _securityCheckers) { if (checker.checkAccess(caller, entity)) { @@ -681,6 +689,21 @@ public class AccountManagerImpl implements AccountManager, AccountService { throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + entity); } } + + for (Map.Entry> domain : domains.entrySet()) { + for (SecurityChecker checker : _securityCheckers) { + Domain d = _domainDao.findById(domain.getKey()); + if (d == null || d.getRemoved() != null) { + throw new PermissionDeniedException("Domain is not found.", caller, domain.getValue()); + } + try { + checker.checkAccess(caller, d); + } catch (PermissionDeniedException e) { + e.addDetails(caller, domain.getValue()); + throw e; + } + } + } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 0682232f665..327113d47b8 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2131,7 +2131,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM if ((vm.getDomainRouterId() != null) && _vmDao.listBy(vm.getDomainRouterId(), State.Starting, State.Running).size() == 0) { DomainRouterVO router = _routerDao.findById(vm.getDomainRouterId()); if (router.getState().equals(State.Stopped)) { - _dcDao.releaseVnet(vnet, router.getDataCenterId(), router.getAccountId()); + _dcDao.releaseVnet(vnet, router.getDataCenterId(), router.getAccountId(), null); } } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 05587b73f56..91c0e1276e0 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -393,6 +393,7 @@ CREATE TABLE `cloud`.`op_dc_ip_address_alloc` ( `data_center_id` bigint unsigned NOT NULL COMMENT 'data center it belongs to', `pod_id` bigint unsigned NOT NULL COMMENT 'pod it belongs to', `instance_id` bigint unsigned NULL COMMENT 'instance id', + `reservation_id` char(40) NULL COMMENT 'reservation id', `taken` datetime COMMENT 'Date taken', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -424,6 +425,7 @@ CREATE TABLE `cloud`.`op_dc_vnet_alloc` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'primary id', `vnet` varchar(18) NOT NULL COMMENT 'vnet', `data_center_id` bigint unsigned NOT NULL COMMENT 'data center the vnet belongs to', + `reservation_id` char(40) NULL COMMENT 'reservation id', `account_id` bigint unsigned NULL COMMENT 'account the vnet belongs to right now', `taken` datetime COMMENT 'Date taken', PRIMARY KEY (`id`)