http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef22b42b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java 
b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
index 252cf8a..cdd46ce 100644
--- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
+++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
@@ -30,6 +30,7 @@ import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
 import org.apache.cloudstack.affinity.AffinityGroupProcessor;
+import org.apache.cloudstack.affinity.AffinityGroupService;
 import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
 import org.apache.cloudstack.affinity.AffinityGroupVO;
 import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
@@ -66,6 +67,7 @@ import com.cloud.deploy.dao.PlannerHostReservationDao;
 import com.cloud.exception.AffinityConflictException;
 import com.cloud.exception.ConnectionException;
 import com.cloud.exception.InsufficientServerCapacityException;
+import com.cloud.exception.PermissionDeniedException;
 import com.cloud.host.Host;
 import com.cloud.host.HostVO;
 import com.cloud.host.Status;
@@ -133,6 +135,8 @@ public class DeploymentPlanningManagerImpl extends 
ManagerBase implements Deploy
     @Inject
     protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
     @Inject
+    AffinityGroupService _affinityGroupService;
+    @Inject
     DataCenterDao _dcDao;
     @Inject
     PlannerHostReservationDao _plannerHostReserveDao;
@@ -215,7 +219,9 @@ public class DeploymentPlanningManagerImpl extends 
ManagerBase implements Deploy
             }
         }
 
