Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,7 @@ public class ApiConstants {
public static final String OVM3_CLUSTER = "ovm3cluster";
public static final String OVM3_VIP = "ovm3vip";
public static final String CLEAN_UP_DETAILS = "cleanupdetails";
public static final String CLEAN_UP_EXTERNAL_DETAILS = "cleanupexternaldetails";
public static final String CLEAN_UP_PARAMETERS = "cleanupparameters";
public static final String VIRTUAL_SIZE = "virtualsize";
public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ public class UpdateHostCmd extends BaseCmd {
@Parameter(name = ApiConstants.EXTERNAL_DETAILS, type = CommandType.MAP, description = "Details in key/value pairs using format externaldetails[i].keyname=keyvalue. Example: externaldetails[0].endpoint.url=urlvalue", since = "4.21.0")
protected Map externalDetails;

@Parameter(name = ApiConstants.CLEAN_UP_EXTERNAL_DETAILS,
type = CommandType.BOOLEAN,
description = "Optional boolean field, which indicates if external details should be cleaned up or not " +
"(If set to true, external details removed for this host, externaldetails field ignored; " +
"if false or not set, no action)",
since = "4.22.0")
protected Boolean cleanupExternalDetails;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -112,6 +120,10 @@ public Map<String, String> getExternalDetails() {
return convertExternalDetailsToMap(externalDetails);
}

public boolean isCleanupExternalDetails() {
return Boolean.TRUE.equals(cleanupExternalDetails);
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ public class UpdateServiceOfferingCmd extends BaseCmd {
since = "4.21.0")
private Map externalDetails;

@Parameter(name = ApiConstants.CLEAN_UP_EXTERNAL_DETAILS,
type = CommandType.BOOLEAN,
description = "Optional boolean field, which indicates if external details should be cleaned up or not " +
"(If set to true, external details removed for this offering, externaldetails field ignored; " +
"if false or not set, no action)",
since = "4.22.0")
protected Boolean cleanupExternalDetails;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -205,6 +213,10 @@ public Map<String, String> getExternalDetails() {
return convertExternalDetailsToMap(externalDetails);
}

public boolean isCleanupExternalDetails() {
return Boolean.TRUE.equals(cleanupExternalDetails);
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public interface HostDetailsDao extends GenericDao<DetailVO, Long> {

List<DetailVO> findByName(String name);

void removeExternalDetails(long hostId);

void replaceExternalDetails(long hostId, Map<String, String> details);

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class HostDetailsDaoImpl extends GenericDaoBase<DetailVO, Long> implement
protected final SearchBuilder<DetailVO> HostSearch;
protected final SearchBuilder<DetailVO> DetailSearch;
protected final SearchBuilder<DetailVO> DetailNameSearch;
protected final SearchBuilder<DetailVO> ExternalDetailSearch;

public HostDetailsDaoImpl() {
HostSearch = createSearchBuilder();
Expand All @@ -53,6 +54,11 @@ public HostDetailsDaoImpl() {
DetailNameSearch = createSearchBuilder();
DetailNameSearch.and("name", DetailNameSearch.entity().getName(), SearchCriteria.Op.EQ);
DetailNameSearch.done();

ExternalDetailSearch = createSearchBuilder();
ExternalDetailSearch.and("hostId", ExternalDetailSearch.entity().getHostId(), SearchCriteria.Op.EQ);
ExternalDetailSearch.and("name", ExternalDetailSearch.entity().getName(), SearchCriteria.Op.LIKE);
ExternalDetailSearch.done();
}

@Override
Expand Down Expand Up @@ -133,6 +139,17 @@ public List<DetailVO> findByName(String name) {
return listBy(sc);
}

@Override
public void removeExternalDetails(long hostId) {
TransactionLegacy txn = TransactionLegacy.currentTxn();
txn.start();
SearchCriteria<DetailVO> sc = ExternalDetailSearch.create();
sc.setParameters("hostId", hostId);
sc.setParameters("name", VmDetailConstants.EXTERNAL_DETAIL_PREFIX + "%");
remove(sc);
txn.commit();
}

@Override
public void replaceExternalDetails(long hostId, Map<String, String> details) {
if (details.isEmpty()) {
Expand All @@ -149,11 +166,7 @@ public void replaceExternalDetails(long hostId, Map<String, String> details) {
}
detailVOs.add(new DetailVO(hostId, name, value));
}
SearchBuilder<DetailVO> sb = createSearchBuilder();
sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);
sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
sb.done();
SearchCriteria<DetailVO> sc = sb.create();
SearchCriteria<DetailVO> sc = ExternalDetailSearch.create();
sc.setParameters("hostId", hostId);
sc.setParameters("name", VmDetailConstants.EXTERNAL_DETAIL_PREFIX + "%");
remove(sc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class UpdateExtensionCmd extends BaseCmd {
@Parameter(name = ApiConstants.CLEAN_UP_DETAILS,
type = CommandType.BOOLEAN,
description = "Optional boolean field, which indicates if details should be cleaned up or not " +
"(If set to true, details removed for this action, details field ignored; " +
"(If set to true, details removed for this extension, details field ignored; " +
"if false or not set, no action)")
private Boolean cleanupDetails;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3799,15 +3799,19 @@ private void setBytesRate(DiskOffering offering, Long bytesReadRate, Long bytesR
}

protected boolean serviceOfferingExternalDetailsNeedUpdate(final Map<String, String> offeringDetails,
final Map<String, String> externalDetails) {
if (MapUtils.isEmpty(externalDetails)) {
final Map<String, String> externalDetails, final boolean cleanupExternalDetails) {
if (MapUtils.isEmpty(externalDetails) && !cleanupExternalDetails) {
return false;
}

Map<String, String> existingExternalDetails = offeringDetails.entrySet().stream()
.filter(detail -> detail.getKey().startsWith(VmDetailConstants.EXTERNAL_DETAIL_PREFIX))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

if (cleanupExternalDetails) {
return !MapUtils.isEmpty(existingExternalDetails);
}

if (MapUtils.isEmpty(existingExternalDetails) || existingExternalDetails.size() != externalDetails.size()) {
return true;
}
Expand Down Expand Up @@ -3837,6 +3841,7 @@ public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd)
ServiceOffering.State state = cmd.getState();
boolean purgeResources = cmd.isPurgeResources();
final Map<String, String> externalDetails = cmd.getExternalDetails();
final boolean cleanupExternalDetails = cmd.isCleanupExternalDetails();

if (userId == null) {
userId = Long.valueOf(User.UID_SYSTEM);
Expand Down Expand Up @@ -3930,7 +3935,7 @@ public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd)

final boolean updateNeeded = name != null || displayText != null || sortKey != null || storageTags != null || hostTags != null || state != null;
final boolean serviceOfferingExternalDetailsNeedUpdate =
serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails);
serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, cleanupExternalDetails);
final boolean detailsUpdateNeeded = !filteredDomainIds.equals(existingDomainIds) ||
!filteredZoneIds.equals(existingZoneIds) || purgeResources != existingPurgeResources ||
serviceOfferingExternalDetailsNeedUpdate;
Expand Down Expand Up @@ -4005,8 +4010,10 @@ public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd)
SearchCriteria<ServiceOfferingDetailsVO> externalDetailsRemoveSC = sb.create();
externalDetailsRemoveSC.setParameters("detailNameLike", VmDetailConstants.EXTERNAL_DETAIL_PREFIX + "%");
_serviceOfferingDetailsDao.remove(externalDetailsRemoveSC);
for (Map.Entry<String, String> entry : externalDetails.entrySet()) {
detailsVO.add(new ServiceOfferingDetailsVO(id, entry.getKey(), entry.getValue(), true));
if (!cleanupExternalDetails) {
for (Map.Entry<String, String> entry : externalDetails.entrySet()) {
detailsVO.add(new ServiceOfferingDetailsVO(id, entry.getKey(), entry.getValue(), true));
}
}
}
}
Expand Down
19 changes: 13 additions & 6 deletions server/src/main/java/com/cloud/resource/ResourceManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2799,12 +2799,15 @@ private void updateHostTags(HostVO host, Long hostId, List<String> hostTags, Boo

@Override
public Host updateHost(final UpdateHostCmd cmd) throws NoTransitionException {
return updateHost(cmd.getId(), cmd.getName(), cmd.getOsCategoryId(),
cmd.getAllocationState(), cmd.getUrl(), cmd.getHostTags(), cmd.getIsTagARule(), cmd.getAnnotation(), false, cmd.getExternalDetails());
return updateHost(cmd.getId(), cmd.getName(), cmd.getOsCategoryId(), cmd.getAllocationState(), cmd.getUrl(),
cmd.getHostTags(), cmd.getIsTagARule(), cmd.getAnnotation(), false,
cmd.getExternalDetails(), cmd.isCleanupExternalDetails());
}

private Host updateHost(Long hostId, String name, Long guestOSCategoryId, String allocationState,
String url, List<String> hostTags, Boolean isTagARule, String annotation, boolean isUpdateFromHostHealthCheck, Map<String, String> externalDetails) throws NoTransitionException {
String url, List<String> hostTags, Boolean isTagARule, String annotation,
boolean isUpdateFromHostHealthCheck, Map<String, String> externalDetails,
boolean cleanupExternalDetails) throws NoTransitionException {
// Verify that the host exists
final HostVO host = _hostDao.findById(hostId);
if (host == null) {
Expand All @@ -2828,8 +2831,12 @@ private Host updateHost(Long hostId, String name, Long guestOSCategoryId, String
updateHostTags(host, hostId, hostTags, isTagARule);
}

if (MapUtils.isNotEmpty(externalDetails)) {
_hostDetailsDao.replaceExternalDetails(hostId, externalDetails);
if (cleanupExternalDetails) {
_hostDetailsDao.removeExternalDetails(hostId);
} else {
if (MapUtils.isNotEmpty(externalDetails)) {
_hostDetailsDao.replaceExternalDetails(hostId, externalDetails);
}
}

if (url != null) {
Expand Down Expand Up @@ -2888,7 +2895,7 @@ private void sendAlertAndAnnotationForAutoEnableDisableKVMHostFeature(HostVO hos

@Override
public Host autoUpdateHostAllocationState(Long hostId, ResourceState.Event resourceEvent) throws NoTransitionException {
return updateHost(hostId, null, null, resourceEvent.toString(), null, null, null, null, true, null);
return updateHost(hostId, null, null, resourceEvent.toString(), null, null, null, null, true, null, false);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1028,17 +1028,47 @@ public void serviceOfferingExternalDetailsNeedUpdateReturnsFalseWhenExternalDeta
Map<String, String> offeringDetails = Map.of("key1", "value1");
Map<String, String> externalDetails = Collections.emptyMap();

boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails);
boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, false);

Assert.assertFalse(result);
}

@Test
public void serviceOfferingExternalDetailsNeedUpdateReturnsFalseWhenExternalDetailsIsEmptyAndCleanupTrue() {
Map<String, String> offeringDetails = Map.of("key1", "value1");
Map<String, String> externalDetails = Collections.emptyMap();

boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, true);

Assert.assertFalse(result);
}

@Test
public void serviceOfferingExternalDetailsNeedUpdateReturnsTrueWhenExistingDetailsExistExternalDetailsIsEmptyAndCleanupTrue() {
Map<String, String> offeringDetails = Map.of("External:key1", "value1");
Map<String, String> externalDetails = Collections.emptyMap();

boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, true);

Assert.assertTrue(result);
}

@Test
public void serviceOfferingExternalDetailsNeedUpdateReturnsTrueWhenExistingExternalDetailsExistValidExternalDetailsAndCleanupTrue() {
Map<String, String> offeringDetails = Map.of("External:key1", "value1");
Map<String, String> externalDetails = Collections.emptyMap();

boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, true);

Assert.assertTrue(result);
}

@Test
public void serviceOfferingExternalDetailsNeedUpdateReturnsTrueWhenExistingExternalDetailsIsEmpty() {
Map<String, String> offeringDetails = Map.of("key1", "value1");
Map<String, String> externalDetails = Map.of("External:key1", "value1");

boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails);
boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, false);

Assert.assertTrue(result);
}
Expand All @@ -1048,7 +1078,7 @@ public void serviceOfferingExternalDetailsNeedUpdateReturnsTrueWhenSizesDiffer()
Map<String, String> offeringDetails = Map.of("External:key1", "value1");
Map<String, String> externalDetails = Map.of("External:key1", "value1", "External:key2", "value2");

boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails);
boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, false);

Assert.assertTrue(result);
}
Expand All @@ -1058,7 +1088,7 @@ public void serviceOfferingExternalDetailsNeedUpdateReturnsTrueWhenValuesDiffer(
Map<String, String> offeringDetails = Map.of("External:key1", "value1");
Map<String, String> externalDetails = Map.of("External:key1", "differentValue");

boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails);
boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, false);

