Update DB to add new fields required for planned features

Signed-off-by: Matthew Heon <matthew.heon@gmail.com>

Closes: #209
Approved by: rhatdan
This commit is contained in:
Matthew Heon
2018-01-10 13:49:38 -05:00
committed by Atomic Bot
parent f0843e94cf
commit e6be800ec6
6 changed files with 338 additions and 132 deletions

View File

@ -61,8 +61,8 @@ const (
artifactsDir = "artifacts"
)
// CGroupParent is the prefix to a cgroup path in libpod
var CGroupParent = "/libpod_parent"
// CgroupParent is the default prefix to a cgroup path in libpod
var CgroupParent = "/libpod_parent"
// Container is a single OCI container
type Container struct {
@ -78,6 +78,13 @@ type Container struct {
runtime *Runtime
}
// TODO fetch IP and Subnet Mask from networks once we have updated OCICNI
// TODO enable pod support
// TODO Add readonly support
// TODO add SHM size support
// TODO add shared namespace support
// TODO add cgroup parent support
// containerRuntimeInfo contains the current state of the container
// It is stored on disk in a tmpfs and recreated on reboot
type containerRuntimeInfo struct {
@ -107,7 +114,10 @@ type containerRuntimeInfo struct {
// Will only be set if config.CreateNetNS is true, or the container was
// told to join another container's network namespace
NetNS ns.NetNS
// TODO: Save information about image used in container if one is used
// IP address of container (if network namespace was created)
IPAddress string
// Subnet mask of container (if network namespace was created)
SubnetMask string
}
// ContainerConfig contains all information that was used to create the
@ -117,49 +127,76 @@ type ContainerConfig struct {
Spec *spec.Spec `json:"spec"`
ID string `json:"id"`
Name string `json:"name"`
// Full ID of the pood the container belongs to
Pod string `json:"pod,omitempty"`
// TODO consider breaking these subsections up into smaller structs
// Storage Config
// Information on the image used for the root filesystem
RootfsImageID string `json:"rootfsImageID,omitempty"`
RootfsImageName string `json:"rootfsImageName,omitempty"`
UseImageConfig bool `json:"useImageConfig"`
// Whether to mount volumes specified in the image
ImageVolumes bool `json:"imageVolumes"`
// Whether to make the container read only
ReadOnly bool `json:"readOnly"`
// Src path to be mounted on /dev/shm in container
ShmDir string `json:"ShmDir,omitempty"`
// Size of the container's SHM
ShmSize int64 `json:"shmSize"`
// Static directory for container content that will persist across
// reboot
StaticDir string `json:"staticDir"`
// Mounts list contains all additional mounts into the container rootfs
// These include the SHM mount
// These must be unmounted before the container's rootfs is unmounted
Mounts []string `json:"mounts,omitempty"`
// Security Config
// SELinux process label for container
ProcessLabel string `json:"ProcessLabel,omitempty"`
// SELinux mount label for root filesystem
MountLabel string `json:"MountLabel,omitempty"`
// Src path to be mounted on /dev/shm in container
ShmDir string `json:"ShmDir,omitempty"`
// User and group to use in the container
// Can be specified by name or UID/GID
User string `json:"user"`
// Namespace Config
// IDs of container to share namespaces with
// NetNsCtr conflicts with the CreateNetNS bool
IPCNsCtr string `json:"ipcNsCtr"`
MountNsCtr string `json:"mountNsCtr"`
NetNsCtr string `json:"netNsCtr"`
PIDNsCtr string `json:"pidNsCtr"`
UserNsCtr string `json:"userNsCtr"`
UTSNsCtr string `json:"utsNsCtr"`
// Network Config
// CreateNetNS indicates that libpod should create and configure a new
// network namespace for the container
// This cannot be set if NetNsCtr is also set
CreateNetNS bool `json:"createNetNS"`
// PortMappings are the ports forwarded to the container's network
// namespace
// These are not used unless CreateNetNS is true
PortMappings []ocicni.PortMapping
// Static directory for container content that will persist across
// reboot
StaticDir string `json:"staticDir"`
PortMappings []ocicni.PortMapping `json:"portMappings,omitempty"`
// Misc Options
// Whether to keep container STDIN open
Stdin bool `json:"stdin,omitempty"`
// Pod the container belongs to
Pod string `json:"pod,omitempty"`
// Labels is a set of key-value pairs providing additional information
// about a container
Labels map[string]string `json:"labels,omitempty"`
// Mounts list contains all additional mounts by the container runtime.
Mounts []string `json:"mounts,omitempty"`
// StopSignal is the signal that will be used to stop the container
StopSignal uint `json:"stopSignal,omitempty"`
// StopTimeout is the signal that will be used to stop the container
StopTimeout uint `json:"stopTimeout,omitempty"`
// Shared namespaces with container
SharedNamespaceCtr *string `json:"shareNamespacesWith,omitempty"`
SharedNamespaceMap map[string]string `json:"sharedNamespaces"`
// Time container was created
CreatedTime time.Time `json:"createdTime"`
// User/GID to use within the container
User string `json:"user"`
// Cgroup parent of the container
CgroupParent string `json:"cgroupParent"`
// TODO save log location here and pass into OCI code
// TODO allow overriding of log path
// TODO log options - logpath for plaintext, others for log drivers
}
// ContainerStater returns a string representation for users
@ -192,6 +229,12 @@ func (c *Container) Name() string {
return c.config.Name
}
// PodID returns the full ID of the pod the container belongs to, or "" if it
// does not belong to a pod
func (c *Container) PodID() string {
return c.config.Pod
}
// ShmDir returns the sources path to be mounted on /dev/shm in container
func (c *Container) ShmDir() string {
return c.config.ShmDir
@ -468,6 +511,9 @@ func newContainer(rspec *spec.Spec, lockDir string) (*Container, error) {
deepcopier.Copy(rspec).To(ctr.config.Spec)
ctr.config.CreatedTime = time.Now()
ctr.config.ShmSize = DefaultShmSize
ctr.config.CgroupParent = CgroupParent
// Path our lock file will reside at
lockPath := filepath.Join(lockDir, ctr.config.ID)
// Grab a lockfile at the given path
@ -679,7 +725,7 @@ func (c *Container) Init() (err error) {
// With the spec complete, do an OCI create
// TODO set cgroup parent in a sane fashion
if err := c.runtime.ociRuntime.createContainer(c, CGroupParent); err != nil {
if err := c.runtime.ociRuntime.createContainer(c, CgroupParent); err != nil {
return err
}
@ -1182,7 +1228,7 @@ func (c *Container) cleanupStorage() error {
// CGroupPath returns a cgroups "path" for a given container.
func (c *Container) CGroupPath() cgroups.Path {
return cgroups.StaticPath(filepath.Join(CGroupParent, fmt.Sprintf("libpod-conmon-%s", c.ID())))
return cgroups.StaticPath(filepath.Join(CgroupParent, fmt.Sprintf("libpod-conmon-%s", c.ID())))
}
// copyHostFileToRundir copies the provided file to the runtimedir

View File

@ -25,7 +25,7 @@ func (c *Container) GetContainerPids() ([]string, error) {
// Gets the pids for a container without locking. should only be called from a func where
// locking has already been established.
func (c *Container) getContainerPids() ([]string, error) {
taskFile := filepath.Join("/sys/fs/cgroup/pids", CGroupParent, fmt.Sprintf("libpod-conmon-%s", c.ID()), c.ID(), "tasks")
taskFile := filepath.Join("/sys/fs/cgroup/pids", CgroupParent, fmt.Sprintf("libpod-conmon-%s", c.ID()), c.ID(), "tasks")
logrus.Debug("reading pids from ", taskFile)
content, err := ioutil.ReadFile(taskFile)
if err != nil {

View File

@ -325,7 +325,7 @@ func WithUser(user string) CtrCreateOption {
// If useImageConfig is specified, image volumes, environment variables, and
// other configuration from the image will be added to the config
// TODO: Replace image name and ID with a libpod.Image struct when that is finished
func WithRootFSFromImage(imageID string, imageName string, useImageConfig bool) CtrCreateOption {
func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return ErrCtrFinalized
@ -337,7 +337,7 @@ func WithRootFSFromImage(imageID string, imageName string, useImageConfig bool)
ctr.config.RootfsImageID = imageID
ctr.config.RootfsImageName = imageName
ctr.config.UseImageConfig = useImageConfig
ctr.config.ImageVolumes = useImageVolumes
return nil
}

View File

@ -15,7 +15,7 @@ import (
// DBSchema is the current DB schema version
// Increments every time a change is made to the database's tables
const DBSchema = 6
const DBSchema = 7
// SQLState is a state implementation backed by a persistent SQLite3 database
type SQLState struct {
@ -104,7 +104,9 @@ func (s *SQLState) Refresh() (err error) {
State=?,
Mountpoint=?,
Pid=?,
NetNSPath=?;`
NetNSPath=?,
IPAddress=?,
SubnetMask=?;`
if !s.valid {
return ErrDBClosed
@ -130,6 +132,8 @@ func (s *SQLState) Refresh() (err error) {
ContainerStateConfigured,
"",
0,
"",
"",
"")
if err != nil {
return errors.Wrapf(err, "error refreshing database state")
@ -154,7 +158,9 @@ func (s *SQLState) Container(id string) (*Container, error) {
containerState.ExitCode,
containerState.OomKilled,
containerState.Pid,
containerState.NetNSPath
containerState.NetNSPath,
containerState.IPAddress,
containerState.SubnetMask
FROM containers
INNER JOIN
containerState ON containers.Id = containerState.Id
@ -170,7 +176,7 @@ func (s *SQLState) Container(id string) (*Container, error) {
row := s.db.QueryRow(query, id)
ctr, err := ctrFromScannable(row, s.runtime, s.specsDir, s.lockDir)
ctr, err := s.ctrFromScannable(row)
if err != nil {
return nil, errors.Wrapf(err, "error retrieving container %s from database", id)
}
@ -190,7 +196,9 @@ func (s *SQLState) LookupContainer(idOrName string) (*Container, error) {
containerState.ExitCode,
containerState.OomKilled,
containerState.Pid,
containerState.NetNSPath
containerState.NetNSPath,
containerState.IPAddress,
containerState.SubnetMask
FROM containers
INNER JOIN
containerState ON containers.Id = containerState.Id
@ -218,7 +226,7 @@ func (s *SQLState) LookupContainer(idOrName string) (*Container, error) {
}
var err error
ctr, err = ctrFromScannable(rows, s.runtime, s.specsDir, s.lockDir)
ctr, err = s.ctrFromScannable(rows)
if err != nil {
return nil, errors.Wrapf(err, "error retrieving container %s from database", idOrName)
}
@ -271,10 +279,17 @@ func (s *SQLState) HasContainer(id string) (bool, error) {
func (s *SQLState) AddContainer(ctr *Container) (err error) {
const (
addCtr = `INSERT INTO containers VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?
);`
addCtrState = `INSERT INTO containerState VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?
);`
)
@ -286,11 +301,6 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
return ErrCtrRemoved
}
labelsJSON, err := json.Marshal(ctr.config.Labels)
if err != nil {
return errors.Wrapf(err, "error marshaling container %s labels to JSON", ctr.ID())
}
mounts, err := json.Marshal(ctr.config.Mounts)
if err != nil {
return errors.Wrapf(err, "error marshaling container %s mounts to JSON", ctr.ID())
@ -301,6 +311,11 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
return errors.Wrapf(err, "error marshaling container %s port mappings to JSON", ctr.ID())
}
labelsJSON, err := json.Marshal(ctr.config.Labels)
if err != nil {
return errors.Wrapf(err, "error marshaling container %s labels to JSON", ctr.ID())
}
netNSPath := ""
if ctr.state.NetNS != nil {
netNSPath = ctr.state.NetNS.Path()
@ -322,22 +337,37 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
_, err = tx.Exec(addCtr,
ctr.ID(),
ctr.Name(),
stringToNullString(ctr.PodID()),
ctr.config.RootfsImageID,
ctr.config.RootfsImageName,
boolToSQL(ctr.config.ImageVolumes),
boolToSQL(ctr.config.ReadOnly),
ctr.config.ShmDir,
ctr.config.ShmSize,
ctr.config.StaticDir,
string(mounts),
ctr.config.ProcessLabel,
ctr.config.MountLabel,
string(mounts),
ctr.config.ShmDir,
ctr.config.User,
stringToNullString(ctr.config.IPCNsCtr),
stringToNullString(ctr.config.MountNsCtr),
stringToNullString(ctr.config.NetNsCtr),
stringToNullString(ctr.config.PIDNsCtr),
stringToNullString(ctr.config.UserNsCtr),
stringToNullString(ctr.config.UTSNsCtr),
boolToSQL(ctr.config.CreateNetNS),
string(portsJSON),
ctr.config.StaticDir,
boolToSQL(ctr.config.Stdin),
string(labelsJSON),
ctr.config.StopSignal,
ctr.config.StopTimeout,
timeToSQL(ctr.config.CreatedTime),
ctr.config.RootfsImageID,
ctr.config.RootfsImageName,
boolToSQL(ctr.config.UseImageConfig),
ctr.config.User)
ctr.config.CgroupParent)
if err != nil {
return errors.Wrapf(err, "error adding static information for container %s to database", ctr.ID())
}
@ -354,7 +384,9 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
ctr.state.ExitCode,
boolToSQL(ctr.state.OOMKilled),
ctr.state.PID,
netNSPath)
netNSPath,
ctr.state.IPAddress,
ctr.state.SubnetMask)
if err != nil {
return errors.Wrapf(err, "error adding container %s state to database", ctr.ID())
}
@ -394,7 +426,9 @@ func (s *SQLState) UpdateContainer(ctr *Container) error {
ExitCode,
OomKilled,
Pid,
NetNSPath
NetNSPath,
IPAddress,
SubnetMask
FROM containerState WHERE ID=?;`
var (
@ -408,6 +442,8 @@ func (s *SQLState) UpdateContainer(ctr *Container) error {
oomKilled int
pid int
netNSPath string
ipAddress string
subnetMask string
)
if !s.valid {
@ -429,7 +465,9 @@ func (s *SQLState) UpdateContainer(ctr *Container) error {
&exitCode,
&oomKilled,
&pid,
&netNSPath)
&netNSPath,
&ipAddress,
&subnetMask)
if err != nil {
// The container may not exist in the database
if err == sql.ErrNoRows {
@ -451,6 +489,8 @@ func (s *SQLState) UpdateContainer(ctr *Container) error {
newState.ExitCode = exitCode
newState.OOMKilled = boolFromSQL(oomKilled)
newState.PID = pid
newState.IPAddress = ipAddress
newState.SubnetMask = subnetMask
if newState.Mountpoint != "" {
newState.Mounted = true
@ -512,7 +552,9 @@ func (s *SQLState) SaveContainer(ctr *Container) error {
ExitCode=?,
OomKilled=?,
Pid=?,
NetNSPath=?
NetNSPath=?,
IPAddress=?,
SubnetMask=?
WHERE Id=?;`
if !ctr.valid {
@ -552,6 +594,8 @@ func (s *SQLState) SaveContainer(ctr *Container) error {
boolToSQL(ctr.state.OOMKilled),
ctr.state.PID,
netNSPath,
ctr.state.IPAddress,
ctr.state.SubnetMask,
ctr.ID())
if err != nil {
return errors.Wrapf(err, "error updating container %s state in database", ctr.ID())
@ -642,7 +686,9 @@ func (s *SQLState) AllContainers() ([]*Container, error) {
containerState.ExitCode,
containerState.OomKilled,
containerState.Pid,
containerState.NetNSPath
containerState.NetNSPath,
containerState.IPAddress,
containerState.SubnetMask
FROM containers
INNER JOIN
containerState ON containers.Id = containerState.Id
@ -661,7 +707,7 @@ func (s *SQLState) AllContainers() ([]*Container, error) {
containers := []*Container{}
for rows.Next() {
ctr, err := ctrFromScannable(rows, s.runtime, s.specsDir, s.lockDir)
ctr, err := s.ctrFromScannable(rows)
if err != nil {
return nil, err
}

View File

@ -22,13 +22,13 @@ func checkDB(db *sql.DB, r *Runtime) (err error) {
// 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,
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)
);
`
@ -155,6 +155,7 @@ func prepareDB(db *sql.DB) (err error) {
// TODO add ctr shared namespaces information - A separate table, probably? So we can FOREIGN KEY the ID
// TODO schema migration might be necessary and should be handled here
// TODO maybe make a port mappings table instead of JSONing the array and storing it?
// TODO prepared statements for common queries for performance
// Enable foreign keys in SQLite
if _, err := db.Exec("PRAGMA foreign_keys = ON;"); err != nil {
@ -164,51 +165,88 @@ func prepareDB(db *sql.DB) (err error) {
// Create a table for unchanging container data
const createCtr = `
CREATE TABLE IF NOT EXISTS containers(
Id TEXT NOT NULL PRIMARY KEY,
Name TEXT NOT NULL UNIQUE,
ProcessLabel TEXT NOT NULL,
MountLabel TEXT NOT NULL,
Mounts TEXT NOT NULL,
ShmDir TEXT NOT NULL,
CreateNetNS INTEGER NOT NULL,
PortMappings TEXT NOT NULL,
StaticDir TEXT NOT NULL,
Stdin INTEGER NOT NULL,
LabelsJSON TEXT NOT NULL,
StopSignal INTEGER NOT NULL,
StopTimeout INTEGER NOT NULL,
CreatedTime TEXT NOT NULL,
RootfsImageID TEXT NOT NULL,
RootfsImageName TEXT NOT NULL,
UseImageConfig INTEGER NOT NULL,
User TEXT NOT NULL,
CHECK (Stdin IN (0, 1)),
Id TEXT NOT NULL PRIMARY KEY,
Name TEXT NOT NULL UNIQUE,
Pod TEXT,
RootfsImageID TEXT NOT NULL,
RootfsImageName TEXT NOT NULL,
ImageVolumes INTEGER NOT NULL,
ReadOnly INTEGER NOT NULL,
ShmDir TEXT NOT NULL,
ShmSize INTEGER NOT NULL,
StaticDir TEXT NOT NULL,
Mounts TEXT NOT NULL,
ProcessLabel TEXT NOT NULL,
MountLabel TEXT NOT NULL,
User TEXT NOT NULL,
IPCNsCtr TEXT,
MountNsCtr TEXT,
NetNsCtr TEXT,
PIDNsCtr TEXT,
UserNsCtr TEXT,
UTSNsCtr TEXT,
CreateNetNS INTEGER NOT NULL,
PortMappings TEXT NOT NULL,
Stdin INTEGER NOT NULL,
LabelsJSON TEXT NOT NULL,
StopSignal INTEGER NOT NULL,
StopTimeout INTEGER NOT NULL,
CreatedTime TEXT NOT NULL,
CgroupParent TEXT NOT NULL,
CHECK (ImageVolumes IN (0, 1)),
CHECK (ReadOnly IN (0, 1)),
CHECK (SHMSize>=0),
CHECK (CreateNetNS IN (0, 1)),
CHECK (UseImageConfig IN (0, 1)),
CHECK (StopSignal>=0)
CHECK (Stdin IN (0, 1)),
CHECK (StopSignal>=0),
FOREIGN KEY (Pod) REFERENCES pod(Id) DEFERRABLE INITIALLY DEFERRED,
FOREIGN KEY (IPCNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
FOREIGN KEY (MountNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
FOREIGN KEY (NetNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
FOREIGN KEY (PIDNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
FOREIGN KEY (UserNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
FOREIGN KEY (UTSNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED
);
`
// Create a table for changing container state
const createCtrState = `
CREATE TABLE IF NOT EXISTS containerState(
Id TEXT NOT NULL PRIMARY KEY,
State INTEGER NOT NULL,
ConfigPath TEXT NOT NULL,
RunDir TEXT NOT NULL,
Mountpoint TEXT NOT NULL,
StartedTime TEXT NUT NULL,
FinishedTime TEXT NOT NULL,
ExitCode INTEGER NOT NULL,
OomKilled INTEGER NOT NULL,
Pid INTEGER NOT NULL,
NetNSPath TEXT NOT NULL,
Id TEXT NOT NULL PRIMARY KEY,
State INTEGER NOT NULL,
ConfigPath TEXT NOT NULL,
RunDir TEXT NOT NULL,
Mountpoint TEXT NOT NULL,
StartedTime TEXT NUT NULL,
FinishedTime TEXT NOT NULL,
ExitCode INTEGER NOT NULL,
OomKilled INTEGER NOT NULL,
Pid INTEGER NOT NULL,
NetNSPath TEXT NOT NULL,
IPAddress TEXT NOT NULL,
SubnetMask TEXT NOT NULL,
CHECK (State>0),
CHECK (OomKilled IN (0, 1)),
FOREIGN KEY (Id) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED
);
`
// Create a table for pod config
const createPod = `
CREATE TABLE IF NOT EXISTS pod(
Id TEXT NOT NULL PRIMARY KEY,
Name TEXT NOT NULL UNIQUE,
Labels TEXT NOT NULL
);
`
// Create the tables
tx, err := db.Begin()
if err != nil {
@ -229,6 +267,9 @@ func prepareDB(db *sql.DB) (err error) {
if _, err := tx.Exec(createCtrState); err != nil {
return errors.Wrapf(err, "error creating container state table in database")
}
if _, err := tx.Exec(createPod); err != nil {
return errors.Wrapf(err, "error creating pods table in database")
}
if err := tx.Commit(); err != nil {
return errors.Wrapf(err, "error committing table creation transaction in database")
@ -251,6 +292,25 @@ func boolToSQL(b bool) int {
return 0
}
// Convert a null string from SQL-readable format
func stringFromNullString(s sql.NullString) string {
if s.Valid {
return s.String
}
return ""
}
// Convert a string to a SQL nullable string
func stringToNullString(s string) sql.NullString {
if s == "" {
return sql.NullString{}
}
return sql.NullString{
String: s,
Valid: true,
}
}
// Convert a bool from SQL-readable format
func boolFromSQL(i int) bool {
return i != 0
@ -272,26 +332,42 @@ type scannable interface {
}
// Read a single container from a single row result in the database
func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir string) (*Container, error) {
func (s *SQLState) ctrFromScannable(row scannable) (*Container, error) {
var (
id string
name string
processLabel string
mountLabel string
mounts string
shmDir string
createNetNS int
portMappingsJSON string
staticDir string
stdin int
labelsJSON string
stopSignal uint
stopTimeout uint
createdTimeString string
rootfsImageID string
rootfsImageName string
useImageConfig int
user string
id string
name string
pod sql.NullString
rootfsImageID string
rootfsImageName string
imageVolumes int
readOnly int
shmDir string
shmSize int64
staticDir string
mounts string
processLabel string
mountLabel string
user string
ipcNsCtrNullStr sql.NullString
mountNsCtrNullStr sql.NullString
netNsCtrNullStr sql.NullString
pidNsCtrNullStr sql.NullString
userNsCtrNullStr sql.NullString
utsNsCtrNullStr sql.NullString
createNetNS int
portMappingsJSON string
stdin int
labelsJSON string
stopSignal uint
stopTimeout uint
createdTimeString string
cgroupParent string
state int
configPath string
runDir string
@ -302,27 +378,45 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
oomKilled int
pid int
netNSPath string
ipAddress string
subnetMask string
)
err := row.Scan(
&id,
&name,
&pod,
&rootfsImageID,
&rootfsImageName,
&imageVolumes,
&readOnly,
&shmDir,
&shmSize,
&staticDir,
&mounts,
&processLabel,
&mountLabel,
&mounts,
&shmDir,
&user,
&ipcNsCtrNullStr,
&mountNsCtrNullStr,
&netNsCtrNullStr,
&pidNsCtrNullStr,
&userNsCtrNullStr,
&utsNsCtrNullStr,
&createNetNS,
&portMappingsJSON,
&staticDir,
&stdin,
&labelsJSON,
&stopSignal,
&stopTimeout,
&createdTimeString,
&rootfsImageID,
&rootfsImageName,
&useImageConfig,
&user,
&cgroupParent,
&state,
&configPath,
&runDir,
@ -332,7 +426,9 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
&exitCode,
&oomKilled,
&pid,
&netNSPath)
&netNSPath,
&ipAddress,
&subnetMask)
if err != nil {
if err == sql.ErrNoRows {
return nil, ErrNoSuchCtr
@ -347,18 +443,33 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
ctr.config.ID = id
ctr.config.Name = name
ctr.config.Pod = stringFromNullString(pod)
ctr.config.RootfsImageID = rootfsImageID
ctr.config.RootfsImageName = rootfsImageName
ctr.config.UseImageConfig = boolFromSQL(useImageConfig)
ctr.config.ImageVolumes = boolFromSQL(imageVolumes)
ctr.config.ReadOnly = boolFromSQL(readOnly)
ctr.config.ShmDir = shmDir
ctr.config.ShmSize = shmSize
ctr.config.StaticDir = staticDir
ctr.config.ProcessLabel = processLabel
ctr.config.MountLabel = mountLabel
ctr.config.ShmDir = shmDir
ctr.config.User = user
ctr.config.IPCNsCtr = stringFromNullString(ipcNsCtrNullStr)
ctr.config.MountNsCtr = stringFromNullString(mountNsCtrNullStr)
ctr.config.NetNsCtr = stringFromNullString(netNsCtrNullStr)
ctr.config.PIDNsCtr = stringFromNullString(pidNsCtrNullStr)
ctr.config.UserNsCtr = stringFromNullString(userNsCtrNullStr)
ctr.config.UTSNsCtr = stringFromNullString(utsNsCtrNullStr)
ctr.config.CreateNetNS = boolFromSQL(createNetNS)
ctr.config.StaticDir = staticDir
ctr.config.Stdin = boolFromSQL(stdin)
ctr.config.StopSignal = stopSignal
ctr.config.StopTimeout = stopTimeout
ctr.config.User = user
ctr.config.CgroupParent = cgroupParent
ctr.state.State = ContainerState(state)
ctr.state.ConfigPath = configPath
@ -367,18 +478,14 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
ctr.state.ExitCode = exitCode
ctr.state.OOMKilled = boolFromSQL(oomKilled)
ctr.state.PID = pid
ctr.state.IPAddress = ipAddress
ctr.state.SubnetMask = subnetMask
// TODO should we store this in the database separately instead?
if ctr.state.Mountpoint != "" {
ctr.state.Mounted = true
}
labels := make(map[string]string)
if err := json.Unmarshal([]byte(labelsJSON), &labels); err != nil {
return nil, errors.Wrapf(err, "error parsing container %s labels JSON", id)
}
ctr.config.Labels = labels
if err := json.Unmarshal([]byte(mounts), &ctr.config.Mounts); err != nil {
return nil, errors.Wrapf(err, "error parsing container %s mounts JSON", id)
}
@ -387,6 +494,12 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
return nil, errors.Wrapf(err, "error parsing container %s port mappings JSON", id)
}
labels := make(map[string]string)
if err := json.Unmarshal([]byte(labelsJSON), &labels); err != nil {
return nil, errors.Wrapf(err, "error parsing container %s labels JSON", id)
}
ctr.config.Labels = labels
createdTime, err := timeFromSQL(createdTimeString)
if err != nil {
return nil, errors.Wrapf(err, "error parsing container %s created time", id)
@ -415,10 +528,10 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
}
ctr.valid = true
ctr.runtime = runtime
ctr.runtime = s.runtime
// Open and set the lockfile
lockPath := filepath.Join(lockDir, id)
lockPath := filepath.Join(s.lockDir, id)
lock, err := storage.GetLockfile(lockPath)
if err != nil {
return nil, errors.Wrapf(err, "error retrieving lockfile for container %s", id)
@ -427,7 +540,7 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
// Retrieve the spec from disk
ociSpec := new(spec.Spec)
specPath := getSpecPath(specsDir, id)
specPath := getSpecPath(s.specsDir, id)
fileContents, err := ioutil.ReadFile(specPath)
if err != nil {
return nil, errors.Wrapf(err, "error reading container %s OCI spec", id)

View File

@ -21,7 +21,8 @@ func getTestContainer(id, name, locksDir string) (*Container, error) {
Name: name,
RootfsImageID: id,
RootfsImageName: "testimg",
UseImageConfig: true,
ImageVolumes: true,
ReadOnly: true,
StaticDir: "/does/not/exist/",
Stdin: true,
Labels: make(map[string]string),