cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From prachida...@apache.org
Subject [1/4] CLOUDSTACK-681: Dedicated Resources - Explicit Dedication, Private zone, pod, cluster or host. <Patch1>
Date Thu, 30 May 2013 08:07:32 GMT
Updated Branches:
  refs/heads/master 4989f73fd -> 965c7b9c3


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/plugins/dedicated-resources/test/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java
----------------------------------------------------------------------
diff --git a/plugins/dedicated-resources/test/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java b/plugins/dedicated-resources/test/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java
new file mode 100644
index 0000000..3cf5129
--- /dev/null
+++ b/plugins/dedicated-resources/test/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java
@@ -0,0 +1,324 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.dedicated.manager;
+
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import junit.framework.Assert;
+
+import org.apache.cloudstack.test.utils.SpringUtils;
+import org.apache.log4j.Logger;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.ComponentScan.Filter;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.filter.TypeFilter;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.HostPodVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.DedicatedResourceDao;
+import com.cloud.dc.dao.HostPodDao;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.host.dao.HostDao;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.AccountVO;
+import com.cloud.user.UserContext;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.component.ComponentContext;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.dao.UserVmDao;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
+public class DedicatedApiUnitTest {
+    public static final Logger s_logger = Logger.getLogger(DedicatedApiUnitTest.class);
+    @Inject
+    DedicatedResourceManagerImpl _dedicatedService = new DedicatedResourceManagerImpl();
+
+    @Inject
+    AccountManager _acctMgr;
+
+    @Inject
+    AccountDao _accountDao;
+
+    @Inject
+    DomainDao _domainDao;
+
+    @Inject
+    UserVmDao _vmDao;
+
+    @Inject
+    DedicatedResourceDao _dedicatedDao;
+
+    @Inject
+    DataCenterDao _dcDao;
+
+    @Inject
+    HostPodDao _podDao;
+
+    @Inject
+    ClusterDao _clusterDao;
+
+    @Inject
+    HostDao _hostDao;
+
+    @Inject
+    ConfigurationDao _configDao;
+
+    private static long domainId = 5L;
+    private static long accountId = 5L;
+    private static String accountName = "admin";
+
+    @BeforeClass
+    public static void setUp() throws ConfigurationException {
+
+    }
+
+    @Before
+    public void testSetUp() {
+        ComponentContext.initComponentsLifeCycle();
+        AccountVO account = new AccountVO(accountName, domainId, "networkDomain", Account.ACCOUNT_TYPE_NORMAL, "uuid");
+        DomainVO domain = new DomainVO("rootDomain", 5L, 5L, "networkDomain");
+
+        UserContext.registerContext(1, account, null, true);
+        when(_acctMgr.finalizeOwner((Account) anyObject(), anyString(), anyLong(), anyLong())).thenReturn(account);
+        when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(account);
+        when(_accountDao.findById(anyLong())).thenReturn(account);
+        when(_domainDao.findById(domainId)).thenReturn(domain);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void InvalidDomainIDForAccountTest() {
+        _dedicatedService.dedicateZone(10L, domainId, accountName);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void dedicateResourceInvalidAccountIDTest() {
+        _dedicatedService.dedicateZone(10L, domainId, accountName);
+    }
+
+    @Test
+    public void releaseDedicatedZoneInvalidIdTest() {
+        when(_dedicatedDao.findByZoneId(10L)).thenReturn(null);
+        try {
+            _dedicatedService.releaseDedicatedResource(10L, null, null, null);
+        } catch (InvalidParameterValueException e) {
+            Assert.assertTrue(e.getMessage().contains(
+                    "No Dedicated Resource available to release"));
+        }
+    }
+
+/*    @Test
+    public void runDedicateZoneTest() {
+        DataCenterVO dc = new DataCenterVO(10L, "TestZone", "Dedicated",
+                "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", null, null,
+                NetworkType.Basic, null, null);
+        when(_dcDao.findById(10L)).thenReturn(dc);
+        try {
+            List<DedicatedResourceVO> result = _dedicatedService.dedicateZone(10L, domainId, accountName);
+            Assert.assertNotNull(result);
+        } catch (Exception e) {
+            s_logger.info("exception in testing dedication of zone "
+                    + e.toString());
+        }
+    }
+
+    @Test
+    public void runDedicatePodTest() {
+        HostPodVO pod = new HostPodVO("TestPod", 20L, "10.0.0.1", "10.0.0.0",
+                22, null);
+        when(_podDao.findById(10L)).thenReturn(pod);
+        try {
+            List<DedicatedResourceVO> result = _dedicatedService.dedicatePod(10L, domainId, accountName);
+            Assert.assertNotNull(result);
+        } catch (Exception e) {
+            s_logger.info("exception in testing dedication of pod "
+                    + e.toString());
+        }
+    }
+
+    @Test
+    public void runDedicateClusterTest() {
+        ClusterVO cluster = new ClusterVO(10L, 10L, "TestCluster");
+        when(_clusterDao.findById(10L)).thenReturn(cluster);
+        try {
+            List<DedicatedResourceVO> result = _dedicatedService.dedicateCluster(10L, domainId, accountName);
+            Assert.assertNotNull(result);
+        } catch (Exception e) {
+            s_logger.info("exception in testing dedication of cluster "
+                    + e.toString());
+        }
+    }
+
+    @Test
+    public void runDedicateHostTest() {
+        HostVO host = new HostVO(10L, "Host-1", Host.Type.Routing, null,
+                "10.0.0.0", null, null, null, null, null, null, null, null,
+                Status.Up, null, null, null, 10L, 10L, 30L, 10233, null, null,
+                null, 0, null);
+        when(_hostDao.findById(10L)).thenReturn(host);
+        try {
+            List<DedicatedResourceVO> result = _dedicatedService.dedicateHost(10L, domainId, accountName);
+            Assert.assertNotNull(result);
+        } catch (Exception e) {
+            s_logger.info("exception in testing dedication of host "
+                    + e.toString());
+        }
+    }
+*/
+
+    @Test(expected = CloudRuntimeException.class)
+    public void dedicateZoneExistTest() {
+        DedicatedResourceVO dr = new DedicatedResourceVO(10L, null, null, null, domainId, accountId);
+        when(_dedicatedDao.findByZoneId(10L)).thenReturn(dr);
+        _dedicatedService.dedicateZone(10L, domainId, accountName);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void dedicatePodExistTest() {
+        DedicatedResourceVO dr = new DedicatedResourceVO(null, 10L, null, null, domainId, accountId);
+        when(_dedicatedDao.findByPodId(10L)).thenReturn(dr);
+        _dedicatedService.dedicatePod(10L, domainId, accountName);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void dedicateClusterExistTest() {
+        DedicatedResourceVO dr = new DedicatedResourceVO(null, null, 10L, null, domainId, accountId);
+        when(_dedicatedDao.findByClusterId(10L)).thenReturn(dr);
+        _dedicatedService.dedicateCluster(10L, domainId, accountName);
+    }
+
+    @Test(expected = CloudRuntimeException.class)
+    public void dedicateHostExistTest() {
+        DedicatedResourceVO dr = new DedicatedResourceVO(null, null, null, 10L, domainId, accountId);
+        when(_dedicatedDao.findByHostId(10L)).thenReturn(dr);
+        _dedicatedService.dedicateHost(10L, domainId, accountName);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void releaseDedicatedPodInvalidIdTest() {
+        when(_dedicatedDao.findByPodId(10L)).thenReturn(null);
+        _dedicatedService.releaseDedicatedResource(null, 10L, null, null);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void releaseDedicatedClusterInvalidIdTest() {
+        when(_dedicatedDao.findByClusterId(10L)).thenReturn(null);
+        _dedicatedService.releaseDedicatedResource(null, null, 10L, null);
+    }
+
+    @Test(expected = InvalidParameterValueException.class)
+    public void releaseDedicatedHostInvalidIdTest() {
+        when(_dedicatedDao.findByHostId(10L)).thenReturn(null);
+        _dedicatedService.releaseDedicatedResource(null, null, null, 10L);
+    }
+
+    @Configuration
+    @ComponentScan(basePackageClasses = {DedicatedResourceManagerImpl.class},
+    includeFilters = {@Filter(value = TestConfiguration.Library.class,
+    type = FilterType.CUSTOM)}, useDefaultFilters = false)
+    public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {
+
+        @Bean
+        public AccountDao accountDao() {
+            return Mockito.mock(AccountDao.class);
+        }
+
+        @Bean
+        public DomainDao domainDao() {
+            return Mockito.mock(DomainDao.class);
+        }
+
+        @Bean
+        public DedicatedResourceDao dedicatedDao() {
+            return Mockito.mock(DedicatedResourceDao.class);
+        }
+
+        @Bean
+        public HostDao hostDao() {
+            return Mockito.mock(HostDao.class);
+        }
+
+        @Bean
+        public AccountManager acctManager() {
+            return Mockito.mock(AccountManager.class);
+        }
+
+        @Bean
+        public UserVmDao userVmDao() {
+            return Mockito.mock(UserVmDao.class);
+        }
+        @Bean
+        public DataCenterDao dataCenterDao() {
+            return Mockito.mock(DataCenterDao.class);
+        }
+        @Bean
+        public HostPodDao hostPodDao() {
+            return Mockito.mock(HostPodDao.class);
+        }
+
+        @Bean
+        public ClusterDao clusterDao() {
+            return Mockito.mock(ClusterDao.class);
+        }
+
+        @Bean
+        public ConfigurationDao configDao() {
+            return Mockito.mock(ConfigurationDao.class);
+        }
+
+        public static class Library implements TypeFilter {
+            @Override
+            public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
+                ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
+                return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/plugins/dedicated-resources/test/resource/dedicatedContext.xml
----------------------------------------------------------------------
diff --git a/plugins/dedicated-resources/test/resource/dedicatedContext.xml b/plugins/dedicated-resources/test/resource/dedicatedContext.xml
new file mode 100644
index 0000000..9ce8362
--- /dev/null
+++ b/plugins/dedicated-resources/test/resource/dedicatedContext.xml
@@ -0,0 +1,45 @@
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+  license agreements. See the NOTICE file distributed with this work for additional
+  information regarding copyright ownership. The ASF licenses this file to
+  you under the Apache License, Version 2.0 (the "License"); you may not use
+  this file except in compliance with the License. You may obtain a copy of
+  the License at http://www.apache.org/licenses/LICENSE-2.0 Unless require
+  by applicable law or agreed to in writing, software distributed under the
+  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+  OF ANY KIND, either express or implied. See the License for the specific
+  language governing permissions and limitations under the License. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+  xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                      http://www.springframework.org/schema/tx
+                      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
+                      http://www.springframework.org/schema/aop
+                      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
+                      http://www.springframework.org/schema/context
+                      http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+     <context:annotation-config />
+     <context:component-scan
+     base-package="org.apache.cloudstack.dedicated"/>
+
+  <bean id="componentContext" class="com.cloud.utils.component.ComponentContext" />
+  <bean id="transactionContextBuilder" class="com.cloud.utils.db.TransactionContextBuilder" />
+  <bean id="actionEventInterceptor" class="com.cloud.event.ActionEventInterceptor" />
+  <bean id="instantiatePostProcessor" class="com.cloud.utils.component.ComponentInstantiationPostProcessor">
+    <property name="Interceptors">
+        <list>
+            <ref bean="transactionContextBuilder" />
+            <ref bean="actionEventInterceptor" />
+        </list>
+    </property>
+  </bean>
+
+    <bean id="ConfigurationManager" class="com.cloud.configuration.ConfigurationManagerImpl">
+        <property name="name" value="ConfigurationManager"/>
+    </bean>
+
+    <bean class="org.apache.cloudstack.dedicated.DedicatedApiTestConfiguration" />
+
+</beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 2efa248..eab4755 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -35,11 +35,13 @@
     <module>api/rate-limit</module>
     <module>api/discovery</module>
     <module>acl/static-role-based</module>
-	<module>affinity-group-processors/host-anti-affinity</module>
+    <module>affinity-group-processors/host-anti-affinity</module>
+    <module>affinity-group-processors/explicit-dedication</module>
     <module>deployment-planners/user-concentrated-pod</module>
     <module>deployment-planners/user-dispersing</module>
     <module>deployment-planners/implicit-dedication</module>
     <module>host-allocators/random</module>
+    <module>dedicated-resources</module>
     <module>hypervisors/ovm</module>
     <module>hypervisors/xen</module>
     <module>hypervisors/kvm</module>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/server/src/com/cloud/api/query/QueryManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java
index 5a25732..28aecfc 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -97,6 +97,8 @@ import com.cloud.api.query.vo.UserAccountJoinVO;
 import com.cloud.api.query.vo.UserVmJoinVO;
 import com.cloud.api.query.vo.VolumeJoinVO;
 import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.dao.DedicatedResourceDao;
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
@@ -255,6 +257,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
     @Inject
     private AffinityGroupJoinDao _affinityGroupJoinDao;
 
+    @Inject
+    private DedicatedResourceDao _dedicatedDao;
     /* (non-Javadoc)
      * @see com.cloud.api.query.QueryService#searchForUsers(org.apache.cloudstack.api.command.admin.user.ListUsersCmd)
      */
@@ -2252,12 +2256,14 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
                 sc.addAnd("name", SearchCriteria.Op.SC, ssc);
             }
 
-            if (domainId != null) {
+            /*List all resources due to Explicit Dedication except the dedicated resources of other account
+             * if (domainId != null) {
                 // for domainId != null
                 // right now, we made the decision to only list zones associated
                 // with this domain, private zone
                 sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
-            }  else if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) {
+            }  else */
+            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) {
                 // it was decided to return all zones for the user's domain, and
                 // everything above till root
                 // list all zones belonging to this domain, and all of its
@@ -2287,6 +2293,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
                 // remove disabled zones
                 sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled);
 
+                //remove Dedicated zones not dedicated to this domainId or subdomainId
+                List<Long> dedicatedZoneIds = removeDedicatedZoneNotSuitabe(domainIds);
+                if(!dedicatedZoneIds.isEmpty()){
+                    sdc.addAnd("id", SearchCriteria.Op.NIN, dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()]));
+                }
+
             } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
                 // it was decided to return all zones for the domain admin, and
                 // everything above till root, as well as zones till the domain leaf
@@ -2316,6 +2328,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
 
                 // remove disabled zones
                 sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled);
+
+              //remove Dedicated zones not dedicated to this domainId or subdomainId
+                List<Long> dedicatedZoneIds = removeDedicatedZoneNotSuitabe(domainIds);
+                if(!dedicatedZoneIds.isEmpty()){
+                    sdc.addAnd("id", SearchCriteria.Op.NIN, dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()]));
+                }
             }
 
             // handle available=FALSE option, only return zones with at least one VM running there
@@ -2341,6 +2359,17 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
         return _dcJoinDao.searchAndCount(sc, searchFilter);
     }
 
