Skip to content

Commit 4730e59

Browse files
author
Pearl Dsilva
committed
Merge branch 'main' of https://github.com/apache/cloudstack into clvm-enhancements
2 parents f6a82ee + 6b831f5 commit 4730e59

57 files changed

Lines changed: 2931 additions & 470 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.asf.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ github:
5151

5252
collaborators:
5353
- ingox
54-
- gpordeus
54+
- gp-santos
5555
- erikbocks
5656
- Imvedansh
5757
- Damans227

.github/workflows/merge-conflict-checker.yml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,14 @@
1717

1818
name: "PR Merge Conflict Check"
1919
on:
20-
push:
21-
pull_request:
22-
types: [opened, synchronize, reopened]
20+
schedule:
21+
- cron: '*/10 * * * *'
22+
workflow_dispatch:
2323

24-
permissions: # added using https://github.com/step-security/secure-workflows
25-
contents: read
24+
permissions: {}
2625

2726
concurrency:
28-
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
29-
cancel-in-progress: true
27+
group: "gh-aw-${{ github.workflow }}"
3028

3129
jobs:
3230
triage:

api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class VirtualMachineTO {
5151

5252
private long minRam;
5353
private long maxRam;
54+
private long requestedRam;
5455
private String hostName;
5556
private String arch;
5657
private String os;
@@ -207,15 +208,20 @@ public long getMinRam() {
207208
return minRam;
208209
}
209210

210-
public void setRam(long minRam, long maxRam) {
211+
public void setRam(long minRam, long maxRam, long requestedRam) {
211212
this.minRam = minRam;
212213
this.maxRam = maxRam;
214+
this.requestedRam = requestedRam;
213215
}
214216

215217
public long getMaxRam() {
216218
return maxRam;
217219
}
218220

221+
public long getRequestedRam() {
222+
return requestedRam;
223+
}
224+
219225
public String getHostName() {
220226
return hostName;
221227
}

api/src/main/java/org/apache/cloudstack/api/command/admin/ca/ProvisionCertificateCmd.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ public class ProvisionCertificateCmd extends BaseAsyncCmd {
6363
description = "Name of the CA service provider, otherwise the default configured provider plugin will be used")
6464
private String provider;
6565

66+
@Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN,
67+
description = "When true, uses SSH to re-provision the agent's certificate, bypassing the NIO agent connection. " +
68+
"Use this when agents are disconnected due to a CA change. Supported for KVM hosts and SystemVMs. Default is false",
69+
since = "4.23.0")
70+
private Boolean forced;
71+
6672
/////////////////////////////////////////////////////
6773
/////////////////// Accessors ///////////////////////
6874
/////////////////////////////////////////////////////
@@ -79,6 +85,10 @@ public String getProvider() {
7985
return provider;
8086
}
8187

88+
public boolean isForced() {
89+
return forced != null && forced;
90+
}
91+
8292
/////////////////////////////////////////////////////
8393
/////////////// API Implementation///////////////////
8494
/////////////////////////////////////////////////////
@@ -90,7 +100,7 @@ public void execute() {
90100
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to find host by ID: " + getHostId());
91101
}
92102

93-
boolean result = caManager.provisionCertificate(host, getReconnect(), getProvider());
103+
boolean result = caManager.provisionCertificate(host, getReconnect(), getProvider(), isForced());
94104
SuccessResponse response = new SuccessResponse(getCommandName());
95105
response.setSuccess(result);
96106
setResponseObject(response);

api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import org.apache.cloudstack.api.BaseCmd;
2323
import org.apache.cloudstack.api.Parameter;
2424
import org.apache.cloudstack.api.response.UserResponse;
25-
25+
import org.apache.cloudstack.api.ApiArgValidator;
2626
import com.cloud.exception.InvalidParameterValueException;
2727
import com.cloud.user.UserAccount;
2828

@@ -35,7 +35,7 @@ public class GetUserCmd extends BaseCmd {
3535
//////////////// API parameters /////////////////////
3636
/////////////////////////////////////////////////////
3737

38-
@Parameter(name = ApiConstants.USER_API_KEY, type = CommandType.STRING, required = true, description = "API key of the user")
38+
@Parameter(name = ApiConstants.USER_API_KEY, type = CommandType.STRING, required = true, description = "API key of the user", validations = {ApiArgValidator.NotNullOrEmpty})
3939
private String apiKey;
4040

4141
/////////////////////////////////////////////////////

api/src/main/java/org/apache/cloudstack/ca/CAManager.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import java.util.List;
2424
import java.util.Map;
2525

26+
import com.trilead.ssh2.Connection;
27+
2628
import org.apache.cloudstack.framework.ca.CAProvider;
2729
import org.apache.cloudstack.framework.ca.CAService;
2830
import org.apache.cloudstack.framework.ca.Certificate;
@@ -39,7 +41,10 @@ public interface CAManager extends CAService, Configurable, PluggableService {
3941
ConfigKey<String> CAProviderPlugin = new ConfigKey<>("Advanced", String.class,
4042
"ca.framework.provider.plugin",
4143
"root",
42-
"The CA provider plugin that is used for secure CloudStack management server-agent communication for encryption and authentication. Restart management server(s) when changed.", true);
44+
"The CA provider plugin used for CloudStack internal certificate management (MS-agent encryption and authentication). " +
45+
"The default 'root' provider auto-generates a CA on first startup, but also supports user-provided custom CA material " +
46+
"via the ca.plugin.root.private.key, ca.plugin.root.public.key, and ca.plugin.root.ca.certificate settings. " +
47+
"Restart management server(s) when changed.", false);
4348

4449
ConfigKey<Integer> CertKeySize = new ConfigKey<>("Advanced", Integer.class,
4550
"ca.framework.cert.keysize",
@@ -85,6 +90,12 @@ public interface CAManager extends CAService, Configurable, PluggableService {
8590
"The actual implementation will depend on the configured CA provider.",
8691
false);
8792

93+
ConfigKey<Boolean> CaInjectDefaultTruststore = new ConfigKey<>("Advanced", Boolean.class,
94+
"ca.framework.inject.default.truststore", "true",
95+
"When true, injects the CA provider's certificate into the JVM default truststore on management server startup. " +
96+
"This allows outgoing HTTPS connections from the management server to trust servers with certificates signed by the configured CA. " +
97+
"Restart management server(s) when changed.", false);
98+
8899
/**
89100
* Returns a list of available CA provider plugins
90101
* @return returns list of CAProvider
@@ -130,12 +141,26 @@ public interface CAManager extends CAService, Configurable, PluggableService {
130141
boolean revokeCertificate(final BigInteger certSerial, final String certCn, final String provider);
131142

132143
/**
133-
* Provisions certificate for given active and connected agent host
144+
* Provisions certificate for given agent host.
145+
* When forced=true, uses SSH to re-provision bypassing the NIO agent connection (for disconnected agents).
134146
* @param host
147+
* @param reconnect
135148
* @param provider
149+
* @param forced when true, provisions via SSH instead of NIO; supports KVM hosts and SystemVMs
136150
* @return returns success/failure as boolean
137151
*/
138-
boolean provisionCertificate(final Host host, final Boolean reconnect, final String provider);
152+
boolean provisionCertificate(final Host host, final Boolean reconnect, final String provider, final boolean forced);
153+
154+
/**
155+
* Provisions certificate for a KVM host using an existing SSH connection.
156+
* Runs keystore-setup to generate a CSR, issues a certificate, then runs keystore-cert-import.
157+
* Used during host discovery and for forced re-provisioning when the NIO agent is unreachable.
158+
* @param sshConnection active SSH connection to the KVM host
159+
* @param agentIp IP address of the KVM host agent
160+
* @param agentHostname hostname of the KVM host agent
161+
* @param caProvider optional CA provider plugin name (null uses default)
162+
*/
163+
void provisionCertificateViaSsh(Connection sshConnection, String agentIp, String agentHostname, String caProvider);
139164

140165
/**
141166
* Setups up a new keystore and generates CSR for a host

core/src/main/java/com/cloud/agent/api/ScaleVmCommand.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class ScaleVmCommand extends Command {
3030
Integer maxSpeed;
3131
long minRam;
3232
long maxRam;
33+
private boolean limitCpuUseChange;
3334

3435
public VirtualMachineTO getVm() {
3536
return vm;
@@ -43,7 +44,7 @@ public int getCpus() {
4344
return cpus;
4445
}
4546

46-
public ScaleVmCommand(String vmName, int cpus, Integer minSpeed, Integer maxSpeed, long minRam, long maxRam, boolean limitCpuUse) {
47+
public ScaleVmCommand(String vmName, int cpus, Integer minSpeed, Integer maxSpeed, long minRam, long maxRam, boolean limitCpuUse, Double cpuQuotaPercentage, boolean limitCpuUseChange) {
4748
super();
4849
this.vmName = vmName;
4950
this.cpus = cpus;
@@ -52,6 +53,8 @@ public ScaleVmCommand(String vmName, int cpus, Integer minSpeed, Integer maxSpee
5253
this.minRam = minRam;
5354
this.maxRam = maxRam;
5455
this.vm = new VirtualMachineTO(1L, vmName, null, cpus, minSpeed, maxSpeed, minRam, maxRam, null, null, false, limitCpuUse, null);
56+
this.vm.setCpuQuotaPercentage(cpuQuotaPercentage);
57+
this.limitCpuUseChange = limitCpuUseChange;
5558
}
5659

5760
public void setCpus(int cpus) {
@@ -102,6 +105,10 @@ public VirtualMachineTO getVirtualMachine() {
102105
return vm;
103106
}
104107

108+
public boolean getLimitCpuUseChange() {
109+
return limitCpuUseChange;
110+
}
111+
105112
@Override
106113
public boolean executeInSequence() {
107114
return true;

engine/components-api/src/main/java/com/cloud/capacity/CapacityManager.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,20 @@ public interface CapacityManager {
133133
"capacity.calculate.workers", "1",
134134
"Number of worker threads to be used for capacities calculation", true);
135135

136+
ConfigKey<Integer> KvmMemoryDynamicScalingCapacity = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED,
137+
Integer.class, "kvm.memory.dynamic.scaling.capacity", "0",
138+
"Defines the maximum memory capacity in MiB for which VMs can be dynamically scaled to with KVM. " +
139+
"The 'kvm.memory.dynamic.scaling.capacity' setting's value will be used to define the value of the " +
140+
"'<maxMemory />' element of domain XMLs. If it is set to a value less than or equal to '0', then the host's memory capacity will be considered.",
141+
true, ConfigKey.Scope.Cluster);
142+
143+
ConfigKey<Integer> KvmCpuDynamicScalingCapacity = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED,
144+
Integer.class, "kvm.cpu.dynamic.scaling.capacity", "0",
145+
"Defines the maximum vCPU capacity for which VMs can be dynamically scaled to with KVM. " +
146+
"The 'kvm.cpu.dynamic.scaling.capacity' setting's value will be used to define the value of the " +
147+
"'<vcpu />' element of domain XMLs. If it is set to a value less than or equal to '0', then the host's CPU cores capacity will be considered.",
148+
true, ConfigKey.Scope.Cluster);
149+
136150
public boolean releaseVmCapacity(VirtualMachine vm, boolean moveFromReserved, boolean moveToReservered, Long hostId);
137151

138152
void allocateVmCapacity(VirtualMachine vm, boolean fromLastHost);

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252

5353
import com.cloud.agent.api.PostMigrationCommand;
5454
import com.cloud.storage.clvm.ClvmPoolManager;
55+
import com.cloud.hypervisor.KVMGuru;
5556
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
5657
import org.apache.cloudstack.annotation.AnnotationService;
5758
import org.apache.cloudstack.annotation.dao.AnnotationDao;
@@ -5228,7 +5229,7 @@ public VMInstanceVO reConfigureVm(final String vmUuid, final ServiceOffering old
52285229
try {
52295230
result = retrieveResultFromJobOutcomeAndThrowExceptionIfNeeded(outcome);
52305231
} catch (Exception ex) {
5231-
throw new RuntimeException("Unhandled exception", ex);
5232+
throw new RuntimeException("Unable to reconfigure VM.", ex);
52325233
}
52335234

52345235
if (result != null) {
@@ -5241,22 +5242,29 @@ public VMInstanceVO reConfigureVm(final String vmUuid, final ServiceOffering old
52415242

52425243
private VMInstanceVO orchestrateReConfigureVm(String vmUuid, ServiceOffering oldServiceOffering, ServiceOffering newServiceOffering,
52435244
boolean reconfiguringOnExistingHost) throws ResourceUnavailableException, ConcurrentOperationException {
5244-
final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
5245+
VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
52455246

52465247
HostVO hostVo = _hostDao.findById(vm.getHostId());
52475248

5248-
Long clustedId = hostVo.getClusterId();
5249-
Float memoryOvercommitRatio = CapacityManager.MemOverprovisioningFactor.valueIn(clustedId);
5250-
Float cpuOvercommitRatio = CapacityManager.CpuOverprovisioningFactor.valueIn(clustedId);
5251-
boolean divideMemoryByOverprovisioning = HypervisorGuruBase.VmMinMemoryEqualsMemoryDividedByMemOverprovisioningFactor.valueIn(clustedId);
5252-
boolean divideCpuByOverprovisioning = HypervisorGuruBase.VmMinCpuSpeedEqualsCpuSpeedDividedByCpuOverprovisioningFactor.valueIn(clustedId);
5249+
Long clusterId = hostVo.getClusterId();
5250+
Float memoryOvercommitRatio = CapacityManager.MemOverprovisioningFactor.valueIn(clusterId);
5251+
Float cpuOvercommitRatio = CapacityManager.CpuOverprovisioningFactor.valueIn(clusterId);
5252+
boolean divideMemoryByOverprovisioning = HypervisorGuruBase.VmMinMemoryEqualsMemoryDividedByMemOverprovisioningFactor.valueIn(clusterId);
5253+
boolean divideCpuByOverprovisioning = HypervisorGuruBase.VmMinCpuSpeedEqualsCpuSpeedDividedByCpuOverprovisioningFactor.valueIn(clusterId);
52535254

52545255
int minMemory = (int)(newServiceOffering.getRamSize() / (divideMemoryByOverprovisioning ? memoryOvercommitRatio : 1));
52555256
int minSpeed = (int)(newServiceOffering.getSpeed() / (divideCpuByOverprovisioning ? cpuOvercommitRatio : 1));
52565257

5257-
ScaleVmCommand scaleVmCommand =
5258-
new ScaleVmCommand(vm.getInstanceName(), newServiceOffering.getCpu(), minSpeed,
5259-
newServiceOffering.getSpeed(), minMemory * 1024L * 1024L, newServiceOffering.getRamSize() * 1024L * 1024L, newServiceOffering.getLimitCpuUse());
5258+
Double cpuQuotaPercentage = null;
5259+
if (newServiceOffering.getLimitCpuUse() && vm.getHypervisorType().equals(HypervisorType.KVM)) {
5260+
KVMGuru kvmGuru = (KVMGuru) _hvGuruMgr.getGuru(vm.getHypervisorType());
5261+
cpuQuotaPercentage = kvmGuru.getCpuQuotaPercentage(minSpeed, hostVo.getSpeed());
5262+
}
5263+
5264+
boolean limitCpuUseChange = oldServiceOffering.getLimitCpuUse() != newServiceOffering.getLimitCpuUse();
5265+
ScaleVmCommand scaleVmCommand = new ScaleVmCommand(vm.getInstanceName(), newServiceOffering.getCpu(), minSpeed, newServiceOffering.getSpeed(),
5266+
minMemory * 1024L * 1024L, newServiceOffering.getRamSize() * 1024L * 1024L,
5267+
newServiceOffering.getLimitCpuUse(), cpuQuotaPercentage, limitCpuUseChange);
52605268

52615269
scaleVmCommand.getVirtualMachine().setId(vm.getId());
52625270
scaleVmCommand.getVirtualMachine().setUuid(vm.getUuid());
@@ -5285,16 +5293,20 @@ private VMInstanceVO orchestrateReConfigureVm(String vmUuid, ServiceOffering old
52855293
throw new CloudRuntimeException("Unable to scale vm due to " + (reconfigureAnswer == null ? "" : reconfigureAnswer.getDetails()));
52865294
}
52875295

5288-
upgradeVmDb(vm.getId(), newServiceOffering, oldServiceOffering);
5296+
if (reconfiguringOnExistingHost) {
5297+
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId());
5298+
}
5299+
5300+
boolean vmUpgraded = upgradeVmDb(vm.getId(), newServiceOffering, oldServiceOffering);
5301+
if (vmUpgraded) {
5302+
vm = _vmDao.findById(vm.getId());
5303+
}
52895304

52905305
if (vm.getType().equals(VirtualMachine.Type.User)) {
52915306
_userVmMgr.generateUsageEvent(vm, vm.isDisplayVm(), EventTypes.EVENT_VM_DYNAMIC_SCALE);
52925307
}
52935308

52945309
if (reconfiguringOnExistingHost) {
5295-
vm.setServiceOfferingId(oldServiceOffering.getId());
5296-
_capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId());
5297-
vm.setServiceOfferingId(newServiceOffering.getId());
52985310
_capacityMgr.allocateVmCapacity(vm, false);
52995311
}
53005312

engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ protected void updateRegisteredTemplateDetails(Long templateId, MetadataTemplate
10731073
}
10741074
Hypervisor.HypervisorType hypervisorType = templateDetails.getHypervisorType();
10751075
updateSystemVMEntries(templateId, hypervisorType);
1076-
updateConfigurationParams(hypervisorType, templateDetails.getName(), zoneId);
1076+
updateConfigurationParams(hypervisorType, templateVO.getName(), zoneId);
10771077
}
10781078

10791079
protected void updateTemplateUrlChecksumAndGuestOsId(VMTemplateVO templateVO,

0 commit comments

Comments
 (0)