Skip to content

Commit

Permalink
Only allow databases within the data directory to be mounted
Browse files Browse the repository at this point in the history
We no longer support mounting databases on arbitrary paths. Individual
databases are now specified by name rather than path and the directory
structure within the data directory is an implementation detail.
  • Loading branch information
benbc committed Feb 22, 2016
1 parent ff54181 commit fc42d29
Show file tree
Hide file tree
Showing 49 changed files with 219 additions and 169 deletions.
Expand Up @@ -30,9 +30,9 @@
import java.util.function.Function;
import java.util.regex.Pattern;

import org.neo4j.function.Functions;
import org.neo4j.graphdb.config.InvalidSettingException;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.function.Functions;
import org.neo4j.helpers.HostnamePort;
import org.neo4j.helpers.TimeUtil;
import org.neo4j.helpers.collection.Iterables;
Expand Down Expand Up @@ -149,27 +149,52 @@ public static <T> Setting<T> setting( final String name, final Function<String,
defaultLookup = inheritedDefault( defaultLookup, inheritedSetting );
}

return new DefaultSetting<T>( name, parser, valueLookup, defaultLookup, valueConverters );
return new DefaultSetting<>( name, parser, valueLookup, defaultLookup, valueConverters );
}

private static <T> Function<Function<String, String>, String> inheritedValue( final Function<Function<String,
String>, String> lookup, final Setting<T> inheritedSetting )
public static <OUT, IN1, IN2> Setting<OUT> derivedSetting( String name,
Setting<IN1> in1, Setting<IN2> in2,
BiFunction<IN1, IN2, OUT> derivation )
{
return new Function<Function<String, String>, String>()
return new Setting<OUT>()
{
@Override
public String apply( Function<String, String> settings )
public String name()
{
String value = lookup.apply( settings );
if ( value == null )
return name;
}

@Override
public String getDefaultValue()
{
return NO_DEFAULT;
}

@Override
public OUT apply( Function<String, String> config )
{
if ( config.apply( name ) != null )
{
value = ((SettingHelper<T>) inheritedSetting).lookup( settings );
throw new IllegalArgumentException( "You may not set a value for derived setting " + name );
}
return value;
return derivation.apply( in1.apply( config ), in2.apply( config ) );
}
};
}

private static <T> Function<Function<String, String>, String> inheritedValue( final Function<Function<String,
String>, String> lookup, final Setting<T> inheritedSetting )
{
return settings -> {
String value = lookup.apply( settings );
if ( value == null )
{
value = ((SettingHelper<T>) inheritedSetting).lookup( settings );
}
return value;
};
}

