diff --git a/api/src/com/cloud/dc/DedicatedResources.java b/api/src/com/cloud/dc/DedicatedResources.java
new file mode 100755
index 00000000000..e8e5ab3dffc
--- /dev/null
+++ b/api/src/com/cloud/dc/DedicatedResources.java
@@ -0,0 +1,33 @@
+// 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 org.apache.cloudstack.acl.InfrastructureEntity;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface DedicatedResources extends InfrastructureEntity, InternalIdentity, Identity{
+ long getId();
+ Long getDataCenterId();
+ Long getPodId();
+ Long getClusterId();
+ Long getHostId();
+ Long getDomainId();
+ Long getAccountId();
+ String getUuid();
+
+}
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index 6dfb1ab57b6..ed4ba1254f0 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -438,6 +438,10 @@ public class EventTypes {
public static final String EVENT_PORTABLE_IP_RANGE_DELETE = "PORTABLE.IP.RANGE.DELETE";
public static final String EVENT_PORTABLE_IP_TRANSFER = "PORTABLE.IP.TRANSFER";
+ // Dedicated Resources
+ public static final String EVENT_DEDICATE_RESOURCE = "DEDICATE.RESOURCE";
+ public static final String EVENT_DEDICATE_RESOURCE_RELEASE = "DEDICATE.RESOURCE.RELEASE";
+
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
diff --git a/client/pom.xml b/client/pom.xml
index 0c38ecb65d2..ab758eb2a67 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -29,6 +29,11 @@
org.apache.cloudstack
cloud-plugin-acl-static-role-based
${project.version}
+
+
+ org.apache.cloudstack
+ cloud-plugin-dedicated-resources
+ ${project.version}
org.apache.cloudstack
@@ -136,6 +141,11 @@
cloud-plugin-planner-implicit-dedication
${project.version}
+
+ org.apache.cloudstack
+ cloud-plugin-explicit-dedication
+ ${project.version}
+
org.apache.cloudstack
cloud-plugin-host-allocator-random
diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in
index edf83a94ae6..26b698af144 100644
--- a/client/tomcatconf/applicationContext.xml.in
+++ b/client/tomcatconf/applicationContext.xml.in
@@ -93,7 +93,7 @@
-
+
@@ -156,9 +156,17 @@
-
+
-
+
+
+
+
+
+
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index fd5479f44b4..f0ae7bf3dd7 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -641,3 +641,16 @@ listInternalLoadBalancerVMs=1
### Network Isolation methods listing
listNetworkIsolationMethods=1
+#### Dedicated Resource commands
+dedicateZone=1
+dedicatePod=1
+dedicateCluster=1
+dedicateHost=1
+releaseDedicatedZone=1
+releaseDedicatedPod=1
+releaseDedicatedCluster=1
+releaseDedicatedHost=1
+listDedicatedZones=1
+listDedicatedPods=1
+listDedicatedClusters=1
+listDedicatedHosts=1
diff --git a/client/tomcatconf/componentContext.xml.in b/client/tomcatconf/componentContext.xml.in
index e946f448d90..fcbcc1bb50b 100644
--- a/client/tomcatconf/componentContext.xml.in
+++ b/client/tomcatconf/componentContext.xml.in
@@ -24,28 +24,27 @@
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
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">
+ http://www.springframework.org/schema/context/spring-context-3.0.xsd">
-
@@ -171,7 +170,7 @@
-
+
@@ -260,13 +259,22 @@
-
+
+
-
+
+
+
+
+
+
+
diff --git a/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
index 963e4d7d967..ca299ea45bc 100755
--- a/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
@@ -89,10 +89,9 @@ public class CloudOrchestrator implements OrchestrationService {
public CloudOrchestrator() {
}
-
+
public VirtualMachineEntity createFromScratch(String uuid, String iso, String os, String hypervisor, String hostName, int cpu, int speed, long memory, List networks, List computeTags,
Map details, String owner) {
- // TODO Auto-generated method stub
return null;
}
diff --git a/engine/schema/src/com/cloud/dc/dao/ClusterDao.java b/engine/schema/src/com/cloud/dc/dao/ClusterDao.java
index 3ce0798a8a2..673888bc2ab 100644
--- a/engine/schema/src/com/cloud/dc/dao/ClusterDao.java
+++ b/engine/schema/src/com/cloud/dc/dao/ClusterDao.java
@@ -34,4 +34,5 @@ public interface ClusterDao extends GenericDao {
Map> getPodClusterIdMap(List clusterIds);
List listDisabledClusters(long zoneId, Long podId);
List listClustersWithDisabledPods(long zoneId);
+ List listClustersByDcId(long zoneId);
}
diff --git a/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java
index 86dc65e05bd..ba2686a4004 100644
--- a/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java
+++ b/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java
@@ -52,6 +52,7 @@ public class ClusterDaoImpl extends GenericDaoBase implements C
protected final SearchBuilder AvailHyperSearch;
protected final SearchBuilder ZoneSearch;
protected final SearchBuilder ZoneHyTypeSearch;
+ protected final SearchBuilder ZoneClusterSearch;
private static final String GET_POD_CLUSTER_MAP_PREFIX = "SELECT pod_id, id FROM cloud.cluster WHERE cluster.id IN( ";
private static final String GET_POD_CLUSTER_MAP_SUFFIX = " )";
@@ -85,12 +86,16 @@ public class ClusterDaoImpl extends GenericDaoBase implements C
AvailHyperSearch.and("zoneId", AvailHyperSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
AvailHyperSearch.select(null, Func.DISTINCT, AvailHyperSearch.entity().getHypervisorType());
AvailHyperSearch.done();
+
+ ZoneClusterSearch = createSearchBuilder();
+ ZoneClusterSearch.and("dataCenterId", ZoneClusterSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
+ ZoneClusterSearch.done();
}
@Override
public List listByZoneId(long zoneId) {
SearchCriteria sc = ZoneSearch.create();
- sc.setParameters("dataCenterId", zoneId);
+ sc.setParameters("dataCenterId", zoneId);
return listBy(sc);
}
@@ -223,6 +228,13 @@ public class ClusterDaoImpl extends GenericDaoBase implements C
return customSearch(sc, null);
}
+ @Override
+ public List listClustersByDcId(long zoneId) {
+ SearchCriteria sc = ZoneClusterSearch.create();
+ sc.setParameters("dataCenterId", zoneId);
+ return listBy(sc);
+ }
+
@Override
public boolean remove(Long id) {
Transaction txn = Transaction.currentTxn();
diff --git a/engine/schema/src/com/cloud/domain/dao/DomainDaoImpl.java b/engine/schema/src/com/cloud/domain/dao/DomainDaoImpl.java
index 9460a73dc57..c84aa60897c 100644
--- a/engine/schema/src/com/cloud/domain/dao/DomainDaoImpl.java
+++ b/engine/schema/src/com/cloud/domain/dao/DomainDaoImpl.java
@@ -288,5 +288,5 @@ public class DomainDaoImpl extends GenericDaoBase implements Dom
return parentDomains;
}
-
+
}
diff --git a/engine/schema/src/com/cloud/host/dao/HostDao.java b/engine/schema/src/com/cloud/host/dao/HostDao.java
index 98bdcb470e1..8ceb8f23132 100755
--- a/engine/schema/src/com/cloud/host/dao/HostDao.java
+++ b/engine/schema/src/com/cloud/host/dao/HostDao.java
@@ -80,4 +80,10 @@ public interface HostDao extends GenericDao, StateDao listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long podId, long dcId, String haTag);
+
+ List findByPodId(Long podId);
+
+ List findByClusterId(Long clusterId);
+
+ List listByDataCenterId(long id);
}
diff --git a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
index 07a42322ce3..810b973e296 100755
--- a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
@@ -37,6 +37,7 @@ import com.cloud.cluster.agentlb.HostTransferMapVO;
import com.cloud.cluster.agentlb.dao.HostTransferMapDao;
import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl;
import com.cloud.dc.ClusterVO;
+import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.ClusterDaoImpl;
import com.cloud.host.Host;
@@ -86,6 +87,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
protected SearchBuilder GuidSearch;
protected SearchBuilder DcSearch;
protected SearchBuilder PodSearch;
+ protected SearchBuilder ClusterSearch;
protected SearchBuilder TypeSearch;
protected SearchBuilder StatusSearch;
protected SearchBuilder ResourceStateSearch;
@@ -201,6 +203,9 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
DcSearch = createSearchBuilder();
DcSearch.and("dc", DcSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
+ DcSearch.and("type", DcSearch.entity().getType(), Op.EQ);
+ DcSearch.and("status", DcSearch.entity().getStatus(), Op.EQ);
+ DcSearch.and("resourceState", DcSearch.entity().getResourceState(), Op.EQ);
DcSearch.done();
ClusterStatusSearch = createSearchBuilder();
@@ -215,9 +220,13 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
TypeNameZoneSearch.done();
PodSearch = createSearchBuilder();
- PodSearch.and("pod", PodSearch.entity().getPodId(), SearchCriteria.Op.EQ);
+ PodSearch.and("podId", PodSearch.entity().getPodId(), SearchCriteria.Op.EQ);
PodSearch.done();
+ ClusterSearch = createSearchBuilder();
+ ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ);
+ ClusterSearch.done();
+
TypeSearch = createSearchBuilder();
TypeSearch.and("type", TypeSearch.entity().getType(), SearchCriteria.Op.EQ);
TypeSearch.done();
@@ -373,7 +382,17 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
List hosts = listBy(sc);
return hosts.size();
}
-
+
+ @Override
+ public List listByDataCenterId(long id) {
+ SearchCriteria sc = DcSearch.create();
+ sc.setParameters("dcId", id);
+ sc.setParameters("status", Status.Up);
+ sc.setParameters("type", Host.Type.Routing);
+ sc.setParameters("resourceState", ResourceState.Enabled);
+
+ return listBy(sc);
+ }
@Override
public HostVO findByGuid(String guid) {
@@ -906,6 +925,20 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
return findOneBy(sc);
}
+ @Override
+ public List findByPodId(Long podId) {
+ SearchCriteria sc = PodSearch.create();
+ sc.setParameters("podId", podId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List findByClusterId(Long clusterId) {
+ SearchCriteria sc = ClusterSearch.create();
+ sc.setParameters("clusterId", clusterId);
+ return listBy(sc);
+ }
+
@Override
public List findHypervisorHostInCluster(long clusterId) {
SearchCriteria sc = TypeClusterStatusSearch.create();
diff --git a/plugins/affinity-group-processors/explicit-dedication/pom.xml b/plugins/affinity-group-processors/explicit-dedication/pom.xml
new file mode 100644
index 00000000000..bb3c595841a
--- /dev/null
+++ b/plugins/affinity-group-processors/explicit-dedication/pom.xml
@@ -0,0 +1,33 @@
+
+
+ 4.0.0
+ cloud-plugin-explicit-dedication
+ Apache CloudStack Plugin - Explicit Dedication Processor
+
+ org.apache.cloudstack
+ cloudstack-plugins
+ 4.2.0-SNAPSHOT
+ ../../pom.xml
+
+
+ install
+ src
+
+
diff --git a/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java b/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java
new file mode 100644
index 00000000000..a0eb56cbb8a
--- /dev/null
+++ b/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java
@@ -0,0 +1,383 @@
+// 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.affinity;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
+import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenter;
+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.DeploymentPlan;
+import com.cloud.deploy.DeploymentPlanner.ExcludeList;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.AffinityConflictException;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.dao.UserVmDao;
+import com.cloud.vm.dao.VMInstanceDao;
+
+@Local(value = AffinityGroupProcessor.class)
+public class ExplicitDedicationProcessor extends AffinityProcessorBase implements AffinityGroupProcessor {
+
+ private static final Logger s_logger = Logger.getLogger(ExplicitDedicationProcessor.class);
+ @Inject
+ protected UserVmDao _vmDao;
+ @Inject
+ protected VMInstanceDao _vmInstanceDao;
+ @Inject
+ protected DataCenterDao _dcDao;
+ @Inject
+ protected DedicatedResourceDao _dedicatedDao;
+ @Inject
+ protected HostPodDao _podDao;
+ @Inject
+ protected ClusterDao _clusterDao;
+ @Inject
+ protected HostDao _hostDao;
+ @Inject
+ protected DomainDao _domainDao;
+ @Inject
+ protected AffinityGroupDao _affinityGroupDao;
+ @Inject
+ protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
+
+ /**
+ * This method will process the affinity group of type 'Explicit Dedication' for a deployment of a VM that demands dedicated resources.
+ * For ExplicitDedicationProcessor we need to add dedicated resources into the IncludeList based on the level we have dedicated resources available.
+ * For eg. if admin dedicates a pod to a domain, then all the user in that domain can use the resources of that pod.
+ * We need to take care of the situation when dedicated resources further have resources dedicated to sub-domain/account.
+ * This IncludeList is then used to update the avoid list for a given data center.
+ */
+ @Override
+ public void process(VirtualMachineProfile extends VirtualMachine> vmProfile, DeploymentPlan plan,
+ ExcludeList avoid) throws AffinityConflictException {
+ VirtualMachine vm = vmProfile.getVirtualMachine();
+ List vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType());
+ DataCenter dc = _dcDao.findById(vm.getDataCenterId());
+ long domainId = vm.getDomainId();
+ long accountId = vm.getAccountId();
+
+ for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings) {
+ if (vmGroupMapping != null) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Processing affinity group of type 'ExplicitDedication' for VM Id: " + vm.getId());
+ }
+
+ List dr = _dedicatedDao.listByAccountId(accountId);
+ List drOfDomain = searchInDomainResources(domainId);
+ List drOfParentDomain = searchInParentDomainResources(domainId);
+ List resourceList = new ArrayList();
+ resourceList.addAll(dr);
+ resourceList.addAll(drOfDomain);
+ resourceList.addAll(drOfParentDomain);
+ boolean canUse = false;
+
+ if (plan.getHostId() != null) {
+ HostVO host = _hostDao.findById(plan.getHostId());
+ ClusterVO clusterofHost = _clusterDao.findById(host.getClusterId());
+ HostPodVO podOfHost = _podDao.findById(host.getPodId());
+ DataCenterVO zoneOfHost = _dcDao.findById(host.getDataCenterId());
+ if (resourceList != null && resourceList.size() != 0) {
+ for(DedicatedResourceVO resource : resourceList){
+ if ((resource.getHostId() != null && resource.getHostId() == plan.getHostId()) ||
+ (resource.getClusterId() != null && resource.getClusterId() == clusterofHost.getId()) ||
+ (resource.getPodId() != null && resource.getPodId() == podOfHost.getId()) ||
+ (resource.getDataCenterId() != null && resource.getDataCenterId() == zoneOfHost.getId())){
+ canUse = true;
+ }
+ }
+ }
+ if (!canUse) {
+ throw new CloudRuntimeException("Cannot use this host " + host.getName() + " for explicit dedication");
+ }
+ } else if (plan.getClusterId() != null) {
+ ClusterVO cluster = _clusterDao.findById(plan.getClusterId());
+ HostPodVO podOfCluster = _podDao.findById(cluster.getPodId());
+ DataCenterVO zoneOfCluster = _dcDao.findById(cluster.getDataCenterId());
+ List hostToUse = new ArrayList();
+ // check whether this cluster or its pod is dedicated
+ if (resourceList != null && resourceList.size() != 0) {
+ for(DedicatedResourceVO resource : resourceList){
+ if ((resource.getClusterId() != null && resource.getClusterId() == cluster.getId()) ||
+ (resource.getPodId() != null && resource.getPodId() == podOfCluster.getId()) ||
+ (resource.getDataCenterId() != null && resource.getDataCenterId() == zoneOfCluster.getId())){
+ canUse = true;
+ }
+
+ // check for all dedicated host; if it belongs to this cluster
+ if (!canUse){
+ if (resource.getHostId() != null) {
+ HostVO dHost = _hostDao.findById(resource.getHostId());
+ if (dHost.getClusterId() == cluster.getId()) {
+ hostToUse.add(dHost);
+ }
+ }
+ }
+
+ }
+ }
+
+ if (hostToUse.isEmpty() && !canUse) {
+ throw new CloudRuntimeException("Cannot use this cluster " + cluster.getName() + " for explicit dedication");
+ }
+
+ if (hostToUse != null && hostToUse.size() != 0) {
+ // add other non-dedicated hosts to avoid list
+ List hostList = _hostDao.findByClusterId(cluster.getId());
+ for (HostVO host : hostList){
+ if (!hostToUse.contains(host)) {
+ avoid.addHost(host.getId());
+ }
+ }
+ }
+
+ } else if (plan.getPodId() != null) {
+ HostPodVO pod = _podDao.findById(plan.getPodId());
+ DataCenterVO zoneOfPod = _dcDao.findById(pod.getDataCenterId());
+ List clustersToUse = new ArrayList();
+ List hostsToUse = new ArrayList();
+ // check whether this cluster or its pod is dedicated
+ if (resourceList != null && resourceList.size() != 0) {
+ for(DedicatedResourceVO resource : resourceList){
+ if ((resource.getPodId() != null && resource.getPodId() == pod.getId()) ||
+ (resource.getDataCenterId() != null && resource.getDataCenterId() == zoneOfPod.getId())){
+ canUse = true;
+ }
+
+ // check for all dedicated cluster/host; if it belongs to this pod
+ if (!canUse){
+ if (resource.getClusterId() != null) {
+ ClusterVO dCluster = _clusterDao.findById(resource.getClusterId());
+ if (dCluster.getPodId() == pod.getId()) {
+ clustersToUse.add(dCluster);
+ }
+ }
+ if (resource.getHostId() != null) {
+ HostVO dHost = _hostDao.findById(resource.getHostId());
+ if (dHost.getPodId() == pod.getId()) {
+ hostsToUse.add(dHost);
+ }
+ }
+ }
+
+ }
+ }
+
+ if (hostsToUse.isEmpty() && clustersToUse.isEmpty() && !canUse) {
+ throw new CloudRuntimeException("Cannot use this pod " + pod.getName() + " for explicit dedication");
+ }
+
+ if (clustersToUse != null && clustersToUse.size() != 0) {
+ // add other non-dedicated clusters to avoid list
+ List clusterList = _clusterDao.listByPodId(pod.getId());
+ for (ClusterVO cluster : clusterList){
+ if (!clustersToUse.contains(cluster)) {
+ avoid.addCluster(cluster.getId());
+ }
+ }
+ }
+
+ if (hostsToUse != null && hostsToUse.size() != 0) {
+ // add other non-dedicated hosts to avoid list
+ List hostList = _hostDao.findByPodId(pod.getId());
+ for (HostVO host : hostList){
+ if (!hostsToUse.contains(host)) {
+ avoid.addHost(host.getId());
+ }
+ }
+ }
+
+ } else {
+ //check all resources under this zone
+ if (dr != null && dr.size() != 0) {
+ avoid = updateAvoidList(dr, avoid, dc);
+ } else if(drOfDomain != null && drOfDomain.size() != 0){
+ avoid = updateAvoidList(drOfDomain, avoid, dc);
+ } else if(drOfParentDomain != null && drOfParentDomain.size() != 0){
+ avoid = updateAvoidList(drOfParentDomain, avoid, dc);
+ } else {
+ avoid.addDataCenter(dc.getId());
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("No dedicated resources available for this domain or account");
+ }
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("ExplicitDedicationProcessor returns Avoid List as: Deploy avoids pods: " + avoid.getPodsToAvoid() + ", clusters: "
+ + avoid.getClustersToAvoid() + ", hosts: " + avoid.getHostsToAvoid());
+ }
+ }
+ }
+ }
+ }
+
+ private ExcludeList updateAvoidList(List dedicatedResources, ExcludeList avoidList, DataCenter dc) {
+ ExcludeList includeList = new ExcludeList();
+ for (DedicatedResourceVO dr : dedicatedResources) {
+ if (dr.getHostId() != null){
+ includeList.addHost(dr.getHostId());
+ HostVO dedicatedHost = _hostDao.findById(dr.getHostId());
+ includeList.addCluster(dedicatedHost.getClusterId());
+ includeList.addPod(dedicatedHost.getPodId());
+ }
+
+ if (dr.getClusterId() != null) {
+ includeList.addCluster(dr.getClusterId());
+ //add all hosts inside this in includeList
+ List hostList = _hostDao.findByClusterId(dr.getClusterId());
+ for (HostVO host : hostList) {
+ DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId());
+ if (dHost != null) {
+ avoidList.addHost(host.getId());
+ } else {
+ includeList.addHost(host.getId());
+ }
+ }
+ ClusterVO dedicatedCluster = _clusterDao.findById(dr.getClusterId());
+ includeList.addPod(dedicatedCluster.getPodId());
+ }
+
+ if (dr.getPodId() != null) {
+ includeList.addPod(dr.getPodId());
+ //add all cluster under this pod in includeList
+ List clusterList = _clusterDao.listByPodId(dr.getPodId());
+ for (ClusterVO cluster : clusterList) {
+ if (_dedicatedDao.findByClusterId(cluster.getId()) != null) {
+ avoidList.addCluster(cluster.getId());
+ } else {
+ includeList.addCluster(cluster.getId());
+ }
+ }
+ //add all hosts inside this pod in includeList
+ List hostList = _hostDao.findByPodId(dr.getPodId());
+ for (HostVO host : hostList) {
+ if (_dedicatedDao.findByHostId(host.getId()) != null) {
+ avoidList.addHost(host.getId());
+ } else {
+ includeList.addHost(host.getId());
+ }
+ }
+ }
+
+ if (dr.getDataCenterId() != null) {
+ includeList.addDataCenter(dr.getDataCenterId());
+ //add all Pod under this data center in includeList
+ List podList = _podDao.listByDataCenterId(dr.getDataCenterId());
+ for (HostPodVO pod : podList) {
+ if (_dedicatedDao.findByPodId(pod.getId()) != null) {
+ avoidList.addPod(pod.getId());
+ } else {
+ includeList.addPod(pod.getId());
+ }
+ }
+ List clusterList = _clusterDao.listClustersByDcId(dr.getDataCenterId());
+ for (ClusterVO cluster : clusterList) {
+ if (_dedicatedDao.findByClusterId(cluster.getId()) != null) {
+ avoidList.addCluster(cluster.getId());
+ } else {
+ includeList.addCluster(cluster.getId());
+ }
+ }
+ //add all hosts inside this in includeList
+ List hostList = _hostDao.listByDataCenterId(dr.getDataCenterId());
+ for (HostVO host : hostList) {
+ if (_dedicatedDao.findByHostId(host.getId()) != null) {
+ avoidList.addHost(host.getId());
+ } else {
+ includeList.addHost(host.getId());
+ }
+ }
+ }
+ }
+ //Update avoid list using includeList.
+ //add resources in avoid list which are not in include list.
+
+ List pods = _podDao.listByDataCenterId(dc.getId());
+ List clusters = _clusterDao.listClustersByDcId(dc.getId());
+ List hosts = _hostDao.listByDataCenterId(dc.getId());
+ Set podsInIncludeList = includeList.getPodsToAvoid();
+ Set clustersInIncludeList = includeList.getClustersToAvoid();
+ Set hostsInIncludeList = includeList.getHostsToAvoid();
+
+ for (HostPodVO pod : pods){
+ if (podsInIncludeList != null && !podsInIncludeList.contains(pod.getId())) {
+ avoidList.addPod(pod.getId());
+ }
+ }
+
+ for (ClusterVO cluster : clusters) {
+ if (clustersInIncludeList != null && !clustersInIncludeList.contains(cluster.getId())) {
+ avoidList.addCluster(cluster.getId());
+ }
+ }
+
+ for (HostVO host : hosts) {
+ if (hostsInIncludeList != null && !hostsInIncludeList.contains(host.getId())) {
+ avoidList.addHost(host.getId());
+ }
+ }
+ return avoidList;
+ }
+
+ private List searchInParentDomainResources(long domainId) {
+ List domainIds = getDomainParentIds(domainId);
+ List dr = new ArrayList();
+ for (Long id : domainIds) {
+ List resource = _dedicatedDao.listByDomainId(id);
+ if(resource != null) {
+ dr.addAll(resource);
+ }
+ }
+ return dr;
+ }
+
+ private List searchInDomainResources(long domainId) {
+ List dr = _dedicatedDao.listByDomainId(domainId);
+ return dr;
+ }
+
+ private List getDomainParentIds(long domainId) {
+ DomainVO domainRecord = _domainDao.findById(domainId);
+ List domainIds = new ArrayList();
+ domainIds.add(domainRecord.getId());
+ while (domainRecord.getParent() != null ){
+ domainRecord = _domainDao.findById(domainRecord.getParent());
+ domainIds.add(domainRecord.getId());
+ }
+ return domainIds;
+ }
+
+}
diff --git a/plugins/dedicated-resources/pom.xml b/plugins/dedicated-resources/pom.xml
new file mode 100644
index 00000000000..4c908f4ff96
--- /dev/null
+++ b/plugins/dedicated-resources/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+ cloud-plugin-dedicated-resources
+ Apache CloudStack Plugin - Dedicated Resources
+
+ org.apache.cloudstack
+ cloudstack-plugins
+ 4.2.0-SNAPSHOT
+ ../pom.xml
+
+
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicateClusterCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicateClusterCmd.java
new file mode 100644
index 00000000000..58e20dee025
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicateClusterCmd.java
@@ -0,0 +1,115 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateClusterResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "dedicateCluster", description= "Dedicate an existing cluster", responseObject = DedicateClusterResponse.class )
+public class DedicateClusterCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DedicateClusterCmd.class.getName());
+
+ private static final String s_name = "dedicateclusterresponse";
+ @Inject DedicatedService dedicatedService;
+
+ @Parameter(name=ApiConstants.CLUSTER_ID, type=CommandType.UUID, entityType=ClusterResponse.class,
+ required=true, description="the ID of the Cluster")
+ private Long clusterId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class, required=true, description="the ID of the containing domain")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the name of the account which needs dedication. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getClusterId() {
+ return clusterId;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "dedicating a cluster";
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ List extends DedicatedResources> result = dedicatedService.dedicateCluster(getClusterId(), getDomainId(), getAccountName());
+ ListResponse response = new ListResponse();
+ List clusterResponseList = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result) {
+ DedicateClusterResponse clusterResponse = dedicatedService.createDedicateClusterResponse(resource);
+ clusterResponseList.add(clusterResponse);
+ }
+ response.setResponses(clusterResponseList);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate cluster");
+ }
+ }
+
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicateHostCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicateHostCmd.java
new file mode 100644
index 00000000000..f0269b11048
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicateHostCmd.java
@@ -0,0 +1,118 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateHostResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "dedicateHost", description = "Dedicates a host.", responseObject = DedicateHostResponse.class)
+public class DedicateHostCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DedicateHostCmd.class.getName());
+ private static final String s_name = "dedicatehostresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.HOST_ID, type=CommandType.UUID, entityType = HostResponse.class,
+ required=true, description="the ID of the host to update")
+ private Long hostId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class, required=true, description="the ID of the containing domain")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the name of the account which needs dedication. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ List extends DedicatedResources> result = dedicatedService.dedicateHost(getHostId(), getDomainId(), getAccountName());
+ ListResponse response = new ListResponse();
+ List hostResponseList = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result) {
+ DedicateHostResponse hostResponse = dedicatedService.createDedicateHostResponse(resource);
+ hostResponseList.add(hostResponse);
+ }
+ response.setResponses(hostResponseList);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate host");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "dedicating a host";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicatePodCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicatePodCmd.java
new file mode 100644
index 00000000000..be5eac26feb
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicatePodCmd.java
@@ -0,0 +1,120 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.PodResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicatePodResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "dedicatePod", description ="Dedicates a Pod.", responseObject = DedicatePodResponse.class)
+public class DedicatePodCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DedicatePodCmd.class.getName());
+
+ private static final String s_name = "dedicatepodresponse";
+ @Inject public DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class,
+ required=true, description="the ID of the Pod")
+ private Long podId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class, required=true, description="the ID of the containing domain")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the name of the account which needs dedication. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getPodId() {
+ return podId;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ List extends DedicatedResources> result = dedicatedService.dedicatePod(getPodId(), getDomainId(), getAccountName());
+ ListResponse response = new ListResponse();
+ List podResponseList = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result) {
+ DedicatePodResponse podresponse = dedicatedService.createDedicatePodResponse(resource);
+ podResponseList.add(podresponse);
+ }
+ response.setResponses(podResponseList);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate pod");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "dedicating a pod";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicateZoneCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicateZoneCmd.java
new file mode 100644
index 00000000000..134fb972757
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/DedicateZoneCmd.java
@@ -0,0 +1,120 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateZoneResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "dedicateZone", description ="Dedicates a zones.", responseObject = DedicateZoneResponse.class)
+public class DedicateZoneCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DedicateZoneCmd.class.getName());
+
+ private static final String s_name = "dedicatezoneresponse";
+ @Inject public DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
+ required=true, description="the ID of the zone")
+ private Long zoneId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class, required=true, description="the ID of the containing domain")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the name of the account which needs dedication. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ List extends DedicatedResources> result = dedicatedService.dedicateZone(getZoneId(), getDomainId(), getAccountName());
+ ListResponse response = new ListResponse();
+ List zoneResponseList = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result) {
+ DedicateZoneResponse zoneresponse = dedicatedService.createDedicateZoneResponse(resource);
+ zoneResponseList.add(zoneresponse);
+ }
+ response.setResponses(zoneResponseList);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate zone");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "dedicating a zone";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedClustersCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedClustersCmd.java
new file mode 100644
index 00000000000..c60c5240d9a
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedClustersCmd.java
@@ -0,0 +1,105 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateClusterResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listDedicatedClusters", description = "Lists dedicated clusters.", responseObject = DedicateClusterResponse.class)
+public class ListDedicatedClustersCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListDedicatedClustersCmd.class.getName());
+
+ private static final String s_name = "listdedicatedclustersresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+ @Parameter(name=ApiConstants.CLUSTER_ID, type=CommandType.UUID, entityType=ClusterResponse.class,
+ description="the ID of the cluster")
+ private Long clusterId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+ description="the ID of the domain associated with the cluster")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
+ description = "the name of the account associated with the cluster. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getClusterId() {
+ return clusterId;
+ }
+
+ public Long getDomainId(){
+ return domainId;
+ }
+
+ public String getAccountName(){
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+ Pair, Integer> result = dedicatedService.listDedicatedClusters(this);
+ ListResponse response = new ListResponse();
+ List Responses = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result.first()) {
+ DedicateClusterResponse clusterResponse = dedicatedService.createDedicateClusterResponse(resource);
+ Responses.add(clusterResponse);
+ }
+ response.setResponses(Responses, result.second());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to list dedicated clusters");
+ }
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedHostsCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedHostsCmd.java
new file mode 100644
index 00000000000..2c1ad002e0d
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedHostsCmd.java
@@ -0,0 +1,105 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateHostResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listDedicatedHosts", description = "Lists dedicated hosts.", responseObject = DedicateHostResponse.class)
+public class ListDedicatedHostsCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListDedicatedHostsCmd.class.getName());
+
+ private static final String s_name = "listdedicatedhostsresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+ @Parameter(name=ApiConstants.HOST_ID, type=CommandType.UUID, entityType=HostResponse.class,
+ description="the ID of the host")
+ private Long hostId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+ description="the ID of the domain associated with the host")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
+ description = "the name of the account associated with the host. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ public Long getDomainId(){
+ return domainId;
+ }
+
+ public String getAccountName(){
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////l
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+ Pair, Integer> result = dedicatedService.listDedicatedHosts(this);
+ ListResponse response = new ListResponse();
+ List Responses = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result.first()) {
+ DedicateHostResponse hostResponse = dedicatedService.createDedicateHostResponse(resource);
+ Responses.add(hostResponse);
+ }
+ response.setResponses(Responses, result.second());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to list dedicated hosts");
+ }
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedPodsCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedPodsCmd.java
new file mode 100644
index 00000000000..31b1ecfbb51
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedPodsCmd.java
@@ -0,0 +1,105 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.PodResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicatePodResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listDedicatedPods", description = "Lists dedicated pods.", responseObject = DedicatePodResponse.class)
+public class ListDedicatedPodsCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListDedicatedPodsCmd.class.getName());
+
+ private static final String s_name = "listdedicatedpodsresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+ @Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class,
+ description="the ID of the pod")
+ private Long podId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+ description="the ID of the domain associated with the pod")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
+ description = "the name of the account associated with the pod. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getPodId() {
+ return podId;
+ }
+
+ public Long getDomainId(){
+ return domainId;
+ }
+
+ public String getAccountName(){
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+ Pair, Integer> result = dedicatedService.listDedicatedPods(this);
+ ListResponse response = new ListResponse();
+ List Responses = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result.first()) {
+ DedicatePodResponse podresponse = dedicatedService.createDedicatePodResponse(resource);
+ Responses.add(podresponse);
+ }
+ response.setResponses(Responses, result.second());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to list dedicated pods");
+ }
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedZonesCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedZonesCmd.java
new file mode 100644
index 00000000000..c88c42b82a6
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ListDedicatedZonesCmd.java
@@ -0,0 +1,105 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateZoneResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listDedicatedZones", description = "List dedicated zones.", responseObject = DedicateZoneResponse.class)
+public class ListDedicatedZonesCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListDedicatedZonesCmd.class.getName());
+
+ private static final String s_name = "listdedicatedzonesresponse";
+ @Inject DedicatedService _dedicatedservice;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+ @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
+ description="the ID of the Zone")
+ private Long zoneId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+ description="the ID of the domain associated with the zone")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
+ description = "the name of the account associated with the zone. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ public Long getDomainId(){
+ return domainId;
+ }
+
+ public String getAccountName(){
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+ Pair, Integer> result = _dedicatedservice.listDedicatedZones(this);
+ ListResponse response = new ListResponse();
+ List Responses = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result.first()) {
+ DedicateZoneResponse zoneResponse = _dedicatedservice.createDedicateZoneResponse(resource);
+ Responses.add(zoneResponse);
+ }
+ response.setResponses(Responses, result.second());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to list dedicated zones");
+ }
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedClusterCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedClusterCmd.java
new file mode 100644
index 00000000000..6a317885f10
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedClusterCmd.java
@@ -0,0 +1,91 @@
+// 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.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "releaseDedicatedCluster", description = "Release the dedication for cluster", responseObject = SuccessResponse.class)
+public class ReleaseDedicatedClusterCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleaseDedicatedClusterCmd.class.getName());
+
+ private static final String s_name = "releasededicatedclusterresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.CLUSTER_ID, type=CommandType.UUID, entityType=ClusterResponse.class,
+ required=true, description="the ID of the Cluster")
+ private Long clusterId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getClusterId() {
+ return clusterId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = dedicatedService.releaseDedicatedResource(null, null, getClusterId(), null);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release dedicated cluster");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "releasing dedicated cluster";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedHostCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedHostCmd.java
new file mode 100644
index 00000000000..29cfdeb9ab5
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedHostCmd.java
@@ -0,0 +1,91 @@
+// 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.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "releaseDedicatedHost", description = "Release the dedication for host", responseObject = SuccessResponse.class)
+public class ReleaseDedicatedHostCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleaseDedicatedHostCmd.class.getName());
+
+ private static final String s_name = "releasededicatedhostresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.HOST_ID, type=CommandType.UUID, entityType=HostResponse.class,
+ required=true, description="the ID of the host")
+ private Long hostId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = dedicatedService.releaseDedicatedResource(null, null, null, getHostId());
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release dedicated Host");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "releasing dedicated host";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedPodCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedPodCmd.java
new file mode 100644
index 00000000000..51d3fe20477
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedPodCmd.java
@@ -0,0 +1,91 @@
+// 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.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.PodResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "releaseDedicatedPod", description = "Release the dedication for the pod", responseObject = SuccessResponse.class)
+public class ReleaseDedicatedPodCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleaseDedicatedPodCmd.class.getName());
+
+ private static final String s_name = "releasededicatedpodresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class,
+ required=true, description="the ID of the Pod")
+ private Long podId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getPodId() {
+ return podId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = dedicatedService.releaseDedicatedResource(null, getPodId(), null, null);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release dedicated pod");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "releasing dedicated pod";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedZoneCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedZoneCmd.java
new file mode 100644
index 00000000000..23f955711bf
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/commands/ReleaseDedicatedZoneCmd.java
@@ -0,0 +1,91 @@
+// 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.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "releaseDedicatedZone", description = "Release dedication of zone", responseObject = SuccessResponse.class)
+public class ReleaseDedicatedZoneCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleaseDedicatedZoneCmd.class.getName());
+
+ private static final String s_name = "releasededicatedzoneresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType= ZoneResponse.class,
+ required=true, description="the ID of the Zone")
+ private Long zoneId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = dedicatedService.releaseDedicatedResource(getZoneId(), null, null, null);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release dedicated zone");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "releasing dedicated zone";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicateClusterResponse.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicateClusterResponse.java
new file mode 100644
index 00000000000..faa362777f2
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicateClusterResponse.java
@@ -0,0 +1,79 @@
+// 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.api.response;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class DedicateClusterResponse extends BaseResponse {
+ @SerializedName("id") @Param(description="the ID of the dedicated resource")
+ private String id;
+
+ @SerializedName("clusterid") @Param(description="the ID of the cluster")
+ private String clusterId;
+
+ @SerializedName("clustername") @Param(description="the name of the cluster")
+ private String clusterName;
+
+ @SerializedName("domainid") @Param(description="the domain ID of the cluster")
+ private String domainId;
+
+ @SerializedName("accountid") @Param(description="the Account ID of the cluster")
+ private String accountId;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getClusterId() {
+ return clusterId;
+ }
+
+ public void setClusterId(String clusterId) {
+ this.clusterId = clusterId;
+ }
+
+ public String getClusterName() {
+ return clusterName;
+ }
+
+ public void setClusterName(String clusterName) {
+ this.clusterName = clusterName;
+ }
+
+ public String getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(String accountId) {
+ this.accountId = accountId;
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicateHostResponse.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicateHostResponse.java
new file mode 100644
index 00000000000..e48ee35610d
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicateHostResponse.java
@@ -0,0 +1,79 @@
+// 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.api.response;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class DedicateHostResponse extends BaseResponse {
+ @SerializedName("id") @Param(description="the ID of the dedicated resource")
+ private String id;
+
+ @SerializedName("hostid") @Param(description="the ID of the host")
+ private String hostId;
+
+ @SerializedName("hostname") @Param(description="the name of the host")
+ private String hostName;
+
+ @SerializedName("domainid") @Param(description="the domain ID of the host")
+ private String domainId;
+
+ @SerializedName("accountid") @Param(description="the Account ID of the host")
+ private String accountId;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getHostId() {
+ return hostId;
+ }
+
+ public void setHostId(String hostId) {
+ this.hostId = hostId;
+ }
+
+ public String getHostName() {
+ return hostName;
+ }
+
+ public void setHostName(String hostName) {
+ this.hostName = hostName;
+ }
+
+ public String getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(String accountId) {
+ this.accountId = accountId;
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicatePodResponse.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicatePodResponse.java
new file mode 100644
index 00000000000..fabaca166ea
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicatePodResponse.java
@@ -0,0 +1,82 @@
+// 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.api.response;
+
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+@EntityReference(value = DedicatedResources.class)
+public class DedicatePodResponse extends BaseResponse {
+ @SerializedName("id") @Param(description="the ID of the dedicated resource")
+ private String id;
+
+ @SerializedName("podid") @Param(description="the ID of the Pod")
+ private String podId;
+
+ @SerializedName("podname") @Param(description="the Name of the Pod")
+ private String podName;
+
+ @SerializedName("domainid") @Param(description="the domain ID to which the Pod is dedicated")
+ private String domainId;
+
+ @SerializedName("accountid") @Param(description="the Account Id to which the Pod is dedicated")
+ private String accountId;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getPodId() {
+ return podId;
+ }
+
+ public void setPodId(String podId) {
+ this.podId = podId;
+ }
+
+ public String getPodName() {
+ return podName;
+ }
+
+ public void setPodName(String podName) {
+ this.podName = podName;
+ }
+
+ public String getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(String accountId) {
+ this.accountId = accountId;
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicateZoneResponse.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicateZoneResponse.java
new file mode 100644
index 00000000000..06f4877d211
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/api/response/DedicateZoneResponse.java
@@ -0,0 +1,83 @@
+// 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.api.response;
+
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+@EntityReference(value = DedicatedResources.class)
+public class DedicateZoneResponse extends BaseResponse {
+ @SerializedName("id") @Param(description="the ID of the dedicated resource")
+ private String id;
+
+ @SerializedName("zoneid") @Param(description="the ID of the Zone")
+ private String zoneId;
+
+ @SerializedName("zonename") @Param(description="the Name of the Zone")
+ private String zoneName;
+
+ @SerializedName("domainid") @Param(description="the domain ID to which the Zone is dedicated")
+ private String domainId;
+
+ @SerializedName("accountid") @Param(description="the Account Id to which the Zone is dedicated")
+ private String accountId;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ public void setZoneId(String zoneId) {
+ this.zoneId = zoneId;
+ }
+
+ public String getZoneName() {
+ return zoneName;
+ }
+
+ public void setZoneName(String zoneName) {
+ this.zoneName = zoneName;
+ }
+
+ public String getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(String accountId) {
+ this.accountId = accountId;
+ }
+
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/manager/DedicatedResourceManagerImpl.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/manager/DedicatedResourceManagerImpl.java
new file mode 100755
index 00000000000..51087e2f56a
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/manager/DedicatedResourceManagerImpl.java
@@ -0,0 +1,816 @@
+// 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 java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.dedicated.api.commands.DedicateClusterCmd;
+import org.apache.cloudstack.dedicated.api.commands.DedicateHostCmd;
+import org.apache.cloudstack.dedicated.api.commands.DedicatePodCmd;
+import org.apache.cloudstack.dedicated.api.commands.DedicateZoneCmd;
+import org.apache.cloudstack.dedicated.api.commands.ListDedicatedClustersCmd;
+import org.apache.cloudstack.dedicated.api.commands.ListDedicatedHostsCmd;
+import org.apache.cloudstack.dedicated.api.commands.ListDedicatedPodsCmd;
+import org.apache.cloudstack.dedicated.api.commands.ListDedicatedZonesCmd;
+import org.apache.cloudstack.dedicated.api.commands.ReleaseDedicatedClusterCmd;
+import org.apache.cloudstack.dedicated.api.commands.ReleaseDedicatedHostCmd;
+import org.apache.cloudstack.dedicated.api.commands.ReleaseDedicatedPodCmd;
+import org.apache.cloudstack.dedicated.api.commands.ReleaseDedicatedZoneCmd;
+import org.apache.cloudstack.dedicated.api.response.DedicateClusterResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateHostResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicatePodResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateZoneResponse;
+import org.apache.cloudstack.dedicated.services.DedicatedService;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.configuration.Config;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.dc.HostPodVO;
+import com.cloud.dc.Pod;
+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.event.ActionEvent;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+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.DateUtil;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.dao.UserVmDao;
+
+@Component
+@Local({DedicatedService.class })
+public class DedicatedResourceManagerImpl implements DedicatedService {
+ private static final Logger s_logger = Logger.getLogger(DedicatedResourceManagerImpl.class);
+
+ @Inject AccountDao _accountDao;
+ @Inject DomainDao _domainDao;
+ @Inject HostPodDao _podDao;
+ @Inject ClusterDao _clusterDao;
+ @Inject HostDao _hostDao;
+ @Inject DedicatedResourceDao _dedicatedDao;
+ @Inject DataCenterDao _zoneDao;
+ @Inject AccountManager _accountMgr;
+ @Inject UserVmDao _userVmDao;
+ @Inject ConfigurationDao _configDao;
+
+ private int capacityReleaseInterval;
+
+ public boolean configure(final String name, final Map params) throws ConfigurationException {
+ capacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.CapacitySkipcountingHours.key()), 3600);
+ return true;
+ }
+
+ @Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Zone")
+ public List dedicateZone(Long zoneId, Long domainId, String accountName) {
+ Long accountId = null;
+ List hosts = null;
+ if(accountName != null){
+ Account caller = UserContext.current().getCaller();
+ Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null);
+ accountId = owner.getId();
+ }
+ List childDomainIds = getDomainChildIds(domainId);
+ childDomainIds.add(domainId);
+ checkAccountAndDomain(accountId, domainId);
+ DataCenterVO dc = _zoneDao.findById(zoneId);
+ if (dc == null) {
+ throw new InvalidParameterValueException("Unable to find zone by id " + zoneId);
+ } else {
+ DedicatedResourceVO dedicatedZone = _dedicatedDao.findByZoneId(zoneId);
+ //check if zone is dedicated
+ if(dedicatedZone != null) {
+ s_logger.error("Zone " + dc.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Zone " + dc.getName() + " is already dedicated");
+ }
+
+ //check if any resource under this zone is dedicated to different account or sub-domain
+ List pods = _podDao.listByDataCenterId(dc.getId());
+ List podsToRelease = new ArrayList();
+ List clustersToRelease = new ArrayList();
+ List hostsToRelease = new ArrayList();
+ for (HostPodVO pod : pods) {
+ DedicatedResourceVO dPod = _dedicatedDao.findByPodId(pod.getId());
+ if (dPod != null) {
+ if(!(childDomainIds.contains(dPod.getDomainId()))) {
+ throw new CloudRuntimeException("Pod " + pod.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ if (accountId != null) {
+ if (dPod.getAccountId() == accountId) {
+ podsToRelease.add(dPod);
+ } else {
+ s_logger.error("Pod " + pod.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Pod " + pod.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dPod.getAccountId() == null && dPod.getDomainId() == domainId) {
+ podsToRelease.add(dPod);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : podsToRelease) {
+ releaseDedicatedResource(null, dr.getPodId(), null, null);
+ }
+
+ List clusters = _clusterDao.listClustersByDcId(dc.getId());
+ for (ClusterVO cluster : clusters) {
+ DedicatedResourceVO dCluster = _dedicatedDao.findByClusterId(cluster.getId());
+ if (dCluster != null) {
+ if(!(childDomainIds.contains(dCluster.getDomainId()))) {
+ throw new CloudRuntimeException("Cluster " + cluster.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ if (accountId != null) {
+ if (dCluster.getAccountId() == accountId) {
+ clustersToRelease.add(dCluster);
+ } else {
+ s_logger.error("Cluster " + cluster.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Cluster " + cluster.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dCluster.getAccountId() == null && dCluster.getDomainId() == domainId) {
+ clustersToRelease.add(dCluster);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : clustersToRelease) {
+ releaseDedicatedResource(null, null, dr.getClusterId(), null);
+ }
+
+ hosts = _hostDao.listByDataCenterId(dc.getId());
+ for (HostVO host : hosts) {
+ DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId());
+ if (dHost != null) {
+ if(!(childDomainIds.contains(dHost.getDomainId()))) {
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ if (accountId != null) {
+ if (dHost.getAccountId() == accountId) {
+ hostsToRelease.add(dHost);
+ } else {
+ s_logger.error("Host " + host.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dHost.getAccountId() == null && dHost.getDomainId() == domainId) {
+ hostsToRelease.add(dHost);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : hostsToRelease) {
+ releaseDedicatedResource(null, null, null, dr.getHostId());
+ }
+ }
+
+ checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts);
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(zoneId, null, null, null, null, null);
+ try {
+ dedicatedResource.setDomainId(domainId);
+ if (accountId != null) {
+ dedicatedResource.setAccountId(accountId);
+ }
+ dedicatedResource = _dedicatedDao.persist(dedicatedResource);
+ } catch (Exception e) {
+ s_logger.error("Unable to dedicate zone due to " + e.getMessage(), e);
+ throw new CloudRuntimeException("Failed to dedicate zone. Please contact Cloud Support.");
+ }
+ txn.commit();
+
+ List result = new ArrayList();
+ result.add(dedicatedResource);
+ return result;
+ }
+
+ @Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Pod")
+ public List dedicatePod(Long podId, Long domainId, String accountName) {
+ Long accountId = null;
+ if(accountName != null){
+ Account caller = UserContext.current().getCaller();
+ Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null);
+ accountId = owner.getId();
+ }
+ List childDomainIds = getDomainChildIds(domainId);
+ childDomainIds.add(domainId);
+ checkAccountAndDomain(accountId, domainId);
+ HostPodVO pod = _podDao.findById(podId);
+ List hosts = null;
+ if (pod == null) {
+ throw new InvalidParameterValueException("Unable to find pod by id " + podId);
+ } else {
+ DedicatedResourceVO dedicatedPod = _dedicatedDao.findByPodId(podId);
+ DedicatedResourceVO dedicatedZoneOfPod = _dedicatedDao.findByZoneId(pod.getDataCenterId());
+ //check if pod is dedicated
+ if(dedicatedPod != null ) {
+ s_logger.error("Pod " + pod.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Pod " + pod.getName() + " is already dedicated");
+ }
+
+ if (dedicatedZoneOfPod != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedZoneOfPod.getDomainId()).contains(domainId);
+ //can dedicate a pod to an account/domain if zone is dedicated to parent-domain
+ if (dedicatedZoneOfPod.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedZoneOfPod.getDomainId() == domainId || domainIdInChildreanList))) {
+ DataCenterVO zone = _zoneDao.findById(pod.getDataCenterId());
+ s_logger.error("Cannot dedicate Pod. Its zone is already dedicated");
+ throw new CloudRuntimeException("Pod's Zone " + zone.getName() + " is already dedicated");
+ }
+ }
+
+ //check if any resource under this pod is dedicated to different account or sub-domain
+ List clusters = _clusterDao.listByPodId(pod.getId());
+ List clustersToRelease = new ArrayList();
+ List hostsToRelease = new ArrayList();
+ for (ClusterVO cluster : clusters) {
+ DedicatedResourceVO dCluster = _dedicatedDao.findByClusterId(cluster.getId());
+ if (dCluster != null) {
+ if(!(childDomainIds.contains(dCluster.getDomainId()))) {
+ throw new CloudRuntimeException("Cluster " + cluster.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ }
+ /*if all dedicated resources belongs to same account and domain then we should release dedication
+ and make new entry for this Pod*/
+ if (accountId != null) {
+ if (dCluster.getAccountId() == accountId) {
+ clustersToRelease.add(dCluster);
+ } else {
+ s_logger.error("Cluster " + cluster.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Cluster " + cluster.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dCluster.getAccountId() == null && dCluster.getDomainId() == domainId) {
+ clustersToRelease.add(dCluster);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : clustersToRelease) {
+ releaseDedicatedResource(null, null, dr.getClusterId(), null);
+ }
+
+ hosts = _hostDao.findByPodId(pod.getId());
+ for (HostVO host : hosts) {
+ DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId());
+ if (dHost != null) {
+ if(!(getDomainChildIds(domainId).contains(dHost.getDomainId()))) {
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ }
+ if (accountId != null) {
+ if (dHost.getAccountId() == accountId) {
+ hostsToRelease.add(dHost);
+ } else {
+ s_logger.error("Host " + host.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dHost.getAccountId() == null && dHost.getDomainId() == domainId) {
+ hostsToRelease.add(dHost);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : hostsToRelease) {
+ releaseDedicatedResource(null, null, null, dr.getHostId());
+ }
+ }
+
+ checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts);
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, podId, null, null, null, null);
+ try {
+ dedicatedResource.setDomainId(domainId);
+ if (accountId != null) {
+ dedicatedResource.setAccountId(accountId);
+ }
+ dedicatedResource = _dedicatedDao.persist(dedicatedResource);
+ } catch (Exception e) {
+ s_logger.error("Unable to dedicate pod due to " + e.getMessage(), e);
+ throw new CloudRuntimeException("Failed to dedicate pod. Please contact Cloud Support.");
+ }
+ txn.commit();
+
+ List result = new ArrayList();
+ result.add(dedicatedResource);
+ return result;
+ }
+
+ @Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Cluster")
+ public List dedicateCluster(Long clusterId, Long domainId, String accountName) {
+ Long accountId = null;
+ List hosts = null;
+ if(accountName != null){
+ Account caller = UserContext.current().getCaller();
+ Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null);
+ accountId = owner.getId();
+ }
+ List childDomainIds = getDomainChildIds(domainId);
+ childDomainIds.add(domainId);
+ checkAccountAndDomain(accountId, domainId);
+ ClusterVO cluster = _clusterDao.findById(clusterId);
+ if (cluster == null) {
+ throw new InvalidParameterValueException("Unable to find cluster by id " + clusterId);
+ } else {
+ DedicatedResourceVO dedicatedCluster = _dedicatedDao.findByClusterId(clusterId);
+ DedicatedResourceVO dedicatedPodOfCluster = _dedicatedDao.findByPodId(cluster.getPodId());
+ DedicatedResourceVO dedicatedZoneOfCluster = _dedicatedDao.findByZoneId(cluster.getDataCenterId());
+
+ //check if cluster is dedicated
+ if(dedicatedCluster != null) {
+ s_logger.error("Cluster " + cluster.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Cluster "+ cluster.getName() + " is already dedicated");
+ }
+
+ if (dedicatedPodOfCluster != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedPodOfCluster.getDomainId()).contains(domainId);
+ //can dedicate a cluster to an account/domain if pod is dedicated to parent-domain
+ if (dedicatedPodOfCluster.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedPodOfCluster.getDomainId() == domainId || domainIdInChildreanList))) {
+ s_logger.error("Cannot dedicate Cluster. Its Pod is already dedicated");
+ HostPodVO pod = _podDao.findById(cluster.getPodId());
+ throw new CloudRuntimeException("Cluster's Pod " + pod.getName() + " is already dedicated");
+ }
+ }
+
+ if (dedicatedZoneOfCluster != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedZoneOfCluster.getDomainId()).contains(domainId);
+ //can dedicate a cluster to an account/domain if zone is dedicated to parent-domain
+ if (dedicatedZoneOfCluster.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedZoneOfCluster.getDomainId() == domainId || domainIdInChildreanList))) {
+ s_logger.error("Cannot dedicate Cluster. Its zone is already dedicated");
+ DataCenterVO zone = _zoneDao.findById(cluster.getDataCenterId());
+ throw new CloudRuntimeException("Cluster's Zone "+ zone.getName() + " is already dedicated");
+ }
+ }
+
+ //check if any resource under this cluster is dedicated to different account or sub-domain
+ hosts = _hostDao.findByClusterId(cluster.getId());
+ List hostsToRelease = new ArrayList();
+ for (HostVO host : hosts) {
+ DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId());
+ if (dHost != null) {
+ if(!(childDomainIds.contains(dHost.getDomainId()))) {
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Cluster " + cluster.getName() + " is dedicated to different account/domain");
+ }
+ /*if all dedicated resources belongs to same account and domain then we should release dedication
+ and make new entry for this cluster */
+ if (accountId != null) {
+ if (dHost.getAccountId() == accountId) {
+ hostsToRelease.add(dHost);
+ } else {
+ s_logger.error("Cannot dedicate Cluster " + cluster.getName() + " to account" + accountName);
+ throw new CloudRuntimeException("Cannot dedicate Cluster " + cluster.getName() + " to account" + accountName);
+ }
+ } else {
+ if (dHost.getAccountId() == null && dHost.getDomainId() == domainId) {
+ hostsToRelease.add(dHost);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : hostsToRelease) {
+ releaseDedicatedResource(null, null, null, dr.getHostId());
+ }
+ }
+
+ checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts);
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, null, clusterId, null, null, null);
+ try {
+ dedicatedResource.setDomainId(domainId);
+ if (accountId != null) {
+ dedicatedResource.setAccountId(accountId);
+ }
+ dedicatedResource = _dedicatedDao.persist(dedicatedResource);
+ } catch (Exception e) {
+ s_logger.error("Unable to dedicate host due to " + e.getMessage(), e);
+ throw new CloudRuntimeException("Failed to dedicate cluster. Please contact Cloud Support.");
+ }
+ txn.commit();
+
+ List result = new ArrayList();
+ result.add(dedicatedResource);
+ return result;
+ }
+
+ @Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Host")
+ public List dedicateHost(Long hostId, Long domainId, String accountName) {
+ Long accountId = null;
+ if(accountName != null){
+ Account caller = UserContext.current().getCaller();
+ Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null);
+ accountId = owner.getId();
+ }
+ checkAccountAndDomain(accountId, domainId);
+ HostVO host = _hostDao.findById(hostId);
+ if (host == null) {
+ throw new InvalidParameterValueException("Unable to find host by id " + hostId);
+ } else {
+ //check if host is of routing type
+ if (host.getType() != Host.Type.Routing) {
+ throw new CloudRuntimeException("Invalid host type for host " + host.getName());
+ }
+
+ DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(hostId);
+ DedicatedResourceVO dedicatedClusterOfHost = _dedicatedDao.findByClusterId(host.getClusterId());
+ DedicatedResourceVO dedicatedPodOfHost = _dedicatedDao.findByPodId(host.getPodId());
+ DedicatedResourceVO dedicatedZoneOfHost = _dedicatedDao.findByZoneId(host.getDataCenterId());
+
+ if(dedicatedHost != null) {
+ s_logger.error("Host "+ host.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Host "+ host.getName() + " is already dedicated");
+ }
+
+ if (dedicatedClusterOfHost != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedClusterOfHost.getDomainId()).contains(domainId);
+ //can dedicate a host to an account/domain if cluster is dedicated to parent-domain
+ if (dedicatedClusterOfHost.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedClusterOfHost.getDomainId() == domainId || domainIdInChildreanList))) {
+ ClusterVO cluster = _clusterDao.findById(host.getClusterId());
+ s_logger.error("Host's Cluster " + cluster.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Host's Cluster " + cluster.getName() + " is already dedicated");
+ }
+ }
+
+ if (dedicatedPodOfHost != null){
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedPodOfHost.getDomainId()).contains(domainId);
+ //can dedicate a host to an account/domain if pod is dedicated to parent-domain
+ if (dedicatedPodOfHost.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedPodOfHost.getDomainId() == domainId || domainIdInChildreanList))) {
+ HostPodVO pod = _podDao.findById(host.getPodId());
+ s_logger.error("Host's Pod " + pod.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Host's Pod " + pod.getName() + " is already dedicated");
+ }
+ }
+
+ if (dedicatedZoneOfHost != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedZoneOfHost.getDomainId()).contains(domainId);
+ //can dedicate a host to an account/domain if zone is dedicated to parent-domain
+ if (dedicatedZoneOfHost.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedZoneOfHost.getDomainId() == domainId || domainIdInChildreanList))) {
+ DataCenterVO zone = _zoneDao.findById(host.getDataCenterId());
+ s_logger.error("Host's Data Center " + zone.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Host's Data Center " + zone.getName() + " is already dedicated");
+ }
+ }
+ }
+
+ List childDomainIds = getDomainChildIds(domainId);
+ childDomainIds.add(domainId);
+ checkHostSuitabilityForExplicitDedication(accountId, childDomainIds, hostId);
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, null, null, hostId, null, null);
+ try {
+ dedicatedResource.setDomainId(domainId);
+ if (accountId != null) {
+ dedicatedResource.setAccountId(accountId);
+ }
+ dedicatedResource = _dedicatedDao.persist(dedicatedResource);
+ } catch (Exception e) {
+ s_logger.error("Unable to dedicate host due to " + e.getMessage(), e);
+ throw new CloudRuntimeException("Failed to dedicate host. Please contact Cloud Support.");
+ }
+ txn.commit();
+
+ List result = new ArrayList();
+ result.add(dedicatedResource);
+ return result;
+ }
+
+ private List getVmsOnHost(long hostId) {
+ List vms = _userVmDao.listUpByHostId(hostId);
+ List vmsByLastHostId = _userVmDao.listByLastHostId(hostId);
+ if (vmsByLastHostId.size() > 0) {
+ // check if any VMs are within skip.counting.hours, if yes we have to consider the host.
+ for (UserVmVO stoppedVM : vmsByLastHostId) {
+ long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - stoppedVM.getUpdateTime()
+ .getTime()) / 1000;
+ if (secondsSinceLastUpdate < capacityReleaseInterval) {
+ vms.add(stoppedVM);
+ }
+ }
+ }
+
+ return vms;
+ }
+
+ private boolean checkHostSuitabilityForExplicitDedication(Long accountId, List domainIds, long hostId) {
+ boolean suitable = true;
+ List allVmsOnHost = getVmsOnHost(hostId);
+ if (accountId != null) {
+ for (UserVmVO vm : allVmsOnHost) {
+ if (vm.getAccountId() != accountId) {
+ s_logger.info("Host " + vm.getHostId() + " found to be unsuitable for explicit dedication as it is " +
+ "running instances of another account");
+ throw new CloudRuntimeException("Host " + hostId + " found to be unsuitable for explicit dedication as it is " +
+ "running instances of another account");
+ }
+ }
+ } else {
+ for (UserVmVO vm : allVmsOnHost) {
+ if (!domainIds.contains(vm.getDomainId())) {
+ s_logger.info("Host " + vm.getHostId() + " found to be unsuitable for explicit dedication as it is " +
+ "running instances of another domain");
+ throw new CloudRuntimeException("Host " + hostId + " found to be unsuitable for explicit dedication as it is " +
+ "running instances of another domain");
+ }
+ }
+ }
+ return suitable;
+ }
+
+ private boolean checkHostsSuitabilityForExplicitDedication(Long accountId, List domainIds, List hosts) {
+ boolean suitable = true;
+ for (HostVO host : hosts){
+ checkHostSuitabilityForExplicitDedication(accountId, domainIds, host.getId());
+ }
+ return suitable;
+ }
+
+ private void checkAccountAndDomain(Long accountId, Long domainId) {
+ DomainVO domain = _domainDao.findById(domainId);
+ if (domain == null) {
+ throw new InvalidParameterValueException("Unable to find the domain by id " + domainId + ", please specify valid domainId");
+ }
+ //check if account belongs to the domain id
+ if (accountId != null) {
+ AccountVO account = _accountDao.findById(accountId);
+ if (account == null || domainId != account.getDomainId()){
+ throw new InvalidParameterValueException("Please specify the domain id of the account: " + account.getAccountName());
+ }
+ }
+ }
+
+ private List getDomainChildIds(long domainId) {
+ DomainVO domainRecord = _domainDao.findById(domainId);
+ List domainIds = new ArrayList();
+ domainIds.add(domainRecord.getId());
+ // find all domain Ids till leaf
+ List allChildDomains = _domainDao.findAllChildren(domainRecord.getPath(), domainRecord.getId());
+ for (DomainVO domain : allChildDomains) {
+ domainIds.add(domain.getId());
+ }
+ return domainIds;
+ }
+
+ @Override
+ public DedicateZoneResponse createDedicateZoneResponse(DedicatedResources resource) {
+ DedicateZoneResponse dedicateZoneResponse = new DedicateZoneResponse();
+ DataCenterVO dc = _zoneDao.findById(resource.getDataCenterId());
+ DomainVO domain = _domainDao.findById(resource.getDomainId());
+ AccountVO account = _accountDao.findById(resource.getAccountId());
+ dedicateZoneResponse.setId(resource.getUuid());
+ dedicateZoneResponse.setZoneId(dc.getUuid());
+ dedicateZoneResponse.setZoneName(dc.getName());
+ dedicateZoneResponse.setDomainId(domain.getUuid());
+ if (account != null) {
+ dedicateZoneResponse.setAccountId(account.getUuid());
+ }
+ dedicateZoneResponse.setObjectName("dedicatedzone");
+ return dedicateZoneResponse;
+ }
+
+ @Override
+ public DedicatePodResponse createDedicatePodResponse(DedicatedResources resource) {
+ DedicatePodResponse dedicatePodResponse = new DedicatePodResponse();
+ HostPodVO pod = _podDao.findById(resource.getPodId());
+ DomainVO domain = _domainDao.findById(resource.getDomainId());
+ AccountVO account = _accountDao.findById(resource.getAccountId());
+ dedicatePodResponse.setId(resource.getUuid());
+ dedicatePodResponse.setPodId(pod.getUuid());
+ dedicatePodResponse.setPodName(pod.getName());
+ dedicatePodResponse.setDomainId(domain.getUuid());
+ if (account != null) {
+ dedicatePodResponse.setAccountId(account.getUuid());
+ }
+ dedicatePodResponse.setObjectName("dedicatedpod");
+ return dedicatePodResponse;
+ }
+
+ @Override
+ public DedicateClusterResponse createDedicateClusterResponse(DedicatedResources resource) {
+ DedicateClusterResponse dedicateClusterResponse = new DedicateClusterResponse();
+ ClusterVO cluster = _clusterDao.findById(resource.getClusterId());
+ DomainVO domain = _domainDao.findById(resource.getDomainId());
+ AccountVO account = _accountDao.findById(resource.getAccountId());
+ dedicateClusterResponse.setId(resource.getUuid());
+ dedicateClusterResponse.setClusterId(cluster.getUuid());
+ dedicateClusterResponse.setClusterName(cluster.getName());
+ dedicateClusterResponse.setDomainId(domain.getUuid());
+ if (account != null) {
+ dedicateClusterResponse.setAccountId(account.getUuid());
+ }
+ dedicateClusterResponse.setObjectName("dedicatedcluster");
+ return dedicateClusterResponse;
+ }
+
+ @Override
+ public DedicateHostResponse createDedicateHostResponse(DedicatedResources resource) {
+ DedicateHostResponse dedicateHostResponse = new DedicateHostResponse();
+ HostVO host = _hostDao.findById(resource.getHostId());
+ DomainVO domain = _domainDao.findById(resource.getDomainId());
+ AccountVO account = _accountDao.findById(resource.getAccountId());
+ dedicateHostResponse.setId(resource.getUuid());
+ dedicateHostResponse.setHostId(host.getUuid());
+ dedicateHostResponse.setHostName(host.getName());
+ dedicateHostResponse.setDomainId(domain.getUuid());
+ if (account != null) {
+ dedicateHostResponse.setAccountId(account.getUuid());
+ }
+ dedicateHostResponse.setObjectName("dedicatedhost");
+ return dedicateHostResponse;
+ }
+
+ @Override
+ public List> getCommands() {
+ List> cmdList = new ArrayList>();
+ cmdList.add(DedicateZoneCmd.class);
+ cmdList.add(DedicatePodCmd.class);
+ cmdList.add(DedicateClusterCmd.class);
+ cmdList.add(DedicateHostCmd.class);
+ cmdList.add(ListDedicatedZonesCmd.class);
+ cmdList.add(ListDedicatedPodsCmd.class);
+ cmdList.add(ListDedicatedClustersCmd.class);
+ cmdList.add(ListDedicatedHostsCmd.class);
+ cmdList.add(ReleaseDedicatedClusterCmd.class);
+ cmdList.add(ReleaseDedicatedHostCmd.class);
+ cmdList.add(ReleaseDedicatedPodCmd.class);
+ cmdList.add(ReleaseDedicatedZoneCmd.class);
+ return cmdList;
+ }
+
+ @Override
+ public Pair, Integer> listDedicatedZones(ListDedicatedZonesCmd cmd) {
+ Long zoneId = cmd.getZoneId();
+ Long domainId = cmd.getDomainId();
+ String accountName = cmd.getAccountName();
+ Long accountId = null;
+ if (accountName != null) {
+ if (domainId != null) {
+ Account account = _accountDao.findActiveAccount(accountName, domainId);
+ if (account != null) {
+ accountId = account.getId();
+ }
+ } else {
+ throw new InvalidParameterValueException("Please specify the domain id of the account: " + accountName);
+ }
+ }
+ Pair, Integer> result = _dedicatedDao.searchDedicatedZones(zoneId, domainId, accountId);
+ return new Pair, Integer>(result.first(), result.second());
+ }
+
+ @Override
+ public Pair, Integer> listDedicatedPods(ListDedicatedPodsCmd cmd) {
+ Long podId = cmd.getPodId();
+ Long domainId = cmd.getDomainId();
+ String accountName = cmd.getAccountName();
+ Long accountId = null;
+ if (accountName != null) {
+ if (domainId != null) {
+ Account account = _accountDao.findActiveAccount(accountName, domainId);
+ if (account != null) {
+ accountId = account.getId();
+ }
+ } else {
+ throw new InvalidParameterValueException("Please specify the domain id of the account: " + accountName);
+ }
+ }
+ Pair, Integer> result = _dedicatedDao.searchDedicatedPods(podId, domainId, accountId);
+ return new Pair, Integer>(result.first(), result.second());
+ }
+
+ @Override
+ public Pair, Integer> listDedicatedClusters(ListDedicatedClustersCmd cmd) {
+ Long clusterId = cmd.getClusterId();
+ Long domainId = cmd.getDomainId();
+ String accountName = cmd.getAccountName();
+ Long accountId = null;
+ if (accountName != null) {
+ if (domainId != null) {
+ Account account = _accountDao.findActiveAccount(accountName, domainId);
+ if (account != null) {
+ accountId = account.getId();
+ }
+ } else {
+ throw new InvalidParameterValueException("Please specify the domain id of the account: " + accountName);
+ }
+ }
+ Pair, Integer> result = _dedicatedDao.searchDedicatedClusters(clusterId, domainId, accountId);
+ return new Pair, Integer>(result.first(), result.second());
+ }
+
+ @Override
+ public Pair, Integer> listDedicatedHosts(ListDedicatedHostsCmd cmd) {
+ Long hostId = cmd.getHostId();
+ Long domainId = cmd.getDomainId();
+ String accountName = cmd.getAccountName();
+ Long accountId = null;
+ if (accountName != null) {
+ if (domainId != null) {
+ Account account = _accountDao.findActiveAccount(accountName, domainId);
+ if (account != null) {
+ accountId = account.getId();
+ }
+ } else {
+ throw new InvalidParameterValueException("Please specify the domain id of the account: " + accountName);
+ }
+ }
+
+ Pair, Integer> result = _dedicatedDao.searchDedicatedHosts(hostId, domainId, accountId);
+ return new Pair, Integer>(result.first(), result.second());
+ }
+
+ @Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE, eventDescription = "Releasing dedicated resource")
+ public boolean releaseDedicatedResource(Long zoneId, Long podId, Long clusterId, Long hostId) throws InvalidParameterValueException{
+ DedicatedResourceVO resource = null;
+ Long resourceId = null;
+ if (zoneId != null) {
+ resource = _dedicatedDao.findByZoneId(zoneId);
+ }
+ if (podId != null) {
+ resource = _dedicatedDao.findByPodId(podId);
+ }
+ if (clusterId != null) {
+ resource = _dedicatedDao.findByClusterId(clusterId);
+ }
+ if (hostId != null ) {
+ resource = _dedicatedDao.findByHostId(hostId);
+ }
+ if (resource == null){
+ throw new InvalidParameterValueException("No Dedicated Resource available to release");
+ } else {
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ resourceId = resource.getId();
+ if (!_dedicatedDao.remove(resourceId)) {
+ throw new CloudRuntimeException("Failed to delete Resource " + resourceId);
+ }
+ txn.commit();
+ }
+ return true;
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/services/DedicatedService.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/services/DedicatedService.java
new file mode 100755
index 00000000000..360852ae8e6
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/services/DedicatedService.java
@@ -0,0 +1,63 @@
+// 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.services;
+
+import java.util.List;
+
+import org.apache.cloudstack.dedicated.api.commands.ListDedicatedClustersCmd;
+import org.apache.cloudstack.dedicated.api.commands.ListDedicatedHostsCmd;
+import org.apache.cloudstack.dedicated.api.commands.ListDedicatedPodsCmd;
+import org.apache.cloudstack.dedicated.api.commands.ListDedicatedZonesCmd;
+import org.apache.cloudstack.dedicated.api.response.DedicateClusterResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateHostResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicatePodResponse;
+import org.apache.cloudstack.dedicated.api.response.DedicateZoneResponse;
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.utils.Pair;
+import com.cloud.utils.component.PluggableService;
+
+public interface DedicatedService extends PluggableService{
+
+ DedicatePodResponse createDedicatePodResponse(DedicatedResources resource);
+
+ DedicateClusterResponse createDedicateClusterResponse(
+ DedicatedResources resource);
+
+ DedicateHostResponse createDedicateHostResponse(DedicatedResources resource);
+
+ Pair, Integer> listDedicatedPods(ListDedicatedPodsCmd cmd);
+
+ Pair, Integer> listDedicatedHosts(ListDedicatedHostsCmd cmd);
+
+ Pair, Integer> listDedicatedClusters(ListDedicatedClustersCmd cmd);
+
+ boolean releaseDedicatedResource(Long zoneId, Long podId, Long clusterId, Long hostId);
+
+ DedicateZoneResponse createDedicateZoneResponse(DedicatedResources resource);
+
+ Pair, Integer> listDedicatedZones(ListDedicatedZonesCmd cmd);
+
+ List dedicateZone(Long zoneId, Long domainId, String accountName);
+
+ List dedicatePod(Long podId, Long domainId, String accountName);
+
+ List dedicateCluster(Long clusterId, Long domainId, String accountName);
+
+ List dedicateHost(Long hostId, Long domainId, String accountName);
+
+}
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 00000000000..3cf51299b6e
--- /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 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 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 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 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);
+ }
+ }
+ }
+}
diff --git a/plugins/dedicated-resources/test/resource/dedicatedContext.xml b/plugins/dedicated-resources/test/resource/dedicatedContext.xml
new file mode 100644
index 00000000000..9ce8362d4b0
--- /dev/null
+++ b/plugins/dedicated-resources/test/resource/dedicatedContext.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 2efa2488e86..eab47554e6b 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -35,11 +35,13 @@
api/rate-limit
api/discovery
acl/static-role-based
- affinity-group-processors/host-anti-affinity
+ affinity-group-processors/host-anti-affinity
+ affinity-group-processors/explicit-dedication
deployment-planners/user-concentrated-pod
deployment-planners/user-dispersing
deployment-planners/implicit-dedication
host-allocators/random
+ dedicated-resources
hypervisors/ovm
hypervisors/xen
hypervisors/kvm
diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java
index 5a25732bca0..28aecfc223d 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 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 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 removeDedicatedZoneNotSuitabe(List domainIds) {
+ //remove dedicated zone of other domain
+ List dedicatedZoneIds = new ArrayList();
+ List 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
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 79375f9a86e..52c5e2e3f87 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());
diff --git a/server/src/com/cloud/dc/DedicatedResourceVO.java b/server/src/com/cloud/dc/DedicatedResourceVO.java
new file mode 100644
index 00000000000..a4c88f57e02
--- /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;
+ }
+}
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 00000000000..a5d65d46c8e
--- /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 findByZoneId(Long zoneId);
+
+ DedicatedResourceVO findByPodId(Long podId);
+
+ DedicatedResourceVO findByClusterId(Long clusterId);
+
+ DedicatedResourceVO findByHostId(Long hostId);
+
+ Pair, Integer> searchDedicatedHosts(Long hostId, Long domainId, Long accountId);
+
+ Pair, Integer> searchDedicatedClusters(Long clusterId, Long domainId, Long accountId);
+
+ Pair, Integer> searchDedicatedPods(Long podId, Long domainId, Long accountId);
+
+ Pair, Integer> searchDedicatedZones(Long dataCenterId, Long domainId, Long accountId);
+
+ List listByAccountId(Long accountId);
+
+ List listByDomainId(Long domainId);
+
+ List listZonesNotInDomainIds(List domainIds);
+}
\ No newline at end of file
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 00000000000..2a3b4690a0c
--- /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 implements DedicatedResourceDao {
+ protected final SearchBuilder ZoneSearch;
+ protected final SearchBuilder PodSearch;
+ protected final SearchBuilder ClusterSearch;
+ protected final SearchBuilder HostSearch;
+
+ protected SearchBuilder ListZonesByDomainIdSearch;
+ protected SearchBuilder ListPodsByDomainIdSearch;
+ protected SearchBuilder ListClustersByDomainIdSearch;
+ protected SearchBuilder ListHostsByDomainIdSearch;
+
+ protected SearchBuilder ListZonesByAccountIdSearch;
+ protected SearchBuilder ListPodsByAccountIdSearch;
+ protected SearchBuilder ListClustersByAccountIdSearch;
+ protected SearchBuilder ListHostsByAccountIdSearch;
+
+ protected SearchBuilder ListAllZonesSearch;
+ protected SearchBuilder ListAllPodsSearch;
+ protected SearchBuilder ListAllClustersSearch;
+ protected SearchBuilder ListAllHostsSearch;
+
+ protected SearchBuilder ListByAccountId;
+ protected SearchBuilder ListByDomainId;
+
+ protected SearchBuilder 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 sc = ZoneSearch.create();
+ sc.setParameters("zoneId", zoneId);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public DedicatedResourceVO findByPodId(Long podId) {
+ SearchCriteria sc = PodSearch.create();
+ sc.setParameters("podId", podId);
+
+ return findOneBy(sc);
+ }
+
+ @Override
+ public DedicatedResourceVO findByClusterId(Long clusterId) {
+ SearchCriteria sc = ClusterSearch.create();
+ sc.setParameters("clusterId", clusterId);
+
+ return findOneBy(sc);
+ }
+
+ @Override
+ public DedicatedResourceVO findByHostId(Long hostId) {
+ SearchCriteria sc = HostSearch.create();
+ sc.setParameters("hostId", hostId);
+
+ return findOneBy(sc);
+ }
+
+ @Override
+ public Pair, Integer> searchDedicatedZones(Long dataCenterId, Long domainId, Long accountId){
+ SearchCriteria 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, Integer> searchDedicatedPods(Long podId, Long domainId, Long accountId){
+ SearchCriteria 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, Integer> searchDedicatedClusters(Long clusterId, Long domainId, Long accountId){
+ SearchCriteria 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, Integer> searchDedicatedHosts(Long hostId, Long domainId, Long accountId){
+ SearchCriteria 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 listByAccountId(Long accountId){
+ SearchCriteria sc = ListByAccountId.create();
+ sc.setParameters("accountId", accountId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByDomainId(Long domainId){
+ SearchCriteria sc = ListByDomainId.create();
+ sc.setParameters("domainId", domainId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listZonesNotInDomainIds(List domainIds) {
+ SearchCriteria 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;
+ }
+}
diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java
index 74bd6d04a3e..c6e8d7d7729 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;
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index e72005e8214..3f06e419cdb 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 _userAuthenticators;
List _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 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 accountsForCleanupInDomain = _accountDao.findCleanupsForRemovedAccounts(domainId);
if (accountsForCleanupInDomain.isEmpty()) {
+ //release dedication if any, before deleting the domain
+ List