Merge remote-tracking branch 'origin/main' into testing
This commit is contained in:
commit
5897b4b386
6 changed files with 67 additions and 5 deletions
|
|
@ -1019,6 +1019,11 @@ spec:
|
||||||
- accessConsole
|
- accessConsole
|
||||||
- "*"
|
- "*"
|
||||||
default: []
|
default: []
|
||||||
|
loggingProperties:
|
||||||
|
type: string
|
||||||
|
description: >-
|
||||||
|
Override the default logging properties for
|
||||||
|
the runner for this VM.
|
||||||
vm:
|
vm:
|
||||||
type: object
|
type: object
|
||||||
description: Defines the VM.
|
description: Defines the VM.
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,18 @@
|
||||||
metallb.universe.tf/loadBalancerIPs: 192.168.168.1
|
metallb.universe.tf/loadBalancerIPs: 192.168.168.1
|
||||||
metallb.universe.tf/ip-allocated-from-pool: single-common
|
metallb.universe.tf/ip-allocated-from-pool: single-common
|
||||||
metallb.universe.tf/allow-shared-ip: single-common
|
metallb.universe.tf/allow-shared-ip: single-common
|
||||||
|
loggingProperties: |
|
||||||
|
# Defaults for namespace (VM domain)
|
||||||
|
handlers=java.util.logging.ConsoleHandler
|
||||||
|
|
||||||
|
#org.jgrapes.level=FINE
|
||||||
|
#org.jgrapes.core.handlerTracking.level=FINER
|
||||||
|
|
||||||
|
org.jdrupes.vmoperator.runner.qemu.level=FINEST
|
||||||
|
|
||||||
|
java.util.logging.ConsoleHandler.level=ALL
|
||||||
|
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||||
|
java.util.logging.SimpleFormatter.format=%1$tb %1$td %1$tT %4$s %5$s%6$s%n
|
||||||
"/GuiSocketServer":
|
"/GuiSocketServer":
|
||||||
port: 8888
|
port: 8888
|
||||||
"/GuiHttpServer":
|
"/GuiHttpServer":
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.jdrupes.vmoperator.manager;
|
package org.jdrupes.vmoperator.manager;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
import freemarker.template.TemplateException;
|
import freemarker.template.TemplateException;
|
||||||
import io.kubernetes.client.custom.V1Patch;
|
import io.kubernetes.client.custom.V1Patch;
|
||||||
|
|
@ -36,6 +37,8 @@ import org.jdrupes.vmoperator.common.K8s;
|
||||||
import static org.jdrupes.vmoperator.manager.Constants.APP_NAME;
|
import static org.jdrupes.vmoperator.manager.Constants.APP_NAME;
|
||||||
import static org.jdrupes.vmoperator.manager.Constants.VM_OP_NAME;
|
import static org.jdrupes.vmoperator.manager.Constants.VM_OP_NAME;
|
||||||
import org.jdrupes.vmoperator.manager.events.VmChannel;
|
import org.jdrupes.vmoperator.manager.events.VmChannel;
|
||||||
|
import org.jdrupes.vmoperator.util.DataPath;
|
||||||
|
import org.jdrupes.vmoperator.util.GsonPtr;
|
||||||
import org.yaml.snakeyaml.LoaderOptions;
|
import org.yaml.snakeyaml.LoaderOptions;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
import org.yaml.snakeyaml.constructor.SafeConstructor;
|
import org.yaml.snakeyaml.constructor.SafeConstructor;
|
||||||
|
|
@ -71,10 +74,6 @@ import org.yaml.snakeyaml.constructor.SafeConstructor;
|
||||||
public Map<String, Object> reconcile(Map<String, Object> model,
|
public Map<String, Object> reconcile(Map<String, Object> model,
|
||||||
VmChannel channel)
|
VmChannel channel)
|
||||||
throws IOException, TemplateException, ApiException {
|
throws IOException, TemplateException, ApiException {
|
||||||
// Get API
|
|
||||||
DynamicKubernetesApi cmApi = new DynamicKubernetesApi("", "v1",
|
|
||||||
"configmaps", channel.client());
|
|
||||||
|
|
||||||
// Combine template and data and parse result
|
// Combine template and data and parse result
|
||||||
var fmTemplate = fmConfig.getTemplate("runnerConfig.ftl.yaml");
|
var fmTemplate = fmConfig.getTemplate("runnerConfig.ftl.yaml");
|
||||||
StringWriter out = new StringWriter();
|
StringWriter out = new StringWriter();
|
||||||
|
|
@ -84,8 +83,26 @@ import org.yaml.snakeyaml.constructor.SafeConstructor;
|
||||||
var mapDef = Dynamics.newFromYaml(
|
var mapDef = Dynamics.newFromYaml(
|
||||||
new Yaml(new SafeConstructor(new LoaderOptions())), out.toString());
|
new Yaml(new SafeConstructor(new LoaderOptions())), out.toString());
|
||||||
|
|
||||||
|
// Maybe override logging.properties from reconciler configuration.
|
||||||
|
DataPath.<String> get(model, "reconciler", "loggingProperties")
|
||||||
|
.ifPresent(props -> {
|
||||||
|
GsonPtr.to(mapDef.getRaw()).get(JsonObject.class, "data")
|
||||||
|
.get().addProperty("logging.properties", props);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Maybe override logging.properties from VM definition.
|
||||||
|
DataPath.<String> get(model, "cr", "spec", "loggingProperties")
|
||||||
|
.ifPresent(props -> {
|
||||||
|
GsonPtr.to(mapDef.getRaw()).get(JsonObject.class, "data")
|
||||||
|
.get().addProperty("logging.properties", props);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get API
|
||||||
|
DynamicKubernetesApi cmApi = new DynamicKubernetesApi("", "v1",
|
||||||
|
"configmaps", channel.client());
|
||||||
|
|
||||||
// Apply and maybe force pod update
|
// Apply and maybe force pod update
|
||||||
var newState = K8s.apply(cmApi, mapDef, out.toString());
|
var newState = K8s.apply(cmApi, mapDef, mapDef.getRaw().toString());
|
||||||
maybeForceUpdate(channel.client(), newState);
|
maybeForceUpdate(channel.client(), newState);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
var res = (Map<String, Object>) channel.client().getJSON().getGson()
|
var res = (Map<String, Object>) channel.client().getJSON().getGson()
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,11 @@ import org.jgrapes.util.events.ConfigurationUpdate;
|
||||||
* ```
|
* ```
|
||||||
* This makes all VM consoles available at IP address 192.168.168.1
|
* This makes all VM consoles available at IP address 192.168.168.1
|
||||||
* with the port numbers from the VM definitions.
|
* with the port numbers from the VM definitions.
|
||||||
|
*
|
||||||
|
* * `loggingProperties`: If defined, specifies the default logging
|
||||||
|
* properties to be used by the runners managed by the controller.
|
||||||
|
* This property is a string that holds the content of
|
||||||
|
* a logging.properties file.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "PMD.DataflowAnomalyAnalysis",
|
@SuppressWarnings({ "PMD.DataflowAnomalyAnalysis",
|
||||||
"PMD.AvoidDuplicateLiterals" })
|
"PMD.AvoidDuplicateLiterals" })
|
||||||
|
|
|
||||||
|
|
@ -69,4 +69,9 @@ class CommandDefinition {
|
||||||
public String name() {
|
public String name() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Command " + name + ": " + command;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -48,6 +48,8 @@ import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.LogManager;
|
import java.util.logging.LogManager;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
import org.apache.commons.cli.CommandLineParser;
|
||||||
import org.apache.commons.cli.DefaultParser;
|
import org.apache.commons.cli.DefaultParser;
|
||||||
|
|
@ -318,6 +320,7 @@ public class Runner extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("PMD.LambdaCanBeMethodReference")
|
||||||
private void processInitialConfiguration(Configuration newConfig) {
|
private void processInitialConfiguration(Configuration newConfig) {
|
||||||
try {
|
try {
|
||||||
config = newConfig;
|
config = newConfig;
|
||||||
|
|
@ -333,12 +336,15 @@ public class Runner extends Component {
|
||||||
var tplData = dataFromTemplate();
|
var tplData = dataFromTemplate();
|
||||||
swtpmDefinition = Optional.ofNullable(tplData.get(SWTPM))
|
swtpmDefinition = Optional.ofNullable(tplData.get(SWTPM))
|
||||||
.map(d -> new CommandDefinition(SWTPM, d)).orElse(null);
|
.map(d -> new CommandDefinition(SWTPM, d)).orElse(null);
|
||||||
|
logger.finest(() -> swtpmDefinition.toString());
|
||||||
qemuDefinition = Optional.ofNullable(tplData.get(QEMU))
|
qemuDefinition = Optional.ofNullable(tplData.get(QEMU))
|
||||||
.map(d -> new CommandDefinition(QEMU, d)).orElse(null);
|
.map(d -> new CommandDefinition(QEMU, d)).orElse(null);
|
||||||
|
logger.finest(() -> qemuDefinition.toString());
|
||||||
cloudInitImgDefinition
|
cloudInitImgDefinition
|
||||||
= Optional.ofNullable(tplData.get(CLOUD_INIT_IMG))
|
= Optional.ofNullable(tplData.get(CLOUD_INIT_IMG))
|
||||||
.map(d -> new CommandDefinition(CLOUD_INIT_IMG, d))
|
.map(d -> new CommandDefinition(CLOUD_INIT_IMG, d))
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
logger.finest(() -> cloudInitImgDefinition.toString());
|
||||||
|
|
||||||
// Forward some values to child components
|
// Forward some values to child components
|
||||||
qemuMonitor.configure(config.monitorSocket,
|
qemuMonitor.configure(config.monitorSocket,
|
||||||
|
|
@ -364,6 +370,12 @@ public class Runner extends Component {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (codePaths.iterator().hasNext() && config.firmwareRom == null) {
|
||||||
|
throw new IllegalArgumentException("No ROM found, candidates were: "
|
||||||
|
+ StreamSupport.stream(codePaths.spliterator(), false)
|
||||||
|
.map(JsonNode::asText).collect(Collectors.joining(", ")));
|
||||||
|
}
|
||||||
|
|
||||||
// Get file for firmware vars, if necessary
|
// Get file for firmware vars, if necessary
|
||||||
config.firmwareVars = config.dataDir.resolve(FW_VARS);
|
config.firmwareVars = config.dataDir.resolve(FW_VARS);
|
||||||
if (!Files.exists(config.firmwareVars)) {
|
if (!Files.exists(config.firmwareVars)) {
|
||||||
|
|
@ -405,12 +417,14 @@ public class Runner extends Component {
|
||||||
model.put("hasDisplayPassword", config.hasDisplayPassword);
|
model.put("hasDisplayPassword", config.hasDisplayPassword);
|
||||||
model.put("cloudInit", config.cloudInit);
|
model.put("cloudInit", config.cloudInit);
|
||||||
model.put("vm", config.vm);
|
model.put("vm", config.vm);
|
||||||
|
logger.finest(() -> "Processing template with model: " + model);
|
||||||
|
|
||||||
// Combine template and data and parse result
|
// Combine template and data and parse result
|
||||||
// (tempting, but no need to use a pipe here)
|
// (tempting, but no need to use a pipe here)
|
||||||
var fmTemplate = fmConfig.getTemplate(templatePath.toString());
|
var fmTemplate = fmConfig.getTemplate(templatePath.toString());
|
||||||
StringWriter out = new StringWriter();
|
StringWriter out = new StringWriter();
|
||||||
fmTemplate.process(model, out);
|
fmTemplate.process(model, out);
|
||||||
|
logger.finest(() -> "Result of processing template: " + out);
|
||||||
return yamlMapper.readValue(out.toString(), JsonNode.class);
|
return yamlMapper.readValue(out.toString(), JsonNode.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -746,6 +760,10 @@ public class Runner extends Component {
|
||||||
props = Runner.class.getResourceAsStream("logging.properties");
|
props = Runner.class.getResourceAsStream("logging.properties");
|
||||||
}
|
}
|
||||||
LogManager.getLogManager().readConfiguration(props);
|
LogManager.getLogManager().readConfiguration(props);
|
||||||
|
Logger.getLogger(Runner.class.getName()).log(Level.CONFIG,
|
||||||
|
() -> path.isPresent()
|
||||||
|
? "Using logging configuration from " + path.get()
|
||||||
|
: "Using default logging configuration");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue