move work on execution service
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
parent
dd5f74edec
commit
c857213b4c
15 changed files with 596 additions and 1016 deletions
213
container.go
213
container.go
|
@ -1,213 +0,0 @@
|
|||
package containerd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
type ContainerConfig interface {
|
||||
ID() string
|
||||
Root() string // bundle path
|
||||
Spec() (*specs.Spec, error)
|
||||
Runtime() (Runtime, error)
|
||||
}
|
||||
|
||||
func NewContainer(config ContainerConfig) (*Container, error) {
|
||||
var (
|
||||
id = config.ID()
|
||||
root = config.Root()
|
||||
path = filepath.Join(root, id)
|
||||
)
|
||||
s, err := config.Spec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// HACK: for runc to allow to use this path without a premounted rootfs
|
||||
if err := os.MkdirAll(filepath.Join(path, s.Root.Path), 0711); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f, err := os.Create(filepath.Join(path, "config.json"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write the spec file to the container's directory
|
||||
err = json.NewEncoder(f).Encode(s)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r, err := config.Runtime()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Container{
|
||||
id: id,
|
||||
path: path,
|
||||
s: s,
|
||||
driver: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func LoadContainer(config ContainerConfig) (*Container, error) {
|
||||
var (
|
||||
id = config.ID()
|
||||
root = config.Root()
|
||||
path = filepath.Join(root, id)
|
||||
)
|
||||
spec, err := loadSpec(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r, err := config.Runtime()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
process, err := r.Load(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: load exec processes
|
||||
return &Container{
|
||||
id: id,
|
||||
path: path,
|
||||
s: spec,
|
||||
driver: r,
|
||||
init: &Process{
|
||||
d: process,
|
||||
driver: r,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func loadSpec(path string) (*specs.Spec, error) {
|
||||
f, err := os.Open(filepath.Join(path, "config.json"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var s specs.Spec
|
||||
err = json.NewDecoder(f).Decode(&s)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
mu sync.Mutex
|
||||
id string
|
||||
path string
|
||||
s *specs.Spec
|
||||
|
||||
driver Runtime
|
||||
|
||||
Stdin io.Reader
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
|
||||
// init is the container's init processes
|
||||
init *Process
|
||||
// processes is a list of additional processes executed inside the container
|
||||
// via the NewProcess method on the container
|
||||
processes []*Process
|
||||
}
|
||||
|
||||
// ID returns the id of the container
|
||||
func (c *Container) ID() string {
|
||||
return c.id
|
||||
}
|
||||
|
||||
// Path returns the fully qualified path to the container on disk
|
||||
func (c *Container) Path() string {
|
||||
return c.path
|
||||
}
|
||||
|
||||
// Spec returns the OCI runtime spec for the container
|
||||
func (c *Container) Spec() *specs.Spec {
|
||||
return c.s
|
||||
}
|
||||
|
||||
// Create will create the container on the system by running the runtime's
|
||||
// initial setup and process waiting for the user process to be started
|
||||
func (c *Container) Create() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
d, err := c.driver.Create(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.init = &Process{
|
||||
d: d,
|
||||
driver: c.driver,
|
||||
Stdin: c.Stdin,
|
||||
Stdout: c.Stdout,
|
||||
Stderr: c.Stderr,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start will start the container's user specified process
|
||||
func (c *Container) Start() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.driver.Start(c)
|
||||
}
|
||||
|
||||
// NewProcess will create a new process that will be executed inside the
|
||||
// container and tied to the init processes lifecycle
|
||||
func (c *Container) NewProcess(spec *specs.Process) (*Process, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
process := &Process{
|
||||
s: spec,
|
||||
c: c,
|
||||
exec: true,
|
||||
driver: c.driver,
|
||||
}
|
||||
c.processes = append(c.processes, process)
|
||||
return process, nil
|
||||
}
|
||||
|
||||
// Pid returns the pid of the init or main process hosted inside the container
|
||||
func (c *Container) Pid() int {
|
||||
c.mu.Lock()
|
||||
if c.init == nil {
|
||||
c.mu.Unlock()
|
||||
return -1
|
||||
}
|
||||
pid := c.init.Pid()
|
||||
c.mu.Unlock()
|
||||
return pid
|
||||
}
|
||||
|
||||
// Wait will perform a blocking wait on the init process of the container
|
||||
func (c *Container) Wait() (uint32, error) {
|
||||
c.mu.Lock()
|
||||
proc := c.init
|
||||
c.mu.Unlock()
|
||||
return proc.Wait()
|
||||
}
|
||||
|
||||
// Signal will send the provided signal to the init process of the container
|
||||
func (c *Container) Signal(s os.Signal) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.init.Signal(s)
|
||||
}
|
||||
|
||||
// Delete will delete the container if it no long has any processes running
|
||||
// inside the container and removes all state on disk for the container
|
||||
func (c *Container) Delete() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
err := c.driver.Delete(c)
|
||||
if rerr := os.RemoveAll(c.path); err == nil {
|
||||
err = rerr
|
||||
}
|
||||
return err
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue