pf-sdn/app/src/main/java/ru/kirillius/pf/sdn/App.java

142 lines
4.9 KiB
Java

package ru.kirillius.pf.sdn;
import lombok.Getter;
import lombok.SneakyThrows;
import ru.kirillius.pf.sdn.External.API.Components.FRR;
import ru.kirillius.pf.sdn.External.API.Components.OVPN;
import ru.kirillius.pf.sdn.External.API.Components.TDNS;
import ru.kirillius.pf.sdn.External.API.HEInfoProvider;
import ru.kirillius.pf.sdn.core.*;
import ru.kirillius.pf.sdn.core.Auth.AuthManager;
import ru.kirillius.pf.sdn.core.Auth.TokenService;
import ru.kirillius.pf.sdn.core.Networking.BGPInfoService;
import ru.kirillius.pf.sdn.core.Networking.NetworkingService;
import ru.kirillius.pf.sdn.core.Subscription.SubscriptionService;
import ru.kirillius.pf.sdn.core.Util.Wait;
import ru.kirillius.pf.sdn.web.WebService;
import ru.kirillius.utils.logging.SystemLogger;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import static ru.kirillius.pf.sdn.core.Util.CommandLineUtils.getArgument;
/**
* Entry point for the SDN control application that wires configuration, services, and shutdown handling.
*/
public class App implements Context, Closeable {
protected final static String CTX = App.class.getSimpleName();
static {
SystemLogger.initializeLogging(Level.INFO, List.of(InMemoryLogHandler.class));
}
private final AtomicBoolean shouldRestart = new AtomicBoolean(false);
private final AtomicBoolean running = new AtomicBoolean(true);
@Getter
private final ContextEventsHandler EventsHandler = new ContextEventsHandler();
@Getter
private final ServiceManager serviceManager;
@Getter
private final LauncherConfig launcherConfig;
@Getter
private final Config config;
/**
* Loads configuration from disk, creating a default file if missing.
*/
private Config loadConfig() {
Config loadedConfig = null;
try {
loadedConfig = Config.load(launcherConfig.getConfigFile());
} catch (IOException e) {
loadedConfig = new Config();
try {
Config.store(loadedConfig, launcherConfig.getConfigFile());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
return loadedConfig;
}
/**
* Instantiates all application services and performs initial wiring.
*/
private ServiceManager loadServiceManager() {
var manager = new ServiceManager(this, List.of(AuthManager.class, ComponentHandlerService.class, TokenService.class, AppUpdateService.class, BGPInfoService.class, NetworkingService.class, SubscriptionService.class, ResourceUpdateService.class, WebService.class));
manager.getService(BGPInfoService.class).setProvider(new HEInfoProvider());
return manager;
}
/**
* Ensures an admin password exists, defaulting to {@code admin} when missing.
*/
private void checkDefaultPassword() {
if (config.getPasswordHash() == null || config.getPasswordHash().isEmpty()) {
SystemLogger.error("There is no password for admin. Setting default password: admin", CTX);
getServiceManager().getService(AuthManager.class).updatePassword("admin");
}
}
/**
* Constructs the application binding to the provided launcher configuration.
*/
@SneakyThrows
public App(LauncherConfig launcherConfig) {
this.launcherConfig = launcherConfig;
config = loadConfig();
if (config.isDisplayDebuggingInfo()) {
SystemLogger.setExceptionDumping(true);
}
serviceManager = loadServiceManager();
serviceManager.getService(SubscriptionService.class).triggerUpdate();
checkDefaultPassword();
serviceManager.getService(ComponentHandlerService.class).syncComponentsWithConfig();
serviceManager.getService(ResourceUpdateService.class).start();
}
/**
* Application entry point.
*/
public static void main(String[] args) {
try (var app = new App(LauncherConfig.builder()
.configFile(new File(getArgument("c", args)))
.appLibrary(new File(getArgument("l", args)))
.repository(getArgument("r", args))
.availableComponentClasses(List.of(FRR.class, OVPN.class, TDNS.class)).build())) {
Wait.when(app.running::get);
if (app.shouldRestart.get()) {
System.exit(303);
} else {
System.exit(0);
}
} catch (Exception e) {
SystemLogger.error("Unhandled error", CTX, e);
System.exit(1);
}
}
/**
* Requests the application to exit, optionally restarting.
*/
public void requestExit(boolean restart) {
running.set(false);
shouldRestart.set(restart);
}
/**
* Closes all managed services.
*/
@Override
public void close() throws IOException {
serviceManager.close();
}
}