summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/boltdb_state.go70
-rw-r--r--libpod/boltdb_state_internal.go186
-rw-r--r--libpod/container_inspect.go6
-rw-r--r--libpod/lock/shm/shm_lock.c6
-rw-r--r--libpod/lock/shm/shm_lock.go1
-rw-r--r--libpod/lock/shm/shm_lock.h3
-rw-r--r--libpod/oci_linux.go4
7 files changed, 173 insertions, 103 deletions
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 63e40a98f..12c364993 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -73,42 +73,50 @@ func NewBoltState(path string, runtime *Runtime) (State, error) {
// As such, just a db.Close() is fine here.
defer db.Close()
- // Perform initial database setup
- err = db.Update(func(tx *bolt.Tx) error {
- if _, err := tx.CreateBucketIfNotExists(idRegistryBkt); err != nil {
- return errors.Wrapf(err, "error creating id-registry bucket")
- }
- if _, err := tx.CreateBucketIfNotExists(nameRegistryBkt); err != nil {
- return errors.Wrapf(err, "error creating name-registry bucket")
- }
- if _, err := tx.CreateBucketIfNotExists(nsRegistryBkt); err != nil {
- return errors.Wrapf(err, "error creating ns-registry bucket")
- }
- if _, err := tx.CreateBucketIfNotExists(ctrBkt); err != nil {
- return errors.Wrapf(err, "error creating containers bucket")
- }
- if _, err := tx.CreateBucketIfNotExists(allCtrsBkt); err != nil {
- return errors.Wrapf(err, "error creating all containers bucket")
- }
- if _, err := tx.CreateBucketIfNotExists(podBkt); err != nil {
- return errors.Wrapf(err, "error creating pods bucket")
- }
- if _, err := tx.CreateBucketIfNotExists(allPodsBkt); err != nil {
- return errors.Wrapf(err, "error creating all pods bucket")
- }
- if _, err := tx.CreateBucketIfNotExists(volBkt); err != nil {
- return errors.Wrapf(err, "error creating volume bucket")
- }
- if _, err := tx.CreateBucketIfNotExists(allVolsBkt); err != nil {
- return errors.Wrapf(err, "error creating all volumes bucket")
+ createBuckets := [][]byte{
+ idRegistryBkt,
+ nameRegistryBkt,
+ nsRegistryBkt,
+ ctrBkt,
+ allCtrsBkt,
+ podBkt,
+ allPodsBkt,
+ volBkt,
+ allVolsBkt,
+ runtimeConfigBkt,
+ }
+
+ // Does the DB need an update?
+ needsUpdate := false
+ err = db.View(func(tx *bolt.Tx) error {
+ for _, bkt := range createBuckets {
+ if test := tx.Bucket(bkt); test == nil {
+ needsUpdate = true
+ break
+ }
}
- if _, err := tx.CreateBucketIfNotExists(runtimeConfigBkt); err != nil {
- return errors.Wrapf(err, "error creating runtime-config bucket")
+ return nil
+ })
+ if err != nil {
+ return nil, errors.Wrapf(err, "error checking DB schema")
+ }
+
+ if !needsUpdate {
+ state.valid = true
+ return state, nil
+ }
+
+ // Ensure schema is properly created in DB
+ err = db.Update(func(tx *bolt.Tx) error {
+ for _, bkt := range createBuckets {
+ if _, err := tx.CreateBucketIfNotExists(bkt); err != nil {
+ return errors.Wrapf(err, "error creating bucket %s", string(bkt))
+ }
}
return nil
})
if err != nil {
- return nil, errors.Wrapf(err, "error creating initial database layout")
+ return nil, errors.Wrapf(err, "error creating buckets for DB")
}
state.valid = true
diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go
index a4818f2c8..b7930e158 100644
--- a/libpod/boltdb_state_internal.go
+++ b/libpod/boltdb_state_internal.go
@@ -73,98 +73,160 @@ var (
volPathKey = []byte(volPathName)
)
+// This represents a field in the runtime configuration that will be validated
+// against the DB to ensure no configuration mismatches occur.
+type dbConfigValidation struct {
+ name string // Only used for error messages
+ runtimeValue string
+ key []byte
+ defaultValue string
+}
+
// Check if the configuration of the database is compatible with the
// configuration of the runtime opening it
// If there is no runtime configuration loaded, load our own
func checkRuntimeConfig(db *bolt.DB, rt *Runtime) error {
- err := db.Update(func(tx *bolt.Tx) error {
+ storeOpts, err := storage.DefaultStoreOptions(rootless.IsRootless(), rootless.GetRootlessUID())
+ if err != nil {
+ return err
+ }
+
+ // We need to validate the following things
+ checks := []dbConfigValidation{
+ {
+ "OS",
+ runtime.GOOS,
+ osKey,
+ runtime.GOOS,
+ },
+ {
+ "libpod root directory (staticdir)",
+ rt.config.StaticDir,
+ staticDirKey,
+ "",
+ },
+ {
+ "libpod temporary files directory (tmpdir)",
+ rt.config.TmpDir,
+ tmpDirKey,
+ "",
+ },
+ {
+ "storage temporary directory (runroot)",
+ rt.config.StorageConfig.RunRoot,
+ runRootKey,
+ storeOpts.RunRoot,
+ },
+ {
+ "storage graph root directory (graphroot)",
+ rt.config.StorageConfig.GraphRoot,
+ graphRootKey,
+ storeOpts.GraphRoot,
+ },
+ {
+ "storage graph driver",
+ rt.config.StorageConfig.GraphDriverName,
+ graphDriverKey,
+ storeOpts.GraphDriverName,
+ },
+ {
+ "volume path",
+ rt.config.VolumePath,
+ volPathKey,
+ "",
+ },
+ }
+
+ // These fields were missing and will have to be recreated.
+ missingFields := []dbConfigValidation{}
+
+ // Let's try and validate read-only first
+ err = db.View(func(tx *bolt.Tx) error {
configBkt, err := getRuntimeConfigBucket(tx)
if err != nil {
return err
}
- if err := validateDBAgainstConfig(configBkt, "OS", runtime.GOOS, osKey, runtime.GOOS); err != nil {
- return err
+ for _, check := range checks {
+ exists, err := readOnlyValidateConfig(configBkt, check)
+ if err != nil {
+ return err
+ }
+ if !exists {
+ missingFields = append(missingFields, check)
+ }
}
- if err := validateDBAgainstConfig(configBkt, "libpod root directory (staticdir)",
- rt.config.StaticDir, staticDirKey, ""); err != nil {
- return err
- }
+ return nil
+ })
+ if err != nil {
+ return err
+ }
- if err := validateDBAgainstConfig(configBkt, "libpod temporary files directory (tmpdir)",
- rt.config.TmpDir, tmpDirKey, ""); err != nil {
- return err
- }
+ if len(missingFields) == 0 {
+ return nil
+ }
- storeOpts, err := storage.DefaultStoreOptions(rootless.IsRootless(), rootless.GetRootlessUID())
+ // Populate missing fields
+ return db.Update(func(tx *bolt.Tx) error {
+ configBkt, err := getRuntimeConfigBucket(tx)
if err != nil {
return err
}
- if err := validateDBAgainstConfig(configBkt, "storage temporary directory (runroot)",
- rt.config.StorageConfig.RunRoot, runRootKey,
- storeOpts.RunRoot); err != nil {
- return err
- }
- if err := validateDBAgainstConfig(configBkt, "storage graph root directory (graphroot)",
- rt.config.StorageConfig.GraphRoot, graphRootKey,
- storeOpts.GraphRoot); err != nil {
- return err
- }
+ for _, missing := range missingFields {
+ dbValue := []byte(missing.runtimeValue)
+ if missing.runtimeValue == "" && missing.defaultValue != "" {
+ dbValue = []byte(missing.defaultValue)
+ }
- if err := validateDBAgainstConfig(configBkt, "storage graph driver",
- rt.config.StorageConfig.GraphDriverName,
- graphDriverKey,
- storeOpts.GraphDriverName); err != nil {
- return err
+ if err := configBkt.Put(missing.key, dbValue); err != nil {
+ return errors.Wrapf(err, "error updating %s in DB runtime config", missing.name)
+ }
}
- return validateDBAgainstConfig(configBkt, "volume path",
- rt.config.VolumePath, volPathKey, "")
+ return nil
})
-
- return err
}
-// Validate a configuration entry in the DB against current runtime config
-// If the given configuration key does not exist it will be created
-// If the given runtimeValue or value retrieved from the database are the empty
-// string and defaultValue is not, defaultValue will be checked instead. This
-// ensures that we will not fail on configuration changes in configured c/storage.
-func validateDBAgainstConfig(bucket *bolt.Bucket, fieldName, runtimeValue string, keyName []byte, defaultValue string) error {
- keyBytes := bucket.Get(keyName)
+// Attempt a read-only validation of a configuration entry in the DB against an
+// element of the current runtime configuration.
+// If the configuration key in question does not exist, (false, nil) will be
+// returned.
+// If the configuration key does exist, and matches the runtime configuration
+// successfully, (true, nil) is returned.
+// An error is only returned when validation fails.
+// if the given runtimeValue or value retrieved from the database are empty,
+// and defaultValue is not, defaultValue will be checked instead. This ensures
+// that we will not fail on configuration changes in c/storage (where we may
+// pass the empty string to use defaults).
+func readOnlyValidateConfig(bucket *bolt.Bucket, toCheck dbConfigValidation) (bool, error) {
+ keyBytes := bucket.Get(toCheck.key)
if keyBytes == nil {
- dbValue := []byte(runtimeValue)
- if runtimeValue == "" && defaultValue != "" {
- dbValue = []byte(defaultValue)
- }
+ // False return indicates missing key
+ return false, nil
+ }
- if err := bucket.Put(keyName, dbValue); err != nil {
- return errors.Wrapf(err, "error updating %s in DB runtime config", fieldName)
- }
- } else {
- if runtimeValue != string(keyBytes) {
- // If runtimeValue is the empty string, check against
- // the default
- if runtimeValue == "" && defaultValue != "" &&
- string(keyBytes) == defaultValue {
- return nil
- }
+ dbValue := string(keyBytes)
- // If DB value is the empty string, check that the
- // runtime value is the default
- if string(keyBytes) == "" && defaultValue != "" &&
- runtimeValue == defaultValue {
- return nil
- }
+ if toCheck.runtimeValue != dbValue {
+ // If the runtime value is the empty string and default is not,
+ // check against default.
+ if toCheck.runtimeValue == "" && toCheck.defaultValue != "" && dbValue == toCheck.defaultValue {
+ return true, nil
+ }
- return errors.Wrapf(ErrDBBadConfig, "database %s %s does not match our %s %s",
- fieldName, string(keyBytes), fieldName, runtimeValue)
+ // If the DB value is the empty string, check that the runtime
+ // value is the default.
+ if dbValue == "" && toCheck.defaultValue != "" && toCheck.runtimeValue == toCheck.defaultValue {
+ return true, nil
}
+
+ return true, errors.Wrapf(ErrDBBadConfig, "database %s %q does not match our %s %q",
+ toCheck.name, dbValue, toCheck.name, toCheck.runtimeValue)
}
- return nil
+ return true, nil
}
// Open a connection to the database.
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index af42de3d8..1d12b1b35 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -242,7 +242,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
}
}
- mounts, err := c.getInspectMounts()
+ mounts, err := c.getInspectMounts(spec)
if err != nil {
return nil, err
}
@@ -359,7 +359,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
// Get inspect-formatted mounts list.
// Only includes user-specified mounts. Only includes bind mounts and named
// volumes, not tmpfs volumes.
-func (c *Container) getInspectMounts() ([]*InspectMount, error) {
+func (c *Container) getInspectMounts(ctrSpec *spec.Spec) ([]*InspectMount, error) {
inspectMounts := []*InspectMount{}
// No mounts, return early
@@ -376,7 +376,7 @@ func (c *Container) getInspectMounts() ([]*InspectMount, error) {
for _, namedVol := range c.config.NamedVolumes {
namedVolumes[namedVol.Dest] = namedVol
}
- for _, mount := range c.config.Spec.Mounts {
+ for _, mount := range ctrSpec.Mounts {
mounts[mount.Destination] = mount
}
diff --git a/libpod/lock/shm/shm_lock.c b/libpod/lock/shm/shm_lock.c
index 047d3c417..fbb3f57cc 100644
--- a/libpod/lock/shm/shm_lock.c
+++ b/libpod/lock/shm/shm_lock.c
@@ -413,7 +413,7 @@ int32_t allocate_given_semaphore(shm_struct_t *shm, uint32_t sem_index) {
// Returns 0 on success, negative ERRNO values on failure
int32_t deallocate_semaphore(shm_struct_t *shm, uint32_t sem_index) {
bitmap_t test_map;
- int bitmap_index, index_in_bitmap, ret_code, i;
+ int bitmap_index, index_in_bitmap, ret_code;
if (shm == NULL) {
return -1 * EINVAL;
@@ -500,7 +500,7 @@ int32_t deallocate_all_semaphores(shm_struct_t *shm) {
// subsequently realize they have been removed).
// Returns 0 on success, -1 on failure
int32_t lock_semaphore(shm_struct_t *shm, uint32_t sem_index) {
- int bitmap_index, index_in_bitmap, ret_code;
+ int bitmap_index, index_in_bitmap;
if (shm == NULL) {
return -1 * EINVAL;
@@ -522,7 +522,7 @@ int32_t lock_semaphore(shm_struct_t *shm, uint32_t sem_index) {
// subsequently realize they have been removed).
// Returns 0 on success, -1 on failure
int32_t unlock_semaphore(shm_struct_t *shm, uint32_t sem_index) {
- int bitmap_index, index_in_bitmap, ret_code;
+ int bitmap_index, index_in_bitmap;
if (shm == NULL) {
return -1 * EINVAL;
diff --git a/libpod/lock/shm/shm_lock.go b/libpod/lock/shm/shm_lock.go
index c21e9a221..76dd5729e 100644
--- a/libpod/lock/shm/shm_lock.go
+++ b/libpod/lock/shm/shm_lock.go
@@ -1,6 +1,7 @@
package shm
// #cgo LDFLAGS: -lrt -lpthread
+// #cgo CFLAGS: -Wall -Werror
// #include <stdlib.h>
// #include "shm_lock.h"
// const uint32_t bitmap_size_c = BITMAP_SIZE;
diff --git a/libpod/lock/shm/shm_lock.h b/libpod/lock/shm/shm_lock.h
index 759f8178a..8796b43f4 100644
--- a/libpod/lock/shm/shm_lock.h
+++ b/libpod/lock/shm/shm_lock.h
@@ -32,9 +32,6 @@ typedef struct shm_struct {
lock_group_t locks[];
} shm_struct_t;
-static size_t compute_shm_size(uint32_t num_bitmaps);
-static int take_mutex(pthread_mutex_t *mutex);
-static int release_mutex(pthread_mutex_t *mutex);
shm_struct_t *setup_lock_shm(char *path, uint32_t num_locks, int *error_code);
shm_struct_t *open_lock_shm(char *path, uint32_t num_locks, int *error_code);
int32_t close_lock_shm(shm_struct_t *shm);
diff --git a/libpod/oci_linux.go b/libpod/oci_linux.go
index 9bbefdb06..6e84c0759 100644
--- a/libpod/oci_linux.go
+++ b/libpod/oci_linux.go
@@ -246,7 +246,9 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
}
logDriver := KubernetesLogging
- if ctr.LogDriver() != "" {
+ if ctr.LogDriver() == JSONLogging {
+ logrus.Errorf("json-file logging specified but not supported. Choosing k8s-file logging instead")
+ } else if ctr.LogDriver() != "" {
logDriver = ctr.LogDriver()
}
args = append(args, "-l", fmt.Sprintf("%s:%s", logDriver, ctr.LogPath()))