diff --git a/api/src/main/java/com/cloud/dc/DedicatedResources.java b/api/src/main/java/com/cloud/dc/DedicatedResources.java index 63188ca0b0e..23e6cc88a1e 100644 --- a/api/src/main/java/com/cloud/dc/DedicatedResources.java +++ b/api/src/main/java/com/cloud/dc/DedicatedResources.java @@ -21,6 +21,10 @@ import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; public interface DedicatedResources extends InfrastructureEntity, InternalIdentity, Identity { + enum Type { + Zone, Pod, Cluster, Host + } + @Override long getId(); diff --git a/api/src/main/java/org/apache/cloudstack/affinity/AffinityGroupResponse.java b/api/src/main/java/org/apache/cloudstack/affinity/AffinityGroupResponse.java index 6cda8d07bd8..69f391a5656 100644 --- a/api/src/main/java/org/apache/cloudstack/affinity/AffinityGroupResponse.java +++ b/api/src/main/java/org/apache/cloudstack/affinity/AffinityGroupResponse.java @@ -25,6 +25,7 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; import org.apache.cloudstack.api.response.ControlledViewEntityResponse; +import org.apache.cloudstack.dedicated.DedicatedResourceResponse; import com.cloud.serializer.Param; @@ -76,6 +77,10 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledVie @Param(description = "virtual machine IDs associated with this affinity group") private List vmIdList; + @SerializedName("dedicatedresources") + @Param(description = "dedicated resources associated with this affinity group") + private List dedicatedResources; + public AffinityGroupResponse() { } @@ -171,4 +176,12 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledVie this.vmIdList.add(vmId); } + public void addDedicatedResource(DedicatedResourceResponse dedicatedResourceResponse) { + if (this.dedicatedResources == null) { + this.dedicatedResources = new ArrayList<>(); + } + + this.dedicatedResources.add(dedicatedResourceResponse); + } + } diff --git a/api/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceResponse.java b/api/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceResponse.java new file mode 100644 index 00000000000..fc116cbb91e --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceResponse.java @@ -0,0 +1,44 @@ +// 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 com.cloud.dc.DedicatedResources; +import com.cloud.serializer.Param; + +import com.google.gson.annotations.SerializedName; + +import org.apache.cloudstack.api.BaseResponse; + +public class DedicatedResourceResponse extends BaseResponse { + @SerializedName("resourceid") + @Param(description = "the ID of the resource") + private String resourceId; + + @SerializedName("resourcename") + @Param(description = "the name of the resource") + private String resourceName; + + @SerializedName("resourcetype") + @Param(description = "the type of the resource") + private DedicatedResources.Type resourceType; + + public DedicatedResourceResponse(String resourceId, String resourceName, DedicatedResources.Type resourceType) { + this.resourceId = resourceId; + this.resourceName = resourceName; + this.resourceType = resourceType; + } +} diff --git a/plugins/dedicated-resources/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java b/plugins/dedicated-resources/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java index 9060eccb64a..4f1db396b7c 100644 --- a/plugins/dedicated-resources/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java +++ b/plugins/dedicated-resources/src/main/java/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java @@ -23,6 +23,7 @@ import java.util.Map; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.commons.lang3.StringUtils; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupService; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; @@ -236,7 +237,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService { @Override public List doInTransaction(TransactionStatus status) { // find or create the affinity group by name under this account/domain - AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal); + AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal, DedicatedResources.Type.Zone); if (group == null) { 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."); @@ -372,10 +373,10 @@ public class DedicatedResourceManagerImpl implements DedicatedService { @Override public List doInTransaction(TransactionStatus status) { // find or create the affinity group by name under this account/domain - AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal); + AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal, DedicatedResources.Type.Pod); if (group == null) { - 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."); + logger.error("Unable to dedicate pod due to, failed to create dedication affinity group"); + throw new CloudRuntimeException("Failed to dedicate pod. Please contact Cloud Support."); } DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, podId, null, null, null, null, group.getId()); try { @@ -485,10 +486,10 @@ public class DedicatedResourceManagerImpl implements DedicatedService { @Override public List doInTransaction(TransactionStatus status) { // find or create the affinity group by name under this account/domain - AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal); + AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal, DedicatedResources.Type.Cluster); if (group == null) { - 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."); + logger.error("Unable to dedicate cluster due to, failed to create dedication affinity group"); + throw new CloudRuntimeException("Failed to dedicate cluster. Please contact Cloud Support."); } DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, null, clusterId, null, null, null, group.getId()); try { @@ -582,10 +583,10 @@ public class DedicatedResourceManagerImpl implements DedicatedService { @Override public List doInTransaction(TransactionStatus status) { // find or create the affinity group by name under this account/domain - AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal); + AffinityGroup group = findOrCreateDedicatedAffinityGroup(domainId, accountIdFinal, DedicatedResources.Type.Host); if (group == null) { - 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."); + logger.error("Unable to dedicate host due to, failed to create dedication affinity group"); + throw new CloudRuntimeException("Failed to dedicate host. Please contact Cloud Support."); } DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, null, null, hostId, null, null, group.getId()); try { @@ -607,7 +608,7 @@ public class DedicatedResourceManagerImpl implements DedicatedService { } - private AffinityGroup findOrCreateDedicatedAffinityGroup(Long domainId, Long accountId) { + private AffinityGroup findOrCreateDedicatedAffinityGroup(Long domainId, Long accountId, DedicatedResources.Type dedicatedResource) { if (domainId == null) { return null; } @@ -624,24 +625,25 @@ public class DedicatedResourceManagerImpl implements DedicatedService { if (group != null) { return group; } - // default to a groupname with account/domain information - affinityGroupName = "DedicatedGrp-" + accountName; + // defaults to a groupName with resourceType and account/domain information + affinityGroupName = String.format("Dedicated%sGrp-%s", dedicatedResource, accountName); } else { // domain level group group = _affinityGroupDao.findDomainLevelGroupByType(domainId, "ExplicitDedication"); if (group != null) { return group; } - // default to a groupname with account/domain information + + // defaults to a groupName with resourceType and account/domain information String domainName = _domainDao.findById(domainId).getName(); - affinityGroupName = "DedicatedGrp-domain-" + domainName; + affinityGroupName = String.format("Dedicated%sGrp-domain-%s", dedicatedResource, domainName); } - group = _affinityGroupService.createAffinityGroup(accountName, null, domainId, affinityGroupName, "ExplicitDedication", "dedicated resources group"); + String description = String.format("Dedicated %s group", StringUtils.lowerCase(dedicatedResource.toString())); + group = _affinityGroupService.createAffinityGroup(accountName, null, domainId, affinityGroupName, "ExplicitDedication", description); return group; - } private List getVmsOnHost(long hostId) { diff --git a/server/src/main/java/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java index 2a876ea8226..a5fd2bf11f1 100644 --- a/server/src/main/java/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java @@ -21,21 +21,46 @@ import java.util.List; import javax.inject.Inject; - import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.dedicated.DedicatedResourceResponse; import com.cloud.api.ApiResponseHelper; import com.cloud.api.query.vo.AffinityGroupJoinVO; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.dc.DataCenter; +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.host.Host; +import com.cloud.host.dao.HostDao; +import com.cloud.org.Cluster; +import com.cloud.user.AccountManager; public class AffinityGroupJoinDaoImpl extends GenericDaoBase implements AffinityGroupJoinDao { @Inject private ConfigurationDao _configDao; + @Inject + private DedicatedResourceDao dedicatedResourceDao; + @Inject + private DataCenterDao dataCenterDao; + @Inject + private HostPodDao podDao; + @Inject + private ClusterDao clusterDao; + @Inject + private HostDao hostDao; + @Inject + private AccountManager accountManager; private final SearchBuilder agSearch; @@ -64,6 +89,14 @@ public class AffinityGroupJoinDaoImpl extends GenericDaoBase dedicatedResources = dedicatedResourceDao.listByAffinityGroupId(vag.getId()); + this.populateDedicatedResourcesField(dedicatedResources, agResponse); + } + // update vm information long instanceId = vag.getVmId(); if (instanceId > 0) { @@ -76,6 +109,32 @@ public class AffinityGroupJoinDaoImpl extends GenericDaoBase dedicatedResources, AffinityGroupResponse agResponse) { + if (dedicatedResources.isEmpty()) { + return; + } + + for (DedicatedResourceVO resource : dedicatedResources) { + DedicatedResourceResponse dedicatedResourceResponse = null; + + if (resource.getDataCenterId() != null) { + DataCenter dataCenter = dataCenterDao.findById(resource.getDataCenterId()); + dedicatedResourceResponse = new DedicatedResourceResponse(dataCenter.getUuid(), dataCenter.getName(), DedicatedResources.Type.Zone); + } else if (resource.getPodId() != null) { + HostPodVO pod = podDao.findById(resource.getPodId()); + dedicatedResourceResponse = new DedicatedResourceResponse(pod.getUuid(), pod.getName(), DedicatedResources.Type.Pod); + } else if (resource.getClusterId() != null) { + Cluster cluster = clusterDao.findById(resource.getClusterId()); + dedicatedResourceResponse = new DedicatedResourceResponse(cluster.getUuid(), cluster.getName(), DedicatedResources.Type.Cluster); + } else if (resource.getHostId() != null) { + Host host = hostDao.findById(resource.getHostId()); + dedicatedResourceResponse = new DedicatedResourceResponse(host.getUuid(), host.getName(), DedicatedResources.Type.Host); + } + + agResponse.addDedicatedResource(dedicatedResourceResponse); + } + } + @Override public AffinityGroupResponse setAffinityGroupResponse(AffinityGroupResponse vagData, AffinityGroupJoinVO vag) { // update vm information diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 6ca710d4095..7336c038c89 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -673,6 +673,7 @@ "label.dedicate.zone": "Dedicate zone", "label.dedicated": "Dedicated", "label.dedicated.vlan.vni.ranges": "Dedicated VLAN/VNI ranges", +"label.dedicatedresources": "Dedicated resources", "label.default": "Default", "label.default.use": "Default use", "label.default.view": "Default view", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index 79333c100d3..f02aee747eb 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -472,6 +472,7 @@ "label.dedicate.zone": "Zona dedicada", "label.dedicated": "Dedicado", "label.dedicated.vlan.vni.ranges": "Intervalo(s) de VLAN/VNI dedicados", +"label.dedicatedresources": "Recursos dedicados", "label.default": "Padr\u00e3o", "label.default.use": "Uso padr\u00e3o", "label.default.view": "Visualiza\u00e7\u00e3o padr\u00e3o", diff --git a/ui/src/components/view/DetailsTab.vue b/ui/src/components/view/DetailsTab.vue index 3f6f37aa08b..f5f180c8f19 100644 --- a/ui/src/components/view/DetailsTab.vue +++ b/ui/src/components/view/DetailsTab.vue @@ -115,6 +115,15 @@
{{ JSON.stringify(JSON.parse(dataResource[item]), null, 4) || dataResource[item] }}
+
+
+
+ + {{ resource.resourcename }} + +
+
+
{{ dataResource[item] }}
@@ -150,6 +159,7 @@ import DedicateData from './DedicateData' import HostInfo from '@/views/infra/HostInfo' import VmwareData from './VmwareData' +import { genericCompare } from '@/utils/sort' export default { name: 'DetailsTab', @@ -386,6 +396,16 @@ export default { }, getDetailTitle (detail) { return `label.${String(this.detailsTitles[detail]).toLowerCase()}` + }, + getResourceLink (type, id) { + return `/${type.toLowerCase()}/${id}` + }, + sortDedicatedResourcesByName (resources) { + resources.sort((resource, otherResource) => { + return genericCompare(resource.resourcename, otherResource.resourcename) + }) + + return resources } } } diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index b992229962b..c6d16d6ea78 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -988,7 +988,7 @@ export default { } return fields }, - details: ['name', 'id', 'description', 'type', 'account', 'domain'], + details: ['name', 'id', 'description', 'type', 'account', 'domain', 'dedicatedresources'], related: [{ name: 'vm', title: 'label.instances',