+    private List<Long> removeDedicatedZoneNotSuitabe(List<Long> domainIds) {
+      //remove dedicated zone of other domain
+        List<Long> dedicatedZoneIds = new ArrayList<Long>();
+        List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listZonesNotInDomainIds(domainIds);
+        for (DedicatedResourceVO dr : dedicatedResources) {
+            if(dr != null) {
+                dedicatedZoneIds.add(dr.getDataCenterId());
+            }
+        }
+        return dedicatedZoneIds;
+    }
 
     // This method is used for permissions check for both disk and service
     // offerings

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 79375f9..52c5e2e 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -96,6 +96,7 @@ import com.cloud.dc.DataCenterIpAddressVO;
 import com.cloud.dc.DataCenterLinkLocalIpAddressVO;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.DcDetailVO;
+import com.cloud.dc.DedicatedResourceVO;
 import com.cloud.dc.HostPodVO;
 import com.cloud.dc.Pod;
 import com.cloud.dc.PodVlanMapVO;
@@ -310,9 +311,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
     NicSecondaryIpDao _nicSecondaryIpDao;
     @Inject
     NicIpAliasDao _nicIpAliasDao;
-
     @Inject
     public ManagementService _mgr;
+    @Inject
+    DedicatedResourceDao _dedicatedDao;
 
     // FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao?
     @Inject protected DataCenterLinkLocalIpAddressDao _LinkLocalIpAllocDao;
