aboutsummaryrefslogtreecommitdiff
path: root/libpod/sql_state_internal.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-11-29 14:37:35 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2017-11-30 18:05:56 +0000
commit7eb5ce940c8145ef57920ef90b52857e9716ffc9 (patch)
tree0a9d90a27d87820f8c08c802ad6c0a1859e614fb /libpod/sql_state_internal.go
parented5d686076b9b01ce5da7ed0bd37faeed216ae75 (diff)
downloadpodman-7eb5ce940c8145ef57920ef90b52857e9716ffc9.tar.gz
podman-7eb5ce940c8145ef57920ef90b52857e9716ffc9.tar.bz2
podman-7eb5ce940c8145ef57920ef90b52857e9716ffc9.zip
Add schema validation to DB
This ensures we don't open a DB with an earlier schema or a config that differs from ours Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #86 Approved by: rhatdan
Diffstat (limited to 'libpod/sql_state_internal.go')
-rw-r--r--libpod/sql_state_internal.go131
1 files changed, 131 insertions, 0 deletions
diff --git a/libpod/sql_state_internal.go b/libpod/sql_state_internal.go
index 58a6daa58..6e0142b9b 100644
--- a/libpod/sql_state_internal.go
+++ b/libpod/sql_state_internal.go
@@ -15,6 +15,137 @@ import (
_ "github.com/mattn/go-sqlite3"
)
+// Checks that the DB configuration matches the runtime's configuration
+func checkDB(db *sql.DB, r *Runtime) (err error) {
+ // Create a table to hold runtime information
+ // TODO: Include UID/GID mappings
+ const runtimeTable = `
+ CREATE TABLE runtime(
+ Id INTEGER NOT NULL PRIMARY KEY,
+ SchemaVersion INTEGER NOT NULL,
+ StaticDir TEXT NOT NULL,
+ TmpDir TEXT NOT NULL,
+ RunRoot TEXT NOT NULL,
+ GraphRoot TEXT NOT NULL,
+ GraphDriverName TEXT NOT NULL,
+ CHECK (Id=0)
+ );
+ `
+ const fillRuntimeTable = `INSERT INTO runtime VALUES (
+ ?, ?, ?, ?, ?, ?, ?
+ );`
+
+ const selectRuntimeTable = `SELECT SchemaVersion,
+ StaticDir,
+ TmpDir,
+ RunRoot,
+ GraphRoot,
+ GraphDriverName
+ FROM runtime WHERE id=0;`
+
+ const checkRuntimeExists = "SELECT name FROM sqlite_master WHERE type='table' AND name='runtime';"
+
+ tx, err := db.Begin()
+ if err != nil {
+ return errors.Wrapf(err, "error beginning database transaction")
+ }
+ defer func() {
+ if err != nil {
+ if err2 := tx.Rollback(); err2 != nil {
+ logrus.Errorf("Error rolling back transaction to check runtime table: %v", err2)
+ }
+ }
+
+ }()
+
+ row := tx.QueryRow(checkRuntimeExists)
+ var table string
+ if err := row.Scan(&table); err != nil {
+ // There is no runtime table
+ // Create and populate the runtime table
+ if err == sql.ErrNoRows {
+ if _, err := tx.Exec(runtimeTable); err != nil {
+ return errors.Wrapf(err, "error creating runtime table in database")
+ }
+
+ _, err := tx.Exec(fillRuntimeTable,
+ 0,
+ DBSchema,
+ r.config.StaticDir,
+ r.config.TmpDir,
+ r.config.StorageConfig.RunRoot,
+ r.config.StorageConfig.GraphRoot,
+ r.config.StorageConfig.GraphDriverName)
+ if err != nil {
+ return errors.Wrapf(err, "error populating runtime table in database")
+ }
+
+ if err := tx.Commit(); err != nil {
+ return errors.Wrapf(err, "error committing runtime table transaction in database")
+ }
+
+ return nil
+ }
+
+ return errors.Wrapf(err, "error checking for presence of runtime table in database")
+ }
+
+ // There is a runtime table
+ // Retrieve its contents
+ var (
+ schemaVersion int
+ staticDir string
+ tmpDir string
+ runRoot string
+ graphRoot string
+ graphDriverName string
+ )
+
+ row = tx.QueryRow(selectRuntimeTable)
+ err = row.Scan(
+ &schemaVersion,
+ &staticDir,
+ &tmpDir,
+ &runRoot,
+ &graphRoot,
+ &graphDriverName)
+ if err != nil {
+ return errors.Wrapf(err, "error retrieving runtime information from database")
+ }
+
+ // Compare the information in the database against our runtime config
+ if schemaVersion != DBSchema {
+ return errors.Wrapf(ErrDBBadConfig, "database schema version %d does not match our schema version %d",
+ schemaVersion, DBSchema)
+ }
+ if staticDir != r.config.StaticDir {
+ return errors.Wrapf(ErrDBBadConfig, "database static directory %s does not match our static directory %s",
+ staticDir, r.config.StaticDir)
+ }
+ if tmpDir != r.config.TmpDir {
+ return errors.Wrapf(ErrDBBadConfig, "database temp directory %s does not match our temp directory %s",
+ tmpDir, r.config.TmpDir)
+ }
+ if runRoot != r.config.StorageConfig.RunRoot {
+ return errors.Wrapf(ErrDBBadConfig, "database runroot directory %s does not match our runroot directory %s",
+ runRoot, r.config.StorageConfig.RunRoot)
+ }
+ if graphRoot != r.config.StorageConfig.GraphRoot {
+ return errors.Wrapf(ErrDBBadConfig, "database graph root directory %s does not match our graph root directory %s",
+ graphRoot, r.config.StorageConfig.GraphRoot)
+ }
+ if graphDriverName != r.config.StorageConfig.GraphDriverName {
+ return errors.Wrapf(ErrDBBadConfig, "database runroot directory %s does not match our runroot directory %s",
+ graphDriverName, r.config.StorageConfig.GraphDriverName)
+ }
+
+ if err := tx.Commit(); err != nil {
+ return errors.Wrapf(err, "error committing runtime table transaction in database")
+ }
+
+ return nil
+}
+
// Performs database setup including by not limited to initializing tables in
// the database
func prepareDB(db *sql.DB) (err error) {