Skip to content

Commit

Permalink
Add ZooKeeper 3.9.3
Browse files Browse the repository at this point in the history
  • Loading branch information
hmusum committed Dec 5, 2024
1 parent d5e7a12 commit 7b06f9c
Show file tree
Hide file tree
Showing 22 changed files with 8,168 additions and 0 deletions.
1 change: 1 addition & 0 deletions zookeeper-server/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
add_subdirectory(zookeeper-server-common)
add_subdirectory(zookeeper-server)
add_subdirectory(zookeeper-server-3.9.2)

1 change: 1 addition & 0 deletions zookeeper-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<modules>
<module>zookeeper-server-common</module>
<module>zookeeper-server</module>
<module>zookeeper-server-3.9.3</module>
</modules>
<dependencies>
<dependency>
Expand Down
4 changes: 4 additions & 0 deletions zookeeper-server/zookeeper-server-3.9.3/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
install_jar(zookeeper-server-3.9.3-jar-with-dependencies.jar)
# Make symlink so that we have a default version, should be done only in zookeeper-server module
#install_symlink(lib/jars/zookeeper-server-3.9.2-jar-with-dependencies.jar lib/jars/zookeeper-server-jar-with-dependencies.jar)
99 changes: 99 additions & 0 deletions zookeeper-server/zookeeper-server-3.9.3/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?xml version="1.0"?>
<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.yahoo.vespa</groupId>
<artifactId>zookeeper-server-parent</artifactId>
<version>8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>zookeeper-server-3.9.3</artifactId>
<packaging>container-plugin</packaging>
<version>8-SNAPSHOT</version>
<properties>
<zookeeper.version>3.9.3</zookeeper.version>
</properties>
<dependencies>
<dependency>
<groupId>com.yahoo.vespa</groupId>
<artifactId>zookeeper-server-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.yahoo.vespa</groupId>
<artifactId>zookeeper-client-common</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<!-- Don't use ZK version from zookeeper-client-common -->
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
<exclusions>
<!--
Container provides wiring for all common log libraries
Duplicate embedding results in various warnings being printed to stderr
-->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- snappy-java and metrics-core are included here
to be able to work with ZooKeeper 3.7.0 due to
class loading issues -->
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<!-- Turn off classfile warnings where spotbugs is pulled in transitively. -->
<arg>${vespaCompilerArgs.xlint}</arg>
<arg>-Xlint:-classfile</arg>
<arg>-Werror</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.yahoo.vespa</groupId>
<artifactId>bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<importPackage>com.sun.management</importPackage>
<bundleSymbolicName>zookeeper-server</bundleSymbolicName>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.zookeeper;

import com.yahoo.cloud.config.ZookeeperServerConfig;
import com.yahoo.component.AbstractComponent;
import com.yahoo.component.annotation.Inject;
import com.yahoo.vespa.zookeeper.server.VespaZooKeeperServer;

import java.nio.file.Path;