private static <T> Function<Function<String, String>, String> inheritedDefault( final Function<Function<String,
String>, String> lookup, final Setting<T> inheritedSetting )
{
Expand Down Expand Up @@ -318,7 +343,7 @@ public String toString()
public List<String> apply( String value )
{
String[] list = value.split( SEPARATOR );
List<String> result = new ArrayList();
List<String> result = new ArrayList<>();
for( String item : list)
{
item = item.trim();
Expand Down Expand Up @@ -500,7 +525,7 @@ public static <T extends Enum> Function<String, T> options( final Class<T> enumC

public static <T> Function<String, T> options( T... optionValues )
{
return Settings.<T>options( Iterables.<T,T>iterable( optionValues ) );
return Settings.options( Iterables.iterable( optionValues ) );
}

public static <T> Function<String, T> options( final Iterable<T> optionValues )
Expand Down Expand Up @@ -544,7 +569,7 @@ public static <T> Function<String, List<T>> list( final String separator, final
@Override
public List<T> apply( String value )
{
List<T> list = new ArrayList<T>();
List<T> list = new ArrayList<>();
if ( value.length() > 0 )
{
String[] parts = value.split( separator );
Expand Down
Expand Up @@ -19,8 +19,6 @@
*/
package org.neo4j.harness.internal;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
Expand All @@ -30,6 +28,8 @@
import java.util.Random;
import java.util.function.Function;

import org.apache.commons.io.FileUtils;

import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
Expand Down Expand Up @@ -67,8 +67,8 @@ public abstract class AbstractInProcessServerBuilder implements TestServerBuilde

public AbstractInProcessServerBuilder( File workingDir )
{
File storeDir = new File( workingDir, randomFolderName() ).getAbsoluteFile();
init( storeDir );
File dataDir = new File( workingDir, randomFolderName() ).getAbsoluteFile();
init( dataDir );
}

private void init( File workingDir )
Expand Down Expand Up @@ -195,7 +195,7 @@ public TestServerBuilder withProcedure( Class<?> procedureClass )
private TestServerBuilder setDirectory( File dir )
{
this.serverFolder = dir;
config.put( ServerSettings.legacy_db_location.name(), serverFolder.getAbsolutePath() );
config.put( ServerSettings.data_directory.name(), serverFolder.getAbsolutePath() );
return this;
}

Expand Down
Expand Up @@ -19,11 +19,6 @@
*/
package org.neo4j.harness;

import org.apache.commons.io.FileUtils;
import org.codehaus.jackson.JsonNode;
import org.junit.Rule;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.net.URI;
Expand All @@ -41,6 +36,11 @@
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.io.FileUtils;
import org.codehaus.jackson.JsonNode;
import org.junit.Rule;
import org.junit.Test;

import org.neo4j.bolt.v1.transport.socket.client.SocketConnection;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
Expand All @@ -51,6 +51,7 @@
import org.neo4j.helpers.HostnamePort;
import org.neo4j.helpers.collection.Iterables;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.server.ServerTestUtils;
import org.neo4j.server.configuration.ServerSettings;
import org.neo4j.server.rest.domain.JsonParseException;
Expand All @@ -66,7 +67,9 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import static org.neo4j.harness.TestServerBuilders.newInProcessBuilder;
import static org.neo4j.helpers.collection.MapUtil.stringMap;

public class InProcessBuilderTest
{
Expand Down Expand Up @@ -172,12 +175,12 @@ public void shouldRunBuilderOnExistingStoreDir() throws Exception
{
// When
// create graph db with one node upfront
Path dir = Files.createTempDirectory( getClass().getSimpleName() +
"_shouldRunBuilderOnExistingStorageDir" );
Path dir = Files.createTempDirectory( getClass().getSimpleName() + "_shouldRunBuilderOnExistingStorageDir" );
File storeDir = new Config( stringMap( ServerSettings.data_directory.name(), dir.toString() ) )
.get( ServerSettings.database_path );
try
{

GraphDatabaseService db = new TestGraphDatabaseFactory().newEmbeddedDatabase( dir.toString() );
GraphDatabaseService db = new TestGraphDatabaseFactory().newEmbeddedDatabase( storeDir );
try
{
db.execute( "create ()" );
Expand All @@ -204,7 +207,7 @@ public void shouldRunBuilderOnExistingStoreDir() throws Exception
}

// Then: we still only have one node since the server is supposed to work on a copy
db = new TestGraphDatabaseFactory().newEmbeddedDatabase( dir.toString() );
db = new TestGraphDatabaseFactory().newEmbeddedDatabase( storeDir );
try
{
try ( Transaction tx = db.beginTx() )
Expand Down
18 changes: 4 additions & 14 deletions community/neo4j/src/docs/ops/upgrades.asciidoc
Expand Up @@ -43,29 +43,19 @@ This typically means only within patch releases of the same Neo4j version.
To perform an automatic store upgrade:

. Cleanly shut down the older version of Neo4j, if it is running.

. Install Neo4j {neo4j-version}, and set it up to use the same database store directory (typically _data/databases/graph.db_).

. Make a copy of the database.
+
[IMPORTANT]
It is strongly advised to make a copy of the database store directory at this time, to use as a backup in case rollback/downgrade is required.
This is not necessary if a backup has been made using the
ifndef::upgradetext[<<operations-backup, online backup tool>>, ]
ifdef::upgradetext[online backup tool (see http://neo4j.com/docs/{neo4j-version}/operations-backup.html), ]
available with Neo4j Enterprise.

. Install Neo4j {neo4j-version}.
. Copy the database from the old installation (typically _data/graph.db_) into the new one (_data/databases/graph.db_).
. Start up Neo4j.

. Any database store upgrade required will occur during startup.

[[explicit-upgrade]]
== Explicit Store Upgrade

To perform an explicit store upgrade:

. Install Neo4j {neo4j-version}, and set it up to use the same database store directory (typically _data/databases/graph.db_).
. Cleanly shut down the older version of Neo4j, if it is running.
. Install Neo4j {neo4j-version}.
. Copy the database from the old installation (typically _data/graph.db_) into the new one (_data/databases/graph.db_).
. Set the Neo4j configuration parameter `allow_store_upgrade=true` in _neo4j.conf_.
Neo4j will fail to start without this configuration set.
. Start up Neo4j.
Expand Down
3 changes: 0 additions & 3 deletions community/server/README.asciidoc
Expand Up @@ -16,9 +16,6 @@ Run the server using:

mvn exec:java

If this fails, ensure you are not missing _neo4j.conf_ with a line containing `org.neo4j.server.database.location=<path-to-database-files>`.
This may happen if you delete neo4j-home during development to reset the database.

== Webadmin development ==

The web administration interface, webadmin, can be found in two places of the source tree:
Expand Down
10 changes: 8 additions & 2 deletions community/server/src/docs/ops/server-configuration.asciidoc
Expand Up @@ -14,10 +14,16 @@ The main configuration file for Neo4j is <<file-locations, _neo4j.conf_>>.
This file contains several important settings, and although the defaults are sensible
administrators might choose to make changes (especially to the port settings).

Set the location on disk of the database directory like this:
Chose the database to mount like this:
[source,properties]
----
org.neo4j.server.database.location=data/databases/graph.db
dbms.active_database=graph.db
----

The location of the Neo4j's data directory can be customized:
[source,properties]
----
dbms.directories.data=data
----

NOTE: On Windows systems, absolute locations including drive letters need to read '"c:/data/db"'.
Expand Down
6 changes: 3 additions & 3 deletions community/server/src/docs/ops/server-installation.asciidoc
Expand Up @@ -24,13 +24,13 @@ We recommend that you install http://openjdk.java.net/[OpenJDK 8] or http://www.
== Setting Proper File Permissions ==

When installing Neo4j Server, keep in mind that the _bin/neo4j_ executable will need to be run by some OS system user, and that user will need write permissions to some files/directories.
This goes specifically for the _data/databases/graph.db_ directory.
That user will also need execute permissions on other files, such as those in _bin/_.
This goes specifically for the _data_ directory.
That user will also need execute permissions on other files, such as those in the _bin_ directory.

It is recommended to either choose or create a user who will own and manage the Neo4j Server.
This user should own the entire Neo4j directory, so make sure to untar/unzip it as this user and not with `sudo` (UNIX/Linux/OSx) etc.

If _data/databases/graph.db_ is not writable by the user Neo4j won't be able to write anything either to the store or its log files.
If the _data_ directory is not writable by the user Neo4j won't be able to write anything either to the store.
As a result any logs would be appended to _console.log_.
The following error message would indicate a possible permissions issue: `Write transactions to database disabled`.

Expand Down
Expand Up @@ -56,7 +56,7 @@
public class CommunityNeoServer extends AbstractNeoServer
{
public static final GraphFactory COMMUNITY_FACTORY = ( config, dependencies ) -> {
File storeDir = config.get( ServerSettings.legacy_db_location );
File storeDir = config.get( ServerSettings.database_path );
return new CommunityFacadeFactory().newFacade( storeDir, config.getParams(), dependencies );
};

Expand Down
Expand Up @@ -34,7 +34,7 @@
* <li>Configuration file can be specified by <strong>--config=path/to/config.properties</strong> or
* <strong>-C=path/to/config.properties</strong></li>
* <li>Specific overridden configuration options, directly specified as arguments can be specified with
* <strong>-c key=value</strong>, for example <strong>-c org.neo4j.server.database.location=my/own/path</strong>
* <strong>-c key=value</strong>, for example <strong>-c dbms.active_database=foo.db</strong>
* or enabled boolean properties with <strong>-c key</strong>, f.ex <strong>-c org.neo4j.server.webserver.port</strong>
* </ul>
*/
Expand Down
Expand Up @@ -42,8 +42,10 @@
import static org.neo4j.kernel.configuration.Settings.NORMALIZED_RELATIVE_URI;
import static org.neo4j.kernel.configuration.Settings.NO_DEFAULT;
import static org.neo4j.kernel.configuration.Settings.PATH;
import static org.neo4j.kernel.configuration.Settings.STRING;
import static org.neo4j.kernel.configuration.Settings.STRING_LIST;
import static org.neo4j.kernel.configuration.Settings.TRUE;
import static org.neo4j.kernel.configuration.Settings.derivedSetting;
import static org.neo4j.kernel.configuration.Settings.min;
import static org.neo4j.kernel.configuration.Settings.port;
import static org.neo4j.kernel.configuration.Settings.setting;
Expand All @@ -61,6 +63,12 @@ public interface ServerSettings
*/
String SERVER_CONFIG_FILE = "config/neo4j.conf";

@Description("Name of the database to load")
Setting<String> active_database = setting( "dbms.active_database", STRING, "graph.db" );

@Description("Path of the data directory")
Setting<File> data_directory = setting( "dbms.directories.data", PATH, "data" );

@Description("Maximum request header size")
Setting<Integer> maximum_request_header_size =
setting( "org.neo4j.server.webserver.max.request.header", INTEGER, "20480" );
Expand Down Expand Up @@ -198,7 +206,9 @@ private ThirdPartyJaxRsPackage createThirdPartyJaxRsPackage( String packageAndMo
FALSE );

@Internal
Setting<File> legacy_db_location = setting( "org.neo4j.server.database.location", PATH, "data/graph.db" );
Setting<File> database_path = derivedSetting( "dbms.internal.derived.directories.database",
data_directory, active_database,
( data, current ) -> new File( new File( data, "databases" ), current ) );

@Internal
Setting<Boolean> webadmin_enabled = setting( "dbms.webadmin.enabled", BOOLEAN, TRUE );
Expand Down
Expand Up @@ -74,7 +74,7 @@ public LifecycleManagingDatabase( Config config, GraphFactory dbFactory,
@Override
public String getLocation()
{
File file = config.get( ServerSettings.legacy_db_location );
File file = config.get( ServerSettings.database_path );
return file.getAbsolutePath();
}

Expand Down
Expand Up @@ -43,7 +43,7 @@ public void stopTheServer()
public void serverShouldNotHangWithThreadPoolSizeSmallerThanCpuCount() throws Exception
{
server = server().withMaxJettyThreads( 3 )
.usingDatabaseDir( folder.directory( name.getMethodName() ).getAbsolutePath() )
.usingDataDir( folder.directory( name.getMethodName() ).getAbsolutePath() )
.build();
server.start();

Expand Down

0 comments on commit fc42d29

Please sign in to comment.