Run most acceptance tests in-memory

This allows the tests to run faster, with lower system overheads.
The new @UseLocalDisk annotation must be added to any test method
that wants the classical init and daemon testing strategy.

A new sshd.requestLog configuration variable is introduced to
permit tests to disable the SSH command log.

Timing for `buck test --all` on my Linux desktop:

  before 3m37.129s
  after  2m18.789s

Change-Id: I18c07ef2d913f6abbb3925b3e7d3df5d28668497
(cherry picked from commit 318bfcae5c)
This commit is contained in:
Shawn Pearce
2013-10-17 22:15:38 -07:00
parent f22e633fca
commit 35e97c2aeb
19 changed files with 362 additions and 98 deletions

View File

@@ -2705,6 +2705,13 @@ by the client and must match for kerberos authentication to work.
+
By default, `host/canonical.host.name`
[[sshd.requestLog]]sshd.requestLog::
+
Enable (or disable) the `'$site_path'/logs/sshd_log` request log.
If enabled, a request log file is written out by the SSH daemon.
+
By default, true.
[[suggest]] Section suggest
~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -12,6 +12,7 @@ java_library(
'//gerrit-pgm:pgm',
'//gerrit-reviewdb:server',
'//gerrit-server:server',
'//gerrit-server:testutil',
'//gerrit-sshd:sshd',
'//lib:args4j',

View File

@@ -30,7 +30,8 @@ public abstract class AbstractDaemonTest {
return new Statement() {
@Override
public void evaluate() throws Throwable {
beforeTest(config(description));
boolean mem = description.getAnnotation(UseLocalDisk.class) == null;
beforeTest(config(description), mem);
base.evaluate();
afterTest();
}
@@ -53,8 +54,8 @@ public abstract class AbstractDaemonTest {
}
}
private void beforeTest(Config cfg) throws Exception {
server = GerritServer.start(cfg);
private void beforeTest(Config cfg, boolean memory) throws Exception {
server = GerritServer.start(cfg, memory);
server.getTestInjector().injectMembers(this);
}

View File

@@ -14,18 +14,19 @@
package com.google.gerrit.acceptance;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.pgm.Daemon;
import com.google.gerrit.pgm.Init;
import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.util.SocketUtil;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import java.io.File;
@@ -46,8 +47,7 @@ import java.util.concurrent.TimeUnit;
public class GerritServer {
/** Returns fully started Gerrit server */
static GerritServer start(Config base) throws Exception {
final File site = initSite(base);
static GerritServer start(Config base, boolean memory) throws Exception {
final CyclicBarrier serverStarted = new CyclicBarrier(2);
final Daemon daemon = new Daemon(new Runnable() {
public void run() {
@@ -61,21 +61,34 @@ public class GerritServer {
}
});
ExecutorService daemonService = Executors.newSingleThreadExecutor();
daemonService.submit(new Callable<Void>() {
public Void call() throws Exception {
int rc = daemon.main(new String[] {"-d", site.getPath(), "--headless" });
if (rc != 0) {
System.out.println("Failed to start Gerrit daemon. Check "
+ site.getPath() + "/logs/error_log");
serverStarted.reset();
}
return null;
};
});
serverStarted.await();
System.out.println("Gerrit Server Started");
final File site;
ExecutorService daemonService = null;
if (memory) {
site = null;
Config cfg = base != null ? base : new Config();
mergeTestConfig(cfg);
cfg.setBoolean("httpd", null, "requestLog", false);
cfg.setBoolean("sshd", null, "requestLog", false);
daemon.setDatabaseForTesting(ImmutableList.<Module>of(
new InMemoryTestingDatabaseModule(cfg)));
daemon.start();
} else {
site = initSite(base);
daemonService = Executors.newSingleThreadExecutor();
daemonService.submit(new Callable<Void>() {
public Void call() throws Exception {
int rc = daemon.main(new String[] {"-d", site.getPath(), "--headless" });
if (rc != 0) {
System.out.println("Failed to start Gerrit daemon. Check "
+ site.getPath() + "/logs/error_log");
serverStarted.reset();
}
return null;
};
});
serverStarted.await();
System.out.println("Gerrit Server Started");
}
Injector i = createTestInjector(daemon);
return new GerritServer(site, i, daemon, daemonService);
@@ -91,14 +104,22 @@ public class GerritServer {
throw new RuntimeException("Couldn't initialize site");
}
InetSocketAddress http = newPort();
InetSocketAddress sshd = newPort();
String url = "http://" + format(http) + "/";
MergeableFileBasedConfig cfg = new MergeableFileBasedConfig(
new File(new File(tmp, "etc"), "gerrit.config"),
FS.DETECTED);
cfg.load();
cfg.merge(base);
mergeTestConfig(cfg);
cfg.save();
return tmp;
}
private static void mergeTestConfig(Config cfg)
throws IOException {
InetSocketAddress http = newPort();
InetSocketAddress sshd = newPort();
String url = "http://" + format(http) + "/";
cfg.setString("gerrit", null, "canonicalWebUrl", url);
cfg.setString("httpd", null, "listenUrl", url);
cfg.setString("sshd", null, "listenAddress", format(sshd));
@@ -106,8 +127,6 @@ public class GerritServer {
cfg.setBoolean("sendemail", null, "enable", false);
cfg.setInt("cache", "projects", "checkFrequency", 0);
cfg.setInt("plugins", null, "checkFrequency", 0);
cfg.save();
return tmp;
}
private static String format(InetSocketAddress s) {
@@ -169,11 +188,8 @@ public class GerritServer {
this.daemon = daemon;
this.daemonService = daemonService;
FileBasedConfig cfg = new FileBasedConfig(
new File(new File(sitePath, "etc"), "gerrit.config"),
FS.DETECTED);
cfg.load();
Config cfg = testInjector.getInstance(
Key.get(Config.class, GerritServerConfig.class));
url = cfg.getString("gerrit", null, "canonicalWebUrl");
URI uri = URI.create(url);
@@ -200,12 +216,15 @@ public class GerritServer {
}
void stop() throws Exception {
LifecycleManager manager = get(daemon, "manager");
System.out.println("Gerrit Server Shutdown");
manager.stop();
daemonService.shutdownNow();
daemonService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
TempFileUtil.recursivelyDelete(sitePath);
daemon.getLifecycleManager().stop();
if (daemonService != null) {
System.out.println("Gerrit Server Shutdown");
daemonService.shutdownNow();
daemonService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
}
if (sitePath != null) {
TempFileUtil.recursivelyDelete(sitePath);
}
RepositoryCache.clear();
}
}

View File

@@ -0,0 +1,129 @@
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.acceptance;
import static com.google.inject.Scopes.SINGLETON;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.config.TrackingFootersProvider;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.schema.DataSourceType;
import com.google.gerrit.server.schema.SchemaModule;
import com.google.gerrit.server.schema.SchemaVersion;
import com.google.gerrit.testutil.InMemoryDatabase;
import com.google.gerrit.testutil.InMemoryH2Type;
import com.google.gerrit.testutil.InMemoryRepositoryManager;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.OrmRuntimeException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.eclipse.jgit.lib.Config;
import java.io.File;
class InMemoryTestingDatabaseModule extends AbstractModule {
private final Config cfg;
InMemoryTestingDatabaseModule(Config cfg) {
this.cfg = cfg;
}
@Override
protected void configure() {
bind(Config.class)
.annotatedWith(GerritServerConfig.class)
.toInstance(cfg);
bind(File.class)
.annotatedWith(SitePath.class)
.toInstance(new File("UNIT_TEST_GERRIT_SITE"));
bind(GitRepositoryManager.class)
.toInstance(new InMemoryRepositoryManager());
bind(DataSourceType.class).to(InMemoryH2Type.class);
bind(InMemoryDatabase.class).in(SINGLETON);
bind(new TypeLiteral<SchemaFactory<ReviewDb>>() {})
.to(InMemoryDatabase.class);
install(new LifecycleModule() {
@Override
protected void configure() {
listener().to(CreateDatabase.class);
}
});
bind(SitePaths.class);
bind(TrackingFooters.class)
.toProvider(TrackingFootersProvider.class)
.in(SINGLETON);
install(new SchemaModule());
bind(SchemaVersion.class).to(SchemaVersion.C);
}
@Provides
@Singleton
KeyPairProvider createHostKey() {
return getHostKeys();
}
private static SimpleGeneratorHostKeyProvider keys;
private static synchronized KeyPairProvider getHostKeys() {
if (keys == null) {
keys = new SimpleGeneratorHostKeyProvider();
keys.setAlgorithm("RSA");
keys.loadKeys();
}
return keys;
}
static class CreateDatabase implements LifecycleListener {
private final InMemoryDatabase mem;
@Inject
CreateDatabase(InMemoryDatabase mem) {
this.mem = mem;
}
@Override
public void start() {
try {
mem.create();
} catch (OrmException e) {
throw new OrmRuntimeException(e);
}
}
@Override
public void stop() {
mem.drop();
}
}
}

View File

@@ -0,0 +1,26 @@
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.acceptance;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Target({METHOD})
@Retention(RUNTIME)
public @interface UseLocalDisk {
}

View File

@@ -24,6 +24,7 @@ import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.RestSession;
import com.google.gerrit.acceptance.SshSession;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gwtorm.server.OrmException;
@@ -83,8 +84,8 @@ public class GarbageCollectionIT extends AbstractDaemonTest {
}
@Test
@UseLocalDisk
public void testGcOneProject() throws JSchException, IOException {
assertEquals(HttpStatus.SC_OK, POST("/projects/" + allProjects.get() + "/gc"));
gcAssert.assertHasPackFile(allProjects);
gcAssert.assertHasNoPackFile(project1, project2);

View File

@@ -24,6 +24,7 @@ import com.google.gerrit.acceptance.AccountCreator;
import com.google.gerrit.acceptance.GcAssert;
import com.google.gerrit.acceptance.SshSession;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gerrit.common.data.GarbageCollectionResult;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.AllProjectsName;
@@ -83,6 +84,7 @@ public class GarbageCollectionIT extends AbstractDaemonTest {
}
@Test
@UseLocalDisk
public void testGc() throws JSchException, IOException {
String response =
sshSession.exec("gerrit gc \"" + project1.get() + "\" \""
@@ -94,6 +96,7 @@ public class GarbageCollectionIT extends AbstractDaemonTest {
}
@Test
@UseLocalDisk
public void testGcAll() throws JSchException, IOException {
String response = sshSession.exec("gerrit gc --all");
assertFalse(sshSession.hasError());
@@ -110,6 +113,7 @@ public class GarbageCollectionIT extends AbstractDaemonTest {
}
@Test
@UseLocalDisk
public void testGcAlreadyScheduled() {
gcQueue.addAll(Arrays.asList(project1));
GarbageCollectionResult result = garbageCollectionFactory.create().run(

View File

@@ -16,6 +16,8 @@ package com.google.gerrit.pgm;
import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.gerrit.common.ChangeHookRunner;
import com.google.gerrit.httpd.AllRequestFilter;
import com.google.gerrit.httpd.CacheBasedWebSession;
@@ -61,14 +63,17 @@ import com.google.gerrit.server.schema.SchemaVersionCheck;
import com.google.gerrit.server.ssh.NoSshKeyCache;
import com.google.gerrit.server.ssh.NoSshModule;
import com.google.gerrit.solr.SolrIndexModule;
import com.google.gerrit.sshd.SshHostKeyModule;
import com.google.gerrit.sshd.SshKeyCacheImpl;
import com.google.gerrit.sshd.SshModule;
import com.google.gerrit.sshd.commands.MasterCommandModule;
import com.google.gerrit.sshd.commands.SlaveCommandModule;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Stage;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
@@ -127,12 +132,14 @@ public class Daemon extends SiteProgram {
private Injector webInjector;
private Injector httpdInjector;
private File runFile;
private boolean test;
private Runnable serverStarted;
public Daemon() {
}
@VisibleForTesting
public Daemon(Runnable serverStarted) {
this.serverStarted = serverStarted;
}
@@ -176,22 +183,7 @@ public class Daemon extends SiteProgram {
}
try {
dbInjector = createDbInjector(MULTI_USER);
cfgInjector = createCfgInjector();
sysInjector = createSysInjector();
sysInjector.getInstance(PluginGuiceEnvironment.class)
.setCfgInjector(cfgInjector);
manager.add(dbInjector, cfgInjector, sysInjector);
if (sshd) {
initSshd();
}
if (httpd) {
initHttpd();
}
manager.start();
start();
RuntimeShutdown.add(new Runnable() {
@Override
public void run() {
@@ -232,6 +224,45 @@ public class Daemon extends SiteProgram {
}
}
@VisibleForTesting
public LifecycleManager getLifecycleManager() {
return manager;
}
@VisibleForTesting
public void setDatabaseForTesting(List<Module> modules) {
dbInjector = Guice.createInjector(Stage.PRODUCTION, modules);
test = true;
headless = true;
}
@VisibleForTesting
public void start() {
if (dbInjector == null) {
dbInjector = createDbInjector(MULTI_USER);
}
cfgInjector = createCfgInjector();
sysInjector = createSysInjector();
sysInjector.getInstance(PluginGuiceEnvironment.class)
.setCfgInjector(cfgInjector);
manager.add(dbInjector, cfgInjector, sysInjector);
if (sshd) {
initSshd();
}
if (Objects.firstNonNull(httpd, true)) {
initHttpd();
}
manager.start();
}
@VisibleForTesting
public void stop() {
manager.stop();
}
private String myVersion() {
return com.google.gerrit.common.Version.getVersion();
}
@@ -268,7 +299,7 @@ public class Daemon extends SiteProgram {
changeIndexModule = new NoIndexModule();
}
modules.add(changeIndexModule);
if (httpd) {
if (Objects.firstNonNull(httpd, true)) {
modules.add(new CanonicalWebUrlModule() {
@Override
protected Class<? extends Provider<String>> provider() {
@@ -311,6 +342,9 @@ public class Daemon extends SiteProgram {
final List<Module> modules = new ArrayList<Module>();
if (sshd) {
modules.add(sysInjector.getInstance(SshModule.class));
if (!test) {
modules.add(new SshHostKeyModule());
}
if (slave) {
modules.add(new SlaveCommandModule());
} else {

View File

@@ -50,7 +50,7 @@ public class GetUserFilter implements Filter {
Module(@GerritServerConfig final Config cfg) {
URI[] urls = JettyServer.listenURLs(cfg);
boolean reverseProxy = JettyServer.isReverseProxied(urls);
this.loggingEnabled = cfg.getBoolean("httpd", "requestlog", !reverseProxy);
this.loggingEnabled = cfg.getBoolean("httpd", "requestLog", !reverseProxy);
}
@Override

View File

@@ -136,7 +136,7 @@ public class JettyServer {
httpd.setThreadPool(threadPool(cfg));
Handler app = makeContext(env, cfg);
if (cfg.getBoolean("httpd", "requestlog", !reverseProxy)) {
if (cfg.getBoolean("httpd", "requestLog", !reverseProxy)) {
RequestLogHandler handler = new RequestLogHandler();
handler.setRequestLog(new HttpLog(site, cfg));
handler.setHandler(app);

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.schema;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.SystemConfig;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -30,10 +31,10 @@ import java.io.File;
import java.util.Collections;
public class Schema_55 extends SchemaVersion {
private final LocalDiskRepositoryManager mgr;
private final GitRepositoryManager mgr;
@Inject
Schema_55(Provider<Schema_54> prior, LocalDiskRepositoryManager mgr) {
Schema_55(Provider<Schema_54> prior, GitRepositoryManager mgr) {
super(prior);
this.mgr = mgr;
}
@@ -46,7 +47,7 @@ public class Schema_55 extends SchemaVersion {
if ("-- All Projects --".equals(oldName)) {
ui.message("Renaming \"" + oldName + "\" to \"" + newName + "\"");
File base = mgr.getBasePath();
File base = ((LocalDiskRepositoryManager) mgr).getBasePath();
File oldDir = FileKey.resolve(new File(base, oldName), FS.DETECTED);
File newDir = new File(base, newName + Constants.DOT_GIT_EXT);
if (!oldDir.renameTo(newDir)) {

View File

@@ -17,11 +17,9 @@ package com.google.gerrit.server.schema;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
@@ -34,12 +32,12 @@ import java.util.Map;
import java.util.Set;
public class Schema_56 extends SchemaVersion {
private final LocalDiskRepositoryManager mgr;
private final GitRepositoryManager mgr;
private final Set<String> keysOne;
private final Set<String> keysTwo;
@Inject
Schema_56(Provider<Schema_55> prior, LocalDiskRepositoryManager mgr) {
Schema_56(Provider<Schema_55> prior, GitRepositoryManager mgr) {
super(prior);
this.mgr = mgr;
@@ -57,7 +55,7 @@ public class Schema_56 extends SchemaVersion {
Repository git;
try {
git = mgr.openRepository(name);
} catch (RepositoryNotFoundException e) {
} catch (IOException e) {
ui.message("warning: Cannot open " + name.get());
continue;
}

View File

@@ -27,7 +27,7 @@ import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gwtorm.jdbc.JdbcSchema;
@@ -49,12 +49,12 @@ import java.util.Collections;
public class Schema_57 extends SchemaVersion {
private final SitePaths site;
private final LocalDiskRepositoryManager mgr;
private final GitRepositoryManager mgr;
private final PersonIdent serverUser;
@Inject
Schema_57(Provider<Schema_56> prior, SitePaths site,
LocalDiskRepositoryManager mgr, @GerritPersonIdent PersonIdent serverUser) {
GitRepositoryManager mgr, @GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.site = site;
this.mgr = mgr;

View File

@@ -25,9 +25,9 @@ import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gerrit.testutil.InMemoryDatabase;
import com.google.gerrit.testutil.InMemoryH2Type;
import com.google.gerrit.testutil.InMemoryRepositoryManager;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.gwtorm.server.StatementExecutor;
@@ -74,7 +74,6 @@ public class SchemaUpdaterTest extends TestCase {
install(new SchemaVersion.Module());
Config cfg = new Config();
cfg.setString("gerrit", null, "basePath", "git");
cfg.setString("user", null, "name", "Gerrit Code Review");
cfg.setString("user", null, "email", "gerrit@localhost");
@@ -89,8 +88,8 @@ public class SchemaUpdaterTest extends TestCase {
bind(AllProjectsName.class)
.toInstance(new AllProjectsName("All-Projects"));
bind(GitRepositoryManager.class) //
.to(LocalDiskRepositoryManager.class);
bind(GitRepositoryManager.class)
.toInstance(new InMemoryRepositoryManager());
bind(String.class) //
.annotatedWith(AnonymousCowardName.class) //

View File

@@ -0,0 +1,28 @@
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.sshd;
import static com.google.inject.Scopes.SINGLETON;
import com.google.inject.AbstractModule;
import org.apache.sshd.common.KeyPairProvider;
public class SshHostKeyModule extends AbstractModule {
@Override
protected void configure() {
bind(KeyPairProvider.class).toProvider(HostKeyProvider.class).in(SINGLETON);
}
}

View File

@@ -72,24 +72,28 @@ class SshLog implements LifecycleListener {
this.context = context;
this.auditService = auditService;
final DailyRollingFileAppender dst = new DailyRollingFileAppender();
dst.setName(LOG_NAME);
dst.setLayout(new MyLayout());
dst.setEncoding("UTF-8");
dst.setFile(new File(resolve(site.logs_dir), LOG_NAME).getPath());
dst.setImmediateFlush(true);
dst.setAppend(true);
dst.setThreshold(Level.INFO);
dst.setErrorHandler(new DieErrorHandler());
dst.activateOptions();
dst.setErrorHandler(new LogLogHandler());
if (config.getBoolean("sshd", "requestLog", true)) {
final DailyRollingFileAppender dst = new DailyRollingFileAppender();
dst.setName(LOG_NAME);
dst.setLayout(new MyLayout());
dst.setEncoding("UTF-8");
dst.setFile(new File(resolve(site.logs_dir), LOG_NAME).getPath());
dst.setImmediateFlush(true);
dst.setAppend(true);
dst.setThreshold(Level.INFO);
dst.setErrorHandler(new DieErrorHandler());
dst.activateOptions();
dst.setErrorHandler(new LogLogHandler());
async = new AsyncAppender();
async.setBlocking(true);
async.setBufferSize(config.getInt("core", "asyncLoggingBufferSize", 64));
async.setLocationInfo(false);
async.addAppender(dst);
async.activateOptions();
async = new AsyncAppender();
async.setBlocking(true);
async.setBufferSize(config.getInt("core", "asyncLoggingBufferSize", 64));
async.setLocationInfo(false);
async.addAppender(dst);
async.activateOptions();
} else {
async = null;
}
}
@Override
@@ -98,11 +102,17 @@ class SshLog implements LifecycleListener {
@Override
public void stop() {
async.close();
if (async != null) {
async.close();
}
}
void onLogin() {
async.append(log("LOGIN FROM " + session.get().getRemoteAddressAsString()));
LoggingEvent entry =
log("LOGIN FROM " + session.get().getRemoteAddressAsString());
if (async != null) {
async.append(entry);
}
audit(context.get(), "0", "LOGIN");
}
@@ -127,8 +137,9 @@ class SshLog implements LifecycleListener {
if (error != null) {
event.setProperty(P_STATUS, error);
}
async.append(event);
if (async != null) {
async.append(event);
}
audit(null, "FAIL", "AUTH");
}
@@ -162,7 +173,9 @@ class SshLog implements LifecycleListener {
}
event.setProperty(P_STATUS, status);
async.append(event);
if (async != null) {
async.append(event);
}
audit(context.get(), status, dcmd);
}
@@ -209,7 +222,10 @@ class SshLog implements LifecycleListener {
}
void onLogout() {
async.append(log("LOGOUT"));
LoggingEvent entry = log("LOGOUT");
if (async != null) {
async.append(entry);
}
audit(context.get(), "0", "LOGOUT");
}

View File

@@ -38,7 +38,6 @@ import com.google.inject.Inject;
import com.google.inject.internal.UniqueAnnotations;
import com.google.inject.servlet.RequestScoped;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.auth.gss.GSSAuthenticator;
@@ -85,7 +84,6 @@ public class SshModule extends FactoryModule {
bind(GSSAuthenticator.class).to(GerritGSSAuthenticator.class);
bind(PublickeyAuthenticator.class).to(DatabasePubKeyAuth.class);
bind(KeyPairProvider.class).toProvider(HostKeyProvider.class).in(SINGLETON);
install(new DefaultCommandModule());

View File

@@ -52,6 +52,7 @@ import com.google.gerrit.server.schema.DatabaseModule;
import com.google.gerrit.server.schema.SchemaModule;
import com.google.gerrit.server.schema.SchemaVersionCheck;
import com.google.gerrit.solr.SolrIndexModule;
import com.google.gerrit.sshd.SshHostKeyModule;
import com.google.gerrit.sshd.SshKeyCacheImpl;
import com.google.gerrit.sshd.SshModule;
import com.google.gerrit.sshd.commands.MasterCommandModule;
@@ -294,6 +295,7 @@ public class WebAppInitializer extends GuiceServletContextListener
private Injector createSshInjector() {
final List<Module> modules = new ArrayList<Module>();
modules.add(sysInjector.getInstance(SshModule.class));
modules.add(new SshHostKeyModule());
modules.add(new MasterCommandModule());
return sysInjector.createChildInjector(modules);
}