Optionally, initialize site from WebAppInitializer.
This supports automatic site initialization on Gerrit server startup when Gerrit runs in a servlet container. Both creation of a new site and upgrade of an existing site are supported. This feature may be useful for such setups where Gerrit admins don't have direct access to the database and the file system of the server where Gerrit should be deployed and, therefore, cannot perform the init from their local machine prior to deploying Gerrit on such a server. It may also make deployment and testing in a local servlet container faster to setup as the init step could be skipped. The site initialization will be performed only if the 'gerrit.init' system property exists (the value of the property is not, used only the existence of the property matters). If the 'gerrit.site_path' system property is defined then the init is run for that site. The database connectivity, in that case, is defined in the etc/gerrit.config. If 'gerrit.site_path' is not defined then Gerrit will try to find an existing site by looking into the system_config table in the database defined via the 'jdbc/ReviewDb' JNDI property. If system_config table exists then the site_path from that table is used for initialization. Database connectivity is defined by the jdbc/ReviewDb JNDI property. Finally, if neither 'gerrit.site_path' property nor the system_config table exists, the 'gerrit.init_path' system property, if defined, will be used to determine the site path. Database connectivity, also for this case,is defined by the jdbc/ReviewDb JNDI property. Example 1: Prepare Tomcat so that a site is initialized at a given path using the H2 database (if the site doesn't exist yet) or using whatever database is defined in the etc/gerrit.config of that site: $ export CATALINA_OPTS='-Dgerrit.init -Dgerrit.site_path=/path/to/site' $ catalina.sh start Example 2: Prepare Tomcat so that an existing site with the path defined in the system_config table is initialized (upgraded) on Gerrit startup. The assumption is that the jdbc/ReviewDb JNDI property is defined in Tomcat: $ export CATALINA_OPTS='-Dgerrit.init' $ catalina.sh start Example 3: Assuming the database schema doesn't exist in the database defined via the jdbc/ReviewDb JNDI property, initialize a new site using that database and a given path: $ export CATALINA_OPTS='-Dgerrit.init -Dgerrit.init_path=/path/to/site' $ catalina.sh start Change-Id: Ic3e8c993087d2fbb38e14479a539dc62495ad908
This commit is contained in:
parent
8e0f6d06fe
commit
e5fc90eb67
82
Documentation/config-auto-site-initialization.txt
Normal file
82
Documentation/config-auto-site-initialization.txt
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
Gerrit Code Review - Automatic Site Initialization on Startup
|
||||||
|
=============================================================
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Gerrit supports automatic site initialization on server startup
|
||||||
|
when Gerrit runs in a servlet container. Both creation of a new site
|
||||||
|
and upgrade of an existing site are supported. Installation of
|
||||||
|
plugins during the site creation/initialization is not yet supported.
|
||||||
|
|
||||||
|
This feature may be useful for such setups where Gerrit administrators
|
||||||
|
don't have direct access to the database and the file system of the
|
||||||
|
server where Gerrit should be deployed and, therefore, cannot perform
|
||||||
|
the init from their local machine prior to deploying Gerrit on such a
|
||||||
|
server. It may also make deployment and testing in a local servlet
|
||||||
|
container faster to setup as the init step could be skipped.
|
||||||
|
|
||||||
|
Gerrit Configuration
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The site initialization will be performed only if the `gerrit.init`
|
||||||
|
system property exists (the value of the property is not used, only the
|
||||||
|
existence of the property matters).
|
||||||
|
|
||||||
|
If the `gerrit.site_path` system property is defined then the init is
|
||||||
|
run for that site. The database connectivity, in that case, is defined
|
||||||
|
in the `etc/gerrit.config`.
|
||||||
|
|
||||||
|
If `gerrit.site_path` is not defined then Gerrit will try to find an
|
||||||
|
existing site by looking into the `system_config` table in the database
|
||||||
|
defined via the `jdbc/ReviewDb` JNDI property. If the `system_config`
|
||||||
|
table exists then the `site_path` from that table is used for the
|
||||||
|
initialization. The database connectivity is defined by the
|
||||||
|
`jdbc/ReviewDb` JNDI property.
|
||||||
|
|
||||||
|
Finally, if neither the `gerrit.site_path` property nor the
|
||||||
|
`system_config` table exists, the `gerrit.init_path` system property,
|
||||||
|
if defined, will be used to determine the site path. The database
|
||||||
|
connectivity, also for this case, is defined by the `jdbc/ReviewDb`
|
||||||
|
JNDI property.
|
||||||
|
|
||||||
|
Example 1
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
Prepare Tomcat so that a site is initialized at a given path using
|
||||||
|
the H2 database (if the site doesn't exist yet) or using whatever
|
||||||
|
database is defined in `etc/gerrit.config` of that site:
|
||||||
|
|
||||||
|
----
|
||||||
|
$ export CATALINA_OPTS='-Dgerrit.init -Dgerrit.site_path=/path/to/site'
|
||||||
|
$ catalina.sh start
|
||||||
|
----
|
||||||
|
|
||||||
|
Example 2
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
Prepare Tomcat so that an existing site with the path defined in the
|
||||||
|
`system_config` table is initialized (upgraded) on Gerrit startup. The
|
||||||
|
assumption is that the `jdbc/ReviewDb` JNDI property is defined in
|
||||||
|
Tomcat:
|
||||||
|
|
||||||
|
----
|
||||||
|
$ export CATALINA_OPTS='-Dgerrit.init'
|
||||||
|
$ catalina.sh start
|
||||||
|
----
|
||||||
|
|
||||||
|
Example 3
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
Assuming the database schema doesn't exist in the database defined
|
||||||
|
via the `jdbc/ReviewDb` JNDI property, initialize a new site using that
|
||||||
|
database and a given path:
|
||||||
|
|
||||||
|
----
|
||||||
|
$ export CATALINA_OPTS='-Dgerrit.init -Dgerrit.init_path=/path/to/site'
|
||||||
|
$ catalina.sh start
|
||||||
|
----
|
||||||
|
|
||||||
|
GERRIT
|
||||||
|
------
|
||||||
|
Part of link:index.html[Gerrit Code Review]
|
@ -62,6 +62,7 @@ Index
|
|||||||
.. link:dev-design.html[System Design]
|
.. link:dev-design.html[System Design]
|
||||||
.. link:config-contact.html[User Contact Information]
|
.. link:config-contact.html[User Contact Information]
|
||||||
.. link:config-reverseproxy.html[Reverse Proxy]
|
.. link:config-reverseproxy.html[Reverse Proxy]
|
||||||
|
.. link:config-auto-site-initialization.html[Automatic Site Initialization on Startup]
|
||||||
.. link:pgm-index.html[Server Side Administrative Tools]
|
.. link:pgm-index.html[Server Side Administrative Tools]
|
||||||
. Developer
|
. Developer
|
||||||
.. link:dev-readme.html[Developer Setup]
|
.. link:dev-readme.html[Developer Setup]
|
||||||
|
@ -46,6 +46,9 @@ If you enabled Bouncy Castle Crypto during 'init', copy the JAR
|
|||||||
from `'$site_path'/lib` into your servlet container's extensions
|
from `'$site_path'/lib` into your servlet container's extensions
|
||||||
directory so it's available to Gerrit Code Review.
|
directory so it's available to Gerrit Code Review.
|
||||||
|
|
||||||
|
* ('Optional') link:config-auto-site-initialization.html[
|
||||||
|
Configure Automatic Site Initialization on Startup]
|
||||||
|
|
||||||
|
|
||||||
Jetty 7.x
|
Jetty 7.x
|
||||||
---------
|
---------
|
||||||
|
@ -146,6 +146,7 @@ For more information, see the related topics in this manual:
|
|||||||
* link:config-themes.html[Themes]
|
* link:config-themes.html[Themes]
|
||||||
* link:config-gitweb.html[Gitweb Integration]
|
* link:config-gitweb.html[Gitweb Integration]
|
||||||
* link:config-gerrit.html[Other System Settings]
|
* link:config-gerrit.html[Other System Settings]
|
||||||
|
* link:config-auto-site-initialization.html[Automatic Site Initialization on Startup]
|
||||||
|
|
||||||
|
|
||||||
[[anonymous_access]]
|
[[anonymous_access]]
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
INIT_SRCS = ['src/main/java/com/google/gerrit/pgm/' + n for n in [
|
SRCS = 'src/main/java/com/google/gerrit/pgm/'
|
||||||
|
|
||||||
|
INIT_API_SRCS = [SRCS + n for n in [
|
||||||
'init/InitFlags.java',
|
'init/InitFlags.java',
|
||||||
'init/InitStep.java',
|
'init/InitStep.java',
|
||||||
'init/InitStep.java',
|
'init/InitStep.java',
|
||||||
@ -10,7 +12,7 @@ INIT_SRCS = ['src/main/java/com/google/gerrit/pgm/' + n for n in [
|
|||||||
|
|
||||||
java_library(
|
java_library(
|
||||||
name = 'init-api',
|
name = 'init-api',
|
||||||
srcs = INIT_SRCS,
|
srcs = INIT_API_SRCS,
|
||||||
deps = [
|
deps = [
|
||||||
'//gerrit-server:server',
|
'//gerrit-server:server',
|
||||||
'//lib:jsr305',
|
'//lib:jsr305',
|
||||||
@ -23,16 +25,65 @@ java_library(
|
|||||||
|
|
||||||
java_sources(
|
java_sources(
|
||||||
name = 'init-api-src',
|
name = 'init-api-src',
|
||||||
srcs = INIT_SRCS,
|
srcs = INIT_API_SRCS,
|
||||||
visibility = ['PUBLIC'],
|
visibility = ['PUBLIC'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
INIT_BASE_SRCS = [SRCS + 'BaseInit.java'] + glob(
|
||||||
|
[SRCS + n for n in [
|
||||||
|
'init/**/*.java',
|
||||||
|
'util/**/*.java',
|
||||||
|
]],
|
||||||
|
excludes = INIT_API_SRCS +
|
||||||
|
[SRCS + n for n in [
|
||||||
|
'init/Browser.java',
|
||||||
|
'util/ErrorLogFile.java',
|
||||||
|
'util/GarbageCollectionLogFile.java',
|
||||||
|
'util/LogFileCompressor.java',
|
||||||
|
'util/RuntimeShutdown.java',
|
||||||
|
]]
|
||||||
|
)
|
||||||
|
|
||||||
|
INIT_BASE_RSRCS = ['src/main/resources/com/google/gerrit/pgm/libraries.config']
|
||||||
|
|
||||||
|
java_library2(
|
||||||
|
name = 'init-base',
|
||||||
|
srcs = INIT_BASE_SRCS,
|
||||||
|
resources = INIT_BASE_RSRCS,
|
||||||
|
deps = [
|
||||||
|
':init-api',
|
||||||
|
'//gerrit-common:server',
|
||||||
|
'//gerrit-extension-api:api',
|
||||||
|
'//gerrit-reviewdb:server',
|
||||||
|
'//gerrit-server:server',
|
||||||
|
'//gerrit-util-cli:cli',
|
||||||
|
'//lib/commons:dbcp',
|
||||||
|
'//lib/guice:guice',
|
||||||
|
'//lib/guice:guice-assistedinject',
|
||||||
|
'//lib/jgit:jgit',
|
||||||
|
'//lib/mina:sshd',
|
||||||
|
'//lib:args4j',
|
||||||
|
'//lib:guava',
|
||||||
|
'//lib:gwtjsonrpc',
|
||||||
|
'//lib:gwtorm',
|
||||||
|
'//lib:jsr305',
|
||||||
|
],
|
||||||
|
compile_deps = ['//gerrit-launcher:launcher'],
|
||||||
|
visibility = ['//gerrit-war:'],
|
||||||
|
)
|
||||||
|
|
||||||
java_library2(
|
java_library2(
|
||||||
name = 'pgm',
|
name = 'pgm',
|
||||||
srcs = glob(['src/main/java/**/*.java'], excludes = INIT_SRCS),
|
srcs = glob(
|
||||||
resources = glob(['src/main/resources/**/*']),
|
['src/main/java/**/*.java'],
|
||||||
|
excludes = INIT_API_SRCS + INIT_BASE_SRCS
|
||||||
|
),
|
||||||
|
resources = glob(
|
||||||
|
['src/main/resources/**/*'],
|
||||||
|
excludes = INIT_BASE_RSRCS),
|
||||||
deps = [
|
deps = [
|
||||||
':init-api',
|
':init-api',
|
||||||
|
':init-base',
|
||||||
'//gerrit-cache-h2:cache-h2',
|
'//gerrit-cache-h2:cache-h2',
|
||||||
'//gerrit-common:server',
|
'//gerrit-common:server',
|
||||||
'//gerrit-extension-api:api',
|
'//gerrit-extension-api:api',
|
||||||
@ -49,13 +100,9 @@ java_library2(
|
|||||||
'//lib:args4j',
|
'//lib:args4j',
|
||||||
'//lib:guava',
|
'//lib:guava',
|
||||||
'//lib:gwtorm',
|
'//lib:gwtorm',
|
||||||
'//lib:gwtjsonrpc',
|
|
||||||
'//lib:h2',
|
'//lib:h2',
|
||||||
'//lib:jsr305',
|
|
||||||
'//lib:servlet-api-3_0',
|
'//lib:servlet-api-3_0',
|
||||||
'//lib/commons:dbcp',
|
|
||||||
'//lib/guice:guice',
|
'//lib/guice:guice',
|
||||||
'//lib/guice:guice-assistedinject',
|
|
||||||
'//lib/guice:guice-servlet',
|
'//lib/guice:guice-servlet',
|
||||||
'//lib/jetty:server',
|
'//lib/jetty:server',
|
||||||
'//lib/jetty:servlet',
|
'//lib/jetty:servlet',
|
||||||
@ -63,7 +110,6 @@ java_library2(
|
|||||||
'//lib/log:api',
|
'//lib/log:api',
|
||||||
'//lib/log:log4j',
|
'//lib/log:log4j',
|
||||||
'//lib/lucene:core',
|
'//lib/lucene:core',
|
||||||
'//lib/mina:sshd',
|
|
||||||
'//lib/prolog:prolog-cafe',
|
'//lib/prolog:prolog-cafe',
|
||||||
],
|
],
|
||||||
compile_deps = ['//gerrit-launcher:launcher'],
|
compile_deps = ['//gerrit-launcher:launcher'],
|
||||||
@ -80,6 +126,7 @@ java_test(
|
|||||||
srcs = glob(['src/test/java/**/*.java']),
|
srcs = glob(['src/test/java/**/*.java']),
|
||||||
deps = [
|
deps = [
|
||||||
':init-api',
|
':init-api',
|
||||||
|
':init-base',
|
||||||
':pgm',
|
':pgm',
|
||||||
'//gerrit-server:server',
|
'//gerrit-server:server',
|
||||||
'//lib:junit',
|
'//lib:junit',
|
||||||
|
291
gerrit-pgm/src/main/java/com/google/gerrit/pgm/BaseInit.java
Normal file
291
gerrit-pgm/src/main/java/com/google/gerrit/pgm/BaseInit.java
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
// 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.pgm;
|
||||||
|
|
||||||
|
import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;
|
||||||
|
import static com.google.inject.Stage.PRODUCTION;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.gerrit.pgm.init.InitFlags;
|
||||||
|
import com.google.gerrit.pgm.init.InitModule;
|
||||||
|
import com.google.gerrit.pgm.init.InstallPlugins;
|
||||||
|
import com.google.gerrit.pgm.init.SitePathInitializer;
|
||||||
|
import com.google.gerrit.pgm.util.ConsoleUI;
|
||||||
|
import com.google.gerrit.pgm.util.Die;
|
||||||
|
import com.google.gerrit.pgm.util.SiteProgram;
|
||||||
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
|
import com.google.gerrit.server.config.SitePath;
|
||||||
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
|
import com.google.gerrit.server.schema.SchemaUpdater;
|
||||||
|
import com.google.gerrit.server.schema.UpdateUI;
|
||||||
|
import com.google.gwtorm.jdbc.JdbcExecutor;
|
||||||
|
import com.google.gwtorm.jdbc.JdbcSchema;
|
||||||
|
import com.google.gwtorm.server.OrmException;
|
||||||
|
import com.google.gwtorm.server.SchemaFactory;
|
||||||
|
import com.google.gwtorm.server.StatementExecutor;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.CreationException;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.spi.Message;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
/** Initialize a new Gerrit installation. */
|
||||||
|
public class BaseInit extends SiteProgram {
|
||||||
|
|
||||||
|
private final boolean standalone;
|
||||||
|
|
||||||
|
public BaseInit() {
|
||||||
|
this.standalone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseInit(File sitePath, boolean standalone) {
|
||||||
|
this(sitePath, null, standalone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseInit(File sitePath, final Provider<DataSource> dsProvider,
|
||||||
|
boolean standalone) {
|
||||||
|
super(sitePath, dsProvider);
|
||||||
|
this.standalone = standalone;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int run() throws Exception {
|
||||||
|
final SiteInit init = createSiteInit();
|
||||||
|
beforeInit(init);
|
||||||
|
|
||||||
|
init.flags.autoStart = getAutoStart() && init.site.isNew;;
|
||||||
|
|
||||||
|
final SiteRun run;
|
||||||
|
try {
|
||||||
|
init.initializer.run();
|
||||||
|
init.flags.deleteOnFailure = false;
|
||||||
|
|
||||||
|
run = createSiteRun(init);
|
||||||
|
run.upgradeSchema();
|
||||||
|
} catch (Exception failure) {
|
||||||
|
if (init.flags.deleteOnFailure) {
|
||||||
|
recursiveDelete(getSitePath());
|
||||||
|
}
|
||||||
|
throw failure;
|
||||||
|
} catch (Error failure) {
|
||||||
|
if (init.flags.deleteOnFailure) {
|
||||||
|
recursiveDelete(getSitePath());
|
||||||
|
}
|
||||||
|
throw failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.err.println("Initialized " + getSitePath().getCanonicalPath());
|
||||||
|
afterInit(run);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void beforeInit(SiteInit init) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void afterInit(SiteRun run) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> getInstallPlugins() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean getAutoStart() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SiteInit {
|
||||||
|
final SitePaths site;
|
||||||
|
final InitFlags flags;
|
||||||
|
final ConsoleUI ui;
|
||||||
|
final SitePathInitializer initializer;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SiteInit(final SitePaths site, final InitFlags flags, final ConsoleUI ui,
|
||||||
|
final SitePathInitializer initializer) {
|
||||||
|
this.site = site;
|
||||||
|
this.flags = flags;
|
||||||
|
this.ui = ui;
|
||||||
|
this.initializer = initializer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SiteInit createSiteInit() {
|
||||||
|
final ConsoleUI ui = getConsoleUI();
|
||||||
|
final File sitePath = getSitePath();
|
||||||
|
final List<Module> m = new ArrayList<Module>();
|
||||||
|
|
||||||
|
m.add(new InitModule(standalone));
|
||||||
|
m.add(new AbstractModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(ConsoleUI.class).toInstance(ui);
|
||||||
|
bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath);
|
||||||
|
List<String> plugins =
|
||||||
|
Objects.firstNonNull(getInstallPlugins(), Lists.<String> newArrayList());
|
||||||
|
bind(new TypeLiteral<List<String>>() {}).annotatedWith(
|
||||||
|
InstallPlugins.class).toInstance(plugins);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Guice.createInjector(PRODUCTION, m).getInstance(SiteInit.class);
|
||||||
|
} catch (CreationException ce) {
|
||||||
|
final Message first = ce.getErrorMessages().iterator().next();
|
||||||
|
Throwable why = first.getCause();
|
||||||
|
|
||||||
|
if (why instanceof Die) {
|
||||||
|
throw (Die) why;
|
||||||
|
}
|
||||||
|
|
||||||
|
final StringBuilder buf = new StringBuilder(ce.getMessage());
|
||||||
|
while (why != null) {
|
||||||
|
buf.append("\n");
|
||||||
|
buf.append(why.getMessage());
|
||||||
|
why = why.getCause();
|
||||||
|
if (why != null) {
|
||||||
|
buf.append("\n caused by ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw die(buf.toString(), new RuntimeException("InitInjector failed", ce));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ConsoleUI getConsoleUI() {
|
||||||
|
return ConsoleUI.getInstance(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SiteRun {
|
||||||
|
final ConsoleUI ui;
|
||||||
|
final SitePaths site;
|
||||||
|
final InitFlags flags;
|
||||||
|
final SchemaUpdater schemaUpdater;
|
||||||
|
final SchemaFactory<ReviewDb> schema;
|
||||||
|
final GitRepositoryManager repositoryManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SiteRun(final ConsoleUI ui, final SitePaths site, final InitFlags flags,
|
||||||
|
final SchemaUpdater schemaUpdater,
|
||||||
|
final SchemaFactory<ReviewDb> schema,
|
||||||
|
final GitRepositoryManager repositoryManager) {
|
||||||
|
this.ui = ui;
|
||||||
|
this.site = site;
|
||||||
|
this.flags = flags;
|
||||||
|
this.schemaUpdater = schemaUpdater;
|
||||||
|
this.schema = schema;
|
||||||
|
this.repositoryManager = repositoryManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void upgradeSchema() throws OrmException {
|
||||||
|
final List<String> pruneList = new ArrayList<String>();
|
||||||
|
schemaUpdater.update(new UpdateUI() {
|
||||||
|
@Override
|
||||||
|
public void message(String msg) {
|
||||||
|
System.err.println(msg);
|
||||||
|
System.err.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean yesno(boolean def, String msg) {
|
||||||
|
return ui.yesno(def, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBatch() {
|
||||||
|
return ui.isBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pruneSchema(StatementExecutor e, List<String> prune) {
|
||||||
|
for (String p : prune) {
|
||||||
|
if (!pruneList.contains(p)) {
|
||||||
|
pruneList.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pruneList.isEmpty()) {
|
||||||
|
StringBuilder msg = new StringBuilder();
|
||||||
|
msg.append("Execute the following SQL to drop unused objects:\n");
|
||||||
|
msg.append("\n");
|
||||||
|
for (String sql : pruneList) {
|
||||||
|
msg.append(" ");
|
||||||
|
msg.append(sql);
|
||||||
|
msg.append(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui.isBatch()) {
|
||||||
|
System.err.print(msg);
|
||||||
|
System.err.flush();
|
||||||
|
|
||||||
|
} else if (ui.yesno(true, "%s\nExecute now", msg)) {
|
||||||
|
final JdbcSchema db = (JdbcSchema) schema.open();
|
||||||
|
try {
|
||||||
|
final JdbcExecutor e = new JdbcExecutor(db);
|
||||||
|
try {
|
||||||
|
for (String sql : pruneList) {
|
||||||
|
e.execute(sql);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
e.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SiteRun createSiteRun(final SiteInit init) {
|
||||||
|
return createSysInjector(init).getInstance(SiteRun.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Injector createSysInjector(final SiteInit init) {
|
||||||
|
final List<Module> modules = new ArrayList<Module>();
|
||||||
|
modules.add(new AbstractModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(ConsoleUI.class).toInstance(init.ui);
|
||||||
|
bind(InitFlags.class).toInstance(init.flags);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return createDbInjector(SINGLE_USER).createChildInjector(modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void recursiveDelete(File path) {
|
||||||
|
File[] entries = path.listFiles();
|
||||||
|
if (entries != null) {
|
||||||
|
for (File e : entries) {
|
||||||
|
recursiveDelete(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!path.delete() && path.exists()) {
|
||||||
|
System.err.println("warn: Cannot remove " + path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,56 +14,36 @@
|
|||||||
|
|
||||||
package com.google.gerrit.pgm;
|
package com.google.gerrit.pgm;
|
||||||
|
|
||||||
import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;
|
|
||||||
import static com.google.inject.Stage.PRODUCTION;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Objects;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.gerrit.common.PageLinks;
|
import com.google.gerrit.common.PageLinks;
|
||||||
import com.google.gerrit.pgm.init.Browser;
|
import com.google.gerrit.pgm.init.Browser;
|
||||||
import com.google.gerrit.pgm.init.InitFlags;
|
|
||||||
import com.google.gerrit.pgm.init.InitModule;
|
|
||||||
import com.google.gerrit.pgm.init.InitPlugins;
|
import com.google.gerrit.pgm.init.InitPlugins;
|
||||||
import com.google.gerrit.pgm.init.InitPlugins.PluginData;
|
import com.google.gerrit.pgm.init.InitPlugins.PluginData;
|
||||||
import com.google.gerrit.pgm.init.InstallPlugins;
|
|
||||||
import com.google.gerrit.pgm.init.SitePathInitializer;
|
|
||||||
import com.google.gerrit.pgm.util.ConsoleUI;
|
import com.google.gerrit.pgm.util.ConsoleUI;
|
||||||
import com.google.gerrit.pgm.util.Die;
|
|
||||||
import com.google.gerrit.pgm.util.ErrorLogFile;
|
import com.google.gerrit.pgm.util.ErrorLogFile;
|
||||||
import com.google.gerrit.pgm.util.IoUtil;
|
import com.google.gerrit.pgm.util.IoUtil;
|
||||||
import com.google.gerrit.pgm.util.SiteProgram;
|
import com.google.gerrit.server.config.GerritServerConfigModule;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.config.SitePath;
|
import com.google.gerrit.server.config.SitePath;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
|
||||||
import com.google.gerrit.server.schema.SchemaUpdater;
|
|
||||||
import com.google.gerrit.server.schema.UpdateUI;
|
|
||||||
import com.google.gerrit.server.util.HostPlatform;
|
import com.google.gerrit.server.util.HostPlatform;
|
||||||
import com.google.gwtorm.jdbc.JdbcExecutor;
|
|
||||||
import com.google.gwtorm.jdbc.JdbcSchema;
|
|
||||||
import com.google.gwtorm.server.OrmException;
|
|
||||||
import com.google.gwtorm.server.SchemaFactory;
|
|
||||||
import com.google.gwtorm.server.StatementExecutor;
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.CreationException;
|
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Injector;
|
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.spi.Message;
|
|
||||||
|
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
/** Initialize a new Gerrit installation. */
|
/** Initialize a new Gerrit installation. */
|
||||||
public class Init extends SiteProgram {
|
public class Init extends BaseInit {
|
||||||
@Option(name = "--batch", usage = "Batch mode; skip interactive prompting")
|
@Option(name = "--batch", usage = "Batch mode; skip interactive prompting")
|
||||||
private boolean batchMode;
|
private boolean batchMode;
|
||||||
|
|
||||||
@ -79,20 +59,26 @@ public class Init extends SiteProgram {
|
|||||||
@Option(name = "--install-plugin", usage = "Install given plugin without asking", multiValued = true)
|
@Option(name = "--install-plugin", usage = "Install given plugin without asking", multiValued = true)
|
||||||
private List<String> installPlugins;
|
private List<String> installPlugins;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Browser browser;
|
||||||
|
|
||||||
public Init() {
|
public Init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Init(File sitePath) {
|
public Init(File sitePath) {
|
||||||
super(sitePath);
|
this(sitePath, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Init(File sitePath, final Provider<DataSource> dsProvider) {
|
||||||
|
super(sitePath, dsProvider, true);
|
||||||
batchMode = true;
|
batchMode = true;
|
||||||
noAutoStart = true;
|
noAutoStart = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int run() throws Exception {
|
protected void beforeInit(SiteInit init) throws Exception {
|
||||||
ErrorLogFile.errorOnlyConsole();
|
ErrorLogFile.errorOnlyConsole();
|
||||||
|
|
||||||
final SiteInit init = createSiteInit();
|
|
||||||
if (!skipPlugins) {
|
if (!skipPlugins) {
|
||||||
final List<PluginData> plugins = InitPlugins.listPlugins(init.site);
|
final List<PluginData> plugins = InitPlugins.listPlugins(init.site);
|
||||||
ConsoleUI ui = ConsoleUI.getInstance(false);
|
ConsoleUI ui = ConsoleUI.getInstance(false);
|
||||||
@ -106,195 +92,56 @@ public class Init extends SiteProgram {
|
|||||||
} else {
|
} else {
|
||||||
ui.message("No plugins found.\n");
|
ui.message("No plugins found.\n");
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init.flags.autoStart = !noAutoStart && init.site.isNew;
|
@Override
|
||||||
init.flags.skipPlugins = skipPlugins;
|
protected void afterInit(SiteRun run) throws Exception {
|
||||||
|
List<Module> modules = Lists.newArrayList();
|
||||||
final SiteRun run;
|
modules.add(new AbstractModule() {
|
||||||
try {
|
|
||||||
init.initializer.run();
|
|
||||||
init.flags.deleteOnFailure = false;
|
|
||||||
|
|
||||||
run = createSiteRun(init);
|
|
||||||
run.upgradeSchema();
|
|
||||||
} catch (Exception failure) {
|
|
||||||
if (init.flags.deleteOnFailure) {
|
|
||||||
recursiveDelete(getSitePath());
|
|
||||||
}
|
|
||||||
throw failure;
|
|
||||||
} catch (Error failure) {
|
|
||||||
if (init.flags.deleteOnFailure) {
|
|
||||||
recursiveDelete(getSitePath());
|
|
||||||
}
|
|
||||||
throw failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
System.err.println("Initialized " + getSitePath().getCanonicalPath());
|
|
||||||
run.start();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class SiteInit {
|
|
||||||
final SitePaths site;
|
|
||||||
final InitFlags flags;
|
|
||||||
final ConsoleUI ui;
|
|
||||||
final SitePathInitializer initializer;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
SiteInit(final SitePaths site, final InitFlags flags, final ConsoleUI ui,
|
|
||||||
final SitePathInitializer initializer) {
|
|
||||||
this.site = site;
|
|
||||||
this.flags = flags;
|
|
||||||
this.ui = ui;
|
|
||||||
this.initializer = initializer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SiteInit createSiteInit() {
|
|
||||||
final ConsoleUI ui = ConsoleUI.getInstance(batchMode);
|
|
||||||
final File sitePath = getSitePath();
|
|
||||||
final List<Module> m = new ArrayList<Module>();
|
|
||||||
|
|
||||||
m.add(new InitModule());
|
|
||||||
m.add(new AbstractModule() {
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(ConsoleUI.class).toInstance(ui);
|
bind(File.class).annotatedWith(SitePath.class).toInstance(getSitePath());
|
||||||
bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath);
|
bind(Browser.class);
|
||||||
List<String> plugins =
|
|
||||||
Objects.firstNonNull(installPlugins, Lists.<String> newArrayList());
|
|
||||||
bind(new TypeLiteral<List<String>>() {}).annotatedWith(
|
|
||||||
InstallPlugins.class).toInstance(plugins);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
modules.add(new GerritServerConfigModule());
|
||||||
try {
|
Guice.createInjector(modules).injectMembers(this);
|
||||||
return Guice.createInjector(PRODUCTION, m).getInstance(SiteInit.class);
|
start(run);
|
||||||
} catch (CreationException ce) {
|
|
||||||
final Message first = ce.getErrorMessages().iterator().next();
|
|
||||||
Throwable why = first.getCause();
|
|
||||||
|
|
||||||
if (why instanceof Die) {
|
|
||||||
throw (Die) why;
|
|
||||||
}
|
|
||||||
|
|
||||||
final StringBuilder buf = new StringBuilder(ce.getMessage());
|
|
||||||
while (why != null) {
|
|
||||||
buf.append("\n");
|
|
||||||
buf.append(why.getMessage());
|
|
||||||
why = why.getCause();
|
|
||||||
if (why != null) {
|
|
||||||
buf.append("\n caused by ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw die(buf.toString(), new RuntimeException("InitInjector failed", ce));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class SiteRun {
|
|
||||||
final ConsoleUI ui;
|
|
||||||
final SitePaths site;
|
|
||||||
final InitFlags flags;
|
|
||||||
final SchemaUpdater schemaUpdater;
|
|
||||||
final SchemaFactory<ReviewDb> schema;
|
|
||||||
final GitRepositoryManager repositoryManager;
|
|
||||||
final Browser browser;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
SiteRun(final ConsoleUI ui, final SitePaths site, final InitFlags flags,
|
|
||||||
final SchemaUpdater schemaUpdater,
|
|
||||||
final SchemaFactory<ReviewDb> schema,
|
|
||||||
final GitRepositoryManager repositoryManager,
|
|
||||||
final Browser browser) {
|
|
||||||
this.ui = ui;
|
|
||||||
this.site = site;
|
|
||||||
this.flags = flags;
|
|
||||||
this.schemaUpdater = schemaUpdater;
|
|
||||||
this.schema = schema;
|
|
||||||
this.repositoryManager = repositoryManager;
|
|
||||||
this.browser = browser;
|
|
||||||
}
|
|
||||||
|
|
||||||
void upgradeSchema() throws OrmException {
|
|
||||||
final List<String> pruneList = new ArrayList<String>();
|
|
||||||
schemaUpdater.update(new UpdateUI() {
|
|
||||||
@Override
|
|
||||||
public void message(String msg) {
|
|
||||||
System.err.println(msg);
|
|
||||||
System.err.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean yesno(boolean def, String msg) {
|
protected List<String> getInstallPlugins() {
|
||||||
return ui.yesno(def, msg);
|
return installPlugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBatch() {
|
protected ConsoleUI getConsoleUI() {
|
||||||
return ui.isBatch();
|
return ConsoleUI.getInstance(batchMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pruneSchema(StatementExecutor e, List<String> prune) {
|
protected boolean getAutoStart() {
|
||||||
for (String p : prune) {
|
return !noAutoStart;
|
||||||
if (!pruneList.contains(p)) {
|
|
||||||
pruneList.add(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!pruneList.isEmpty()) {
|
|
||||||
StringBuilder msg = new StringBuilder();
|
|
||||||
msg.append("Execute the following SQL to drop unused objects:\n");
|
|
||||||
msg.append("\n");
|
|
||||||
for (String sql : pruneList) {
|
|
||||||
msg.append(" ");
|
|
||||||
msg.append(sql);
|
|
||||||
msg.append(";\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ui.isBatch()) {
|
void start(SiteRun run) throws Exception {
|
||||||
System.err.print(msg);
|
if (run.flags.autoStart) {
|
||||||
System.err.flush();
|
|
||||||
|
|
||||||
} else if (ui.yesno(true, "%s\nExecute now", msg)) {
|
|
||||||
final JdbcSchema db = (JdbcSchema) schema.open();
|
|
||||||
try {
|
|
||||||
final JdbcExecutor e = new JdbcExecutor(db);
|
|
||||||
try {
|
|
||||||
for (String sql : pruneList) {
|
|
||||||
e.execute(sql);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
e.close();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() throws Exception {
|
|
||||||
if (flags.autoStart) {
|
|
||||||
if (HostPlatform.isWin32()) {
|
if (HostPlatform.isWin32()) {
|
||||||
System.err.println("Automatic startup not supported on Win32.");
|
System.err.println("Automatic startup not supported on Win32.");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
startDaemon();
|
startDaemon(run);
|
||||||
if (!ui.isBatch()) {
|
if (!run.ui.isBatch()) {
|
||||||
browser.open(PageLinks.ADMIN_PROJECTS);
|
browser.open(PageLinks.ADMIN_PROJECTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void startDaemon() {
|
void startDaemon(SiteRun run) {
|
||||||
final String[] argv = {site.gerrit_sh.getAbsolutePath(), "start"};
|
final String[] argv = {run.site.gerrit_sh.getAbsolutePath(), "start"};
|
||||||
final Process proc;
|
final Process proc;
|
||||||
try {
|
try {
|
||||||
System.err.println("Executing " + argv[0] + " " + argv[1]);
|
System.err.println("Executing " + argv[0] + " " + argv[1]);
|
||||||
@ -325,36 +172,6 @@ public class Init extends SiteProgram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private SiteRun createSiteRun(final SiteInit init) {
|
|
||||||
return createSysInjector(init).getInstance(SiteRun.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Injector createSysInjector(final SiteInit init) {
|
|
||||||
final List<Module> modules = new ArrayList<Module>();
|
|
||||||
modules.add(new AbstractModule() {
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
bind(ConsoleUI.class).toInstance(init.ui);
|
|
||||||
bind(InitFlags.class).toInstance(init.flags);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return createDbInjector(SINGLE_USER).createChildInjector(modules);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void recursiveDelete(File path) {
|
|
||||||
File[] entries = path.listFiles();
|
|
||||||
if (entries != null) {
|
|
||||||
for (File e : entries) {
|
|
||||||
recursiveDelete(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!path.delete() && path.exists()) {
|
|
||||||
System.err.println("warn: Cannot remove " + path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void verifyInstallPluginList(ConsoleUI ui, List<PluginData> plugins) {
|
private void verifyInstallPluginList(ConsoleUI ui, List<PluginData> plugins) {
|
||||||
if (nullOrEmpty(installPlugins) || nullOrEmpty(plugins)) {
|
if (nullOrEmpty(installPlugins) || nullOrEmpty(plugins)) {
|
||||||
return;
|
return;
|
||||||
|
@ -23,6 +23,13 @@ import java.lang.annotation.Annotation;
|
|||||||
|
|
||||||
/** Injection configuration for the site initialization process. */
|
/** Injection configuration for the site initialization process. */
|
||||||
public class InitModule extends FactoryModule {
|
public class InitModule extends FactoryModule {
|
||||||
|
|
||||||
|
private final boolean standalone;
|
||||||
|
|
||||||
|
public InitModule(boolean standalone) {
|
||||||
|
this.standalone = standalone;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(SitePaths.class);
|
bind(SitePaths.class);
|
||||||
@ -36,15 +43,21 @@ public class InitModule extends FactoryModule {
|
|||||||
step().to(UpgradeFrom2_0_x.class);
|
step().to(UpgradeFrom2_0_x.class);
|
||||||
|
|
||||||
step().to(InitGitManager.class);
|
step().to(InitGitManager.class);
|
||||||
|
if (standalone) {
|
||||||
step().to(InitDatabase.class);
|
step().to(InitDatabase.class);
|
||||||
|
}
|
||||||
step().to(InitAuth.class);
|
step().to(InitAuth.class);
|
||||||
step().to(InitSendEmail.class);
|
step().to(InitSendEmail.class);
|
||||||
|
if (standalone) {
|
||||||
step().to(InitContainer.class);
|
step().to(InitContainer.class);
|
||||||
|
}
|
||||||
step().to(InitSshd.class);
|
step().to(InitSshd.class);
|
||||||
step().to(InitHttpd.class);
|
step().to(InitHttpd.class);
|
||||||
step().to(InitCache.class);
|
step().to(InitCache.class);
|
||||||
|
if (standalone) {
|
||||||
step().to(InitPlugins.class);
|
step().to(InitPlugins.class);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected LinkedBindingBuilder<InitStep> step() {
|
protected LinkedBindingBuilder<InitStep> step() {
|
||||||
final Annotation id = UniqueAnnotations.create();
|
final Annotation id = UniqueAnnotations.create();
|
||||||
|
@ -22,7 +22,7 @@ import static com.google.gerrit.pgm.init.InitUtil.savePublic;
|
|||||||
import static com.google.gerrit.pgm.init.InitUtil.saveSecure;
|
import static com.google.gerrit.pgm.init.InitUtil.saveSecure;
|
||||||
import static com.google.gerrit.pgm.init.InitUtil.version;
|
import static com.google.gerrit.pgm.init.InitUtil.version;
|
||||||
|
|
||||||
import com.google.gerrit.pgm.Init;
|
import com.google.gerrit.pgm.BaseInit;
|
||||||
import com.google.gerrit.pgm.util.ConsoleUI;
|
import com.google.gerrit.pgm.util.ConsoleUI;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gerrit.server.mail.OutgoingEmail;
|
import com.google.gerrit.server.mail.OutgoingEmail;
|
||||||
@ -85,7 +85,7 @@ public class SitePathInitializer {
|
|||||||
savePublic(flags.cfg);
|
savePublic(flags.cfg);
|
||||||
saveSecure(flags.sec);
|
saveSecure(flags.sec);
|
||||||
|
|
||||||
extract(site.gerrit_sh, Init.class, "gerrit.sh");
|
extract(site.gerrit_sh, BaseInit.class, "gerrit.sh");
|
||||||
chmod(0755, site.gerrit_sh);
|
chmod(0755, site.gerrit_sh);
|
||||||
chmod(0700, site.tmp_dir);
|
chmod(0700, site.tmp_dir);
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ package com.google.gerrit.pgm.util;
|
|||||||
import static com.google.inject.Scopes.SINGLETON;
|
import static com.google.inject.Scopes.SINGLETON;
|
||||||
import static com.google.inject.Stage.PRODUCTION;
|
import static com.google.inject.Stage.PRODUCTION;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.gerrit.extensions.events.LifecycleListener;
|
||||||
import com.google.gerrit.lifecycle.LifecycleModule;
|
import com.google.gerrit.lifecycle.LifecycleModule;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.config.GerritServerConfigModule;
|
import com.google.gerrit.server.config.GerritServerConfigModule;
|
||||||
@ -29,11 +31,15 @@ import com.google.gerrit.server.schema.DatabaseModule;
|
|||||||
import com.google.gerrit.server.schema.SchemaModule;
|
import com.google.gerrit.server.schema.SchemaModule;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Binding;
|
||||||
import com.google.inject.CreationException;
|
import com.google.inject.CreationException;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.name.Named;
|
||||||
import com.google.inject.name.Names;
|
import com.google.inject.name.Names;
|
||||||
import com.google.inject.spi.Message;
|
import com.google.inject.spi.Message;
|
||||||
|
|
||||||
@ -41,6 +47,8 @@ import org.eclipse.jgit.lib.Config;
|
|||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -51,11 +59,14 @@ public abstract class SiteProgram extends AbstractProgram {
|
|||||||
@Option(name = "--site-path", aliases = {"-d"}, usage = "Local directory containing site data")
|
@Option(name = "--site-path", aliases = {"-d"}, usage = "Local directory containing site data")
|
||||||
private File sitePath = new File(".");
|
private File sitePath = new File(".");
|
||||||
|
|
||||||
|
protected Provider<DataSource> dsProvider;
|
||||||
|
|
||||||
protected SiteProgram() {
|
protected SiteProgram() {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SiteProgram(File sitePath) {
|
protected SiteProgram(File sitePath, final Provider<DataSource> dsProvider) {
|
||||||
this.sitePath = sitePath;
|
this.sitePath = sitePath;
|
||||||
|
this.dsProvider = dsProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return the site path specified on the command line. */
|
/** @return the site path specified on the command line. */
|
||||||
@ -92,17 +103,31 @@ public abstract class SiteProgram extends AbstractProgram {
|
|||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(DataSourceProvider.Context.class).toInstance(context);
|
bind(DataSourceProvider.Context.class).toInstance(context);
|
||||||
|
if (dsProvider != null) {
|
||||||
|
bind(Key.get(DataSource.class, Names.named("ReviewDb")))
|
||||||
|
.toProvider(dsProvider)
|
||||||
|
.in(SINGLETON);
|
||||||
|
if (LifecycleListener.class.isAssignableFrom(dsProvider.getClass())) {
|
||||||
|
listener().toInstance((LifecycleListener) dsProvider);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
bind(Key.get(DataSource.class, Names.named("ReviewDb")))
|
bind(Key.get(DataSource.class, Names.named("ReviewDb")))
|
||||||
.toProvider(SiteLibraryBasedDataSourceProvider.class)
|
.toProvider(SiteLibraryBasedDataSourceProvider.class)
|
||||||
.in(SINGLETON);
|
.in(SINGLETON);
|
||||||
listener().to(SiteLibraryBasedDataSourceProvider.class);
|
listener().to(SiteLibraryBasedDataSourceProvider.class);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
Module configModule = new GerritServerConfigModule();
|
Module configModule = new GerritServerConfigModule();
|
||||||
modules.add(configModule);
|
modules.add(configModule);
|
||||||
Injector cfgInjector = Guice.createInjector(sitePathModule, configModule);
|
Injector cfgInjector = Guice.createInjector(sitePathModule, configModule);
|
||||||
Config cfg = cfgInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
|
Config cfg = cfgInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
|
||||||
String dbType = cfg.getString("database", null, "type");
|
String dbType;
|
||||||
|
if (dsProvider != null) {
|
||||||
|
dbType = getDbType(dsProvider);
|
||||||
|
} else {
|
||||||
|
dbType = cfg.getString("database", null, "type");
|
||||||
|
}
|
||||||
|
|
||||||
final DataSourceType dst = Guice.createInjector(new DataSourceModule(), configModule,
|
final DataSourceType dst = Guice.createInjector(new DataSourceModule(), configModule,
|
||||||
sitePathModule).getInstance(
|
sitePathModule).getInstance(
|
||||||
@ -151,6 +176,44 @@ public abstract class SiteProgram extends AbstractProgram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getDbType(Provider<DataSource> dsProvider) {
|
||||||
|
String dbProductName;
|
||||||
|
try {
|
||||||
|
Connection conn = dsProvider.get().getConnection();
|
||||||
|
try {
|
||||||
|
dbProductName = conn.getMetaData().getDatabaseProductName().toLowerCase();
|
||||||
|
} finally {
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Module> modules = Lists.newArrayList();
|
||||||
|
modules.add(new AbstractModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
modules.add(new GerritServerConfigModule());
|
||||||
|
modules.add(new DataSourceModule());
|
||||||
|
Injector i = Guice.createInjector(modules);
|
||||||
|
List<Binding<DataSourceType>> dsTypeBindings =
|
||||||
|
i.findBindingsByType(new TypeLiteral<DataSourceType>() {});
|
||||||
|
for (Binding<DataSourceType> binding : dsTypeBindings) {
|
||||||
|
Annotation annotation = binding.getKey().getAnnotation();
|
||||||
|
if (annotation instanceof Named) {
|
||||||
|
if (((Named) annotation).value().toLowerCase().contains(dbProductName)) {
|
||||||
|
return ((Named) annotation).value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalStateException(String.format(
|
||||||
|
"Cannot guess database type from the database product name '%s'",
|
||||||
|
dbProductName));
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private static boolean isCannotCreatePoolException(Throwable why) {
|
private static boolean isCannotCreatePoolException(Throwable why) {
|
||||||
return why instanceof org.apache.commons.dbcp.SQLNestedException
|
return why instanceof org.apache.commons.dbcp.SQLNestedException
|
||||||
|
@ -9,11 +9,13 @@ java_library2(
|
|||||||
'//gerrit-httpd:httpd',
|
'//gerrit-httpd:httpd',
|
||||||
'//gerrit-lucene:lucene',
|
'//gerrit-lucene:lucene',
|
||||||
'//gerrit-openid:openid',
|
'//gerrit-openid:openid',
|
||||||
|
'//gerrit-pgm:init-base',
|
||||||
'//gerrit-reviewdb:server',
|
'//gerrit-reviewdb:server',
|
||||||
'//gerrit-server:server',
|
'//gerrit-server:server',
|
||||||
'//gerrit-server/src/main/prolog:common',
|
'//gerrit-server/src/main/prolog:common',
|
||||||
'//gerrit-solr:solr',
|
'//gerrit-solr:solr',
|
||||||
'//gerrit-sshd:sshd',
|
'//gerrit-sshd:sshd',
|
||||||
|
'//lib:guava',
|
||||||
'//lib:gwtorm',
|
'//lib:gwtorm',
|
||||||
'//lib/guice:guice',
|
'//lib/guice:guice',
|
||||||
'//lib/guice:guice-servlet',
|
'//lib/guice:guice-servlet',
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
// 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.httpd;
|
||||||
|
|
||||||
|
import com.google.gerrit.pgm.BaseInit;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public final class SiteInitializer {
|
||||||
|
private static final Logger log = LoggerFactory
|
||||||
|
.getLogger(SiteInitializer.class);
|
||||||
|
|
||||||
|
final String sitePath;
|
||||||
|
final String initPath;
|
||||||
|
|
||||||
|
SiteInitializer(String sitePath, String initPath) {
|
||||||
|
this.sitePath = sitePath;
|
||||||
|
this.initPath = initPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (sitePath != null) {
|
||||||
|
File site = new File(sitePath);
|
||||||
|
log.info(String.format("Initializing site at %s",
|
||||||
|
site.getAbsolutePath()));
|
||||||
|
new BaseInit(site, false).run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection conn = connectToDb();
|
||||||
|
try {
|
||||||
|
File site = getSiteFromReviewDb(conn);
|
||||||
|
if (site == null && initPath != null) {
|
||||||
|
site = new File(initPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (site != null) {
|
||||||
|
log.info(String.format("Initializing site at %s",
|
||||||
|
site.getAbsolutePath()));
|
||||||
|
new BaseInit(site, new ReviewDbDataSourceProvider(), false).run();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Site init failed", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Connection connectToDb() throws SQLException {
|
||||||
|
return new ReviewDbDataSourceProvider().get().getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getSiteFromReviewDb(Connection conn) {
|
||||||
|
try {
|
||||||
|
ResultSet rs = conn.createStatement().executeQuery(
|
||||||
|
"select site_path from system_config");
|
||||||
|
if (rs.next()) {
|
||||||
|
return new File(rs.getString(1));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -115,6 +115,10 @@ public class WebAppInitializer extends GuiceServletContextListener
|
|||||||
sitePath = new File(path);
|
sitePath = new File(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (System.getProperty("gerrit.init") != null) {
|
||||||
|
new SiteInitializer(path, System.getProperty("gerrit.init_path")).init();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dbInjector = createDbInjector();
|
dbInjector = createDbInjector();
|
||||||
} catch (CreationException ce) {
|
} catch (CreationException ce) {
|
||||||
|
Loading…
Reference in New Issue
Block a user