Adding utilities for offline backup/restore.
Relocating local ECM caches and partitions under data/db directory.

Change-Id: I4790c7488765d8195496a1830abfca897129784c
diff --git a/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java b/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java
index 3f7a49b..498f5d0 100644
--- a/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java
+++ b/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java
@@ -25,7 +25,6 @@
 import org.onosproject.persistence.PersistenceService;
 import org.onosproject.persistence.PersistentMapBuilder;
 import org.onosproject.persistence.PersistentSetBuilder;
-import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 
 import java.io.File;
@@ -42,17 +41,19 @@
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
- * Service that maintains local disk backed maps and sets.  This implementation automatically deletes empty structures
- * on shutdown.
+ * Service that maintains local disk backed maps and sets.
+ * This implementation automatically deletes empty structures on shutdown.
  */
 @Component(immediate = true)
 @Service
 public class PersistenceManager implements PersistenceService {
 
-    private static final String DATABASE_PATH = "localDB";
+    private static final String DATABASE_ROOT =
+            System.getProperty("karaf.data") + "/db/local/";
+
+    private static final String DATABASE_PATH = "cache";
 
     static final String MAP_PREFIX = "map:";
-
     static final String SET_PREFIX = "set:";
 
     private final Logger log = getLogger(getClass());
@@ -66,10 +67,10 @@
     private final CommitTask commitTask = new CommitTask();
 
     @Activate
-    public void activate(ComponentContext context) {
+    public void activate() {
         timer = new Timer();
-        // bundle's persistent storage area directory
-        File dbFolderPath = context.getBundleContext().getDataFile("");
+
+        File dbFolderPath = new File(DATABASE_ROOT);
         Path dbPath = dbFolderPath.toPath().resolve(DATABASE_PATH);
         log.debug("dbPath: {}", dbPath);
 
@@ -105,15 +106,15 @@
         for (Map.Entry<String, Object> entry : localDB.getAll().entrySet()) {
             String key = entry.getKey();
             Object value = entry.getValue();
-                //This is a map implementation to be handled as such
             if (value instanceof Map) {
+                // This is a map implementation to be handled as such
                 Map asMap = (Map) value;
                 if (asMap.isEmpty()) {
                     //the map is empty and may be deleted
                     localDB.delete(key);
                 }
-                //This is a set implementation and can be handled as such
             } else if (value instanceof Set) {
+                // This is a set implementation and can be handled as such
                 Set asSet = (Set) value;
                 if (asSet.isEmpty()) {
                     //the set is empty and may be deleted
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CoordinationManager.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CoordinationManager.java
index 80753f3..f92e3f5 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CoordinationManager.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CoordinationManager.java
@@ -57,6 +57,7 @@
 
 import static org.onosproject.security.AppGuard.checkPermission;
 import static org.onosproject.security.AppPermission.Type.STORAGE_WRITE;
+import static org.onosproject.store.primitives.impl.PartitionManager.PARTITIONS_DIR;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -94,7 +95,7 @@
                 null,
                 clusterCommunicator,
                 clusterService,
-                new File(System.getProperty("karaf.data") + "/partitions/coordination"));
+                new File(PARTITIONS_DIR + "/coordination"));
         partition.open().join();
         primitiveCreator = partition.client();
         log.info("Started");
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/PartitionManager.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/PartitionManager.java
index 5bbd681..8d5440d 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/PartitionManager.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/PartitionManager.java
@@ -68,6 +68,9 @@
 public class PartitionManager extends AbstractListenerManager<PartitionEvent, PartitionEventListener>
     implements PartitionService, PartitionAdminService {
 
+    static final String PARTITIONS_DIR =
+            System.getProperty("karaf.data") + "/db/partitions/";
+
     private final Logger log = getLogger(getClass());
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -110,16 +113,14 @@
                                 null,
                                 clusterCommunicator,
                                 clusterService,
-                                new File(System.getProperty("karaf.data") +
-                                        "/partitions/" + sourceVersion + "/" + partition.getId())));
+                                new File(PARTITIONS_DIR + sourceVersion + "/" + partition.getId())));
                         activePartitions.put(partition.getId(), new StoragePartition(
                                 partition,
                                 targetVersion,
                                 sourceVersion,
                                 clusterCommunicator,
                                 clusterService,
-                                new File(System.getProperty("karaf.data") +
-                                        "/partitions/" + targetVersion + "/" + partition.getId())));
+                                new File(PARTITIONS_DIR + targetVersion + "/" + partition.getId())));
                     });
 
             // We have to fork existing partitions before we can start inactive partition servers to
