mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Enhance the listAffinityGroups API by adding the dedicated resources related to an affinity group (#9188)
* add dedicated resource response * populate dedicatedresources field * change affinity group name and description when it contains dedicated resources * display dedicatedresources on UI * add end of line to DedicatedResourceResponse class * remove unnecessary fully qualified names
This commit is contained in:
parent
b1f683db6b
commit
6ec3c486dd
@ -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();
|
||||
|
||||
|
||||
@ -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<String> vmIdList;
|
||||
|
||||
@SerializedName("dedicatedresources")
|
||||
@Param(description = "dedicated resources associated with this affinity group")
|
||||
private List<DedicatedResourceResponse> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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<DedicatedResourceVO> 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<DedicatedResourceVO> 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<DedicatedResourceVO> 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<DedicatedResourceVO> 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<UserVmVO> getVmsOnHost(long hostId) {
|
||||
|
||||
@ -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<AffinityGroupJoinVO, Long> 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<AffinityGroupJoinVO> agSearch;
|
||||
|
||||
@ -64,6 +89,14 @@ public class AffinityGroupJoinDaoImpl extends GenericDaoBase<AffinityGroupJoinVO
|
||||
|
||||
ApiResponseHelper.populateOwner(agResponse, vag);
|
||||
|
||||
Long callerId = CallContext.current().getCallingAccountId();
|
||||
boolean isCallerRootAdmin = accountManager.isRootAdmin(callerId);
|
||||
boolean containsDedicatedResources = vag.getType().equals("ExplicitDedication");
|
||||
if (isCallerRootAdmin && containsDedicatedResources) {
|
||||
List<DedicatedResourceVO> 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<AffinityGroupJoinVO
|
||||
return agResponse;
|
||||
}
|
||||
|
||||
private void populateDedicatedResourcesField(List<DedicatedResourceVO> 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
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -115,6 +115,15 @@
|
||||
<div v-else-if="item === 'payload'" style="white-space: pre-wrap;">
|
||||
{{ JSON.stringify(JSON.parse(dataResource[item]), null, 4) || dataResource[item] }}
|
||||
</div>
|
||||
<div v-else-if="item === 'dedicatedresources'">
|
||||
<div v-for="(resource, idx) in sortDedicatedResourcesByName(dataResource[item])" :key="idx">
|
||||
<div>
|
||||
<router-link :to="getResourceLink(resource.resourcetype, resource.resourceid)">
|
||||
{{ resource.resourcename }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>{{ dataResource[item] }}</div>
|
||||
</div>
|
||||
</a-list-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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user