Skip to content

Instance lease: Allow deployment of instances with lease duration and leaseexpiry action #10560

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d737cea
FR-248: Instance lease, WIP commit
sudo87 Feb 21, 2025
9bef279
insert lease expiry into db and use that to filter exiring vms, add a…
sudo87 Feb 22, 2025
759f1fa
Add leaseDuration and leaseExpiryAction in Service offering create flow
sudo87 Feb 24, 2025
8c7a9f2
Update listVM cmd to allow listing only leased instances
sudo87 Feb 24, 2025
1495b08
Add methods to fetch instances for which lease is expiring in next days
sudo87 Feb 24, 2025
e2da246
Changes included:
sudo87 Feb 25, 2025
0969bf0
Update UI screens for leased properties coming from config and servic…
sudo87 Feb 28, 2025
f239e92
use global lock before running scheduler
sudo87 Mar 1, 2025
e7ce8ae
Unit tests
sudo87 Mar 4, 2025
0cf2fe8
Flow changes done in UI based on discussion
sudo87 Mar 5, 2025
7bc5f2a
Include view changes in schema upgrade files and use feature in vario…
sudo87 Mar 5, 2025
aff544f
Added integration test for vm deployment, UI enhancements for user pe…
sudo87 Mar 6, 2025
62397cc
validate integration tests, minor ui changes and log messages
sudo87 Mar 13, 2025
faf484f
fix build: moving configkey from setup to test itself
sudo87 Mar 17, 2025
410a882
Disable testAlert to unblock build and trim whitespaces in integratio…
sudo87 Mar 17, 2025
f4aa2bc
Address review comments
sudo87 Mar 18, 2025
f77f3ab
Merge latest from main
sudo87 Mar 18, 2025
337401b
Minor changes in EditVM screen
sudo87 Mar 19, 2025
009e0b4
Use ExecutorService instead of Timer and TimerTask
sudo87 Mar 19, 2025
bd10721
Additional review comments
sudo87 Mar 22, 2025
78fc3e0
Incorporate following changes:
sudo87 Mar 27, 2025
b042167
Handle pr review comments
sudo87 Apr 7, 2025
89db8a2
merge latest changes from main
sudo87 Apr 7, 2025
5dbf822
address review comments
sudo87 Apr 24, 2025
aadc305
Merge latest from main
sudo87 Apr 24, 2025
7cd59df
move instance.lease.enabled config to VMLeaseManager interface
sudo87 Apr 24, 2025
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
3 changes: 3 additions & 0 deletions api/src/main/java/com/cloud/vm/VmDetailConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,7 @@ public interface VmDetailConstants {
String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX);
String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX);
String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX);

