Improved directory handling and logging configuration.
This commit is contained in:
parent
601c17c6d1
commit
f4d3905f52
5 changed files with 76 additions and 41 deletions
|
|
@ -24,6 +24,7 @@ dependencies {
|
|||
}
|
||||
|
||||
application {
|
||||
applicationName = 'vm-runner.qemu'
|
||||
applicationDefaultJvmArgs = ['-Xms50m',
|
||||
'-Djava.util.logging.manager=org.jdrupes.vmoperator.util.LongLoggingManager'
|
||||
]
|
||||
|
|
@ -33,7 +34,7 @@ application {
|
|||
|
||||
distributions {
|
||||
main {
|
||||
distributionBaseName = 'runner-qemu'
|
||||
//distributionBaseName = 'runner-qemu'
|
||||
// contents {
|
||||
// from 'src/readme'
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -26,4 +26,4 @@ org.jdrupes.vmoperator.runner.qemu.level=FINE
|
|||
|
||||
java.util.logging.ConsoleHandler.level=ALL
|
||||
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %5$s%6$s%n
|
||||
java.util.logging.SimpleFormatter.format=%1$tb %1$td %1$tT %4$s %5$s%6$s%n
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# VM-Operator
|
||||
# Copyright (C) 2023 Michael N. Lipp
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
handlers=java.util.logging.ConsoleHandler
|
||||
|
||||
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
|
||||
|
|
@ -26,6 +26,7 @@ import java.util.UUID;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.jdrupes.vmoperator.util.Dto;
|
||||
import org.jdrupes.vmoperator.util.FsdUtils;
|
||||
|
||||
/**
|
||||
* The configuration information from the configuration file.
|
||||
|
|
@ -34,8 +35,8 @@ class Configuration implements Dto {
|
|||
@SuppressWarnings("PMD.FieldNamingConventions")
|
||||
protected final Logger logger = Logger.getLogger(getClass().getName());
|
||||
|
||||
public String dataDir;
|
||||
public String runtimeDir;
|
||||
public Path dataDir;
|
||||
public Path runtimeDir;
|
||||
public String template;
|
||||
public boolean updateTemplate;
|
||||
public Path swtpmSocket;
|
||||
|
|
@ -127,22 +128,14 @@ class Configuration implements Dto {
|
|||
private boolean checkRuntimeDir() {
|
||||
// Runtime directory (sockets)
|
||||
if (runtimeDir == null) {
|
||||
runtimeDir = System.getenv("XDG_RUNTIME_DIR");
|
||||
if (runtimeDir == null) {
|
||||
runtimeDir = "/tmp";
|
||||
if (System.getenv("USER") != null) {
|
||||
runtimeDir += "/" + System.getenv("USER");
|
||||
}
|
||||
}
|
||||
runtimeDir += "/vmrunner/" + vm.name;
|
||||
swtpmSocket = Path.of(runtimeDir, "swtpm-sock");
|
||||
monitorSocket = Path.of(runtimeDir, "monitor.sock");
|
||||
runtimeDir = FsdUtils.runtimeDir(Runner.APP_NAME).resolve(vm.name);
|
||||
swtpmSocket = runtimeDir.resolve("swtpm-sock");
|
||||
monitorSocket = runtimeDir.resolve("monitor.sock");
|
||||
}
|
||||
Path runtimePath = Path.of(runtimeDir);
|
||||
if (!Files.exists(runtimePath)) {
|
||||
runtimePath.toFile().mkdirs();
|
||||
if (!Files.exists(runtimeDir)) {
|
||||
runtimeDir.toFile().mkdirs();
|
||||
}
|
||||
if (!Files.isDirectory(runtimePath) || !Files.isWritable(runtimePath)) {
|
||||
if (!Files.isDirectory(runtimeDir) || !Files.isWritable(runtimeDir)) {
|
||||
logger.severe(() -> String.format(
|
||||
"Configured runtime directory \"%s\""
|
||||
+ " does not exist or isn't writable.",
|
||||
|
|
@ -156,20 +149,12 @@ class Configuration implements Dto {
|
|||
private boolean checkDataDir() {
|
||||
// Data directory
|
||||
if (dataDir == null) {
|
||||
dataDir = System.getenv("XDG_DATA_HOME");
|
||||
if (dataDir == null) {
|
||||
dataDir = ".";
|
||||
if (System.getenv("HOME") != null) {
|
||||
dataDir = System.getenv("HOME") + "/.local/share";
|
||||
}
|
||||
}
|
||||
dataDir += "/vmrunner/" + vm.name;
|
||||
dataDir = FsdUtils.dataHome(Runner.APP_NAME).resolve(vm.name);
|
||||
}
|
||||
Path dataPath = Path.of(dataDir);
|
||||
if (!Files.exists(dataPath)) {
|
||||
dataPath.toFile().mkdirs();
|
||||
if (!Files.exists(dataDir)) {
|
||||
dataDir.toFile().mkdirs();
|
||||
}
|
||||
if (!Files.isDirectory(dataPath) || !Files.isWritable(dataPath)) {
|
||||
if (!Files.isDirectory(dataDir) || !Files.isWritable(dataDir)) {
|
||||
logger.severe(() -> String.format(
|
||||
"Configured data directory \"%s\""
|
||||
+ " does not exist or isn't writable.",
|
||||
|
|
@ -186,7 +171,7 @@ class Configuration implements Dto {
|
|||
}
|
||||
|
||||
// Try to read stored uuid.
|
||||
Path uuidPath = Path.of(dataDir, "uuid.txt");
|
||||
Path uuidPath = dataDir.resolve("uuid.txt");
|
||||
if (Files.isReadable(uuidPath)) {
|
||||
try {
|
||||
var stored
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import freemarker.template.TemplateNotFoundException;
|
|||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.nio.file.Files;
|
||||
|
|
@ -41,6 +42,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
|
|
@ -49,6 +51,7 @@ import org.apache.commons.cli.Option;
|
|||
import org.apache.commons.cli.Options;
|
||||
import org.jdrupes.vmoperator.runner.qemu.StateController.State;
|
||||
import org.jdrupes.vmoperator.util.ExtendedObjectWrapper;
|
||||
import org.jdrupes.vmoperator.util.FsdUtils;
|
||||
import org.jgrapes.core.Channel;
|
||||
import org.jgrapes.core.Component;
|
||||
import org.jgrapes.core.Components;
|
||||
|
|
@ -142,10 +145,12 @@ import org.jgrapes.util.events.WatchFile;
|
|||
* @enduml
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("PMD.ExcessiveImports")
|
||||
@SuppressWarnings({ "PMD.ExcessiveImports", "PMD.AvoidPrintStackTrace" })
|
||||
public class Runner extends Component {
|
||||
|
||||
private static final String TEMPLATE_DIR = "/usr/share/vmrunner/templates";
|
||||
public static final String APP_NAME = "vmrunner";
|
||||
private static final String TEMPLATE_DIR
|
||||
= "/usr/share/" + APP_NAME + "/templates";
|
||||
private static final String DEFAULT_TEMPLATE
|
||||
= "Standard-VM-latest.ftl.yaml";
|
||||
private static final String SAVED_TEMPLATE = "VM.ftl.yaml";
|
||||
|
|
@ -167,6 +172,7 @@ public class Runner extends Component {
|
|||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SystemPrintln")
|
||||
public Runner(CommandLine cmdLine) throws IOException {
|
||||
state = new StateController(this);
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
|
||||
|
|
@ -195,9 +201,13 @@ public class Runner extends Component {
|
|||
attach(qemuMonitor = new QemuMonitor(channel()));
|
||||
|
||||
// Configuration store with file in /etc (default)
|
||||
File config = new File(cmdLine.getOptionValue('C',
|
||||
"/etc/vmrunner/config.yaml"));
|
||||
attach(new YamlConfigurationStore(channel(), config, false));
|
||||
File config = new File(cmdLine.getOptionValue('c',
|
||||
"/etc/" + APP_NAME + "/config.yaml"));
|
||||
try {
|
||||
attach(new YamlConfigurationStore(channel(), config, false));
|
||||
} catch (IOException e) {
|
||||
System.err.println("Cannot open configuration file " + config);
|
||||
}
|
||||
fire(new WatchFile(config.toPath()));
|
||||
}
|
||||
|
||||
|
|
@ -264,7 +274,7 @@ public class Runner extends Component {
|
|||
}
|
||||
}
|
||||
// Get file for firmware vars, if necessary
|
||||
config.firmwareVars = Path.of(config.dataDir, FW_VARS);
|
||||
config.firmwareVars = config.dataDir.resolve(FW_VARS);
|
||||
if (!Files.exists(config.firmwareVars)) {
|
||||
for (var p : firmware.path("vars")) {
|
||||
var path = Path.of(p.asText());
|
||||
|
|
@ -281,7 +291,7 @@ public class Runner extends Component {
|
|||
MalformedTemplateNameException, ParseException, TemplateException,
|
||||
JsonProcessingException, JsonMappingException {
|
||||
// Try saved template, copy if not there (or to be updated)
|
||||
Path templatePath = Path.of(config.dataDir, SAVED_TEMPLATE);
|
||||
Path templatePath = config.dataDir.resolve(SAVED_TEMPLATE);
|
||||
if (!Files.isReadable(templatePath) || config.updateTemplate) {
|
||||
// Get template
|
||||
Path sourcePath = Paths.get(TEMPLATE_DIR).resolve(Optional
|
||||
|
|
@ -323,7 +333,7 @@ public class Runner extends Component {
|
|||
|
||||
// Store process id
|
||||
try (var pidFile = Files.newBufferedWriter(
|
||||
Path.of(config.runtimeDir, "runner.pid"))) {
|
||||
config.runtimeDir.resolve("runner.pid"))) {
|
||||
pidFile.write(ProcessHandle.current().pid() + "\n");
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +404,7 @@ public class Runner extends Component {
|
|||
.ifPresent(procDef -> {
|
||||
channel.setAssociated(CommandDefinition.class, procDef);
|
||||
try (var pidFile = Files.newBufferedWriter(
|
||||
Path.of(config.runtimeDir, procDef.name + ".pid"))) {
|
||||
config.runtimeDir.resolve(procDef.name + ".pid"))) {
|
||||
pidFile.write(channel.process().toHandle().pid() + "\n");
|
||||
} catch (IOException e) {
|
||||
throw new UndeclaredThrowableException(e);
|
||||
|
|
@ -472,6 +482,22 @@ public class Runner extends Component {
|
|||
state.set(State.TERMINATING);
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
InputStream props;
|
||||
var path = FsdUtils.findConfigFile(Runner.APP_NAME,
|
||||
"logging.properties");
|
||||
if (path.isPresent()) {
|
||||
props = Files.newInputStream(path.get());
|
||||
} else {
|
||||
props = Runner.class.getResourceAsStream("logging.properties");
|
||||
}
|
||||
LogManager.getLogManager().readConfiguration(props);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main method.
|
||||
*
|
||||
|
|
@ -483,7 +509,7 @@ public class Runner extends Component {
|
|||
CommandLineParser parser = new DefaultParser();
|
||||
// parse the command line arguments
|
||||
final Options options = new Options();
|
||||
options.addOption(new Option("C", "config", true, "The confi"
|
||||
options.addOption(new Option("c", "config", true, "The confi"
|
||||
+ "guration file (defaults to /etc/vmrunner/config.yaml)."));
|
||||
CommandLine cmd = parser.parse(options, args);
|
||||
var app = new Runner(cmd);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue