Refactor Argeo init
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 5 Mar 2024 09:14:58 +0000 (10:14 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 5 Mar 2024 09:14:58 +0000 (10:14 +0100)
etc/argeo/user/slc/argeo.ini
etc/argeo/user/slc/debug.ini
sjbin/src/freed-pid1.java [deleted file]
sjbin/src/freed-register.java [new file with mode: 0644]
usr/lib/systemd/system/argeo@.service
usr/lib/systemd/user/argeo.service
usr/lib/systemd/user/argeo@.service

index 45c47c9d46b87d4e73398bc084c674612eb54db0..0f5be1083f39500a94e6fa7efdf1786054b80d37 100644 (file)
@@ -1,9 +1,10 @@
 
 ## OSGi system extensions
+# giving additional access to Argeo Init and Sun Misc
 org.osgi.framework.system.packages.extra=\
-org.argeo.init,\
-org.argeo.init.a2,\
-org.argeo.init.osgi,\
+org.argeo.api.init,\
+org.argeo.api.a2,\
+sun.misc,\
 sun.security.util,\
 sun.security.internal.spec,\
 sun.security.provider,\
index 0ab492acc58bd618d8a9b8694d43c0f3c72c5e8b..82da55afcdd2cda4fb41fea06f48e413711dfd90 100644 (file)
@@ -1,2 +1,2 @@
-osgi.console=2023
+osgi.console=localhost:2023
 osgi.clean=true
\ No newline at end of file
diff --git a/sjbin/src/freed-pid1.java b/sjbin/src/freed-pid1.java
deleted file mode 100644 (file)
index 446cc0e..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-//#! /usr/bin/java --source 17 @/usr/local/etc/freed/pid1/jvm.args
-
-import static java.lang.System.Logger.Level.DEBUG;
-import static java.lang.System.Logger.Level.ERROR;
-import static java.lang.System.Logger.Level.INFO;
-import static java.lang.System.Logger.Level.WARNING;
-
-import java.io.Console;
-import java.io.IOException;
-import java.lang.System.Logger;
-import java.lang.management.ManagementFactory;
-import java.net.InetAddress;
-import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.TreeMap;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.argeo.init.Service;
-
-import sun.misc.Signal;
-
-/** A minimalistic Linux init process. */
-class FreedPid1 {
-       final static AtomicInteger runLevel = new AtomicInteger(-1);
-
-       private final static Logger logger = System.getLogger(FreedPid1.class.getName());
-
-       private final static List<String> initDServices = Collections.synchronizedList(new ArrayList<>());
-
-       public static void main(String... args) {
-               try {
-                       final long pid = ProcessHandle.current().pid();
-                       Signal.handle(new Signal("TERM"), (signal) -> {
-                               System.out.println("SIGTERM caught");
-                               System.exit(0);
-                       });
-                       Signal.handle(new Signal("INT"), (signal) -> {
-                               System.out.println("SIGINT caught");
-                               System.exit(0);
-                       });
-                       Signal.handle(new Signal("HUP"), (signal) -> {
-                               System.out.println("SIGHUP caught");
-                               System.exit(0);
-                       });
-
-                       boolean isSystemInit = pid == 1 || pid == 2;
-
-                       if (isSystemInit && args.length > 0 && ("1".equals(args[0]) //
-                                       || "single".equals(args[0]) //
-                                       || "emergency".equals(args[0]))) {
-                               runLevel.set(1);
-                               for (Object key : new TreeMap<>(System.getProperties()).keySet()) {
-                                       System.out.println(key + "=" + System.getProperty(key.toString()));
-                               }
-                               System.out.println("Single user mode");
-                               System.out.flush();
-                               ProcessBuilder pb = new ProcessBuilder("/bin/bash");
-                               pb.redirectError(ProcessBuilder.Redirect.INHERIT);
-                               pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
-                               pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
-                               Process singleUserShell = pb.start();
-                               singleUserShell.waitFor();
-                       } else {
-                               if (args.length == 0)
-                                       runLevel.set(5);
-                               else
-                                       runLevel.set(Integer.parseInt(args[0]));
-
-                               if (runLevel.get() == 0) {// shutting down the whole system
-                                       if (!isSystemInit) {
-                                               logger.log(INFO, "Shutting down system...");
-                                               shutdown(false);
-                                               System.exit(0);
-                                       } else {
-                                               logger.log(ERROR, "Cannot start at run level " + runLevel.get());
-                                               System.exit(1);
-                                       }
-                               } else if (runLevel.get() == 6) {// reboot the whole system
-                                       if (!isSystemInit) {
-                                               logger.log(INFO, "Rebooting the system...");
-                                               shutdown(true);
-                                       } else {
-                                               logger.log(ERROR, "Cannot start at run level " + runLevel.get());
-                                               System.exit(1);
-                                       }
-                               }
-
-                               logger.log(INFO, "FREEd Init daemon starting with pid " + pid + " after "
-                                               + ManagementFactory.getRuntimeMXBean().getUptime() + " ms");
-                               // hostname
-                               String hostname = Files.readString(Paths.get("/etc/hostname"));
-                               new ProcessBuilder("/usr/bin/hostname", hostname).start();
-                               logger.log(DEBUG, "Set hostname to " + hostname);
-                               // networking
-                               initSysctl();
-                               startInitDService("networking", true);
-//                             Thread.sleep(3000);// leave some time for network to start up
-                               if (!waitForNetwork(10 * 1000))
-                                       logger.log(ERROR, "No network available");
-
-                               // OpenSSH
-                               // TODO make it coherent with Java sshd
-                               startInitDService("ssh", true);
-
-                               // NSS services
-                               startInitDService("nslcd", false);// Note: nslcd fails to stop
-
-                               // login prompt
-                               Service.addPostStart(() -> new LoginThread().start());
-
-                               // init Argeo CMS
-                               logger.log(INFO, "FREEd Init daemon starting Argeo Init after "
-                                               + ManagementFactory.getRuntimeMXBean().getUptime() + " ms");
-                               Service.main(args);
-                       }
-               } catch (Throwable e) {
-                       logger.log(ERROR, "Unexpected exception in free-pid1 init, shutting down... ", e);
-                       System.exit(1);
-               } finally {
-                       stopInitDServices();
-               }
-       }
-
-       static void initSysctl() {
-               try {
-                       Path sysctlD = Paths.get("/etc/sysctl.d/");
-                       for (Path conf : Files.newDirectoryStream(sysctlD, "*.conf")) {
-                               try {
-                                       new ProcessBuilder("/usr/sbin/sysctl", "-p", conf.toString()).start();
-                               } catch (IOException e) {
-                                       e.printStackTrace();
-                               }
-                       }
-               } catch (IOException e) {
-                       e.printStackTrace();
-               }
-       }
-
-       static void startInitDService(String serviceName, boolean stopOnShutdown) {
-               Path serviceInit = Paths.get("/etc/init.d/", serviceName);
-               if (Files.exists(serviceInit))
-                       try {
-                               int exitCode = new ProcessBuilder(serviceInit.toString(), "start").start().waitFor();
-                               if (exitCode != 0)
-                                       logger.log(ERROR, "Service " + serviceName + " dit not stop properly");
-                               else
-                                       logger.log(DEBUG, "Service " + serviceName + " started");
-                               if (stopOnShutdown)
-                                       initDServices.add(serviceName);
-//                                     Runtime.getRuntime().addShutdownHook(new Thread(() -> {
-//                                             try {
-//                                                     new ProcessBuilder(serviceInit.toString(), "stop").start().waitFor();
-//                                             } catch (IOException | InterruptedException e) {
-//                                                     e.printStackTrace();
-//                                             }
-//                                     }, "FREEd stop service " + serviceName));
-                       } catch (IOException | InterruptedException e) {
-                               e.printStackTrace();
-                       }
-               else
-                       logger.log(WARNING, "Service " + serviceName + " not found and therefore not started");
-       }
-
-       static boolean waitForNetwork(long timeout) {
-               long begin = System.currentTimeMillis();
-               long duration = 0;
-               boolean networkAvailable = false;
-               try {
-                       networkAvailable: while (!networkAvailable) {
-                               duration = System.currentTimeMillis() - begin;
-                               if (duration > timeout)
-                                       break networkAvailable;
-                               Enumeration<NetworkInterface> netInterfaces = null;
-                               try {
-                                       netInterfaces = NetworkInterface.getNetworkInterfaces();
-                               } catch (SocketException e) {
-                                       throw new IllegalStateException("Cannot list network interfaces", e);
-                               }
-                               if (netInterfaces != null) {
-                                       while (netInterfaces.hasMoreElements()) {
-                                               NetworkInterface netInterface = netInterfaces.nextElement();
-                                               logger.log(DEBUG, "Interface:" + netInterface);
-                                               for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) {
-                                                       InetAddress inetAddr = addr.getAddress();
-                                                       logger.log(DEBUG, "  addr: " + inetAddr);
-                                                       if (!inetAddr.isLoopbackAddress() && !inetAddr.isLinkLocalAddress()) {
-                                                               try {
-                                                                       if (inetAddr.isReachable((int) timeout)) {
-                                                                               networkAvailable = true;
-                                                                               duration = System.currentTimeMillis() - begin;
-                                                                               logger.log(DEBUG,
-                                                                                               "Network available after " + duration + " ms. IP: " + inetAddr);
-                                                                               break networkAvailable;
-                                                                       }
-                                                               } catch (IOException e) {
-                                                                       logger.log(ERROR, "Cannot check whether " + inetAddr + " is reachable", e);
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               } else {
-                                       throw new IllegalStateException("No network interface has been found");
-                               }
-                               try {
-                                       Thread.sleep(1000);
-                               } catch (InterruptedException e) {
-                                       // silent
-                               }
-                       }
-               } catch (Exception e) {
-                       logger.log(ERROR, "Cannot check whether network is available", e);
-               }
-               return networkAvailable;
-       }
-
-       static void shutdown(boolean reboot) {
-               try {
-                       stopInitDServices();
-                       Path sysrqP = Paths.get("/proc/sys/kernel/sysrq");
-                       Files.writeString(sysrqP, "1");
-                       Path sysrqTriggerP = Paths.get("/proc/sysrq-trigger");
-                       Files.writeString(sysrqTriggerP, "e");// send SIGTERM to all processes
-                       // Files.writeString(sysrqTriggerP, "i");// send SIGKILL to all processes
-                       Files.writeString(sysrqTriggerP, "e");// flush data to disk
-                       Files.writeString(sysrqTriggerP, "u");// unmount
-                       if (reboot)
-                               Files.writeString(sysrqTriggerP, "b");
-                       else
-                               Files.writeString(sysrqTriggerP, "o");
-               } catch (IOException e) {
-                       logger.log(ERROR, "Cannot shut down system", e);
-               }
-       }
-
-       static void stopInitDServices() {
-               for (int i = initDServices.size() - 1; i >= 0; i--) {
-                       String serviceName = initDServices.get(i);
-                       Path serviceInit = Paths.get("/etc/init.d/", serviceName);
-                       try {
-                               int exitCode = new ProcessBuilder(serviceInit.toString(), "stop").start().waitFor();
-                               if (exitCode != 0)
-                                       logger.log(ERROR, "Service " + serviceName + " dit not stop properly");
-                       } catch (InterruptedException | IOException e) {
-                               logger.log(ERROR, "Cannot stop service " + serviceName, e);
-                       }
-               }
-       }
-
-       /** A thread watching the login prompt. */
-       static class LoginThread extends Thread {
-               private boolean systemShuttingDown = false;
-               private Process process = null;
-
-               public LoginThread() {
-                       super("FREEd login prompt");
-                       setDaemon(true);
-                       Runtime.getRuntime().addShutdownHook(new Thread(() -> {
-                               systemShuttingDown = true;
-                               if (process != null)
-                                       process.destroy();
-                       }));
-               }
-
-               @Override
-               public void run() {
-                       boolean getty = true;
-                       prompt: while (!systemShuttingDown) {
-                               try {
-                                       if (getty) {
-                                               ProcessBuilder pb = new ProcessBuilder("/usr/sbin/getty", "38400", "tty2");
-                                               process = pb.start();
-                                       } else {
-                                               Console console = System.console();
-                                               console.readLine(); // type return once to activate login prompt
-                                               console.printf("login: ");
-                                               String username = console.readLine();
-                                               username = username.trim();
-                                               if ("".equals(username))
-                                                       continue prompt;
-                                               ProcessBuilder pb = new ProcessBuilder("su", "--login", username);
-                                               pb.redirectError(ProcessBuilder.Redirect.INHERIT);
-                                               pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
-                                               pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
-                                               process = pb.start();
-                                       }
-                                       Runtime.getRuntime().addShutdownHook(new Thread(() -> process.destroy()));
-                                       try {
-                                               process.waitFor();
-                                       } catch (InterruptedException e) {
-                                               process.destroy();
-                                       }
-                               } catch (Exception e) {
-                                       e.printStackTrace();
-                               } finally {
-                                       process = null;
-                               }
-                       }
-               }
-
-       }
-}
diff --git a/sjbin/src/freed-register.java b/sjbin/src/freed-register.java
new file mode 100644 (file)
index 0000000..37d63c2
--- /dev/null
@@ -0,0 +1,8 @@
+//#! /usr/bin/java --source 17 @/usr/local/etc/freed/pid1/jvm.args
+
+/** Register to a FREEd-compatible infrastructure. */
+class FreedPid1 {
+
+       public static void main(String... args) {
+       }
+}
index b940216f759e11ca9625277cd98f51e136cb9315..f080622ba29e22c35f7ae38910bb91ab9ed4ef2f 100644 (file)
@@ -29,7 +29,7 @@ ExecStart=java \
 @/etc/argeo.d/jvm.args \
 @${CONFIGURATION_DIRECTORY}/jvm.args \
 @/usr/share/argeo/jvm.args \
-org.argeo.init.Service
+org.argeo.init.ServiceMain
  
 # Exit codes of the JVM when SIGTERM or SIGINT have been caught:
 SuccessExitStatus=143 130
index 8534a94a06d4530f1175e99593d2a3def8771861..ba6f78df362221a99995e76ce6806d9da68ba205 100644 (file)
@@ -21,7 +21,7 @@ ExecStart=java \
 @etc/argeo/user/jvm.args \
 @${CONFIGURATION_DIRECTORY}/jvm.args \
 @lib/argeo/jvm.args \
-org.argeo.init.RuntimeManager \
+org.argeo.init.RuntimeManagerMain \
 etc/argeo/user/slc
 
 # Exit codes of the JVM when SIGTERM or SIGINT have been caught:
index 3e378b8df055bb0e996b23ae5f7cc0db66eb2bc6..04b77b1517a69eb4ae69bfd6e86dd8c049188c65 100644 (file)
@@ -24,7 +24,7 @@ ExecStart=java \
 @/etc/argeo.user.d/jvm.args \
 @/etc/argeo.user.d/%I/jvm.args \
 @/usr/share/argeo/jvm.args \
-org.argeo.init.Service
+org.argeo.init.ServiceMain
 
 # Exit codes of the JVM when SIGTERM or SIGINT have been caught:
 SuccessExitStatus=143 130