diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/boltdb_state.go | 70 | ||||
-rw-r--r-- | libpod/boltdb_state_internal.go | 186 | ||||
-rw-r--r-- | libpod/container_inspect.go | 6 | ||||
-rw-r--r-- | libpod/lock/shm/shm_lock.c | 6 | ||||
-rw-r--r-- | libpod/lock/shm/shm_lock.go | 1 | ||||
-rw-r--r-- | libpod/lock/shm/shm_lock.h | 3 | ||||
-rw-r--r-- | libpod/oci_linux.go | 4 |
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())) |