diff options
Diffstat (limited to 'controller-server')
3 files changed, 152 insertions, 2 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java index b568b1ca6e4..2f33cf6d6ea 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java @@ -26,6 +26,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.routing.RotationStatus; import com.yahoo.vespa.hosted.controller.api.integration.routing.RoutingGenerator; import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry; import com.yahoo.vespa.hosted.controller.persistence.ControllerDb; +import com.yahoo.vespa.hosted.controller.persistence.ControllerDbProxy; import com.yahoo.vespa.hosted.controller.persistence.CuratorDb; import com.yahoo.vespa.hosted.controller.versions.VersionStatus; import com.yahoo.vespa.hosted.controller.versions.VespaVersion; @@ -132,11 +133,12 @@ public class Controller extends AbstractComponent { this.clock = clock; this.athenzClientFactory = athenzClientFactory; - applicationController = new ApplicationController(this, db, curator, athenzClientFactory, + ControllerDbProxy dbProxy = new ControllerDbProxy(db, curator); + applicationController = new ApplicationController(this, dbProxy, curator, athenzClientFactory, rotationsConfig, nameService, configServerClient, artifactRepository, routingGenerator, clock); - tenantController = new TenantController(this, db, curator, athenzClientFactory); + tenantController = new TenantController(this, dbProxy, curator, athenzClientFactory); } /** Returns the instance controlling tenants */ diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ControllerDbProxy.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ControllerDbProxy.java new file mode 100644 index 00000000000..4424433662e --- /dev/null +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ControllerDbProxy.java @@ -0,0 +1,93 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.persistence; + +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.hosted.controller.Application; +import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; +import com.yahoo.vespa.hosted.controller.tenant.Tenant; +import com.yahoo.vespa.hosted.controller.tenant.UserTenant; + +import java.util.List; +import java.util.Optional; + +/** + * Controller database implementation that writes to both a ControllerDb and a CuratorDb. + * + * @author mpolden + */ +// TODO: Remove this and ControllerDb and use only CuratorDb +public class ControllerDbProxy implements ControllerDb { + + private final ControllerDb db; + private final CuratorDb curator; + + public ControllerDbProxy(ControllerDb db, CuratorDb curator) { + this.db = db; + this.curator = curator; + } + + @Override + public void createTenant(UserTenant tenant) { + db.createTenant(tenant); + curator.writeTenant(tenant); + } + + @Override + public void createTenant(AthenzTenant tenant) { + db.createTenant(tenant); + curator.writeTenant(tenant); + } + + @Override + public void updateTenant(AthenzTenant tenant) throws PersistenceException { + db.updateTenant(tenant); + curator.writeTenant(tenant); + } + + @Override + public void deleteTenant(TenantName name) throws PersistenceException { + db.deleteTenant(name); + curator.removeTenant(name); + } + + @Override + public Optional<Tenant> getTenant(TenantName name) throws PersistenceException { + return db.getTenant(name); + } + + @Override + public Optional<AthenzTenant> getAthenzTenant(TenantName name) throws PersistenceException { + return db.getAthenzTenant(name); + } + + @Override + public List<Tenant> listTenants() { + return db.listTenants(); + } + + @Override + public void store(Application application) { + db.store(application); + } + + @Override + public void deleteApplication(ApplicationId applicationId) { + db.deleteApplication(applicationId); + } + + @Override + public Optional<Application> getApplication(ApplicationId applicationId) { + return db.getApplication(applicationId); + } + + @Override + public List<Application> listApplications() { + return db.listApplications(); + } + + @Override + public List<Application> listApplications(TenantName name) { + return db.listApplications(name); + } +} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java index 558e30876df..9c585ad1269 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java @@ -11,6 +11,9 @@ import com.yahoo.vespa.config.SlimeUtils; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.curator.Lock; import com.yahoo.vespa.hosted.controller.application.DeploymentJobs; +import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; +import com.yahoo.vespa.hosted.controller.tenant.Tenant; +import com.yahoo.vespa.hosted.controller.tenant.UserTenant; import com.yahoo.vespa.hosted.controller.versions.VersionStatus; import com.yahoo.vespa.hosted.controller.versions.VespaVersion; @@ -29,6 +32,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; /** * Curator backed database for storing working state shared between controller servers. @@ -44,12 +48,15 @@ public class CuratorDb { private static final Path lockRoot = root.append("locks"); + private static final Path tenantRoot = root.append("tenants"); + private static final Duration defaultLockTimeout = Duration.ofMinutes(5); private final StringSetSerializer stringSetSerializer = new StringSetSerializer(); private final JobQueueSerializer jobQueueSerializer = new JobQueueSerializer(); private final VersionStatusSerializer versionStatusSerializer = new VersionStatusSerializer(); private final ConfidenceOverrideSerializer confidenceOverrideSerializer = new ConfidenceOverrideSerializer(); + private final TenantSerializer tenantSerializer = new TenantSerializer(); private final Curator curator; @@ -188,6 +195,50 @@ public class CuratorDb { .orElseGet(Collections::emptyMap); } + public void writeTenant(UserTenant tenant) { + try { + curator.set(tenantPath(tenant.name()), SlimeUtils.toJsonBytes(tenantSerializer.toSlime(tenant))); + } catch (IOException e) { + throw new UncheckedIOException("Failed to write " + tenant.toString(), e); + } + } + + public Optional<UserTenant> readUserTenant(TenantName name) { + return readSlime(tenantPath(name)).map(tenantSerializer::userTenantFrom); + } + + public void writeTenant(AthenzTenant tenant) { + try { + curator.set(tenantPath(tenant.name()), SlimeUtils.toJsonBytes(tenantSerializer.toSlime(tenant))); + } catch (IOException e) { + throw new UncheckedIOException("Failed to write " + tenant.toString(), e); + } + } + + public Optional<AthenzTenant> readAthenzTenant(TenantName name) { + return readSlime(tenantPath(name)).map(tenantSerializer::athenzTenantFrom); + } + + public Optional<Tenant> readTenant(TenantName name) { + if (name.value().startsWith(Tenant.userPrefix)) { + return readUserTenant(name).map(Tenant.class::cast); + } + return readAthenzTenant(name).map(Tenant.class::cast); + } + + public List<Tenant> readTenants() { + return curator.getChildren(tenantRoot).stream() + .map(TenantName::from) + .map(this::readTenant) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)); + } + + public void removeTenant(TenantName name) { + curator.delete(tenantPath(name)); + } + // The following methods are called by internal code @SuppressWarnings("unused") @@ -286,4 +337,8 @@ public class CuratorDb { private static Path openStackServerPoolPath() { return root.append("openStackServerPool"); } + + private static Path tenantPath(TenantName name) { + return tenantRoot.append(name.value()); + } } |