/**
*
* Server used for starting config server, needed to be able to have different behavior for hosted and
* self-hosted Vespa (controlled by zookeeperServerConfig.dynamicReconfiguration).
*
* @author Harald Musum
*/
public class ConfigServerZooKeeperServer extends AbstractComponent implements VespaZooKeeperServer {

private final VespaZooKeeperServer zooKeeperServer;

@Inject
public ConfigServerZooKeeperServer(ZookeeperServerConfig zookeeperServerConfig) {
this.zooKeeperServer = zookeeperServerConfig.dynamicReconfiguration()
? new ReconfigurableVespaZooKeeperServer(new Reconfigurer(new VespaZooKeeperAdminImpl()), zookeeperServerConfig)
: new VespaZooKeeperServerImpl(zookeeperServerConfig);
}

@Override
public void deconstruct() { zooKeeperServer.shutdown(); }

@Override
public void shutdown() {
zooKeeperServer.shutdown();
}

@Override
public void start(Path configFilePath) {
zooKeeperServer.start(configFilePath);
}

@Override
public boolean reconfigurable() { return zooKeeperServer.reconfigurable(); }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.zookeeper;

import ai.vespa.validation.Validation;
import com.yahoo.cloud.config.ZookeeperServerConfig;
import com.yahoo.component.AbstractComponent;
import com.yahoo.component.annotation.Inject;
import com.yahoo.vespa.zookeeper.server.VespaZooKeeperServer;

import java.nio.file.Path;
import java.time.Duration;

/**
* Starts or reconfigures zookeeper cluster.
* The QuorumPeer conditionally created here is owned by the Reconfigurer;
* when it already has a peer, that peer is used here in case start or shutdown is required.
* Guarantees that server is up by writing a node to ZooKeeper successfully before
* returning from constructor.
*
* @author hmusum
*/
public final class ReconfigurableVespaZooKeeperServer extends AbstractComponent implements VespaZooKeeperServer {

private QuorumPeer peer;

@Inject
public ReconfigurableVespaZooKeeperServer(Reconfigurer reconfigurer, ZookeeperServerConfig zookeeperServerConfig) {
Validation.require(zookeeperServerConfig.dynamicReconfiguration(),
zookeeperServerConfig.dynamicReconfiguration(),
"dynamicReconfiguration must be true");
peer = reconfigurer.startOrReconfigure(zookeeperServerConfig, this, () -> peer = new VespaQuorumPeer());
}

@Override
public void shutdown() {
peer.shutdown(Duration.ofMinutes(1));
}

@Override
public void start(Path configFilePath) {
peer.start(configFilePath);
}

@Override
public boolean reconfigurable() {
return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.zookeeper;

import com.yahoo.security.X509SslContext;
import com.yahoo.security.tls.TlsContext;
import com.yahoo.security.tls.TransportSecurityUtils;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.common.ClientX509Util;
import org.apache.zookeeper.common.X509Exception;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.server.ServerCnxn;
import org.apache.zookeeper.server.auth.AuthenticationProvider;
import org.apache.zookeeper.server.auth.X509AuthenticationProvider;

import javax.net.ssl.KeyManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import java.util.logging.Logger;

/**
* A {@link AuthenticationProvider} to be used in combination with Vespa mTLS.
*
* @author bjorncs
*/
public class VespaMtlsAuthenticationProvider extends X509AuthenticationProvider {

private static final Logger log = Logger.getLogger(VespaMtlsAuthenticationProvider.class.getName());

public VespaMtlsAuthenticationProvider() {
super(null, null);
}

@Override
public KeeperException.Code handleAuthentication(ServerCnxn cnxn, byte[] authData) {
// Vespa's mTLS peer authorization rules are performed by the underlying trust manager implementation.
// The client is authorized once the SSL handshake has completed.
X509Certificate[] certificateChain = (X509Certificate[]) cnxn.getClientCertificateChain();
if (certificateChain == null || certificateChain.length == 0) {
log.warning("Client not authenticated - should not be possible with clientAuth=NEED");
return KeeperException.Code.AUTHFAILED;
}
X509Certificate certificate = certificateChain[0];
cnxn.addAuthInfo(new Id(getScheme(), certificate.getSubjectX500Principal().getName()));
return KeeperException.Code.OK;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.zookeeper;

import com.yahoo.protect.Process;
import org.apache.zookeeper.server.admin.AdminServer;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
import org.apache.zookeeper.server.quorum.QuorumPeerMain;

import java.io.IOException;
import java.nio.file.Path;
import java.time.Duration;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Starts or stops a ZooKeeper server. Extends QuorumPeerMain to be able to call initializeAndRun() and wraps
* exceptions so that it can be used by code that does not depend on ZooKeeper.
*
* @author hmusum
*/
class VespaQuorumPeer extends QuorumPeerMain implements QuorumPeer {

private static final Logger log = java.util.logging.Logger.getLogger(VespaQuorumPeer.class.getName());

@Override
public void start(Path path) {
initializeAndRun(new String[]{ path.toFile().getAbsolutePath()});
}

@Override
public void shutdown(Duration timeout) {
if (quorumPeer != null) {
log.log(Level.FINE, "Shutting down ZooKeeper server");
try {
quorumPeer.shutdown();
quorumPeer.join(timeout.toMillis()); // Wait for shutdown to complete
if (quorumPeer.isAlive())
throw new IllegalStateException("Peer still alive after " + timeout);
} catch (RuntimeException | InterruptedException e) {
// If shutdown fails, we have no other option than forcing the JVM to stop and letting it be restarted.
//
// When a VespaZooKeeperServer component receives a new config, the container will try to start a new
// server with the new config, this will fail until the old server is deconstructed. If the old server
// fails to deconstruct/shutdown, the new one will never start and if that happens forcing a restart is
// the better option.
Process.logAndDie("Failed to shut down ZooKeeper server properly, forcing shutdown", e);
}
}
}

@Override
protected void initializeAndRun(String[] args) {
try {
super.initializeAndRun(args);
} catch (QuorumPeerConfig.ConfigException | IOException | AdminServer.AdminServerException e) {
throw new RuntimeException("Exception when initializing or running ZooKeeper server", e);
}
}

}
Loading

0 comments on commit 7b06f9c

Please sign in to comment.