mirror of
https://github.com/containers/podman.git
synced 2025-06-17 15:08:08 +08:00
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:
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
Reference in New Issue
Block a user