String INSTANCE_LEASE_EXPIRY_DATE = "leaseexpirydate";
String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction";
}
5 changes: 5 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ public class ApiConstants {
public static final String INTERNAL_DNS2 = "internaldns2";
public static final String INTERNET_PROTOCOL = "internetprotocol";
public static final String INTERVAL_TYPE = "intervaltype";
public static final String INSTANCE_LEASE_ENABLED = "instanceleaseenabled";
public static final String LOCATION_TYPE = "locationtype";
public static final String IOPS_READ_RATE = "iopsreadrate";
public static final String IOPS_READ_RATE_MAX = "iopsreadratemax";
Expand Down Expand Up @@ -520,6 +521,10 @@ public class ApiConstants {
public static final String USED_SUBNETS = "usedsubnets";
public static final String USED_IOPS = "usediops";
public static final String USER_DATA = "userdata";
public static final String INSTANCE_LEASE_DURATION = "leaseduration";
public static final String INSTANCE_LEASE_EXPIRY_DATE= "leaseexpirydate";
public static final String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction";
public static final String ONLY_LEASED_INSTANCES = "onlyleasedinstances";

public static final String USER_DATA_NAME = "userdataname";
public static final String USER_DATA_ID = "userdataid";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,14 @@ public class CreateServiceOfferingCmd extends BaseCmd {
since="4.20")
private Boolean purgeResources;

@Parameter(name = ApiConstants.INSTANCE_LEASE_DURATION, type = CommandType.LONG,
description = "Number of days instance is leased for.",
since = "4.21.0")
private Long leaseDuration;

@Parameter(name = ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION, type = CommandType.STRING, since = "4.21.0",
description = "Lease expiry action")
private String leaseExpiryAction;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
Expand Down Expand Up @@ -487,6 +494,14 @@ public boolean getEncryptRoot() {
return false;
}

public String getLeaseExpiryAction() {
return leaseExpiryAction;
}

public Long getLeaseDuration() {
return leaseDuration;
}

public boolean isPurgeResources() {
return Boolean.TRUE.equals(purgeResources);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public void execute() {
response.setInstancesDisksStatsRetentionTime((Integer) capabilities.get(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_TIME));
response.setSharedFsVmMinCpuCount((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT));
response.setSharedFsVmMinRamSize((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE));
response.setInstanceLeaseEnabled((Boolean) capabilities.get(ApiConstants.INSTANCE_LEASE_ENABLED));
response.setObjectName("capability");
response.setResponseName(getCommandName());
this.setResponseObject(response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,14 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG
description = "Enable packed virtqueues or not.")
private Boolean nicPackedVirtQueues;

@Parameter(name = ApiConstants.INSTANCE_LEASE_DURATION, type = CommandType.LONG, since = "4.21.0",
description = "Number of days instance is leased for.")
private Long leaseDuration;

@Parameter(name = ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION, type = CommandType.STRING, since = "4.21.0",
description = "Lease expiry action")
private String leaseExpiryAction;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -475,6 +483,14 @@ public String getPassword() {
return password;
}

public Long getLeaseDuration() {
return leaseDuration;
}

public String getLeaseExpiryAction() {
return leaseExpiryAction;
}

public List<Long> getNetworkIds() {
if (MapUtils.isNotEmpty(vAppNetworks)) {
if (CollectionUtils.isNotEmpty(networkIds) || ipAddress != null || getIp6Address() != null || MapUtils.isNotEmpty(ipToNetworkList)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.BOOLEAN, description = "Whether to return the VMs' user data or not. By default, user data will not be returned.", since = "4.18.0.0")
private Boolean showUserData;

@Parameter(name = ApiConstants.ONLY_LEASED_INSTANCES, type = CommandType.BOOLEAN,
description = "Whether to return the Leased instances",
since = "4.21.0")
private Boolean onlyLeasedInstances = false;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -322,4 +327,10 @@ protected void updateVMResponse(List<UserVmResponse> response) {
vmResponse.setResourceIconResponse(iconResponse);
}
}


public Boolean getOnlyLeasedInstances() {
return onlyLeasedInstances;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction,
" autoscaling groups or CKS, delete protection will be ignored.")
private Boolean deleteProtection;

@Parameter(name = ApiConstants.INSTANCE_LEASE_DURATION, type = CommandType.LONG, since = "4.21.0",
description = "Number of days instance is leased for.")
private Long leaseDuration;

@Parameter(name = ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION, type = CommandType.STRING, since = "4.21.0",
description = "Lease expiry action")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description = "Lease expiry action")
description = "Lease expiry action, valid values are STOP and DESTROY")

private String leaseExpiryAction;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -324,4 +332,13 @@ public Long getApiResourceId() {
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.VirtualMachine;
}

public Long getLeaseDuration() {
return leaseDuration;
}

public String getLeaseExpiryAction() {
return leaseExpiryAction;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ public class CapabilitiesResponse extends BaseResponse {
@Param(description = "the min Ram size for the service offering used by the shared filesystem instance", since = "4.20.0")
private Integer sharedFsVmMinRamSize;

@SerializedName(ApiConstants.INSTANCE_LEASE_ENABLED)
@Param(description = "true if instance lease feature is enabled", since = "4.21.0")
private Boolean instanceLeaseEnabled;

public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
this.securityGroupsEnabled = securityGroupsEnabled;
}
Expand Down Expand Up @@ -247,4 +251,8 @@ public void setSharedFsVmMinCpuCount(Integer sharedFsVmMinCpuCount) {
public void setSharedFsVmMinRamSize(Integer sharedFsVmMinRamSize) {
this.sharedFsVmMinRamSize = sharedFsVmMinRamSize;
}

public void setInstanceLeaseEnabled(Boolean instanceLeaseEnabled) {
this.instanceLeaseEnabled = instanceLeaseEnabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,14 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations {
@Param(description = "Whether to cleanup VM and its associated resource upon expunge", since = "4.20")
private Boolean purgeResources;

@SerializedName(ApiConstants.INSTANCE_LEASE_DURATION)
@Param(description = "Instance lease duration for service offering", since = "4.21.0")
private Long leaseDuration;

@SerializedName(ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION)
@Param(description = "Action to be taken once lease is over", since = "4.21.0")
private String leaseExpiryAction;

public ServiceOfferingResponse() {
}

Expand Down Expand Up @@ -505,6 +513,22 @@ public void setCacheMode(String cacheMode) {
this.cacheMode = cacheMode;
}

public Long getLeaseDuration() {
return leaseDuration;
}

public void setLeaseDuration(Long leaseDuration) {
this.leaseDuration = leaseDuration;
}

public String getLeaseExpiryAction() {
return leaseExpiryAction;
}

public void setLeaseExpiryAction(String leaseExpiryAction) {
this.leaseExpiryAction = leaseExpiryAction;
}

public String getVsphereStoragePolicy() {
return vsphereStoragePolicy;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@
// under the License.
package org.apache.cloudstack.api.response;

import com.cloud.network.router.VirtualRouter;
import com.cloud.serializer.Param;
import com.cloud.uservm.UserVm;
import com.cloud.vm.VirtualMachine;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponseWithTagInformation;
import org.apache.cloudstack.api.EntityReference;
import org.apache.commons.collections.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
Expand All @@ -26,19 +38,6 @@
import java.util.Set;
import java.util.TreeSet;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponseWithTagInformation;
import org.apache.cloudstack.api.EntityReference;

import com.cloud.network.router.VirtualRouter;
import com.cloud.serializer.Param;
import com.cloud.uservm.UserVm;
import com.cloud.vm.VirtualMachine;
import com.google.gson.annotations.SerializedName;
import org.apache.commons.collections.CollectionUtils;

@SuppressWarnings("unused")
@EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class})
public class UserVmResponse extends BaseResponseWithTagInformation implements ControlledEntityResponse, SetResourceIconResponse {
Expand Down Expand Up @@ -392,10 +391,22 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
@Param(description = "VNF details", since = "4.19.0")
private Map<String, String> vnfDetails;

@SerializedName((ApiConstants.VM_TYPE))
@SerializedName(ApiConstants.VM_TYPE)
@Param(description = "User VM type", since = "4.20.0")
private String vmType;

@SerializedName(ApiConstants.INSTANCE_LEASE_DURATION)
@Param(description = "Instance lease duration", since = "4.21.0")
private Long leaseDuration;

@SerializedName(ApiConstants.INSTANCE_LEASE_EXPIRY_DATE)
@Param(description = "Instance lease expiry date", since = "4.21.0")
private Date leaseExpiryDate;

@SerializedName(ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION)
@Param(description = "Instance lease expiry action", since = "4.21.0")
private String leaseExpiryAction;

public UserVmResponse() {
securityGroupList = new LinkedHashSet<>();
nics = new TreeSet<>(Comparator.comparingInt(x -> Integer.parseInt(x.getDeviceId())));
Expand Down Expand Up @@ -1169,4 +1180,29 @@ public String getVmType() {
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}

public Long getLeaseDuration() {
return leaseDuration;
}

public void setLeaseDuration(Long leaseDuration) {
this.leaseDuration = leaseDuration;
}

public String getLeaseExpiryAction() {
return leaseExpiryAction;
}

public void setLeaseExpiryAction(String leaseExpiryAction) {
this.leaseExpiryAction = leaseExpiryAction;
}

public Date getLeaseExpiryDate() {
return leaseExpiryDate;
}

public void setLeaseExpiryDate(Date leaseExpiryDate) {
this.leaseExpiryDate = leaseExpiryDate;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,19 @@ public void testIsPurgeResourcesTrue() {
ReflectionTestUtils.setField(createServiceOfferingCmd, "purgeResources", true);
Assert.assertTrue(createServiceOfferingCmd.isPurgeResources());
}

@Test
public void testGetLeaseDuration() {
ReflectionTestUtils.setField(createServiceOfferingCmd, "leaseDuration", 10L);
Assert.assertEquals(10, createServiceOfferingCmd.getLeaseDuration().longValue());
}

@Test
public void testGetLeaseExpiryAction() {
ReflectionTestUtils.setField(createServiceOfferingCmd, "leaseExpiryAction", "stop");
Assert.assertEquals("stop", createServiceOfferingCmd.getLeaseExpiryAction());

ReflectionTestUtils.setField(createServiceOfferingCmd, "leaseExpiryAction", "DESTROY");
Assert.assertEquals("DESTROY", createServiceOfferingCmd.getLeaseExpiryAction());
}
}
Loading
Loading