| // 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; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.inject.Inject; |
| import javax.naming.ConfigurationException; |
| |
| import org.apache.cloudstack.affinity.AffinityGroup; |
| import org.apache.cloudstack.affinity.AffinityGroupService; |
| import org.apache.cloudstack.affinity.dao.AffinityGroupDao; |
| import org.apache.cloudstack.api.commands.DedicateClusterCmd; |
| import org.apache.cloudstack.api.commands.DedicateHostCmd; |
| import org.apache.cloudstack.api.commands.DedicatePodCmd; |
| import org.apache.cloudstack.api.commands.DedicateZoneCmd; |
| import org.apache.cloudstack.api.commands.ListDedicatedClustersCmd; |
| import org.apache.cloudstack.api.commands.ListDedicatedHostsCmd; |
| import org.apache.cloudstack.api.commands.ListDedicatedPodsCmd; |
| import org.apache.cloudstack.api.commands.ListDedicatedZonesCmd; |
| import org.apache.cloudstack.api.commands.ReleaseDedicatedClusterCmd; |
| import org.apache.cloudstack.api.commands.ReleaseDedicatedHostCmd; |
| import org.apache.cloudstack.api.commands.ReleaseDedicatedPodCmd; |
| import org.apache.cloudstack.api.commands.ReleaseDedicatedZoneCmd; |
| import org.apache.cloudstack.api.response.DedicateClusterResponse; |
| import org.apache.cloudstack.api.response.DedicateHostResponse; |
| import org.apache.cloudstack.api.response.DedicatePodResponse; |
| import org.apache.cloudstack.api.response.DedicateZoneResponse; |
| import org.apache.cloudstack.context.CallContext; |
| import org.apache.cloudstack.framework.config.dao.ConfigurationDao; |
| import org.apache.log4j.Logger; |
| import org.springframework.stereotype.Component; |
| |
| import com.cloud.configuration.Config; |
| 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.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.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.Filter; |
| import com.cloud.utils.db.Transaction; |
| import com.cloud.utils.db.TransactionCallback; |
| import com.cloud.utils.db.TransactionCallbackNoReturn; |
| import com.cloud.utils.db.TransactionStatus; |
| import com.cloud.utils.exception.CloudRuntimeException; |
| import com.cloud.vm.UserVmVO; |
| import com.cloud.vm.dao.UserVmDao; |
| |
| @Component |
| 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; |
| @Inject |
| AffinityGroupDao _affinityGroupDao; |
| |
| @Inject |
| AffinityGroupService _affinityGroupService; |
| |
| private int capacityReleaseInterval; |
| |
| public boolean configure(final String name, final Map<String, Object> 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<DedicatedResourceVO> dedicateZone(final Long zoneId, final Long domainId, final String accountName) { |
| Long accountId = null; |
| List<HostVO> hosts = null; |
| if (accountName != null) { |
| Account caller = CallContext.current().getCallingAccount(); |
| Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null); |
| accountId = owner.getId(); |
| } |
| List<Long> childDomainIds = getDomainChildIds(domainId); |
| childDomainIds.add(domainId); |
| checkAccountAndDomain(accountId, domainId); |
| final 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<HostPodVO> pods = _podDao.listByDataCenterId(dc.getId()); |
| List<DedicatedResourceVO> podsToRelease = new ArrayList<DedicatedResourceVO>(); |
| List<DedicatedResourceVO> clustersToRelease = new ArrayList<DedicatedResourceVO>(); |
| List<DedicatedResourceVO> hostsToRelease = new ArrayList<DedicatedResourceVO>(); |
| 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().equals(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().equals(domainId)) { |
| podsToRelease.add(dPod); |
| } |
| } |
| } |
| } |
| |
| for (DedicatedResourceVO dr : podsToRelease) { |
| releaseDedicatedResource(null, dr.getPodId(), null, null); |
| } |
| |
| List<ClusterVO> 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().equals(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().equals(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().equals(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().equals(domainId)) { |
| hostsToRelease.add(dHost); |
| } |
| } |
| } |
| } |
| |
| for (DedicatedResourceVO dr : hostsToRelease) { |
| releaseDedicatedResource(null, null, null, dr.getHostId()); |
| } |
| } |
| |
| checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts); |
| |
| final Long accountIdFinal = accountId; |
| return Transaction.execute(new TransactionCallback<List<DedicatedResourceVO>>() { |
| @Override |
| public List<DedicatedResourceVO> doInTransaction(TransactionStatus status) { |
| // find or create the affinity group by name under this account/domain |
| AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal); |
| if (group == null) { |
| s_logger.error("Unable to dedicate zone due to, failed to create dedication affinity group"); |
| throw new CloudRuntimeException("Failed to dedicate zone. Please contact Cloud Support."); |
| } |
| |
| DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(zoneId, null, null, null, null, null, group.getId()); |
| try { |
| dedicatedResource.setDomainId(domainId); |
| if (accountIdFinal != null) { |
| dedicatedResource.setAccountId(accountIdFinal); |
| } |
| dedicatedResource = _dedicatedDao.persist(dedicatedResource); |
| |
| // save the domainId in the zone |
| dc.setDomainId(domainId); |
| if (!_zoneDao.update(zoneId, dc)) { |
| throw new CloudRuntimeException("Failed to dedicate zone, could not set domainId. Please contact Cloud Support."); |
| } |
| |
| } 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."); |
| } |
| |
| List<DedicatedResourceVO> result = new ArrayList<DedicatedResourceVO>(); |
| result.add(dedicatedResource); |
| return result; |
| |
| } |
| }); |
| } |
| |
| @Override |
| @DB |
| @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Pod") |
| public List<DedicatedResourceVO> dedicatePod(final Long podId, final Long domainId, final String accountName) { |
| Long accountId = null; |
| if (accountName != null) { |
| Account caller = CallContext.current().getCallingAccount(); |
| Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null); |
| accountId = owner.getId(); |
| } |
| List<Long> childDomainIds = getDomainChildIds(domainId); |
| childDomainIds.add(domainId); |
| checkAccountAndDomain(accountId, domainId); |
| HostPodVO pod = _podDao.findById(podId); |
| List<HostVO> 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().equals(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<ClusterVO> clusters = _clusterDao.listByPodId(pod.getId()); |
| List<DedicatedResourceVO> clustersToRelease = new ArrayList<DedicatedResourceVO>(); |
| List<DedicatedResourceVO> hostsToRelease = new ArrayList<DedicatedResourceVO>(); |
| 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().equals(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().equals(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().equals(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().equals(domainId)) { |
| hostsToRelease.add(dHost); |
| } |
| } |
| } |
| } |
| |
| for (DedicatedResourceVO dr : hostsToRelease) { |
| releaseDedicatedResource(null, null, null, dr.getHostId()); |
| } |
| } |
| |
| checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts); |
| |
| final Long accountIdFinal = accountId; |
| return Transaction.execute(new TransactionCallback<List<DedicatedResourceVO>>() { |
| @Override |
| public List<DedicatedResourceVO> doInTransaction(TransactionStatus status) { |
| // find or create the affinity group by name under this account/domain |
| AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal); |
| if (group == null) { |
| s_logger.error("Unable to dedicate zone due to, failed to create dedication affinity group"); |
| throw new CloudRuntimeException("Failed to dedicate zone. Please contact Cloud Support."); |
| } |
| DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, podId, null, null, null, null, group.getId()); |
| try { |
| dedicatedResource.setDomainId(domainId); |
| if (accountIdFinal != null) { |
| dedicatedResource.setAccountId(accountIdFinal); |
| } |
| 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."); |
| } |
| |
| List<DedicatedResourceVO> result = new ArrayList<DedicatedResourceVO>(); |
| result.add(dedicatedResource); |
| return result; |
| } |
| }); |
| } |
| |
| @Override |
| @DB |
| @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Cluster") |
| public List<DedicatedResourceVO> dedicateCluster(final Long clusterId, final Long domainId, final String accountName) { |
| Long accountId = null; |
| List<HostVO> hosts = null; |
| if (accountName != null) { |
| Account caller = CallContext.current().getCallingAccount(); |
| Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null); |
| accountId = owner.getId(); |
| } |
| List<Long> 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().equals(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().equals(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<DedicatedResourceVO> hostsToRelease = new ArrayList<DedicatedResourceVO>(); |
| 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().equals(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().equals(domainId)) { |
| hostsToRelease.add(dHost); |
| } |
| } |
| } |
| } |
| |
| for (DedicatedResourceVO dr : hostsToRelease) { |
| releaseDedicatedResource(null, null, null, dr.getHostId()); |
| } |
| } |
| |
| checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts); |
| |
| final Long accountIdFinal = accountId; |
| return Transaction.execute(new TransactionCallback<List<DedicatedResourceVO>>() { |
| @Override |
| public List<DedicatedResourceVO> doInTransaction(TransactionStatus status) { |
| // find or create the affinity group by name under this account/domain |
| AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal); |
| if (group == null) { |
| s_logger.error("Unable to dedicate zone due to, failed to create dedication affinity group"); |
| throw new CloudRuntimeException("Failed to dedicate zone. Please contact Cloud Support."); |
| } |
| DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, null, clusterId, null, null, null, group.getId()); |
| try { |
| dedicatedResource.setDomainId(domainId); |
| if (accountIdFinal != null) { |
| dedicatedResource.setAccountId(accountIdFinal); |
| } |
| dedicatedResource = _dedicatedDao.persist(dedicatedResource); |
| } catch (Exception e) { |
| s_logger.error("Unable to dedicate cluster due to " + e.getMessage(), e); |
| throw new CloudRuntimeException("Failed to dedicate cluster. Please contact Cloud Support.", e); |
| } |
| |
| List<DedicatedResourceVO> result = new ArrayList<DedicatedResourceVO>(); |
| result.add(dedicatedResource); |
| return result; |
| } |
| }); |
| } |
| |
| @Override |
| @DB |
| @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Host") |
| public List<DedicatedResourceVO> dedicateHost(final Long hostId, final Long domainId, final String accountName) { |
| Long accountId = null; |
| if (accountName != null) { |
| Account caller = CallContext.current().getCallingAccount(); |
| 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().equals(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().equals(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().equals(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<Long> childDomainIds = getDomainChildIds(domainId); |
| childDomainIds.add(domainId); |
| checkHostSuitabilityForExplicitDedication(accountId, childDomainIds, hostId); |
| |
| final Long accountIdFinal = accountId; |
| return Transaction.execute(new TransactionCallback<List<DedicatedResourceVO>>() { |
| @Override |
| public List<DedicatedResourceVO> doInTransaction(TransactionStatus status) { |
| // find or create the affinity group by name under this account/domain |
| AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal); |
| if (group == null) { |
| s_logger.error("Unable to dedicate zone due to, failed to create dedication affinity group"); |
| throw new CloudRuntimeException("Failed to dedicate zone. Please contact Cloud Support."); |
| } |
| DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, null, null, hostId, null, null, group.getId()); |
| try { |
| dedicatedResource.setDomainId(domainId); |
| if (accountIdFinal != null) { |
| dedicatedResource.setAccountId(accountIdFinal); |
| } |
| 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.", e); |
| } |
| |
| List<DedicatedResourceVO> result = new ArrayList<DedicatedResourceVO>(); |
| result.add(dedicatedResource); |
| return result; |
| } |
| }); |
| |
| } |
| |
| private AffinityGroup findOrCreateDedicatedAffinityGroup(Long domainId, Long accountId) { |
| if (domainId == null) { |
| return null; |
| } |
| |
| AffinityGroup group = null; |
| String accountName = null; |
| String affinityGroupName = null; |
| |
| if (accountId != null) { |
| AccountVO account = _accountDao.findById(accountId); |
| accountName = account.getAccountName(); |
| |
| group = _affinityGroupDao.findByAccountAndType(accountId, "ExplicitDedication"); |
| if (group != null) { |
| return group; |
| } |
| // default to a groupname with account/domain information |
| affinityGroupName = "DedicatedGrp-" + accountName; |
| |
| } else { |
| // domain level group |
| group = _affinityGroupDao.findDomainLevelGroupByType(domainId, "ExplicitDedication"); |
| if (group != null) { |
| return group; |
| } |
| // default to a groupname with account/domain information |
| String domainName = _domainDao.findById(domainId).getName(); |
| affinityGroupName = "DedicatedGrp-domain-" + domainName; |
| } |
| |
| group = _affinityGroupService.createAffinityGroup(accountName, null, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group"); |
| |
| return group; |
| |
| } |
| |
| private List<UserVmVO> getVmsOnHost(long hostId) { |
| List<UserVmVO> vms = _userVmDao.listUpByHostId(hostId); |
| List<UserVmVO> 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<Long> domainIds, long hostId) { |
| boolean suitable = true; |
| List<UserVmVO> 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<Long> domainIds, List<HostVO> 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 id " + accountId); |
| } |
| } |
| } |
| |
| private List<Long> getDomainChildIds(long domainId) { |
| DomainVO domainRecord = _domainDao.findById(domainId); |
| List<Long> domainIds = new ArrayList<Long>(); |
| domainIds.add(domainRecord.getId()); |
| // find all domain Ids till leaf |
| List<DomainVO> 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()); |
| AffinityGroup group = _affinityGroupDao.findById(resource.getAffinityGroupId()); |
| dedicateZoneResponse.setId(resource.getUuid()); |
| dedicateZoneResponse.setZoneId(dc.getUuid()); |
| dedicateZoneResponse.setZoneName(dc.getName()); |
| dedicateZoneResponse.setDomainId(domain.getUuid()); |
| dedicateZoneResponse.setAffinityGroupId(group.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()); |
| AffinityGroup group = _affinityGroupDao.findById(resource.getAffinityGroupId()); |
| dedicatePodResponse.setId(resource.getUuid()); |
| dedicatePodResponse.setPodId(pod.getUuid()); |
| dedicatePodResponse.setPodName(pod.getName()); |
| dedicatePodResponse.setDomainId(domain.getUuid()); |
| dedicatePodResponse.setAffinityGroupId(group.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()); |
| AffinityGroup group = _affinityGroupDao.findById(resource.getAffinityGroupId()); |
| dedicateClusterResponse.setId(resource.getUuid()); |
| dedicateClusterResponse.setClusterId(cluster.getUuid()); |
| dedicateClusterResponse.setClusterName(cluster.getName()); |
| dedicateClusterResponse.setDomainId(domain.getUuid()); |
| dedicateClusterResponse.setAffinityGroupId(group.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()); |
| AffinityGroup group = _affinityGroupDao.findById(resource.getAffinityGroupId()); |
| dedicateHostResponse.setId(resource.getUuid()); |
| dedicateHostResponse.setHostId(host.getUuid()); |
| dedicateHostResponse.setHostName(host.getName()); |
| dedicateHostResponse.setDomainId(domain.getUuid()); |
| dedicateHostResponse.setAffinityGroupId(group.getUuid()); |
| if (account != null) { |
| dedicateHostResponse.setAccountId(account.getUuid()); |
| } |
| dedicateHostResponse.setObjectName("dedicatedhost"); |
| return dedicateHostResponse; |
| } |
| |
| @Override |
| public List<Class<?>> getCommands() { |
| List<Class<?>> cmdList = new ArrayList<Class<?>>(); |
| 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<List<? extends DedicatedResourceVO>, Integer> listDedicatedZones(ListDedicatedZonesCmd cmd) { |
| Long zoneId = cmd.getZoneId(); |
| Long domainId = cmd.getDomainId(); |
| String accountName = cmd.getAccountName(); |
| Long accountId = null; |
| Long affinityGroupId = cmd.getAffinityGroupId(); |
| Long startIndex = cmd.getStartIndex(); |
| Long pageSize = cmd.getPageSizeVal(); |
| |
| 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); |
| } |
| } |
| Filter searchFilter = new Filter(DedicatedResourceVO.class, "id", true, startIndex, pageSize); |
| Pair<List<DedicatedResourceVO>, Integer> result = _dedicatedDao.searchDedicatedZones(zoneId, domainId, accountId, affinityGroupId, searchFilter); |
| return new Pair<List<? extends DedicatedResourceVO>, Integer>(result.first(), result.second()); |
| } |
| |
| @Override |
| public Pair<List<? extends DedicatedResourceVO>, Integer> listDedicatedPods(ListDedicatedPodsCmd cmd) { |
| Long podId = cmd.getPodId(); |
| Long domainId = cmd.getDomainId(); |
| String accountName = cmd.getAccountName(); |
| Long accountId = null; |
| Long affinityGroupId = cmd.getAffinityGroupId(); |
| Long startIndex = cmd.getStartIndex(); |
| Long pageSize = cmd.getPageSizeVal(); |
| |
| 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); |
| } |
| } |
| Filter searchFilter = new Filter(DedicatedResourceVO.class, "id", true, startIndex, pageSize); |
| Pair<List<DedicatedResourceVO>, Integer> result = _dedicatedDao.searchDedicatedPods(podId, domainId, accountId, affinityGroupId, searchFilter); |
| return new Pair<List<? extends DedicatedResourceVO>, Integer>(result.first(), result.second()); |
| } |
| |
| @Override |
| public Pair<List<? extends DedicatedResourceVO>, Integer> listDedicatedClusters(ListDedicatedClustersCmd cmd) { |
| Long clusterId = cmd.getClusterId(); |
| Long domainId = cmd.getDomainId(); |
| String accountName = cmd.getAccountName(); |
| Long accountId = null; |
| Long affinityGroupId = cmd.getAffinityGroupId(); |
| Long startIndex = cmd.getStartIndex(); |
| Long pageSize = cmd.getPageSizeVal(); |
| |
| 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); |
| } |
| } |
| Filter searchFilter = new Filter(DedicatedResourceVO.class, "id", true, startIndex, pageSize); |
| Pair<List<DedicatedResourceVO>, Integer> result = _dedicatedDao.searchDedicatedClusters(clusterId, domainId, accountId, affinityGroupId, searchFilter); |
| return new Pair<List<? extends DedicatedResourceVO>, Integer>(result.first(), result.second()); |
| } |
| |
| @Override |
| public Pair<List<? extends DedicatedResourceVO>, Integer> listDedicatedHosts(ListDedicatedHostsCmd cmd) { |
| Long hostId = cmd.getHostId(); |
| Long domainId = cmd.getDomainId(); |
| String accountName = cmd.getAccountName(); |
| Long affinityGroupId = cmd.getAffinityGroupId(); |
| Long startIndex = cmd.getStartIndex(); |
| Long pageSize = cmd.getPageSizeVal(); |
| |
| 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); |
| } |
| } |
| Filter searchFilter = new Filter(DedicatedResourceVO.class, "id", true, startIndex, pageSize); |
| Pair<List<DedicatedResourceVO>, Integer> result = _dedicatedDao.searchDedicatedHosts(hostId, domainId, accountId, affinityGroupId, searchFilter); |
| return new Pair<List<? extends DedicatedResourceVO>, Integer>(result.first(), result.second()); |
| } |
| |
| @Override |
| @DB |
| @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE, eventDescription = "Releasing dedicated resource") |
| public boolean releaseDedicatedResource(final Long zoneId, Long podId, Long clusterId, Long hostId) throws InvalidParameterValueException { |
| DedicatedResourceVO resource = 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 { |
| final DedicatedResourceVO resourceFinal = resource; |
| Transaction.execute(new TransactionCallbackNoReturn() { |
| @Override |
| public void doInTransactionWithoutResult(TransactionStatus status) { |
| Long resourceId = resourceFinal.getId(); |
| if (!_dedicatedDao.remove(resourceId)) { |
| throw new CloudRuntimeException("Failed to delete Resource " + resourceId); |
| } |
| if (zoneId != null) { |
| // remove the domainId set in zone |
| DataCenterVO dc = _zoneDao.findById(zoneId); |
| if (dc != null) { |
| dc.setDomainId(null); |
| dc.setDomain(null); |
| if (!_zoneDao.update(zoneId, dc)) { |
| throw new CloudRuntimeException("Failed to release dedicated zone, could not clear domainId. Please contact Cloud Support."); |
| } |
| } |
| } |
| } |
| }); |
| |
| // find the group associated and check if there are any more |
| // resources under that group |
| List<DedicatedResourceVO> resourcesInGroup = _dedicatedDao.listByAffinityGroupId(resource.getAffinityGroupId()); |
| if (resourcesInGroup.isEmpty()) { |
| // delete the group |
| _affinityGroupService.deleteAffinityGroup(resource.getAffinityGroupId(), null, null, null, null); |
| } |
| |
| } |
| return true; |
| } |
| } |