diff options
author | gjoranv <gv@verizonmedia.com> | 2020-06-09 11:38:01 +0200 |
---|---|---|
committer | gjoranv <gv@verizonmedia.com> | 2020-06-09 11:38:01 +0200 |
commit | f202879931f279d5602299aa63c8116d74440479 (patch) | |
tree | d8d73f02257ae14f102bdc51e33d582f39c70ca7 /configserver | |
parent | 15dc573d585c13127045c3d3e4209b7d9632bf21 (diff) |
Add maintainer for downloading missing application packages.
- Not yet enabled
Diffstat (limited to 'configserver')
3 files changed, 89 insertions, 2 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileServer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileServer.java index 805ee2bef95..1e7f9fd69e7 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileServer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileServer.java @@ -199,8 +199,9 @@ public class FileServer { downloader.close(); } + // TODO: move to e.g. a util class // Connection pool with all config servers except this one (might be an empty pool if there is only one config server) - private static ConnectionPool createConnectionPool(ConfigserverConfig configserverConfig) { + public static ConnectionPool createConnectionPool(ConfigserverConfig configserverConfig) { List<String> configServers = ConfigServerSpec.fromConfig(configserverConfig) .stream() .filter(spec -> !spec.getHostName().equals(HostName.getLocalhost())) diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java new file mode 100644 index 00000000000..2a00a175fd8 --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ApplicationPackageMaintainer.java @@ -0,0 +1,86 @@ +package com.yahoo.vespa.config.server.maintenance; + +import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.config.FileReference; +import com.yahoo.vespa.config.server.ApplicationRepository; +import com.yahoo.vespa.config.server.filedistribution.FileServer; +import com.yahoo.vespa.config.server.session.RemoteSession; +import com.yahoo.vespa.curator.Curator; +import com.yahoo.vespa.defaults.Defaults; +import com.yahoo.vespa.filedistribution.FileDownloader; +import com.yahoo.vespa.flags.BooleanFlag; +import com.yahoo.vespa.flags.FlagSource; +import com.yahoo.vespa.flags.Flags; + +import java.io.File; +import java.time.Duration; +import java.util.Set; +import java.util.logging.Logger; + +import static com.yahoo.vespa.config.server.ApplicationRepository.getFileReferencesOnDisk; + +/** + * Verifies that all active sessions has an application package on local disk. + * If not, the package is downloaded with file distribution. This can happen e.g. + * if a configserver is down when the application is deployed. + * + * @author gjoranv + */ +public class ApplicationPackageMaintainer extends ConfigServerMaintainer { + private static final Logger log = Logger.getLogger(ApplicationPackageMaintainer.class.getName()); + + private final ApplicationRepository applicationRepository; + private final ConfigserverConfig configserverConfig; + private final File downloadDirectory; + private final BooleanFlag distributeApplicationPackage; + + public ApplicationPackageMaintainer(ApplicationRepository applicationRepository, + Curator curator, + Duration interval, + ConfigserverConfig configserverConfig, + FlagSource flagSource) { + super(applicationRepository, curator, interval, interval); + this.applicationRepository = applicationRepository; + this.configserverConfig = configserverConfig; + + distributeApplicationPackage = Flags.CONFIGSERVER_DISTRIBUTE_APPLICATION_PACKAGE.bindTo(flagSource); + downloadDirectory = new File(Defaults.getDefaults().underVespaHome(configserverConfig.fileReferencesDir())); + if (distributeApplicationPackage.value()) assertDownloadDirectoryIsDefault(downloadDirectory); + } + + @Override + protected void maintain() { + if (! distributeApplicationPackage.value()) return; + + var fileDownloader = new FileDownloader(FileServer.createConnectionPool(configserverConfig)); + try { + for (var applicationId : applicationRepository.listApplications()) { + RemoteSession session = applicationRepository.getActiveSession(applicationId); + FileReference applicationPackage = session.getApplicationPackageReference(); + + if (applicationPackage != null && missingOnDisk(applicationPackage)) { + log.fine(() -> "Downloading missing application package for application " + applicationId + " - session " + session.getSessionId()); + + if (fileDownloader.getFile(applicationPackage).isEmpty()) { + log.warning("Failed to download application package for application " + applicationId + " - session " + session.getSessionId()); + } + } + } + } finally { + fileDownloader.close(); + } + } + + private boolean missingOnDisk(FileReference applicationPackageReference) { + Set<String> fileReferencesOnDisk = getFileReferencesOnDisk(downloadDirectory); + return ! fileReferencesOnDisk.contains(applicationPackageReference.value()); + } + + // Required to use FileDownloader because it has no public ctor that takes a directory. + private static void assertDownloadDirectoryIsDefault(File fileReferencesDir) { + if (fileReferencesDir != FileDownloader.defaultDownloadDirectory) throw new IllegalArgumentException( + "Files must be downloaded to the default download directory (" + + FileDownloader.defaultDownloadDirectory + "), not " + fileReferencesDir); + } + +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java index 8b078f152f3..c553133ba12 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/Session.java @@ -107,7 +107,7 @@ public abstract class Session implements Comparable<Session> { public ApplicationId getApplicationId() { return zooKeeperClient.readApplicationId(); } - FileReference getApplicationPackageReference() {return zooKeeperClient.readApplicationPackageReference(); } + public FileReference getApplicationPackageReference() {return zooKeeperClient.readApplicationPackageReference(); } public Optional<DockerImage> getDockerImageRepository() { return zooKeeperClient.readDockerImageRepository(); } |