From 599f64da4cac76e0316a80260bb904551219378d Mon Sep 17 00:00:00 2001 From: "Michael N. Lipp" Date: Sat, 17 Feb 2024 16:47:10 +0100 Subject: [PATCH] Provide fallback for instance-id. --- .../config-sample.yaml | 5 +++- .../vmoperator/runner/qemu/Configuration.java | 22 ++++++++++++++++ .../vmoperator/runner/qemu/Runner.java | 26 +++++++++---------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/org.jdrupes.vmoperator.runner.qemu/config-sample.yaml b/org.jdrupes.vmoperator.runner.qemu/config-sample.yaml index 34c1511..2211fed 100644 --- a/org.jdrupes.vmoperator.runner.qemu/config-sample.yaml +++ b/org.jdrupes.vmoperator.runner.qemu/config-sample.yaml @@ -33,7 +33,10 @@ # "metaData": # ... # "userData": - # ... + # ... + # + # If .metaData.instance-id is missing, an id is generated from the + # config file's modification timestamp. # Define the VM (required) "vm": diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Configuration.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Configuration.java index ff60176..ba36317 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Configuration.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Configuration.java @@ -24,6 +24,8 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermission; +import java.time.Instant; +import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -39,9 +41,14 @@ import org.jdrupes.vmoperator.util.FsdUtils; */ @SuppressWarnings("PMD.ExcessivePublicCount") public class Configuration implements Dto { + private static final String CI_INSTANCE_ID = "instance-id"; + @SuppressWarnings("PMD.FieldNamingConventions") protected final Logger logger = Logger.getLogger(getClass().getName()); + /** Configuration timestamp */ + public Instant asOf; + /** The data dir. */ public Path dataDir; @@ -259,6 +266,7 @@ public class Configuration implements Dto { } checkDrives(); + checkCloudInit(); return true; } @@ -372,4 +380,18 @@ public class Configuration implements Dto { return true; } + + private void checkCloudInit() { + if (cloudInit == null) { + return; + } + + // Provide default for instance-id + if (cloudInit.metaData == null) { + cloudInit.metaData = new HashMap<>(); + } + if (!cloudInit.metaData.containsKey(CI_INSTANCE_ID)) { + cloudInit.metaData.put(CI_INSTANCE_ID, "v" + asOf.getEpochSecond()); + } + } } \ No newline at end of file diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java index fe3784f..fccdf89 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java @@ -39,10 +39,10 @@ import java.lang.reflect.UndeclaredThrowableException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.Instant; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.logging.Level; @@ -200,6 +200,7 @@ public class Runner extends Component { .build()); private final JsonNode defaults; @SuppressWarnings("PMD.UseConcurrentHashMap") + private final File configFile; private Configuration config = new Configuration(); private final freemarker.template.Configuration fmConfig; private CommandDefinition swtpmDefinition; @@ -252,16 +253,16 @@ public class Runner extends Component { attach(qemuMonitor = new QemuMonitor(channel())); attach(new StatusUpdater(channel())); - // Configuration store with file in /etc/opt (default) - File config = new File(cmdLine.getOptionValue('c', + configFile = new File(cmdLine.getOptionValue('c', "/etc/opt/" + APP_NAME.replace("-", "") + "/config.yaml")); // Don't rely on night config to produce a good exception // for this simple case - if (!Files.isReadable(config.toPath())) { - throw new IOException("Cannot read configuration file " + config); + if (!Files.isReadable(configFile.toPath())) { + throw new IOException( + "Cannot read configuration file " + configFile); } - attach(new YamlConfigurationStore(channel(), config, false)); - fire(new WatchFile(config.toPath())); + attach(new YamlConfigurationStore(channel(), configFile, false)); + fire(new WatchFile(configFile.toPath())); } /** @@ -286,21 +287,20 @@ public class Runner extends Component { @Handler public void onConfigurationUpdate(ConfigurationUpdate event) { event.structured(componentPath()).ifPresent(c -> { + var newConf = yamlMapper.convertValue(c, Configuration.class); + newConf.asOf = Instant.ofEpochSecond(configFile.lastModified()); if (event instanceof InitialConfiguration) { - processInitialConfiguration(c); + processInitialConfiguration(newConf); return; } logger.fine(() -> "Updating configuration"); - var newConf = yamlMapper.convertValue(c, Configuration.class); rep.fire(new RunnerConfigurationUpdate(newConf, state)); }); } - private void processInitialConfiguration( - Map runnerConfiguration) { + private void processInitialConfiguration(Configuration newConfig) { try { - config = yamlMapper.convertValue(runnerConfiguration, - Configuration.class); + config = newConfig; if (!config.check()) { // Invalid configuration, not used, problems already logged. config = null;