Assert.assertTrue(result);
}
Expand All @@ -1068,7 +1098,7 @@ public void serviceOfferingExternalDetailsNeedUpdateReturnsFalseWhenDetailsMatch
Map<String, String> offeringDetails = Map.of("External:key1", "value1", "External:key2", "value2");
Map<String, String> externalDetails = Map.of("External:key1", "value1", "External:key2", "value2");

boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails);
boolean result = configurationManagerImplSpy.serviceOfferingExternalDetailsNeedUpdate(offeringDetails, externalDetails, false);

Assert.assertFalse(result);
}
Expand Down
19 changes: 16 additions & 3 deletions ui/src/views/AutogenView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1772,9 +1772,22 @@ export default {
params[key] = param.opts[input].name
}
} else if (param.type === 'map' && typeof input === 'object') {
Object.entries(values.externaldetails).forEach(([key, value]) => {
params[param.name + '[0].' + key] = value
})
const details = values[key]
if (details && Object.keys(details).length > 0) {
Object.entries(details).forEach(([k, v]) => {
params[key + '[0].' + k] = v
})
} else {
if (['details', 'externaldetails'].includes(key)) {
const updateApiParams = this.$getApiParams(action.api)
const cleanupKey = 'cleanup' + key
if (cleanupKey in updateApiParams) {
params[cleanupKey] = true
break
}
}
params[key] = {}
}
} else {
params[key] = input
}
Expand Down
4 changes: 3 additions & 1 deletion ui/src/views/infra/HostUpdate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,12 @@ export default {
if (values.istagarule !== undefined) {
params.istagarule = values.istagarule
}
if (values.externaldetails) {
if (values.externaldetails && Object.keys(values.externaldetails).length > 0) {
Object.entries(values.externaldetails).forEach(([key, value]) => {
params['externaldetails[0].' + key] = value
})
} else {
params.cleanupexternaldetails = true
}
this.loading = true

Expand Down
Loading