-        checkForNonDedicatedResources(vmProfile, dc, avoids);
+        if (vm.getType() == VirtualMachine.Type.User) {
+            checkForNonDedicatedResources(vmProfile, dc, avoids);
+        }
         if (s_logger.isDebugEnabled()) {
             s_logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() + 
", clusters: "
                     + avoids.getClustersToAvoid() + ", hosts: " + 
avoids.getHostsToAvoid());
@@ -444,20 +450,48 @@ public class DeploymentPlanningManagerImpl extends 
ManagerBase implements Deploy
 
     private void checkForNonDedicatedResources(VirtualMachineProfile 
vmProfile, DataCenter dc, ExcludeList avoids) {
         boolean isExplicit = false;
-        VirtualMachine vm = vmProfile.getVirtualMachine();
-        // check affinity group of type Explicit dedication exists
+        VirtualMachine vm = vmProfile.getVirtualMachine();
+
+        // check if zone is dedicated. if yes check if vm owner has acess to 
it.
+        DedicatedResourceVO dedicatedZone = 
_dedicatedDao.findByZoneId(dc.getId());
+        if (dedicatedZone != null) {
+            long accountDomainId = vmProfile.getOwner().getDomainId();
+            long accountId = vmProfile.getOwner().getAccountId();
+
+            // If a zone is dedicated to an account then all hosts in this zone
+            // will be explicitly dedicated to
+            // that account. So there won't be any shared hosts in the zone, 
the
+            // only way to deploy vms from that
+            // account will be to use explicit dedication affinity group.
+            if (dedicatedZone.getAccountId() != null) {
+                if (dedicatedZone.getAccountId().equals(accountId)) {
+                    return;
+                } else {
+                    throw new CloudRuntimeException("Failed to deploy VM, Zone 
" + dc.getName()
+                            + " not available for the user account " + 
vmProfile.getOwner());
+                }
+            }
+
+            // if zone is dedicated to a domain. Check owner's access to the
+            // domain level dedication group
+            if 
(!_affinityGroupService.isAffinityGroupAvailableInDomain(dedicatedZone.getAffinityGroupId(),
+                    accountDomainId)) {
+                throw new CloudRuntimeException("Failed to deploy VM, Zone " + 
dc.getName()
+                        + " not available for the user domain " + 
vmProfile.getOwner());
+            }
+
+        }
+
+        // check affinity group of type Explicit dedication exists. If No put
+        // dedicated pod/cluster/host in avoid list
         List<AffinityGroupVMMapVO> vmGroupMappings = 
_affinityGroupVMMapDao.findByVmIdType(vm.getId(), "ExplicitDedication");
 
         if (vmGroupMappings != null && !vmGroupMappings.isEmpty()){
             isExplicit = true;
         }
 
-        if (!isExplicit && vm.getType() == VirtualMachine.Type.User) {
+        if (!isExplicit) {
             //add explicitly dedicated resources in avoidList
-            DedicatedResourceVO dedicatedZone = 
_dedicatedDao.findByZoneId(dc.getId());
-            if (dedicatedZone != null && dedicatedZone.getDomainId() != null) {
-                throw new CloudRuntimeException("Failed to deploy VM. Zone " + 
dc.getName() + " is dedicated . Please use Explicit Dedication Affinity Group");
-            }
 
             List<Long> allPodsInDc = _podDao.listAllPods(dc.getId());
             List<Long> allDedicatedPods = _dedicatedDao.listAllPods();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef22b42b/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java 
b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 1ce3f20..53211e1 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -2503,20 +2503,9 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
                             + zone.getId());
         }
 
-        boolean isExplicit = false;
-        // check affinity group type Explicit dedication
-        if (affinityGroupIdList != null) {
-            for (Long affinityGroupId : affinityGroupIdList) {
-                AffinityGroupVO ag = 
_affinityGroupDao.findById(affinityGroupId);
-                String agType = ag.getType();
-                if (agType.equals("ExplicitDedication")) {
-                    isExplicit = true;
-                }
-            }
-        }
         // check if zone is dedicated
         DedicatedResourceVO dedicatedZone = 
_dedicatedDao.findByZoneId(zone.getId());
-        if (isExplicit && dedicatedZone != null) {
+        if (dedicatedZone != null) {
             DomainVO domain = _domainDao.findById(dedicatedZone.getDomainId());
             if (domain == null) {
                 throw new CloudRuntimeException("Unable to find the domain "

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef22b42b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java 
b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
index 06c04cb..c6f1b92 100644
--- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
+++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java
@@ -140,6 +140,7 @@ public class AffinityGroupServiceImpl extends ManagerBase 
implements AffinityGro
 
         ControlledEntity.ACLType aclType = null;
         Account owner = null;
+        boolean domainLevel = false;
 
         if (account != null && domainId != null) {
 
@@ -166,6 +167,7 @@ public class AffinityGroupServiceImpl extends ManagerBase 
implements AffinityGro
             // domain level group, owner is SYSTEM.
             owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM);
             aclType = ControlledEntity.ACLType.Domain;
+            domainLevel = true;
 
         } else {
             owner = caller;
@@ -176,6 +178,10 @@ public class AffinityGroupServiceImpl extends ManagerBase 
implements AffinityGro
             throw new InvalidParameterValueException("Unable to create 
affinity group, a group with name "
                     + affinityGroupName + " already exisits.");
         }
+        if (domainLevel && 
_affinityGroupDao.findDomainLevelGroupByName(domainId, affinityGroupName) != 
null) {
+            throw new InvalidParameterValueException("Unable to create 
affinity group, a group with name "
+                    + affinityGroupName + " already exisits under the 
domain.");
+        }
 
         Transaction txn = Transaction.currentTxn();
         txn.start();
@@ -185,7 +191,9 @@ public class AffinityGroupServiceImpl extends ManagerBase 
implements AffinityGro
         _affinityGroupDao.persist(group);
 
         if (domainId != null && aclType == ACLType.Domain) {
-            AffinityGroupDomainMapVO domainMap = new 
AffinityGroupDomainMapVO(group.getId(), domainId, false);
+            boolean subDomainAccess = false;
+            subDomainAccess = processor.subDomainAccess();
+            AffinityGroupDomainMapVO domainMap = new 
AffinityGroupDomainMapVO(group.getId(), domainId, subDomainAccess);
             _affinityGroupDomainMapDao.persist(domainMap);
         }
 
@@ -251,6 +259,12 @@ public class AffinityGroupServiceImpl extends ManagerBase 
implements AffinityGro
             _affinityGroupVMMapDao.remove(sc);
         }
 
+        // call processor to handle the group delete
+        AffinityGroupProcessor processor = 
getAffinityGroupProcessorForType(group.getType());
+        if (processor != null) {
+            processor.handleDeleteGroup(group);
+        }
+
         _affinityGroupDao.expunge(affinityGroupId);
         txn.commit();
 
@@ -324,8 +338,9 @@ public class AffinityGroupServiceImpl extends ManagerBase 
implements AffinityGro
         if (componentMap.size() > 0) {
             for (Entry<String, AffinityGroupProcessor> entry : 
componentMap.entrySet()) {
                 AffinityGroupProcessor processor = entry.getValue();
-                if (processor.isAdminControlledGroup() && 
!_accountMgr.isRootAdmin(caller.getType())) {
-                    continue;
+                if (processor.isAdminControlledGroup()) {
+                    continue; // we dont list the type if this group can be
+                              // created only as an admin/system operation.
                 }
                 types.add(processor.getType());
             }
@@ -469,6 +484,15 @@ public class AffinityGroupServiceImpl extends ManagerBase 
implements AffinityGro
         return false;
     }
 
+    private AffinityGroupProcessor getAffinityGroupProcessorForType(String 
affinityGroupType) {
+        for (AffinityGroupProcessor processor : _affinityProcessors) {
+            if (affinityGroupType != null && 
affinityGroupType.equals(processor.getType())) {
+                return processor;
+            }
+        }
+        return null;
+    }
+
     @Override
     public boolean isAffinityGroupAvailableInDomain(long affinityGroupId, long 
domainId) {
         Long groupDomainId = null;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef22b42b/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index ba9932f..5887caa 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -447,6 +447,7 @@ CREATE TABLE `cloud`.`dedicated_resources` (
   `host_id` bigint unsigned COMMENT 'host id',
   `domain_id` bigint unsigned COMMENT 'domain id of the domain to which 
resource is dedicated',
   `account_id` bigint unsigned COMMENT 'account id of the account to which 
resource is dedicated',
+  `affinity_group_id` bigint unsigned NOT NULL COMMENT 'affinity group id 
associated',
   PRIMARY KEY (`id`),
   CONSTRAINT `fk_dedicated_resources__data_center_id` FOREIGN KEY 
(`data_center_id`) REFERENCES `cloud`.`data_center`(`id`) ON DELETE CASCADE,
   CONSTRAINT `fk_dedicated_resources__pod_id` FOREIGN KEY (`pod_id`) 
REFERENCES `cloud`.`host_pod_ref`(`id`),
@@ -454,8 +455,10 @@ CREATE TABLE `cloud`.`dedicated_resources` (
   CONSTRAINT `fk_dedicated_resources__host_id` FOREIGN KEY (`host_id`) 
REFERENCES `cloud`.`host`(`id`),
   CONSTRAINT `fk_dedicated_resources__domain_id` FOREIGN KEY (`domain_id`) 
REFERENCES `domain`(`id`),
   CONSTRAINT `fk_dedicated_resources__account_id` FOREIGN KEY (`account_id`) 
REFERENCES `account`(`id`),
+  CONSTRAINT `fk_dedicated_resources__affinity_group_id` FOREIGN KEY 
(`affinity_group_id`) REFERENCES `affinity_group`(`id`) ON DELETE CASCADE,
   INDEX `i_dedicated_resources_domain_id`(`domain_id`),
   INDEX `i_dedicated_resources_account_id`(`account_id`),
+  INDEX `i_dedicated_resources_affinity_group_id`(`affinity_group_id`),
   CONSTRAINT `uc_dedicated_resources__uuid` UNIQUE (`uuid`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
@@ -486,9 +489,6 @@ ALTER TABLE `cloud`.`event` ADD COLUMN `archived` 
tinyint(1) unsigned NOT NULL D
 INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 
'management-server', 'alert.purge.interval', '86400', 'The interval (in 
seconds) to wait before running the alert purge thread');
 INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 
'management-server', 'alert.purge.delay', '0', 'Alerts older than specified 
number days will be purged. Set this value to 0 to never delete alerts');
 
-INSERT INTO `cloud`.`dedicated_resources` (`data_center_id`, `domain_id`) 
SELECT `id`, `domain_id` FROM `cloud`.`data_center` WHERE `domain_id` IS NOT 
NULL;
-UPDATE `cloud`.`data_center` SET `domain_id` = NULL WHERE `domain_id` IS NOT 
NULL;
-
 DROP VIEW IF EXISTS `cloud`.`event_view`;
 CREATE VIEW `cloud`.`event_view` AS
     select

Reply via email to