mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Simplify graphdriver interface: Create, Get. No more external mounting or Dir/Image interface
This commit is contained in:
parent
a63ff8da46
commit
f2bab1557c
7 changed files with 162 additions and 158 deletions
55
container.go
55
container.go
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/dotcloud/docker/archive"
|
||||
"github.com/dotcloud/docker/term"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"github.com/dotcloud/docker/graphdriver" // FIXME: graphdriver.Change is a placeholder for archive.Change
|
||||
"github.com/kr/pty"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -25,7 +26,8 @@ import (
|
|||
)
|
||||
|
||||
type Container struct {
|
||||
root string
|
||||
root string // Path to the "home" of the container, including metadata.
|
||||
rootfs string // Path to the root filesystem of the container.
|
||||
|
||||
ID string
|
||||
|
||||
|
@ -767,6 +769,7 @@ func (container *Container) Start(hostConfig *HostConfig) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
volumesDriver := container.runtime.volumes.driver
|
||||
// Create the requested volumes if they don't exist
|
||||
for volPath := range container.Config.Volumes {
|
||||
volPath = path.Clean(volPath)
|
||||
|
@ -790,9 +793,9 @@ func (container *Container) Start(hostConfig *HostConfig) (err error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srcPath, err = c.layer()
|
||||
srcPath, err = volumesDriver.Get(c.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("Driver %s failed to get volume rootfs %s: %s", volumesDriver, c.ID, err)
|
||||
}
|
||||
srcRW = true // RW by default
|
||||
}
|
||||
|
@ -1338,15 +1341,10 @@ func (container *Container) Resize(h, w int) error {
|
|||
}
|
||||
|
||||
func (container *Container) ExportRw() (archive.Archive, error) {
|
||||
return archive.Tar(container.rwPath(), archive.Uncompressed)
|
||||
}
|
||||
|
||||
func (container *Container) RwChecksum() (string, error) {
|
||||
rwData, err := archive.Tar(container.rwPath(), archive.Xz)
|
||||
if err != nil {
|
||||
return "", err
|
||||
if container.runtime == nil {
|
||||
return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID)
|
||||
}
|
||||
return utils.HashData(rwData)
|
||||
return container.runtime.driver.Diff(container.ID)
|
||||
}
|
||||
|
||||
func (container *Container) Export() (archive.Archive, error) {
|
||||
|
@ -1372,11 +1370,8 @@ func (container *Container) WaitTimeout(timeout time.Duration) error {
|
|||
}
|
||||
|
||||
func (container *Container) EnsureMounted() error {
|
||||
if mounted, err := container.Mounted(); err != nil {
|
||||
return err
|
||||
} else if mounted {
|
||||
return nil
|
||||
}
|
||||
// FIXME: EnsureMounted is deprecated because drivers are now responsible
|
||||
// for re-entrant mounting in their Get() method.
|
||||
return container.Mount()
|
||||
}
|
||||
|
||||
|
@ -1384,7 +1379,7 @@ func (container *Container) Mount() error {
|
|||
return container.runtime.Mount(container)
|
||||
}
|
||||
|
||||
func (container *Container) Changes() ([]Change, error) {
|
||||
func (container *Container) Changes() ([]graphdriver.Change, error) {
|
||||
return container.runtime.Changes(container)
|
||||
}
|
||||
|
||||
|
@ -1395,10 +1390,6 @@ func (container *Container) GetImage() (*Image, error) {
|
|||
return container.runtime.graph.Get(container.Image)
|
||||
}
|
||||
|
||||
func (container *Container) Mounted() (bool, error) {
|
||||
return container.runtime.Mounted(container)
|
||||
}
|
||||
|
||||
func (container *Container) Unmount() error {
|
||||
return container.runtime.Unmount(container)
|
||||
}
|
||||
|
@ -1437,11 +1428,7 @@ func (container *Container) lxcConfigPath() string {
|
|||
|
||||
// This method must be exported to be used from the lxc template
|
||||
func (container *Container) RootfsPath() string {
|
||||
return path.Join(container.root, "rootfs")
|
||||
}
|
||||
|
||||
func (container *Container) rwPath() string {
|
||||
return path.Join(container.root, "rw")
|
||||
return container.rootfs
|
||||
}
|
||||
|
||||
func validateID(id string) error {
|
||||
|
@ -1455,18 +1442,20 @@ func validateID(id string) error {
|
|||
func (container *Container) GetSize() (int64, int64) {
|
||||
var sizeRw, sizeRootfs int64
|
||||
|
||||
filepath.Walk(container.rwPath(), func(path string, fileInfo os.FileInfo, err error) error {
|
||||
if fileInfo != nil {
|
||||
sizeRw += fileInfo.Size()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
driver := container.runtime.driver
|
||||
sizeRw, err := driver.DiffSize(container.ID)
|
||||
if err != nil {
|
||||
utils.Errorf("Warning: driver %s couldn't return diff size of container %s: %s", driver, container.ID, err)
|
||||
// FIXME: GetSize should return an error. Not changing it now in case
|
||||
// there is a side-effect.
|
||||
sizeRw = -1
|
||||
}
|
||||
|
||||
if err := container.EnsureMounted(); err != nil {
|
||||
utils.Errorf("Warning: failed to compute size of container rootfs %s: %s", container.ID, err)
|
||||
return sizeRw, sizeRootfs
|
||||
}
|
||||
_, err := os.Stat(container.RootfsPath())
|
||||
_, err = os.Stat(container.RootfsPath())
|
||||
if err == nil {
|
||||
filepath.Walk(container.RootfsPath(), func(path string, fileInfo os.FileInfo, err error) error {
|
||||
if fileInfo != nil {
|
||||
|
|
86
graph.go
86
graph.go
|
@ -3,10 +3,8 @@ package docker
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/archive"
|
||||
_ "github.com/dotcloud/docker/aufs"
|
||||
_ "github.com/dotcloud/docker/devmapper"
|
||||
"github.com/dotcloud/docker/graphdriver"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"github.com/dotcloud/docker/graphdriver"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -25,7 +23,7 @@ type Graph struct {
|
|||
|
||||
// NewGraph instantiates a new graph at the given root path in the filesystem.
|
||||
// `root` will be created if it doesn't exist.
|
||||
func NewGraph(root string) (*Graph, error) {
|
||||
func NewGraph(root string, driver graphdriver.Driver) (*Graph, error) {
|
||||
abspath, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -35,10 +33,6 @@ func NewGraph(root string) (*Graph, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
driver, err := graphdriver.New(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
graph := &Graph{
|
||||
Root: abspath,
|
||||
|
@ -89,16 +83,22 @@ func (graph *Graph) Get(name string) (*Image, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Check that the filesystem layer exists
|
||||
rootfs, err := graph.driver.Get(img.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Driver %s failed to get image rootfs %s: %s", graph.driver, img.ID, err)
|
||||
}
|
||||
if img.ID != id {
|
||||
return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.ID)
|
||||
}
|
||||
img.graph = graph
|
||||
if img.Size == 0 {
|
||||
root, err := img.root()
|
||||
size, err := utils.TreeSize(rootfs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("Error computing size of rootfs %s: %s", img.ID, err)
|
||||
}
|
||||
if err := StoreSize(img, root); err != nil {
|
||||
img.Size = size
|
||||
if err := img.SaveSize(graph.imageRoot(id)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,17 @@ func (graph *Graph) Register(jsonData []byte, layerData archive.Archive, img *Im
|
|||
if err != nil {
|
||||
return fmt.Errorf("Mktemp failed: %s", err)
|
||||
}
|
||||
if err := StoreImage(img, jsonData, layerData, tmp); err != nil {
|
||||
|
||||
// Create root filesystem in the driver
|
||||
if err := graph.driver.Create(img.ID, img.Parent); err != nil {
|
||||
return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err)
|
||||
}
|
||||
// Mount the root filesystem so we can apply the diff/layer
|
||||
rootfs, err := graph.driver.Get(img.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Driver %s failed to get image rootfs %s: %s", graph.driver, img.ID, err)
|
||||
}
|
||||
if err := StoreImage(img, jsonData, layerData, tmp, rootfs); err != nil {
|
||||
return err
|
||||
}
|
||||
// Commit
|
||||
|
@ -163,7 +173,7 @@ func (graph *Graph) TempLayerArchive(id string, compression archive.Compression,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmp, err := graph.tmp()
|
||||
tmp, err := graph.Mktemp("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -171,7 +181,7 @@ func (graph *Graph) TempLayerArchive(id string, compression archive.Compression,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return archive.NewTempArchive(utils.ProgressReader(ioutil.NopCloser(a), 0, output, sf.FormatProgress("", "Buffering to disk", "%v/%v (%v)"), sf, true), tmp.Root)
|
||||
return archive.NewTempArchive(utils.ProgressReader(ioutil.NopCloser(a), 0, output, sf.FormatProgress("", "Buffering to disk", "%v/%v (%v)"), sf, true), tmp)
|
||||
}
|
||||
|
||||
// Mktemp creates a temporary sub-directory inside the graph's filesystem.
|
||||
|
@ -179,34 +189,26 @@ func (graph *Graph) Mktemp(id string) (string, error) {
|
|||
if id == "" {
|
||||
id = GenerateID()
|
||||
}
|
||||
tmp, err := graph.tmp()
|
||||
// FIXME: use a separate "tmp" driver instead of the regular driver,
|
||||
// to allow for removal at cleanup.
|
||||
// Right now temp directories are never removed!
|
||||
if err := graph.driver.Create(id, ""); err != nil {
|
||||
return "", fmt.Errorf("Driver %s couldn't create temporary directory %s: %s", graph.driver, id, err)
|
||||
}
|
||||
dir, err := graph.driver.Get(id)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Couldn't create temp: %s", err)
|
||||
return "", fmt.Errorf("Driver %s couldn't get temporary directory %s: %s", graph.driver, id, err)
|
||||
}
|
||||
if tmp.Exists(id) {
|
||||
return "", fmt.Errorf("Image %s already exists", id)
|
||||
}
|
||||
return tmp.imageRoot(id), nil
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
// getDockerInitLayer returns the path of a layer containing a mountpoint suitable
|
||||
// setupInitLayer populates a directory with mountpoints suitable
|
||||
// for bind-mounting dockerinit into the container. The mountpoint is simply an
|
||||
// empty file at /.dockerinit
|
||||
//
|
||||
// This extra layer is used by all containers as the top-most ro layer. It protects
|
||||
// the container from unwanted side-effects on the rw layer.
|
||||
func (graph *Graph) getDockerInitLayer() (string, error) {
|
||||
tmp, err := graph.tmp()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
initLayer := tmp.imageRoot("_dockerinit")
|
||||
if err := os.Mkdir(initLayer, 0755); err != nil && !os.IsExist(err) {
|
||||
// If directory already existed, keep going.
|
||||
// For all other errors, abort.
|
||||
return "", err
|
||||
}
|
||||
|
||||
func setupInitLayer(initLayer string) error {
|
||||
for pth, typ := range map[string]string{
|
||||
"/dev/pts": "dir",
|
||||
"/dev/shm": "dir",
|
||||
|
@ -225,32 +227,27 @@ func (graph *Graph) getDockerInitLayer() (string, error) {
|
|||
switch typ {
|
||||
case "dir":
|
||||
if err := os.MkdirAll(path.Join(initLayer, pth), 0755); err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
case "file":
|
||||
if err := os.MkdirAll(path.Join(initLayer, path.Dir(pth)), 0755); err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
|
||||
if f, err := os.OpenFile(path.Join(initLayer, pth), os.O_CREATE, 0755); err != nil {
|
||||
return "", err
|
||||
return err
|
||||
} else {
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Layer is ready to use, if it wasn't before.
|
||||
return initLayer, nil
|
||||
}
|
||||
|
||||
func (graph *Graph) tmp() (*Graph, error) {
|
||||
// Changed to _tmp from :tmp:, because it messed with ":" separators in aufs branch syntax...
|
||||
return NewGraph(path.Join(graph.Root, "_tmp"))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if given error is "not empty".
|
||||
|
@ -282,6 +279,9 @@ func (graph *Graph) Delete(name string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Remove rootfs data from the driver
|
||||
graph.driver.Remove(id)
|
||||
// Remove the trashed image directory
|
||||
return os.RemoveAll(tmp)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,21 +7,20 @@ import (
|
|||
|
||||
type InitFunc func(root string) (Driver, error)
|
||||
|
||||
type Dir interface {
|
||||
ID() string
|
||||
Path() string
|
||||
Parent() (Dir, error)
|
||||
// FIXME: this is a temporary placeholder for archive.Change
|
||||
// (to be merged from master)
|
||||
type Change interface {
|
||||
}
|
||||
|
||||
type Driver interface {
|
||||
OnCreate(dir Dir, layer archive.Archive) error
|
||||
OnRemove(dir Dir) error
|
||||
Create(id, parent string) error
|
||||
Remove(id string) error
|
||||
|
||||
OnMount(dir Dir, dest string) error
|
||||
OnUnmount(dest string) error
|
||||
Mounted(dest string) (bool, error)
|
||||
Get(id string) (dir string, err error)
|
||||
|
||||
Layer(dir Dir, dest string) (archive.Archive, error)
|
||||
Diff(id string) (archive.Archive, error)
|
||||
DiffSize(id string) (bytes int64, err error)
|
||||
Changes(id string) ([]Change, error)
|
||||
|
||||
Cleanup() error
|
||||
}
|
||||
|
|
60
image.go
60
image.go
|
@ -11,7 +11,6 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -59,19 +58,10 @@ func LoadImage(root string) (*Image, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Check that the filesystem layer exists
|
||||
if stat, err := os.Stat(layerPath(root)); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("Couldn't load image %s: no filesystem layer", img.ID)
|
||||
}
|
||||
return nil, err
|
||||
} else if !stat.IsDir() {
|
||||
return nil, fmt.Errorf("Couldn't load image %s: %s is not a directory", img.ID, layerPath(root))
|
||||
}
|
||||
return img, nil
|
||||
}
|
||||
|
||||
func StoreImage(img *Image, jsonData []byte, layerData archive.Archive, root string) error {
|
||||
func StoreImage(img *Image, jsonData []byte, layerData archive.Archive, root, rootfs string) error {
|
||||
// Check that root doesn't already exist
|
||||
if _, err := os.Stat(root); err == nil {
|
||||
return fmt.Errorf("Image %s already exists", img.ID)
|
||||
|
@ -79,7 +69,7 @@ func StoreImage(img *Image, jsonData []byte, layerData archive.Archive, root str
|
|||
return err
|
||||
}
|
||||
// Store the layer
|
||||
layer := layerPath(root)
|
||||
layer := rootfs
|
||||
if err := os.MkdirAll(layer, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -106,29 +96,25 @@ func StoreImage(img *Image, jsonData []byte, layerData archive.Archive, root str
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return StoreSize(img, root)
|
||||
}
|
||||
|
||||
func StoreSize(img *Image, root string) error {
|
||||
layer := layerPath(root)
|
||||
|
||||
var totalSize int64 = 0
|
||||
filepath.Walk(layer, func(path string, fileInfo os.FileInfo, err error) error {
|
||||
totalSize += fileInfo.Size()
|
||||
return nil
|
||||
})
|
||||
img.Size = totalSize
|
||||
|
||||
if err := ioutil.WriteFile(path.Join(root, "layersize"), []byte(strconv.Itoa(int(totalSize))), 0600); err != nil {
|
||||
return nil
|
||||
// Compute and save the size of the rootfs
|
||||
size, err := utils.TreeSize(rootfs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error computing size of rootfs %s: %s", img.ID, err)
|
||||
}
|
||||
img.Size = size
|
||||
if err := img.SaveSize(root); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func layerPath(root string) string {
|
||||
return path.Join(root, "layer")
|
||||
// SaveSize stores the current `size` value of `img` in the directory `root`.
|
||||
func (img *Image) SaveSize(root string) error {
|
||||
if err := ioutil.WriteFile(path.Join(root, "layersize"), []byte(strconv.Itoa(int(img.Size))), 0600); err != nil {
|
||||
return fmt.Errorf("Error storing image size in %s/layersize: %s", root, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func jsonPath(root string) string {
|
||||
|
@ -137,7 +123,10 @@ func jsonPath(root string) string {
|
|||
|
||||
// TarLayer returns a tar archive of the image's filesystem layer.
|
||||
func (image *Image) TarLayer(compression archive.Compression) (archive.Archive, error) {
|
||||
layerPath, err := image.layer()
|
||||
if image.graph == nil {
|
||||
return nil, fmt.Errorf("Can't load storage driver for unregistered image %s", image.ID)
|
||||
}
|
||||
layerPath, err := image.graph.driver.Get(image.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -216,15 +205,6 @@ func (img *Image) root() (string, error) {
|
|||
return img.graph.imageRoot(img.ID), nil
|
||||
}
|
||||
|
||||
// Return the path of an image's layer
|
||||
func (img *Image) layer() (string, error) {
|
||||
root, err := img.root()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return layerPath(root), nil
|
||||
}
|
||||
|
||||
func (img *Image) getParentsSize(size int64) int64 {
|
||||
parentImage, err := img.GetParent()
|
||||
if err != nil || parentImage == nil {
|
||||
|
|
82
runtime.go
82
runtime.go
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/dotcloud/docker/gograph"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"github.com/dotcloud/docker/graphdriver"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
@ -38,6 +39,7 @@ type Runtime struct {
|
|||
srv *Server
|
||||
config *DaemonConfig
|
||||
containerGraph *gograph.Database
|
||||
driver graphdriver.Driver
|
||||
}
|
||||
|
||||
// List returns an array of all containers registered in the runtime.
|
||||
|
@ -113,6 +115,13 @@ func (runtime *Runtime) Register(container *Container) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Get the root filesystem from the driver
|
||||
rootfs, err := runtime.driver.Get(container.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error getting container filesystem %s from driver %s: %s", container.ID, runtime.driver, err)
|
||||
}
|
||||
container.rootfs = rootfs
|
||||
|
||||
// init the wait lock
|
||||
container.waitLock = make(chan struct{})
|
||||
|
||||
|
@ -200,12 +209,8 @@ func (runtime *Runtime) Destroy(container *Container) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if mounted, err := container.Mounted(); err != nil {
|
||||
return err
|
||||
} else if mounted {
|
||||
if err := container.Unmount(); err != nil {
|
||||
return fmt.Errorf("Unable to unmount container %v: %v", container.ID, err)
|
||||
}
|
||||
if err := runtime.driver.Remove(container.ID); err != nil {
|
||||
return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", runtime.driver, container.ID, err)
|
||||
}
|
||||
|
||||
if _, err := runtime.containerGraph.Purge(container.ID); err != nil {
|
||||
|
@ -413,6 +418,21 @@ func (runtime *Runtime) Create(config *Config, name string) (*Container, []strin
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
initID := fmt.Sprintf("%s-init", container.ID)
|
||||
if err := runtime.driver.Create(initID, img.ID); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
initPath, err := runtime.driver.Get(initID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := setupInitLayer(initPath); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := runtime.driver.Create(container.ID, initID); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
resolvConf, err := utils.GetResolvConf()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -568,17 +588,23 @@ func NewRuntime(config *DaemonConfig) (*Runtime, error) {
|
|||
}
|
||||
|
||||
func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) {
|
||||
// Load storage driver
|
||||
driver, err := graphdriver.New(config.Root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
runtimeRepo := path.Join(config.Root, "containers")
|
||||
|
||||
if err := os.MkdirAll(runtimeRepo, 0700); err != nil && !os.IsExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g, err := NewGraph(path.Join(config.Root, "graph"))
|
||||
g, err := NewGraph(path.Join(config.Root, "graph"), driver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
volumes, err := NewGraph(path.Join(config.Root, "volumes"))
|
||||
volumes, err := NewGraph(path.Join(config.Root, "volumes"), driver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -612,6 +638,7 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
runtime := &Runtime{
|
||||
repository: runtimeRepo,
|
||||
containers: list.New(),
|
||||
|
@ -623,6 +650,7 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) {
|
|||
volumes: volumes,
|
||||
config: config,
|
||||
containerGraph: graph,
|
||||
driver: driver,
|
||||
}
|
||||
|
||||
if err := runtime.restore(); err != nil {
|
||||
|
@ -633,40 +661,32 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) {
|
|||
|
||||
func (runtime *Runtime) Close() error {
|
||||
runtime.networkManager.Close()
|
||||
runtime.driver.Cleanup()
|
||||
return runtime.containerGraph.Close()
|
||||
}
|
||||
|
||||
func (runtime *Runtime) Mount(container *Container) error {
|
||||
if mounted, err := runtime.Mounted(container); err != nil {
|
||||
return err
|
||||
} else if mounted {
|
||||
return fmt.Errorf("%s is already mounted", container.RootfsPath())
|
||||
}
|
||||
img, err := container.GetImage()
|
||||
dir, err := runtime.driver.Get(container.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, runtime.driver, err)
|
||||
}
|
||||
return runtime.graph.driver.Mount(img, container.root)
|
||||
if container.rootfs == "" {
|
||||
container.rootfs = dir
|
||||
} else if container.rootfs != dir {
|
||||
return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')",
|
||||
runtime.driver, container.ID, container.rootfs, dir)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (runtime *Runtime) Unmount(container *Container) error {
|
||||
return runtime.graph.driver.Unmount(container.root)
|
||||
// FIXME: Unmount is deprecated because drivers are responsible for mounting
|
||||
// and unmounting when necessary. Use driver.Remove() instead.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (runtime *Runtime) Mounted(container *Container) (bool, error) {
|
||||
return runtime.graph.driver.Mounted(container.root)
|
||||
}
|
||||
|
||||
func (runtime *Runtime) Changes(container *Container) ([]Change, error) {
|
||||
img, err := container.GetImage()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
layers, err := img.Layers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Changes(layers, container.rwPath())
|
||||
func (runtime *Runtime) Changes(container *Container) ([]graphdriver.Change, error) {
|
||||
return runtime.driver.Changes(container.ID)
|
||||
}
|
||||
|
||||
// History is a convenience type for storing a list of containers,
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/dotcloud/docker/gograph"
|
||||
"github.com/dotcloud/docker/registry"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"github.com/dotcloud/docker/graphdriver" // FIXME: graphdriver.Change is a placeholder for archive.Change
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
@ -430,7 +431,7 @@ func (srv *Server) ContainerTop(name, ps_args string) (*APITop, error) {
|
|||
return nil, fmt.Errorf("No such container: %s", name)
|
||||
}
|
||||
|
||||
func (srv *Server) ContainerChanges(name string) ([]Change, error) {
|
||||
func (srv *Server) ContainerChanges(name string) ([]graphdriver.Change, error) {
|
||||
if container := srv.runtime.Get(name); container != nil {
|
||||
return container.Changes()
|
||||
}
|
||||
|
|
15
utils/fs.go
Normal file
15
utils/fs.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// TreeSize walks a directory tree and returns its total size in bytes.
|
||||
func TreeSize(dir string) (size int64, err error) {
|
||||
err = filepath.Walk(dir, func(d string, fileInfo os.FileInfo, e error) error {
|
||||
size += fileInfo.Size()
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
Loading…
Reference in a new issue