@@ -952,6 +954,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             throw new CloudRuntimeException("Failed to delete pod " + podId);
         }
 
+        // remove from dedicated resources
+        DedicatedResourceVO dr = _dedicatedDao.findByPodId(podId);
+        if (dr != null) {
+            _dedicatedDao.remove(dr.getId());
+        }
         txn.commit();
 
         return true;
@@ -1412,6 +1419,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
         if (success) {
             // delete all capacity records for the zone
             _capacityDao.removeBy(null, zoneId, null, null, null);
+            // remove from dedicated resources
+            DedicatedResourceVO dr = _dedicatedDao.findByZoneId(zoneId);
+            if (dr != null) {
+                _dedicatedDao.remove(dr.getId());
+            }
         }
 
         txn.commit();
@@ -1804,15 +1816,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
         try {
             txn.start();
             // Create the new zone in the database
-            DataCenterVO zone = new DataCenterVO(zoneName, null, dns1, dns2, internalDns1, internalDns2, guestCidr, domain, domainId, zoneType, zoneToken, networkDomain, isSecurityGroupEnabled, isLocalStorageEnabled, ip6Dns1, ip6Dns2);
+            DataCenterVO zone = new DataCenterVO(zoneName, null, dns1, dns2, internalDns1, internalDns2, guestCidr, null, null, zoneType, zoneToken, networkDomain, isSecurityGroupEnabled, isLocalStorageEnabled, ip6Dns1, ip6Dns2);
             if (allocationStateStr != null && !allocationStateStr.isEmpty()) {
                 Grouping.AllocationState allocationState = Grouping.AllocationState.valueOf(allocationStateStr);
                 zone.setAllocationState(allocationState);
             } else {
-                // Zone will be disabled since 3.0. Admin shoul enable it after physical network and providers setup.
+                // Zone will be disabled since 3.0. Admin should enable it after physical network and providers setup.
                 zone.setAllocationState(Grouping.AllocationState.Disabled);
             }
             zone = _zoneDao.persist(zone);
+            if (domainId != null) {
+                //zone is explicitly dedicated to this domain
+                DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(zone.getId(), null, null, null, domainId, null);
+                _dedicatedDao.persist(dedicatedResource);
+            }
 
             // Create default system networks
             createDefaultSystemNetworks(zone.getId());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/server/src/com/cloud/dc/DedicatedResourceVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/dc/DedicatedResourceVO.java b/server/src/com/cloud/dc/DedicatedResourceVO.java
new file mode 100644
index 0000000..a4c88f5
--- /dev/null
+++ b/server/src/com/cloud/dc/DedicatedResourceVO.java
@@ -0,0 +1,136 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.dc;
+
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="dedicated_resources")
+public class DedicatedResourceVO implements DedicatedResources{
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name="id")
+    long id;
+
+    @Column(name="data_center_id")
+    Long dataCenterId;
+
+    @Column(name="pod_id")
+    Long podId;
+
+    @Column(name="cluster_id")
+    Long clusterId;
+
+    @Column(name="host_id")
+    Long hostId;
+
+    @Column(name="uuid")
+    String uuid;
+
+    @Column(name = "domain_id")
+    private Long domainId;
+
+    @Column(name = "account_id")
+    private Long accountId;
+
+    public DedicatedResourceVO() {
+        this.uuid = UUID.randomUUID().toString();
+    }
+
+    public DedicatedResourceVO(Long dataCenterId, Long podId, Long clusterId, Long hostId, Long domainId, Long accountId) {
+        this.dataCenterId = dataCenterId;
+        this.podId = podId;
+        this.clusterId = clusterId;
+        this.hostId = hostId;
+        this.domainId = domainId;
+        this.accountId = accountId;
+        this.uuid = UUID.randomUUID().toString();
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public Long getDataCenterId() {
+        return dataCenterId;
+    }
+
+    public void setDataCenterId(long dataCenterId) {
+        this.dataCenterId = dataCenterId;
+    }
+
+    public Long getPodId() {
+        return podId;
+    }
+
+    public void setPodId(long podId) {
+        this.podId = podId;
+    }
+
+    public Long getClusterId() {
+        return clusterId;
+    }
+
+    public void setClusterId(long clusterId) {
+        this.clusterId = clusterId;
+    }
+
+    public Long getHostId() {
+        return hostId;
+    }
+
+    public void setHostId(long hostId) {
+        this.hostId = hostId;
+    }
+
+    public DedicatedResourceVO(long dedicatedResourceId) {
+        this.id = dedicatedResourceId;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public void setDomainId(Long domainId) {
+        this.domainId = domainId;
+    }
+
+    public Long getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(Long accountId) {
+        this.accountId = accountId;
+    }
+
+    public String getUuid() {
+        return this.uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/server/src/com/cloud/dc/dao/DedicatedResourceDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/dc/dao/DedicatedResourceDao.java b/server/src/com/cloud/dc/dao/DedicatedResourceDao.java
new file mode 100644
index 0000000..a5d65d4
--- /dev/null
+++ b/server/src/com/cloud/dc/dao/DedicatedResourceDao.java
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.dc.dao;
+
+import java.util.List;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.GenericDao;
+
+
+public interface DedicatedResourceDao extends GenericDao<DedicatedResourceVO, Long> {
+
+    DedicatedResourceVO findByZoneId(Long zoneId);
+
+    DedicatedResourceVO findByPodId(Long podId);
+
+    DedicatedResourceVO findByClusterId(Long clusterId);
+
+    DedicatedResourceVO findByHostId(Long hostId);
+
+    Pair<List<DedicatedResourceVO>, Integer> searchDedicatedHosts(Long hostId, Long domainId, Long accountId);
+
+    Pair<List<DedicatedResourceVO>, Integer> searchDedicatedClusters(Long clusterId, Long domainId, Long accountId);
+
+    Pair<List<DedicatedResourceVO>, Integer> searchDedicatedPods(Long podId, Long domainId, Long accountId);
+
+    Pair<List<DedicatedResourceVO>, Integer> searchDedicatedZones(Long dataCenterId, Long domainId, Long accountId);
+
+    List<DedicatedResourceVO> listByAccountId(Long accountId);
+
+    List<DedicatedResourceVO> listByDomainId(Long domainId);
+
+    List<DedicatedResourceVO> listZonesNotInDomainIds(List<Long> domainIds);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/server/src/com/cloud/dc/dao/DedicatedResourceDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/dc/dao/DedicatedResourceDaoImpl.java b/server/src/com/cloud/dc/dao/DedicatedResourceDaoImpl.java
new file mode 100644
index 0000000..2a3b469
--- /dev/null
+++ b/server/src/com/cloud/dc/dao/DedicatedResourceDaoImpl.java
@@ -0,0 +1,304 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.dc.dao;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.springframework.stereotype.Component;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.utils.Pair;
+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;
+
+@Component
+@Local(value={DedicatedResourceDao.class}) @DB(txn = false)
+public class DedicatedResourceDaoImpl extends GenericDaoBase<DedicatedResourceVO, Long> implements DedicatedResourceDao {
+    protected final SearchBuilder<DedicatedResourceVO> ZoneSearch;
+    protected final SearchBuilder<DedicatedResourceVO> PodSearch;
+    protected final SearchBuilder<DedicatedResourceVO> ClusterSearch;
+    protected final SearchBuilder<DedicatedResourceVO> HostSearch;
+
+    protected SearchBuilder<DedicatedResourceVO> ListZonesByDomainIdSearch;
+    protected SearchBuilder<DedicatedResourceVO> ListPodsByDomainIdSearch;
+    protected SearchBuilder<DedicatedResourceVO> ListClustersByDomainIdSearch;
+    protected SearchBuilder<DedicatedResourceVO> ListHostsByDomainIdSearch;
+
+    protected SearchBuilder<DedicatedResourceVO> ListZonesByAccountIdSearch;
+    protected SearchBuilder<DedicatedResourceVO> ListPodsByAccountIdSearch;
+    protected SearchBuilder<DedicatedResourceVO> ListClustersByAccountIdSearch;
+    protected SearchBuilder<DedicatedResourceVO> ListHostsByAccountIdSearch;
+
+    protected SearchBuilder<DedicatedResourceVO> ListAllZonesSearch;
+    protected SearchBuilder<DedicatedResourceVO> ListAllPodsSearch;
+    protected SearchBuilder<DedicatedResourceVO> ListAllClustersSearch;
+    protected SearchBuilder<DedicatedResourceVO> ListAllHostsSearch;
+
+    protected SearchBuilder<DedicatedResourceVO> ListByAccountId;
+    protected SearchBuilder<DedicatedResourceVO> ListByDomainId;
+
+    protected SearchBuilder<DedicatedResourceVO> ZoneByDomainIdsSearch;
+
+    protected DedicatedResourceDaoImpl() {
+        PodSearch = createSearchBuilder();
+        PodSearch.and("podId", PodSearch.entity().getPodId(), SearchCriteria.Op.EQ);
+        PodSearch.done();
+
+        ZoneSearch = createSearchBuilder();
+        ZoneSearch.and("zoneId", ZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
+        ZoneSearch.done();
+
+        ClusterSearch = createSearchBuilder();
+        ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ);
+        ClusterSearch.done();
+
+        HostSearch = createSearchBuilder();
+        HostSearch.and("hostId", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ);
+        HostSearch.done();
+
+        ListZonesByDomainIdSearch = createSearchBuilder();
+        ListZonesByDomainIdSearch.and("zoneId", ListZonesByDomainIdSearch.entity().getDataCenterId(), SearchCriteria.Op.NNULL);
+        ListZonesByDomainIdSearch.and("domainId", ListZonesByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
+        ListZonesByDomainIdSearch.and("accountId", ListZonesByDomainIdSearch.entity().getAccountId(), SearchCriteria.Op.NULL);
+        ListZonesByDomainIdSearch.done();
+
+        ListZonesByAccountIdSearch = createSearchBuilder();
+        ListZonesByAccountIdSearch.and("zoneId", ListZonesByAccountIdSearch.entity().getDataCenterId(), SearchCriteria.Op.NNULL);
+        ListZonesByAccountIdSearch.and("accountId", ListZonesByAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+        ListZonesByAccountIdSearch.done();
+
+        ListPodsByDomainIdSearch = createSearchBuilder();
+        ListPodsByDomainIdSearch.and("podId", ListPodsByDomainIdSearch.entity().getPodId(), SearchCriteria.Op.NNULL);
+        ListPodsByDomainIdSearch.and("domainId", ListPodsByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
+        ListPodsByDomainIdSearch.and("accountId", ListPodsByDomainIdSearch.entity().getAccountId(), SearchCriteria.Op.NULL);
+        ListPodsByDomainIdSearch.done();
+
+        ListPodsByAccountIdSearch = createSearchBuilder();
+        ListPodsByAccountIdSearch.and("podId", ListPodsByAccountIdSearch.entity().getPodId(), SearchCriteria.Op.NNULL);
+        ListPodsByAccountIdSearch.and("accountId", ListPodsByAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+        ListPodsByAccountIdSearch.done();
+
+        ListClustersByDomainIdSearch = createSearchBuilder();
+        ListClustersByDomainIdSearch.and("clusterId", ListClustersByDomainIdSearch.entity().getClusterId(), SearchCriteria.Op.NNULL);
+        ListClustersByDomainIdSearch.and("domainId", ListClustersByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
+        ListClustersByDomainIdSearch.and("accountId", ListClustersByDomainIdSearch.entity().getAccountId(), SearchCriteria.Op.NULL);
+        ListClustersByDomainIdSearch.done();
+
+        ListClustersByAccountIdSearch = createSearchBuilder();
+        ListClustersByAccountIdSearch.and("clusterId", ListClustersByAccountIdSearch.entity().getClusterId(), SearchCriteria.Op.NNULL);
+        ListClustersByAccountIdSearch.and("accountId", ListClustersByAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+        ListClustersByAccountIdSearch.done();
+
+        ListHostsByDomainIdSearch = createSearchBuilder();
+        ListHostsByDomainIdSearch.and("hostId", ListHostsByDomainIdSearch.entity().getHostId(), SearchCriteria.Op.NNULL);
+        ListHostsByDomainIdSearch.and("domainId", ListHostsByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
+        ListHostsByDomainIdSearch.and("accountId", ListHostsByDomainIdSearch.entity().getAccountId(), SearchCriteria.Op.NULL);
+        ListHostsByDomainIdSearch.done();
+
+        ListHostsByAccountIdSearch = createSearchBuilder();
+        ListHostsByAccountIdSearch.and("hostId", ListHostsByAccountIdSearch.entity().getHostId(), SearchCriteria.Op.NNULL);
+        ListHostsByAccountIdSearch.and("accountId", ListHostsByAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+        ListHostsByAccountIdSearch.done();
+
+        ListAllZonesSearch = createSearchBuilder();
+        ListAllZonesSearch.and("zoneId", ListAllZonesSearch.entity().getDataCenterId(), Op.EQ);
+        ListAllZonesSearch.and("podId", ListAllZonesSearch.entity().getPodId(), Op.NULL);
+        ListAllZonesSearch.and("clusterId", ListAllZonesSearch.entity().getClusterId(), Op.NULL);
+        ListAllZonesSearch.and("hostId", ListAllZonesSearch.entity().getHostId(), Op.NULL);
+        ListAllZonesSearch.and("accountId", ListAllZonesSearch.entity().getAccountId(), Op.EQ);
+        ListAllZonesSearch.and("domainId", ListAllZonesSearch.entity().getDomainId(), Op.EQ);
+        ListAllZonesSearch.done();
+
+        ListAllPodsSearch = createSearchBuilder();
+        ListAllPodsSearch.and("zoneId", ListAllPodsSearch.entity().getDataCenterId(), Op.NULL);
+        ListAllPodsSearch.and("podId", ListAllPodsSearch.entity().getPodId(), Op.EQ);
+        ListAllPodsSearch.and("clusterId", ListAllPodsSearch.entity().getClusterId(), Op.NULL);
+        ListAllPodsSearch.and("hostId", ListAllPodsSearch.entity().getHostId(), Op.NULL);
+        ListAllPodsSearch.and("accountId", ListAllPodsSearch.entity().getAccountId(), Op.EQ);
+        ListAllPodsSearch.and("domainId", ListAllPodsSearch.entity().getDomainId(), Op.EQ);
+        ListAllPodsSearch.done();
+
+        ListAllClustersSearch = createSearchBuilder();
+        ListAllClustersSearch.and("zoneId", ListAllClustersSearch.entity().getDataCenterId(), Op.NULL);
+        ListAllClustersSearch.and("podId", ListAllClustersSearch.entity().getPodId(), Op.NULL);
+        ListAllClustersSearch.and("clusterId", ListAllClustersSearch.entity().getClusterId(), Op.EQ);
+        ListAllClustersSearch.and("hostId", ListAllClustersSearch.entity().getHostId(), Op.NULL);
+        ListAllClustersSearch.and("accountId", ListAllClustersSearch.entity().getAccountId(), Op.EQ);
+        ListAllClustersSearch.and("domainId", ListAllClustersSearch.entity().getDomainId(), Op.EQ);
+        ListAllClustersSearch.done();
+
+        ListAllHostsSearch = createSearchBuilder();
+        ListAllHostsSearch.and("zoneId", ListAllHostsSearch.entity().getDataCenterId(), Op.NULL);
+        ListAllHostsSearch.and("podId", ListAllHostsSearch.entity().getPodId(), Op.NULL);
+        ListAllHostsSearch.and("clusterId", ListAllHostsSearch.entity().getClusterId(), Op.NULL);
+        ListAllHostsSearch.and("hostId", ListAllHostsSearch.entity().getHostId(), Op.EQ);
+        ListAllHostsSearch.and("accountId", ListAllHostsSearch.entity().getAccountId(), Op.EQ);
+        ListAllHostsSearch.and("domainId", ListAllHostsSearch.entity().getDomainId(), Op.EQ);
+        ListAllHostsSearch.done();
+
+        ListByAccountId = createSearchBuilder();
+        ListByAccountId.and("accountId", ListByAccountId.entity().getAccountId(), SearchCriteria.Op.EQ);
+        ListByAccountId.done();
+
+        ListByDomainId = createSearchBuilder();
+        ListByDomainId.and("accountId", ListByDomainId.entity().getAccountId(), SearchCriteria.Op.NULL);
+        ListByDomainId.and("domainId", ListByDomainId.entity().getDomainId(), SearchCriteria.Op.EQ);
+        ListByDomainId.done();
+
+        ZoneByDomainIdsSearch = createSearchBuilder();
+        ZoneByDomainIdsSearch.and("zoneId", ZoneByDomainIdsSearch.entity().getDataCenterId(), SearchCriteria.Op.NNULL);
+        ZoneByDomainIdsSearch.and("domainId", ZoneByDomainIdsSearch.entity().getDomainId(), SearchCriteria.Op.NIN);
+        ZoneByDomainIdsSearch.done();
+    }
+
+    @Override
+    public DedicatedResourceVO findByZoneId(Long zoneId) {
+        SearchCriteria<DedicatedResourceVO> sc = ZoneSearch.create();
+        sc.setParameters("zoneId", zoneId);
+        return findOneBy(sc);
+    }
+
+    @Override
+    public DedicatedResourceVO findByPodId(Long podId) {
+        SearchCriteria<DedicatedResourceVO> sc = PodSearch.create();
+        sc.setParameters("podId", podId);
+
+        return findOneBy(sc);
+    }
+
+    @Override
+    public DedicatedResourceVO findByClusterId(Long clusterId) {
+        SearchCriteria<DedicatedResourceVO> sc = ClusterSearch.create();
+        sc.setParameters("clusterId", clusterId);
+
+        return findOneBy(sc);
+    }
+
+    @Override
+    public DedicatedResourceVO findByHostId(Long hostId) {
+        SearchCriteria<DedicatedResourceVO> sc = HostSearch.create();
+        sc.setParameters("hostId", hostId);
+
+        return findOneBy(sc);
+    }
+
+    @Override
+    public Pair<List<DedicatedResourceVO>, Integer> searchDedicatedZones(Long dataCenterId, Long domainId, Long accountId){
+        SearchCriteria<DedicatedResourceVO> sc = ListAllZonesSearch.create();
+        if (dataCenterId != null) {
+            sc.setParameters("dataCenterId", dataCenterId);
+        }
+        if(domainId != null) {
+            sc.setParameters("domainId", domainId);
+            if(accountId != null) {
+                sc.setParameters("accountId", accountId);
+            } else {
+                sc.setParameters("accountId", (Object)null);
+            }
+        }
+        return searchAndCount(sc, null);
+    }
+    @Override
+    public Pair<List<DedicatedResourceVO>, Integer> searchDedicatedPods(Long podId, Long domainId, Long accountId){
+        SearchCriteria<DedicatedResourceVO> sc = ListAllPodsSearch.create();
+        if (podId != null) {
+            sc.setParameters("podId", podId);
+        }
+        if(domainId != null) {
+            sc.setParameters("domainId", domainId);
+            if(accountId != null) {
+                sc.setParameters("accountId", accountId);
+            } else {
+                sc.setParameters("accountId", (Object)null);
+            }
+        }
+        return searchAndCount(sc, null);
+    }
+
+    @Override
+    public Pair<List<DedicatedResourceVO>, Integer> searchDedicatedClusters(Long clusterId, Long domainId, Long accountId){
+        SearchCriteria<DedicatedResourceVO> sc = ListAllClustersSearch.create();
+        if (clusterId != null) {
+            sc.setParameters("clusterId", clusterId);
+        }
+        if(domainId != null) {
+            sc.setParameters("domainId", domainId);
+            if(accountId != null) {
+                sc.setParameters("accountId", accountId);
+            } else {
+                sc.setParameters("accountId", (Object)null);
+            }
+        }
+        return searchAndCount(sc, null);
+    }
+
+    @Override
+    public Pair<List<DedicatedResourceVO>, Integer> searchDedicatedHosts(Long hostId, Long domainId, Long accountId){
+        SearchCriteria<DedicatedResourceVO> sc = ListAllHostsSearch.create();
+        if (hostId != null) {
+            sc.setParameters("hostId", hostId);
+        }
+        if(domainId != null) {
+            sc.setParameters("domainId", domainId);
+            if(accountId != null) {
+                sc.setParameters("accountId", accountId);
+            } else {
+                sc.setParameters("accountId", (Object)null);
+            }
+        }
+        return searchAndCount(sc, null);
+    }
+
+    @Override
+    public List<DedicatedResourceVO> listByAccountId(Long accountId){
+        SearchCriteria<DedicatedResourceVO> sc = ListByAccountId.create();
+        sc.setParameters("accountId", accountId);
+        return listBy(sc);
+    }
+
+    @Override
+    public List<DedicatedResourceVO> listByDomainId(Long domainId){
+        SearchCriteria<DedicatedResourceVO> sc = ListByDomainId.create();
+        sc.setParameters("domainId", domainId);
+        return listBy(sc);
+    }
+
+    @Override
+    public List<DedicatedResourceVO> listZonesNotInDomainIds(List<Long> domainIds) {
+        SearchCriteria<DedicatedResourceVO> sc = ZoneByDomainIdsSearch.create();
+        sc.setParameters("domainId", domainIds.toArray(new Object[domainIds.size()]));
+        return listBy(sc);
+    }
+
+    @Override
+    public boolean remove(Long id) {
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        DedicatedResourceVO resource = createForUpdate();
+        update(id, resource);
+
+        boolean result = super.remove(id);
+        txn.commit();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/server/src/com/cloud/resource/ResourceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java
index 74bd6d0..c6e8d7d 100755
--- a/server/src/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/com/cloud/resource/ResourceManagerImpl.java
@@ -30,6 +30,7 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.dc.*;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd;
 import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd;
@@ -84,6 +85,7 @@ import com.cloud.dc.dao.ClusterDao;
 import com.cloud.dc.dao.ClusterVSMMapDao;
 import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.dc.dao.DataCenterIpAddressDao;
+import com.cloud.dc.dao.DedicatedResourceDao;
 import com.cloud.dc.dao.HostPodDao;
 import com.cloud.deploy.PlannerHostReservationVO;
 import com.cloud.deploy.dao.PlannerHostReservationDao;
@@ -219,6 +221,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
     protected StorageService                 _storageSvr;
     @Inject
     PlannerHostReservationDao _plannerHostReserveDao;
+    @Inject
+    protected DedicatedResourceDao           _dedicatedDao;
 
     protected List<? extends Discoverer> _discoverers;
     public List<? extends Discoverer> getDiscoverers() {
@@ -1026,6 +1030,11 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 		hostCapacitySC.addAnd("capacityType", SearchCriteria.Op.IN,
 				capacityTypes);
         _capacityDao.remove(hostCapacitySC);
+        // remove from dedicated resources
+        DedicatedResourceVO dr = _dedicatedDao.findByHostId(hostId);
+        if (dr != null) {
+            _dedicatedDao.remove(dr.getId());
+        }
         txn.commit();
         return true;
     }
@@ -1100,11 +1109,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 						&& Boolean.parseBoolean(_configDao
 								.getValue(Config.VmwareUseNexusVSwitch
 										.toString()))) {
-                    _clusterVSMMapDao.removeByClusterId(cmd.getId());
-                }
-            }
+				    _clusterVSMMapDao.removeByClusterId(cmd.getId());
+				}
+				// remove from dedicated resources
+				DedicatedResourceVO dr = _dedicatedDao.findByClusterId(cluster.getId());
+				if (dr != null) {
+				    _dedicatedDao.remove(dr.getId());
+				}
+			}
 
-            txn.commit();
+			txn.commit();
             return true;
 		} catch (CloudRuntimeException e) {
             throw e;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/server/src/com/cloud/user/AccountManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index e72005e..3f06e41 100755
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -61,8 +61,10 @@ import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.configuration.dao.ResourceCountDao;
 import com.cloud.configuration.dao.ResourceLimitDao;
 import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.DedicatedResourceVO;
 import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.dc.dao.DataCenterVnetDao;
+import com.cloud.dc.dao.DedicatedResourceDao;
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
@@ -229,6 +231,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     @Inject
     private AffinityGroupDao _affinityGroupDao;
     @Inject
+
     private AccountGuestVlanMapDao _accountGuestVlanMapDao;
     @Inject
     private DataCenterVnetDao _dataCenterVnetDao;
@@ -236,6 +239,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
     private ResourceLimitService _resourceLimitMgr;
     @Inject
     private ResourceLimitDao _resourceLimitDao;
+    @Inject
+    private DedicatedResourceDao _dedicatedDao;
 
     private List<UserAuthenticator> _userAuthenticators;
     List<UserAuthenticator> _userPasswordEncoders;
@@ -738,7 +743,16 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
                 s_logger.debug("Releasing portable ip " + ip + " as a part of account id=" + accountId + " cleanup");
                 _networkMgr.releasePortableIpAddress(ip.getId());
             }
-
+            //release dedication if any
+            List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listByAccountId(accountId);
+            if (dedicatedResources != null && !dedicatedResources.isEmpty()) {
+                s_logger.debug("Releasing dedicated resources for account " + accountId);
+                for (DedicatedResourceVO dr : dedicatedResources){
+                    if (!_dedicatedDao.remove(dr.getId())) {
+                        s_logger.warn("Fail to release dedicated resources for account " + accountId);
+                    }
+                }
+            }
             return true;
         } catch (Exception ex) {
             s_logger.warn("Failed to cleanup account " + account + " due to ", ex);
@@ -1488,6 +1502,16 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
                         try {
                             List<AccountVO> accountsForCleanupInDomain = _accountDao.findCleanupsForRemovedAccounts(domainId);
                             if (accountsForCleanupInDomain.isEmpty()) {
+                                //release dedication if any, before deleting the domain
+                                List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listByDomainId(domainId);
+                                if (dedicatedResources != null && !dedicatedResources.isEmpty()) {
+                                    s_logger.debug("Releasing dedicated resources for domain" + domainId);
+                                    for (DedicatedResourceVO dr : dedicatedResources){
+                                        if (!_dedicatedDao.remove(dr.getId())) {
+                                            s_logger.warn("Fail to release dedicated resources for domain " + domainId);
+                                        }
+                                    }
+                                }
                                 s_logger.debug("Removing inactive domain id=" + domainId);
                                 _domainMgr.removeDomain(domainId);
                             } else {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/server/src/com/cloud/user/DomainManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/user/DomainManagerImpl.java b/server/src/com/cloud/user/DomainManagerImpl.java
index 00a779e..20537ba 100644
--- a/server/src/com/cloud/user/DomainManagerImpl.java
+++ b/server/src/com/cloud/user/DomainManagerImpl.java
@@ -35,6 +35,8 @@ import com.cloud.configuration.Resource.ResourceOwnerType;
 import com.cloud.configuration.ResourceLimit;
 import com.cloud.configuration.dao.ResourceCountDao;
 import com.cloud.configuration.dao.ResourceLimitDao;
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.dao.DedicatedResourceDao;
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
@@ -87,6 +89,8 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom
     private RegionManager _regionMgr;
     @Inject
     private ResourceLimitDao _resourceLimitDao;
+    @Inject
+    private DedicatedResourceDao _dedicatedDao;
 
     @Override
     public Domain getDomain(long domainId) {
@@ -237,6 +241,17 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom
                         CloudRuntimeException e = new CloudRuntimeException("Delete failed on domain " + domain.getName() + " (id: " + domain.getId() + "); Please make sure all users and sub domains have been removed from the domain before deleting");
                         e.addProxyObject(domain.getUuid(), "domainId");
                         throw e;
+                    } else {
+                        //release dedication if any, before deleting the domain
+                        List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listByDomainId(domain.getId());
+                        if (dedicatedResources != null && !dedicatedResources.isEmpty()) {
+                            s_logger.debug("Releasing dedicated resources for domain" + domain.getId());
+                            for (DedicatedResourceVO dr : dedicatedResources){
+                                if (!_dedicatedDao.remove(dr.getId())) {
+                                    s_logger.warn("Fail to release dedicated resources for domain " + domain.getId());
+                                }
+                            }
+                        }
                     }
                 } else {
                     rollBackState = true;
@@ -333,6 +348,17 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom
         boolean deleteDomainSuccess = true;
         List<AccountVO> accountsForCleanup = _accountDao.findCleanupsForRemovedAccounts(domainId);
         if (accountsForCleanup.isEmpty()) {
+            //release dedication if any, before deleting the domain
+            List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listByDomainId(domainId);
+            if (dedicatedResources != null && !dedicatedResources.isEmpty()) {
+                s_logger.debug("Releasing dedicated resources for domain" + domainId);
+                for (DedicatedResourceVO dr : dedicatedResources){
+                    if (!_dedicatedDao.remove(dr.getId())) {
+                        s_logger.warn("Fail to release dedicated resources for domain " + domainId);
+                    }
+                }
+            }
+            //delete domain
             deleteDomainSuccess = _domainDao.remove(domainId);
 
             // Delete resource count and resource limits entries set for this domain (if there are any).

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/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 a55c6f8..86bdb14 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -93,9 +93,11 @@ import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.dc.DataCenter;
 import com.cloud.dc.DataCenter.NetworkType;
 import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.DedicatedResourceVO;
 import com.cloud.dc.HostPodVO;
 import com.cloud.dc.dao.ClusterDao;
 import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.DedicatedResourceDao;
 import com.cloud.dc.dao.HostPodDao;
 import com.cloud.deploy.DataCenterDeployment;
 import com.cloud.deploy.DeployDestination;
@@ -402,6 +404,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
     @Inject
     AffinityGroupDao _affinityGroupDao;
     @Inject
+    DedicatedResourceDao _dedicatedDao;
+    @Inject
     ConfigurationServer _configServer;
 
     protected ScheduledExecutorService _executor = null;
@@ -2362,8 +2366,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                             + zone.getId());
         }
 
-        if (zone.getDomainId() != null) {
-            DomainVO domain = _domainDao.findById(zone.getDomainId());
+        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) {
+            DomainVO domain = _domainDao.findById(dedicatedZone.getDomainId());
             if (domain == null) {
                 throw new CloudRuntimeException("Unable to find the domain "
                         + zone.getDomainId() + " for the zone: " + zone);
@@ -3676,6 +3693,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
                             + destinationHost.getResourceState());
         }
 
+        HostVO srcHost = _hostDao.findById(srcHostId);
+        HostVO destHost = _hostDao.findById(destinationHost.getId());
+        //if srcHost is dedicated and destination Host is not
+        if (checkIfHostIsDedicated(srcHost) && !checkIfHostIsDedicated(destHost)) {
+            //raise an alert
+            String msg = "VM is migrated on a non-dedicated host " + destinationHost.getName();
+            _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
+        }
+        //if srcHost is non dedicated but destination Host is.
+        if (!checkIfHostIsDedicated(srcHost) && checkIfHostIsDedicated(destHost)) {
+            //raise an alert
+            String msg = "VM is migrated on a dedicated host " + destinationHost.getName();
+            _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg);
+        }
+
         // call to core process
         DataCenterVO dcVO = _dcDao.findById(destinationHost.getDataCenterId());
         HostPodVO pod = _podDao.findById(destinationHost.getPodId());
@@ -3703,6 +3735,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         return migratedVm;
     }
 
+    private boolean checkIfHostIsDedicated(HostVO host) {
+        long hostId = host.getId();
+        DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(hostId);
+        DedicatedResourceVO dedicatedClusterOfHost = _dedicatedDao.findByClusterId(host.getClusterId());
+        DedicatedResourceVO dedicatedPodOfHost = _dedicatedDao.findByPodId(host.getPodId());
+        if(dedicatedHost != null || dedicatedClusterOfHost != null || dedicatedPodOfHost != null) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_VM_MIGRATE, eventDescription = "migrating VM", async = true)
     public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost,
@@ -3822,7 +3866,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
 
         VMInstanceVO migratedVm = _itMgr.migrateWithStorage(vm, srcHostId, destinationHost.getId(), volToPoolObjectMap);
         return migratedVm;
-    }
+}
 
     @DB
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
----------------------------------------------------------------------
diff --git a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
index f862a2a..3f6fe9c 100644
--- a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
+++ b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
@@ -49,6 +49,7 @@ import com.cloud.dc.dao.DataCenterIpAddressDaoImpl;
 import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDao;
 import com.cloud.dc.dao.DataCenterVnetDaoImpl;
 import com.cloud.dc.dao.DcDetailsDaoImpl;
+import com.cloud.dc.dao.DedicatedResourceDao;
 import com.cloud.dc.dao.HostPodDaoImpl;
 import com.cloud.dc.dao.PodVlanDaoImpl;
 import com.cloud.dc.dao.PodVlanMapDaoImpl;
@@ -173,7 +174,7 @@ import org.apache.cloudstack.region.PortableIpRangeDaoImpl;
     },
 includeFilters={@Filter(value=ChildTestConfiguration.Library.class, type=FilterType.CUSTOM)},
 useDefaultFilters=false
-)
+        )
 
 public class ChildTestConfiguration {
 
@@ -333,13 +334,18 @@ public class ChildTestConfiguration {
     }
 
     @Bean
+    public DedicatedResourceDao DedicatedResourceDao() {
+        return Mockito.mock(DedicatedResourceDao.class);
+    }
+
+    @Bean
     public NetworkOfferingServiceMapDao networkOfferingServiceMapDao() {
         return Mockito.mock(NetworkOfferingServiceMapDao.class);
     }
 
     @Bean
     public DataCenterLinkLocalIpAddressDao datacenterLinkLocalIpAddressDao() {
-    	return Mockito.mock(DataCenterLinkLocalIpAddressDao.class);
+        return Mockito.mock(DataCenterLinkLocalIpAddressDao.class);
     }
 
     @Bean
@@ -357,7 +363,6 @@ public class ChildTestConfiguration {
         return Mockito.mock(AccountDetailsDao.class);
     }
 
-    
     public static class Library implements TypeFilter {
 
         @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/setup/db/create-schema.sql
----------------------------------------------------------------------
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index b1feb02..79550ae 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -2453,7 +2453,6 @@ CREATE TABLE `cloud`.`resource_tags` (
   CONSTRAINT `uc_resource_tags__uuid` UNIQUE (`uuid`)
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-
 CREATE TABLE `cloud`.`external_nicira_nvp_devices` (
   `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
   `uuid` varchar(255) UNIQUE,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index e081a25..196706f 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -178,6 +178,27 @@ CREATE TABLE `cloud`.`affinity_group_vm_map` (
 
 
 
+CREATE TABLE `cloud`.`dedicated_resources` (
+  `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id',
+  `uuid` varchar(40),
+  `data_center_id` bigint unsigned COMMENT 'data center id',
+  `pod_id` bigint unsigned COMMENT 'pod id',
+  `cluster_id` bigint unsigned COMMENT 'cluster id',
+  `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',
+  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`),
+  CONSTRAINT `fk_dedicated_resources__cluster_id` FOREIGN KEY (`cluster_id`) REFERENCES `cloud`.`cluster`(`id`),
+  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`),
+  INDEX `i_dedicated_resources_domain_id`(`domain_id`),
+  INDEX `i_dedicated_resources_account_id`(`account_id`),
+  CONSTRAINT `uc_dedicated_resources__uuid` UNIQUE (`uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
 CREATE TABLE nic_secondary_ips (
   `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
   `uuid` varchar(40),
@@ -203,6 +224,9 @@ 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
@@ -1720,7 +1744,8 @@ UPDATE `cloud`.`snapshots` set swift_id=null where swift_id=0;
 
 
 -- Re-enable foreign key checking, at the end of the upgrade path
-SET foreign_key_checks = 1;			
+SET foreign_key_checks = 1;
+
 UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL;
 #update shared sg enabled network with not null name in Advance Security Group enabled network
 UPDATE `cloud`.`networks` set name='Shared SG enabled network', display_text='Shared SG enabled network' WHERE name IS null AND traffic_type='Guest' AND data_center_id IN (select id from data_center where networktype='Advanced' and is_security_group_enabled=1) AND acl_type='Domain';

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/test/integration/component/test_explicit_dedication.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_explicit_dedication.py b/test/integration/component/test_explicit_dedication.py
new file mode 100644
index 0000000..21a4904
--- /dev/null
+++ b/test/integration/component/test_explicit_dedication.py
@@ -0,0 +1,231 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+""" P1 tests for Storage motion
+"""
+#Import Local Modules
+import marvin
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.remoteSSHClient import remoteSSHClient
+from marvin.integration.lib.utils import *
+from marvin.integration.lib.base import *
+from marvin.integration.lib.common import *
+from nose.plugins.attrib import attr
+#Import System modules
+import time
+
+_multiprocess_shared_ = True
+class Services:
+    """Test explicit dedication
+    """
+
+    def __init__(self):
+        self.services = {
+                "disk_offering":{
+                    "displaytext": "Small",
+                    "name": "Small",
+                    "disksize": 1
+                },
+                "account": {
+                    "email": "test@test.com",
+                    "firstname": "Test",
+                    "lastname": "User",
+                    "username": "testexplicit",
+                    # Random characters are appended in create account to
+                    # ensure unique username generated each time
+                    "password": "password",
+                },
+                "virtual_machine" :
+                {
+                    "affinity": {
+                        "name": "explicit",
+                        "type": "ExplicitDedication",
+                    },
+                    "hypervisor" : "XenServer",
+                },
+                "small":
+                # Create a small virtual machine instance with disk offering
+                {
+                    "displayname": "testserver",
+                    "username": "root", # VM creds for SSH
+                    "password": "password",
+                    "ssh_port": 22,
+                    "hypervisor": 'XenServer',
+                    "privateport": 22,
+                    "publicport": 22,
+                    "protocol": 'TCP',
+                },
+                "service_offerings":
+                {
+                 "for-explicit":
+                    {
+                     # Small service offering ID to for change VM
+                     # service offering from medium to small
+                        "name": "For explicit",
+                        "displaytext": "For explicit",
+                        "cpunumber": 1,
+                        "cpuspeed": 500,
+                        "memory": 512
+                    }
+                },
+                "template": {
+                    "displaytext": "Cent OS Template",
+                    "name": "Cent OS Template",
+                    "passwordenabled": True,
+                },
+                "diskdevice": '/dev/xvdd',
+                # Disk device where ISO is attached to instance
+                "mount_dir": "/mnt/tmp",
+                "sleep": 60,
+                "timeout": 10,
+                "ostype": 'CentOS 5.3 (64-bit)'
+        }
+
+class TestExplicitDedication(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.api_client = super(TestExplicitDedication, cls).getClsTestClient().getApiClient()
+        cls.services = Services().services
+
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.api_client, cls.services)
+        cls.zone = get_zone(cls.api_client, cls.services)
+        cls.services['mode'] = cls.zone.networktype
+
+        cls.template = get_template(
+                            cls.api_client,
+                            cls.zone.id,
+                            cls.services["ostype"]
+                            )
+        # Set Zones and disk offerings
+        cls.services["small"]["zoneid"] = cls.zone.id
+        cls.services["small"]["template"] = cls.template.id
+
+        # Create VMs, NAT Rules etc
+        cls.account = Account.create(
+                            cls.api_client,
+                            cls.services["account"],
+                            domainid=cls.domain.id
+                            )
+
+        cls.small_offering = ServiceOffering.create(
+                                    cls.api_client,
+                                    cls.services["service_offerings"]["for-explicit"]
+                                    )
+
+        #cls.ag = AffinityGroup.create(cls.api_client, cls.services["virtual_machine"]["affinity"],
+         #   account=cls.services["account"], domainid=cls.domain.id)
+
+        cls._cleanup = [
+                        cls.small_offering,
+                        cls.account
+                        ]
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.api_client = super(TestExplicitDedication, cls).getClsTestClient().getApiClient()
+        cleanup_resources(cls.api_client, cls._cleanup)
+        return
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+        self.cleanup = []
+
+    def tearDown(self):
+        #Clean up, terminate the created ISOs
+        cleanup_resources(self.apiclient, self.cleanup)
+        return
+
+    # This test requires multi host and at least one host which is empty (no vms should
+    # be running on that host). It explicitly dedicates empty host to an account, deploys
+    # a vm for that account and verifies that the vm gets deployed to the dedicated host.
+    @attr(tags = ["advanced", "basic", "multihosts", "explicitdedication"])
+    def test_01_deploy_vm_with_explicit_dedication(self):
+        """Test explicit dedication is placing vms of an account on dedicated hosts.
+        """
+        # Validate the following
+        # 1. Find and dedicate an empty host to an account.
+        # 2. Create an affinity group for explicit dedication.
+        # 3. Create a vm deployment by passing the affinity group as a parameter.
+        # 4. Validate the vm got deployed on the dedicated host.
+        # 5. Cleanup.
+
+        # list and find an empty hosts
+        all_hosts = list_hosts(
+                           self.apiclient,
+                           type='Routing',
+                           )
+
+        empty_host = None
+        for host in all_hosts:
+            vms_on_host = list_virtual_machines(
+                                                self.api_client,
+                                                hostid=host.id)
+            if not vms_on_host:
+                empty_host = host
+                break
+
+        # Create an affinity group for explicit dedication.
+        agCmd = createAffinityGroup.createAffinityGroupCmd()
+        agCmd.name = "explicit-affinity"
+        agCmd.displayText = "explicit-affinity"
+        agCmd.account = self.account.name
+        agCmd.domainid = self.account.domainid
+        agCmd.type = self.services['virtual_machine']['affinity']['type']
+        self.apiclient.createAffinityGroup(agCmd)
+
+        # dedicate the empty host to this account.
+        dedicateCmd = dedicateHost.dedicateHostCmd()
+        dedicateCmd.hostid = empty_host.id
+        dedicateCmd.domainid = self.domain.id
+        self.apiclient.dedicateHost(dedicateCmd)
+
+        # deploy vm on the dedicated resource.
+        vm = VirtualMachine.create(
+            self.api_client,
+            self.services["small"],
+            accountid=self.account.name,
+            domainid=self.account.domainid,
+            serviceofferingid=self.small_offering.id,
+            affinitygroupnames=["explicit-affinity"],
+            mode=self.services["mode"]
+        )
+
+        list_vm_response = list_virtual_machines(
+                                            self.apiclient,
+                                            id=vm.id
+                                            )
+
+        vm_response = list_vm_response[0]
+
+        self.assertEqual(
+                        vm_response.hostid,
+                        empty_host.id,
+                        "Check destination hostID of deployed VM"
+                        )
+
+        # release the dedicated host to this account.
+        releaseCmd = releaseDedicatedHost.releaseDedicatedHostCmd()
+        releaseCmd.hostid = empty_host.id
+        releaseCmd.domainid = self.domain.id
+        self.apiclient.releaseDedicatedHost(releaseCmd)
+
+        #Deletion of the created VM and affinity group is taken care as part of account clean
+
+        return

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/17267794/tools/apidoc/gen_toc.py
----------------------------------------------------------------------
diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py
index 793f720..cef50ee 100644
--- a/tools/apidoc/gen_toc.py
+++ b/tools/apidoc/gen_toc.py
@@ -143,7 +143,9 @@ known_categories = {
 	'AffinityGroup': 'Affinity Group',
     'InternalLoadBalancer': 'Internal LB',
 	'DeploymentPlanners': 'Configuration',
-    'PortableIp': 'Portable IP'
+    'PortableIp': 'Portable IP',
+    'dedicateHost': 'Dedicate Resources',
+    'releaseDedicatedHost': 'Dedicate Resources'
     }
 
 


Mime
View raw message