@@ -140,8 +141,7 @@
                             null,
                             clusterCommunicator,
                             clusterService,
-                            new File(System.getProperty("karaf.data") +
-                                    "/partitions/" + version + "/" + partition.getId()))));
+                            new File(PARTITIONS_DIR + version + "/" + partition.getId()))));
             openFuture = CompletableFuture.allOf(activePartitions.values().stream()
                     .map(StoragePartition::open)
                     .toArray(CompletableFuture[]::new));
diff --git a/tools/package/bin/onos-backup b/tools/package/bin/onos-backup
new file mode 100755
index 0000000..a37ee46
--- /dev/null
+++ b/tools/package/bin/onos-backup
@@ -0,0 +1,31 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# ONOS utility to produce a backup archive of all persistent data.
+# -----------------------------------------------------------------------------
+
+ONOS_HOME=${ONOS_HOME:-$(cd $(dirname $0)/.. >/dev/null 2>&1 && pwd)}
+ONOS_DEFAULT_ARCHIVE=$(dirname $ONOS_HOME)/onos-data.tar.gz
+ONOS_KARAF=$ONOS_HOME/apache-karaf-3.0.8
+
+# Fetch the name of the archive or use a default if none is specified
+archive=${1:-$ONOS_DEFAULT_ARCHIVE}
+archive=$(cd "$(dirname "$archive")"; pwd)/$(basename "$archive")
+
+# Make sure that the apache karaf data directory exists
+[ ! -d $ONOS_KARAF/data ] && echo "ONOS data directory not found" && exit 1
+
+# Make sure that the archive lies outside of $ONOS_HOME for safety
+[[ "$archive" =~ ^$ONOS_HOME/.* ]] && \
+    echo "Archive cannot be in $ONOS_HOME directory tree" && exit 1
+
+# Make sure that the archive file does not already exist
+[ -f $archive ] && echo "Archive $archive already exists" && exit 1
+
+# Make sure we can write the archive
+! touch $archive 2>/dev/null && \
+    echo "No permission to write archive $archive" && exit 1
+rm -f $archive
+
+# Now produce the archive using the subset of the data directory tree
+cd $ONOS_KARAF
+tar zcf $archive data/db data/log
diff --git a/tools/package/bin/onos-restore b/tools/package/bin/onos-restore
new file mode 100755
index 0000000..b7204e5
--- /dev/null
+++ b/tools/package/bin/onos-restore
@@ -0,0 +1,26 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# ONOS utility to restore persistent data from a backup archive.
+# -----------------------------------------------------------------------------
+
+ONOS_HOME=${ONOS_HOME:-$(cd $(dirname $0)/.. >/dev/null 2>&1 && pwd)}
+ONOS_DEFAULT_ARCHIVE=$(dirname $ONOS_HOME)/onos-data.tar.gz
+ONOS_KARAF=$ONOS_HOME/apache-karaf-3.0.8
+
+# Fetch the name of the archive or use a default if none is specified
+archive=${1:-$ONOS_DEFAULT_ARCHIVE}
+archive=$(cd "$(dirname "$1")"; pwd)/$(basename "$1")
+
+# Make sure that the apache karaf data directory exists
+[ ! -d $ONOS_KARAF/data ] && echo "ONOS data directory not found" && exit 1
+
+# Make sure that the archive lies outside of $ONOS_HOME for safety
+[[ "$archive" =~ ^$ONOS_HOME/.* ]] && \
+    echo "Archive cannot be in $ONOS_HOME directory tree" && exit 1
+
+# Make sure that the archive file exists
+[ ! -f $archive ] && echo "Archive $archive not found" && exit 1
+
+# Now unroll the archive into the data directory tree
+cd $ONOS_KARAF
+tar zxf $archive
diff --git a/tools/package/bin/onos-secure-ssh b/tools/package/bin/onos-secure-ssh
deleted file mode 100755
index fba3a03..0000000
--- a/tools/package/bin/onos-secure-ssh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-echo "This command has been deprecated!"
-echo "Please use 'onos-user-key' and 'onos-user-password' commands instead."
\ No newline at end of file