Report current CPUs in status.
This commit is contained in:
parent
7f512082f0
commit
8a7d9d6621
3 changed files with 86 additions and 27 deletions
|
|
@ -19,8 +19,8 @@
|
||||||
package org.jdrupes.vmoperator.runner.qemu;
|
package org.jdrupes.vmoperator.runner.qemu;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -81,34 +81,28 @@ public class CpuController extends Component {
|
||||||
/**
|
/**
|
||||||
* On monitor result.
|
* On monitor result.
|
||||||
*
|
*
|
||||||
* @param result the result
|
* @param event the result
|
||||||
*/
|
*/
|
||||||
@Handler
|
@Handler
|
||||||
public void onHotpluggableCpuStatus(HotpluggableCpuStatus result) {
|
public void onHotpluggableCpuStatus(HotpluggableCpuStatus event) {
|
||||||
if (!result.successful()) {
|
if (!event.successful()) {
|
||||||
logger.warning(() -> "Failed to get hotpluggable CPU status "
|
logger.warning(() -> "Failed to get hotpluggable CPU status "
|
||||||
+ "(won't adjust number of CPUs.): " + result.errorMessage());
|
+ "(won't adjust number of CPUs.): " + event.errorMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort
|
|
||||||
List<ObjectNode> used = new ArrayList<>();
|
|
||||||
List<ObjectNode> unused = new ArrayList<>();
|
|
||||||
for (var itr = result.values().iterator(); itr.hasNext();) {
|
|
||||||
ObjectNode cpu = (ObjectNode) itr.next();
|
|
||||||
if (cpu.has("qom-path")) {
|
|
||||||
used.add(cpu);
|
|
||||||
} else {
|
|
||||||
unused.add(cpu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentCpus = used.size();
|
|
||||||
if (desiredCpus == null) {
|
if (desiredCpus == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Process
|
// Process
|
||||||
int diff = used.size() - desiredCpus;
|
currentCpus = event.usedCpus().size();
|
||||||
diff = addCpus(used, unused, diff);
|
int diff = currentCpus - desiredCpus;
|
||||||
deleteCpus(used, diff);
|
if (diff == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
diff = addCpus(event.usedCpus(), event.unusedCpus(), diff);
|
||||||
|
removeCpus(event.usedCpus(), diff);
|
||||||
|
|
||||||
|
// Report result
|
||||||
|
fire(new MonitorCommand(new QmpQueryHotpluggableCpus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
|
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
|
||||||
|
|
@ -123,22 +117,24 @@ public class CpuController extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int nextId = 1;
|
int nextId = 1;
|
||||||
while (diff < 0 && !unused.isEmpty()) {
|
List<ObjectNode> remaining = new LinkedList<>(unused);
|
||||||
|
while (diff < 0 && !remaining.isEmpty()) {
|
||||||
String id;
|
String id;
|
||||||
do {
|
do {
|
||||||
id = "cpu-" + nextId++;
|
id = "cpu-" + nextId++;
|
||||||
} while (usedIds.contains(id));
|
} while (usedIds.contains(id));
|
||||||
fire(new MonitorCommand(new QmpAddCpu(unused.get(0), id)));
|
fire(new MonitorCommand(new QmpAddCpu(remaining.get(0), id)));
|
||||||
unused.remove(0);
|
remaining.remove(0);
|
||||||
diff += 1;
|
diff += 1;
|
||||||
}
|
}
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
|
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
|
||||||
private int deleteCpus(List<ObjectNode> used, int diff) {
|
private int removeCpus(List<ObjectNode> used, int diff) {
|
||||||
while (diff > 0 && !used.isEmpty()) {
|
List<ObjectNode> removable = new LinkedList<>(used);
|
||||||
ObjectNode cpu = used.remove(0);
|
while (diff > 0 && !removable.isEmpty()) {
|
||||||
|
ObjectNode cpu = removable.remove(0);
|
||||||
String qomPath = cpu.get("qom-path").asText();
|
String qomPath = cpu.get("qom-path").asText();
|
||||||
if (!qomPath.startsWith("/machine/peripheral/cpu-")) {
|
if (!qomPath.startsWith("/machine/peripheral/cpu-")) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.jdrupes.vmoperator.runner.qemu.events.BalloonChangeEvent;
|
import org.jdrupes.vmoperator.runner.qemu.events.BalloonChangeEvent;
|
||||||
|
import org.jdrupes.vmoperator.runner.qemu.events.HotpluggableCpuStatus;
|
||||||
import org.jdrupes.vmoperator.runner.qemu.events.RunnerConfigurationUpdate;
|
import org.jdrupes.vmoperator.runner.qemu.events.RunnerConfigurationUpdate;
|
||||||
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange;
|
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange;
|
||||||
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange.State;
|
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange.State;
|
||||||
|
|
@ -223,8 +224,10 @@ public class StatusUpdater extends Component {
|
||||||
if (event.state() == State.STARTING) {
|
if (event.state() == State.STARTING) {
|
||||||
status.addProperty("ram", GsonPtr.to(from.getRaw())
|
status.addProperty("ram", GsonPtr.to(from.getRaw())
|
||||||
.getAsString("spec", "vm", "maximumRam").orElse("0"));
|
.getAsString("spec", "vm", "maximumRam").orElse("0"));
|
||||||
|
status.addProperty("cpus", 1);
|
||||||
} else if (event.state() == State.STOPPED) {
|
} else if (event.state() == State.STOPPED) {
|
||||||
status.addProperty("ram", "0");
|
status.addProperty("ram", "0");
|
||||||
|
status.addProperty("cpus", 0);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
});
|
});
|
||||||
|
|
@ -273,4 +276,24 @@ public class StatusUpdater extends Component {
|
||||||
return status;
|
return status;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On ballon change.
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
* @throws ApiException
|
||||||
|
*/
|
||||||
|
@Handler
|
||||||
|
public void onCpuChange(HotpluggableCpuStatus event) throws ApiException {
|
||||||
|
if (vmCrApi == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var vmCr
|
||||||
|
= vmCrApi.get(namespace, vmName).throwsApiException().getObject();
|
||||||
|
vmCrApi.updateStatus(vmCr, from -> {
|
||||||
|
JsonObject status = currentStatus(from);
|
||||||
|
status.addProperty("cpus", event.usedCpus().size());
|
||||||
|
return status;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@
|
||||||
package org.jdrupes.vmoperator.runner.qemu.events;
|
package org.jdrupes.vmoperator.runner.qemu.events;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import org.jdrupes.vmoperator.runner.qemu.commands.QmpCommand;
|
import org.jdrupes.vmoperator.runner.qemu.commands.QmpCommand;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -26,6 +30,9 @@ import org.jdrupes.vmoperator.runner.qemu.commands.QmpCommand;
|
||||||
*/
|
*/
|
||||||
public class HotpluggableCpuStatus extends MonitorResult {
|
public class HotpluggableCpuStatus extends MonitorResult {
|
||||||
|
|
||||||
|
private List<ObjectNode> usedCpus = new ArrayList<>();
|
||||||
|
private List<ObjectNode> unusedCpus = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new hotpluggable cpu result.
|
* Instantiates a new hotpluggable cpu result.
|
||||||
*
|
*
|
||||||
|
|
@ -34,6 +41,39 @@ public class HotpluggableCpuStatus extends MonitorResult {
|
||||||
*/
|
*/
|
||||||
public HotpluggableCpuStatus(QmpCommand command, JsonNode response) {
|
public HotpluggableCpuStatus(QmpCommand command, JsonNode response) {
|
||||||
super(command, response);
|
super(command, response);
|
||||||
|
if (!successful()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort
|
||||||
|
for (var itr = values().iterator(); itr.hasNext();) {
|
||||||
|
ObjectNode cpu = (ObjectNode) itr.next();
|
||||||
|
if (cpu.has("qom-path")) {
|
||||||
|
usedCpus.add(cpu);
|
||||||
|
} else {
|
||||||
|
unusedCpus.add(cpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usedCpus = Collections.unmodifiableList(usedCpus);
|
||||||
|
unusedCpus = Collections.unmodifiableList(unusedCpus);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the used cpus.
|
||||||
|
*
|
||||||
|
* @return the usedCpus
|
||||||
|
*/
|
||||||
|
public List<ObjectNode> usedCpus() {
|
||||||
|
return usedCpus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the unused cpus.
|
||||||
|
*
|
||||||
|
* @return the unusedCpus
|
||||||
|
*/
|
||||||
|
public List<ObjectNode> unusedCpus() {
|
||||||
|
return unusedCpus;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue