2013-01-18 19:13:39 -05:00
|
|
|
package docker
|
|
|
|
|
|
|
|
import (
|
|
|
|
"container/list"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
2013-01-25 17:09:21 -05:00
|
|
|
"log"
|
2013-01-18 19:13:39 -05:00
|
|
|
"os"
|
|
|
|
"path"
|
2013-01-29 15:15:39 -05:00
|
|
|
"sort"
|
2013-01-18 19:13:39 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
type Docker struct {
|
|
|
|
root string
|
|
|
|
repository string
|
|
|
|
containers *list.List
|
|
|
|
}
|
|
|
|
|
|
|
|
func (docker *Docker) List() []*Container {
|
2013-01-29 15:15:39 -05:00
|
|
|
containers := new(History)
|
2013-01-18 19:13:39 -05:00
|
|
|
for e := docker.containers.Front(); e != nil; e = e.Next() {
|
2013-01-29 15:15:39 -05:00
|
|
|
containers.Add(e.Value.(*Container))
|
2013-01-29 06:24:31 -05:00
|
|
|
}
|
2013-01-29 15:15:39 -05:00
|
|
|
return *containers
|
2013-01-18 19:13:39 -05:00
|
|
|
}
|
|
|
|
|
2013-01-21 21:39:52 -05:00
|
|
|
func (docker *Docker) getContainerElement(id string) *list.Element {
|
2013-01-18 19:13:39 -05:00
|
|
|
for e := docker.containers.Front(); e != nil; e = e.Next() {
|
|
|
|
container := e.Value.(*Container)
|
2013-01-21 21:39:52 -05:00
|
|
|
if container.Id == id {
|
2013-01-18 19:13:39 -05:00
|
|
|
return e
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2013-01-21 21:39:52 -05:00
|
|
|
func (docker *Docker) Get(id string) *Container {
|
|
|
|
e := docker.getContainerElement(id)
|
2013-01-18 19:13:39 -05:00
|
|
|
if e == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return e.Value.(*Container)
|
|
|
|
}
|
|
|
|
|
2013-01-21 21:39:52 -05:00
|
|
|
func (docker *Docker) Exists(id string) bool {
|
|
|
|
return docker.Get(id) != nil
|
2013-01-18 19:13:39 -05:00
|
|
|
}
|
|
|
|
|
2013-01-21 21:39:52 -05:00
|
|
|
func (docker *Docker) Create(id string, command string, args []string, layers []string, config *Config) (*Container, error) {
|
|
|
|
if docker.Exists(id) {
|
|
|
|
return nil, fmt.Errorf("Container %v already exists", id)
|
2013-01-18 19:13:39 -05:00
|
|
|
}
|
2013-01-21 21:39:52 -05:00
|
|
|
root := path.Join(docker.repository, id)
|
|
|
|
container, err := createContainer(id, root, command, args, layers, config)
|
2013-01-18 19:13:39 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
docker.containers.PushBack(container)
|
|
|
|
return container, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (docker *Docker) Destroy(container *Container) error {
|
2013-01-21 21:39:52 -05:00
|
|
|
element := docker.getContainerElement(container.Id)
|
2013-01-18 19:13:39 -05:00
|
|
|
if element == nil {
|
2013-01-21 21:39:52 -05:00
|
|
|
return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.Id)
|
2013-01-18 19:13:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := container.Stop(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2013-01-28 14:58:59 -05:00
|
|
|
if container.Filesystem.IsMounted() {
|
|
|
|
if err := container.Filesystem.Umount(); err != nil {
|
|
|
|
log.Printf("Unable to umount container %v: %v", container.Id, err)
|
|
|
|
}
|
|
|
|
}
|
2013-01-18 19:13:39 -05:00
|
|
|
if err := os.RemoveAll(container.Root); err != nil {
|
2013-01-28 14:58:59 -05:00
|
|
|
log.Printf("Unable to remove filesystem for %v: %v", container.Id, err)
|
2013-01-18 19:13:39 -05:00
|
|
|
}
|
|
|
|
docker.containers.Remove(element)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (docker *Docker) restore() error {
|
|
|
|
dir, err := ioutil.ReadDir(docker.repository)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for _, v := range dir {
|
|
|
|
container, err := loadContainer(path.Join(docker.repository, v.Name()))
|
|
|
|
if err != nil {
|
2013-01-25 17:09:21 -05:00
|
|
|
log.Printf("Failed to load container %v: %v", v.Name(), err)
|
2013-01-18 19:13:39 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
docker.containers.PushBack(container)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func New() (*Docker, error) {
|
|
|
|
return NewFromDirectory("/var/lib/docker")
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewFromDirectory(root string) (*Docker, error) {
|
|
|
|
docker := &Docker{
|
|
|
|
root: root,
|
|
|
|
repository: path.Join(root, "containers"),
|
|
|
|
containers: list.New(),
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.Mkdir(docker.repository, 0700); err != nil && !os.IsExist(err) {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := docker.restore(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return docker, nil
|
|
|
|
}
|
2013-01-29 15:15:39 -05:00
|
|
|
|
|
|
|
type History []*Container
|
|
|
|
|
|
|
|
func (history *History) Len() int {
|
|
|
|
return len(*history)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (history *History) Less(i, j int) bool {
|
|
|
|
containers := *history
|
|
|
|
return containers[j].When().Before(containers[i].When())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (history *History) Swap(i, j int) {
|
|
|
|
containers := *history
|
|
|
|
tmp := containers[i]
|
|
|
|
containers[i] = containers[j]
|
|
|
|
containers[j] = tmp
|
|
|
|
}
|
|
|
|
|
|
|
|
func (history *History) Add(container *Container) {
|
|
|
|
*history = append(*history, container)
|
|
|
|
sort.Sort(history)
|
|
|
|
}
|