mirror of https://github.com/containers/podman.git
225 lines
6.2 KiB
Go
225 lines
6.2 KiB
Go
package libpod
|
|
|
|
import (
|
|
"encoding/json"
|
|
"path/filepath"
|
|
|
|
"github.com/boltdb/bolt"
|
|
"github.com/containers/storage"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const (
|
|
idRegistryName = "id-registry"
|
|
nameRegistryName = "name-registry"
|
|
ctrConfigName = "container-config"
|
|
ctrStateName = "container-state"
|
|
netNSName = "net-ns"
|
|
runtimeConfigName = "runtime-config"
|
|
ctrDependsName = "container-depends"
|
|
podName = "pod"
|
|
podContainersName = "pod-containers"
|
|
)
|
|
|
|
var (
|
|
idRegistryBkt = []byte(idRegistryName)
|
|
nameRegistryBkt = []byte(nameRegistryName)
|
|
ctrConfigBkt = []byte(ctrConfigName)
|
|
ctrStateBkt = []byte(ctrStateName)
|
|
netNSBkt = []byte(netNSName)
|
|
runtimeConfigBkt = []byte(runtimeConfigName)
|
|
ctrDependsBkt = []byte(ctrDependsName)
|
|
podBkt = []byte(podName)
|
|
podContainersBkt = []byte(podContainersName)
|
|
)
|
|
|
|
// 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, runtime *Runtime) error {
|
|
var (
|
|
staticDir = []byte("static-dir")
|
|
tmpDir = []byte("tmp-dir")
|
|
runRoot = []byte("run-root")
|
|
graphRoot = []byte("graph-root")
|
|
graphDriverName = []byte("graph-driver-name")
|
|
)
|
|
|
|
err := db.Update(func(tx *bolt.Tx) error {
|
|
configBkt, err := getRuntimeConfigBucket(tx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := validateDBAgainstConfig(configBkt, "static dir",
|
|
runtime.config.StaticDir, staticDir); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := validateDBAgainstConfig(configBkt, "tmp dir",
|
|
runtime.config.TmpDir, tmpDir); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := validateDBAgainstConfig(configBkt, "run root",
|
|
runtime.config.StorageConfig.RunRoot, runRoot); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := validateDBAgainstConfig(configBkt, "graph root",
|
|
runtime.config.StorageConfig.GraphRoot, graphRoot); err != nil {
|
|
return err
|
|
}
|
|
|
|
return validateDBAgainstConfig(configBkt, "graph driver name",
|
|
runtime.config.StorageConfig.GraphDriverName,
|
|
graphDriverName)
|
|
})
|
|
|
|
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
|
|
func validateDBAgainstConfig(bucket *bolt.Bucket, fieldName, runtimeValue string, keyName []byte) error {
|
|
keyBytes := bucket.Get(keyName)
|
|
if keyBytes == nil {
|
|
if err := bucket.Put(keyName, []byte(runtimeValue)); err != nil {
|
|
return errors.Wrapf(err, "error updating %s in DB runtime config", fieldName)
|
|
}
|
|
} else {
|
|
if runtimeValue != string(keyBytes) {
|
|
return errors.Wrapf(ErrDBBadConfig, "database %s %s does not match our %s %s",
|
|
fieldName, string(keyBytes), fieldName, runtimeValue)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *BoltState) getDBCon() (*bolt.DB, error) {
|
|
db, err := bolt.Open(s.dbPath, 0600, nil)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "error opening database %s", s.dbPath)
|
|
}
|
|
|
|
return db, nil
|
|
}
|
|
|
|
func getIDBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|
bkt := tx.Bucket(idRegistryBkt)
|
|
if bkt == nil {
|
|
return nil, errors.Wrapf(ErrDBBadConfig, "id registry bucket not found in DB")
|
|
}
|
|
return bkt, nil
|
|
}
|
|
|
|
func getNamesBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|
bkt := tx.Bucket(nameRegistryBkt)
|
|
if bkt == nil {
|
|
return nil, errors.Wrapf(ErrDBBadConfig, "name registry bucket not found in DB")
|
|
}
|
|
return bkt, nil
|
|
}
|
|
|
|
func getCtrConfigBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|
bkt := tx.Bucket(ctrConfigBkt)
|
|
if bkt == nil {
|
|
return nil, errors.Wrapf(ErrDBBadConfig, "container config bucket not found in DB")
|
|
}
|
|
return bkt, nil
|
|
}
|
|
|
|
func getCtrStateBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|
bkt := tx.Bucket(ctrStateBkt)
|
|
if bkt == nil {
|
|
return nil, errors.Wrapf(ErrDBBadConfig, "container state bucket not found in DB")
|
|
}
|
|
return bkt, nil
|
|
}
|
|
|
|
func getNetNSBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|
bkt := tx.Bucket(netNSBkt)
|
|
if bkt == nil {
|
|
return nil, errors.Wrapf(ErrDBBadConfig, "network namespace bucket not found in DB")
|
|
}
|
|
return bkt, nil
|
|
}
|
|
|
|
func getRuntimeConfigBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|
bkt := tx.Bucket(runtimeConfigBkt)
|
|
if bkt == nil {
|
|
return nil, errors.Wrapf(ErrDBBadConfig, "runtime configuration bucket not found in DB")
|
|
}
|
|
return bkt, nil
|
|
}
|
|
|
|
func getCtrDependsBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|
bkt := tx.Bucket(ctrDependsBkt)
|
|
if bkt == nil {
|
|
return nil, errors.Wrapf(ErrDBBadConfig, "container dependencies bucket not found in DB")
|
|
}
|
|
return bkt, nil
|
|
}
|
|
|
|
func getPodBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|
bkt := tx.Bucket(podBkt)
|
|
if bkt == nil {
|
|
return nil, errors.Wrapf(ErrDBBadConfig, "pods bucket not found in DB")
|
|
}
|
|
return bkt, nil
|
|
}
|
|
|
|
func getPodContainersBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|
bkt := tx.Bucket(podContainersBkt)
|
|
if bkt == nil {
|
|
return nil, errors.Wrapf(ErrDBBadConfig, "pod containers bucket not found in DB")
|
|
}
|
|
return bkt, nil
|
|
}
|
|
|
|
func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, config, state, netNS *bolt.Bucket) error {
|
|
configBytes := config.Get(id)
|
|
if configBytes == nil {
|
|
return errors.Wrapf(ErrNoSuchCtr, "error unmarshalling container %s config", string(id))
|
|
}
|
|
|
|
if err := json.Unmarshal(configBytes, ctr.config); err != nil {
|
|
return errors.Wrapf(err, "error unmarshalling container %s config", string(id))
|
|
}
|
|
|
|
stateBytes := state.Get(id)
|
|
if stateBytes == nil {
|
|
return errors.Wrapf(ErrInternal, "container %s has config but no state", string(id))
|
|
}
|
|
|
|
if err := json.Unmarshal(stateBytes, ctr.state); err != nil {
|
|
return errors.Wrapf(err, "error unmarshalling container %s state", string(id))
|
|
}
|
|
|
|
// The container may not have a network namespace, so it's OK if this is
|
|
// nil
|
|
netNSBytes := netNS.Get(id)
|
|
if netNSBytes != nil {
|
|
nsPath := string(netNSBytes)
|
|
netNS, err := joinNetNS(nsPath)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error joining network namespace for container %s", string(id))
|
|
}
|
|
ctr.state.NetNS = netNS
|
|
}
|
|
|
|
// Get the lock
|
|
lockPath := filepath.Join(s.lockDir, string(id))
|
|
lock, err := storage.GetLockfile(lockPath)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error retrieving lockfile for container %s", string(id))
|
|
}
|
|
ctr.lock = lock
|
|
|
|
ctr.runtime = s.runtime
|
|
ctr.valid = true
|
|
|
|
return nil
|
|
}
|