| package docker |
| |
| import ( |
| "container/list" |
| "fmt" |
| "github.com/dotcloud/docker/fs" |
| "io/ioutil" |
| "log" |
| "os" |
| "path" |
| "sort" |
| ) |
| |
| type Docker struct { |
| root string |
| repository string |
| containers *list.List |
| networkManager *NetworkManager |
| Store *fs.Store |
| } |
| |
| func (docker *Docker) List() []*Container { |
| containers := new(History) |
| for e := docker.containers.Front(); e != nil; e = e.Next() { |
| containers.Add(e.Value.(*Container)) |
| } |
| return *containers |
| } |
| |
| func (docker *Docker) getContainerElement(id string) *list.Element { |
| for e := docker.containers.Front(); e != nil; e = e.Next() { |
| container := e.Value.(*Container) |
| if container.Id == id { |
| return e |
| } |
| } |
| return nil |
| } |
| |
| func (docker *Docker) Get(id string) *Container { |
| e := docker.getContainerElement(id) |
| if e == nil { |
| return nil |
| } |
| return e.Value.(*Container) |
| } |
| |
| func (docker *Docker) Exists(id string) bool { |
| return docker.Get(id) != nil |
| } |
| |
| func (docker *Docker) Create(id string, command string, args []string, image *fs.Image, config *Config) (*Container, error) { |
| if docker.Exists(id) { |
| return nil, fmt.Errorf("Container %v already exists", id) |
| } |
| root := path.Join(docker.repository, id) |
| |
| container, err := createContainer(id, root, command, args, image, config, docker.networkManager) |
| if err != nil { |
| return nil, err |
| } |
| docker.containers.PushBack(container) |
| return container, nil |
| } |
| |
| func (docker *Docker) Destroy(container *Container) error { |
| element := docker.getContainerElement(container.Id) |
| if element == nil { |
| return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.Id) |
| } |
| |
| if err := container.Stop(); err != nil { |
| return err |
| } |
| if container.Mountpoint.Mounted() { |
| if err := container.Mountpoint.Umount(); err != nil { |
| return fmt.Errorf("Unable to umount container %v: %v", container.Id, err) |
| } |
| } |
| if err := container.Mountpoint.Deregister(); err != nil { |
| return fmt.Errorf("Unable to deregiser -- ? mountpoint %v: %v", container.Mountpoint.Root, err) |
| } |
| if err := os.RemoveAll(container.Root); err != nil { |
| return fmt.Errorf("Unable to remove filesystem for %v: %v", container.Id, err) |
| } |
| 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(docker.Store, path.Join(docker.repository, v.Name()), docker.networkManager) |
| if err != nil { |
| log.Printf("Failed to load container %v: %v", v.Name(), err) |
| continue |
| } |
| docker.containers.PushBack(container) |
| } |
| return nil |
| } |
| |
| func New() (*Docker, error) { |
| return NewFromDirectory("/var/lib/docker") |
| } |
| |
| func NewFromDirectory(root string) (*Docker, error) { |
| docker_repo := path.Join(root, "containers") |
| |
| if err := os.MkdirAll(docker_repo, 0700); err != nil && !os.IsExist(err) { |
| return nil, err |
| } |
| |
| store, err := fs.New(path.Join(root, "images")) |
| if err != nil { |
| return nil, err |
| } |
| netManager, err := newNetworkManager(networkBridgeIface) |
| if err != nil { |
| return nil, err |
| } |
| |
| docker := &Docker{ |
| root: root, |
| repository: docker_repo, |
| containers: list.New(), |
| Store: store, |
| networkManager: netManager, |
| } |
| |
| if err := docker.restore(); err != nil { |
| return nil, err |
| } |
| return docker, nil |
| } |
| |
| 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) |
| } |