|
@@ -5,6 +5,7 @@ import (
|
|
"github.com/dotcloud/docker/archive"
|
|
"github.com/dotcloud/docker/archive"
|
|
"github.com/dotcloud/docker/dockerversion"
|
|
"github.com/dotcloud/docker/dockerversion"
|
|
"github.com/dotcloud/docker/graphdriver"
|
|
"github.com/dotcloud/docker/graphdriver"
|
|
|
|
+ "github.com/dotcloud/docker/image"
|
|
"github.com/dotcloud/docker/runconfig"
|
|
"github.com/dotcloud/docker/runconfig"
|
|
"github.com/dotcloud/docker/utils"
|
|
"github.com/dotcloud/docker/utils"
|
|
"io"
|
|
"io"
|
|
@@ -79,20 +80,20 @@ func (graph *Graph) Exists(id string) bool {
|
|
}
|
|
}
|
|
|
|
|
|
// Get returns the image with the given id, or an error if the image doesn't exist.
|
|
// Get returns the image with the given id, or an error if the image doesn't exist.
|
|
-func (graph *Graph) Get(name string) (*Image, error) {
|
|
|
|
|
|
+func (graph *Graph) Get(name string) (*image.Image, error) {
|
|
id, err := graph.idIndex.Get(name)
|
|
id, err := graph.idIndex.Get(name)
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
// FIXME: return nil when the image doesn't exist, instead of an error
|
|
// FIXME: return nil when the image doesn't exist, instead of an error
|
|
- img, err := LoadImage(graph.imageRoot(id))
|
|
|
|
|
|
+ img, err := image.LoadImage(graph.ImageRoot(id))
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
if img.ID != id {
|
|
if img.ID != id {
|
|
return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.ID)
|
|
return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.ID)
|
|
}
|
|
}
|
|
- img.graph = graph
|
|
|
|
|
|
+ img.SetGraph(graph)
|
|
|
|
|
|
if img.Size < 0 {
|
|
if img.Size < 0 {
|
|
rootfs, err := graph.driver.Get(img.ID)
|
|
rootfs, err := graph.driver.Get(img.ID)
|
|
@@ -119,7 +120,7 @@ func (graph *Graph) Get(name string) (*Image, error) {
|
|
}
|
|
}
|
|
|
|
|
|
img.Size = size
|
|
img.Size = size
|
|
- if err := img.SaveSize(graph.imageRoot(id)); err != nil {
|
|
|
|
|
|
+ if err := img.SaveSize(graph.ImageRoot(id)); err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -127,9 +128,9 @@ func (graph *Graph) Get(name string) (*Image, error) {
|
|
}
|
|
}
|
|
|
|
|
|
// Create creates a new image and registers it in the graph.
|
|
// Create creates a new image and registers it in the graph.
|
|
-func (graph *Graph) Create(layerData archive.ArchiveReader, container *Container, comment, author string, config *runconfig.Config) (*Image, error) {
|
|
|
|
- img := &Image{
|
|
|
|
- ID: GenerateID(),
|
|
|
|
|
|
+func (graph *Graph) Create(layerData archive.ArchiveReader, container *Container, comment, author string, config *runconfig.Config) (*image.Image, error) {
|
|
|
|
+ img := &image.Image{
|
|
|
|
+ ID: utils.GenerateRandomID(),
|
|
Comment: comment,
|
|
Comment: comment,
|
|
Created: time.Now().UTC(),
|
|
Created: time.Now().UTC(),
|
|
DockerVersion: dockerversion.VERSION,
|
|
DockerVersion: dockerversion.VERSION,
|
|
@@ -151,7 +152,7 @@ func (graph *Graph) Create(layerData archive.ArchiveReader, container *Container
|
|
|
|
|
|
// Register imports a pre-existing image into the graph.
|
|
// Register imports a pre-existing image into the graph.
|
|
// FIXME: pass img as first argument
|
|
// FIXME: pass img as first argument
|
|
-func (graph *Graph) Register(jsonData []byte, layerData archive.ArchiveReader, img *Image) (err error) {
|
|
|
|
|
|
+func (graph *Graph) Register(jsonData []byte, layerData archive.ArchiveReader, img *image.Image) (err error) {
|
|
defer func() {
|
|
defer func() {
|
|
// If any error occurs, remove the new dir from the driver.
|
|
// If any error occurs, remove the new dir from the driver.
|
|
// Don't check for errors since the dir might not have been created.
|
|
// Don't check for errors since the dir might not have been created.
|
|
@@ -160,7 +161,7 @@ func (graph *Graph) Register(jsonData []byte, layerData archive.ArchiveReader, i
|
|
graph.driver.Remove(img.ID)
|
|
graph.driver.Remove(img.ID)
|
|
}
|
|
}
|
|
}()
|
|
}()
|
|
- if err := ValidateID(img.ID); err != nil {
|
|
|
|
|
|
+ if err := utils.ValidateID(img.ID); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
// (This is a convenience to save time. Race conditions are taken care of by os.Rename)
|
|
// (This is a convenience to save time. Race conditions are taken care of by os.Rename)
|
|
@@ -171,7 +172,7 @@ func (graph *Graph) Register(jsonData []byte, layerData archive.ArchiveReader, i
|
|
// Ensure that the image root does not exist on the filesystem
|
|
// Ensure that the image root does not exist on the filesystem
|
|
// when it is not registered in the graph.
|
|
// when it is not registered in the graph.
|
|
// This is common when you switch from one graph driver to another
|
|
// This is common when you switch from one graph driver to another
|
|
- if err := os.RemoveAll(graph.imageRoot(img.ID)); err != nil && !os.IsNotExist(err) {
|
|
|
|
|
|
+ if err := os.RemoveAll(graph.ImageRoot(img.ID)); err != nil && !os.IsNotExist(err) {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
|
|
|
|
@@ -197,12 +198,12 @@ func (graph *Graph) Register(jsonData []byte, layerData archive.ArchiveReader, i
|
|
return fmt.Errorf("Driver %s failed to get image rootfs %s: %s", graph.driver, img.ID, err)
|
|
return fmt.Errorf("Driver %s failed to get image rootfs %s: %s", graph.driver, img.ID, err)
|
|
}
|
|
}
|
|
defer graph.driver.Put(img.ID)
|
|
defer graph.driver.Put(img.ID)
|
|
- img.graph = graph
|
|
|
|
- if err := StoreImage(img, jsonData, layerData, tmp, rootfs); err != nil {
|
|
|
|
|
|
+ img.SetGraph(graph)
|
|
|
|
+ if err := image.StoreImage(img, jsonData, layerData, tmp, rootfs); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
// Commit
|
|
// Commit
|
|
- if err := os.Rename(tmp, graph.imageRoot(img.ID)); err != nil {
|
|
|
|
|
|
+ if err := os.Rename(tmp, graph.ImageRoot(img.ID)); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
graph.idIndex.Add(img.ID)
|
|
graph.idIndex.Add(img.ID)
|
|
@@ -233,7 +234,7 @@ func (graph *Graph) TempLayerArchive(id string, compression archive.Compression,
|
|
|
|
|
|
// Mktemp creates a temporary sub-directory inside the graph's filesystem.
|
|
// Mktemp creates a temporary sub-directory inside the graph's filesystem.
|
|
func (graph *Graph) Mktemp(id string) (string, error) {
|
|
func (graph *Graph) Mktemp(id string) (string, error) {
|
|
- dir := path.Join(graph.Root, "_tmp", GenerateID())
|
|
|
|
|
|
+ dir := path.Join(graph.Root, "_tmp", utils.GenerateRandomID())
|
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
|
return "", err
|
|
return "", err
|
|
}
|
|
}
|
|
@@ -320,7 +321,7 @@ func (graph *Graph) Delete(name string) error {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
graph.idIndex.Delete(id)
|
|
graph.idIndex.Delete(id)
|
|
- err = os.Rename(graph.imageRoot(id), tmp)
|
|
|
|
|
|
+ err = os.Rename(graph.ImageRoot(id), tmp)
|
|
if err != nil {
|
|
if err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
@@ -331,9 +332,9 @@ func (graph *Graph) Delete(name string) error {
|
|
}
|
|
}
|
|
|
|
|
|
// Map returns a list of all images in the graph, addressable by ID.
|
|
// Map returns a list of all images in the graph, addressable by ID.
|
|
-func (graph *Graph) Map() (map[string]*Image, error) {
|
|
|
|
- images := make(map[string]*Image)
|
|
|
|
- err := graph.walkAll(func(image *Image) {
|
|
|
|
|
|
+func (graph *Graph) Map() (map[string]*image.Image, error) {
|
|
|
|
+ images := make(map[string]*image.Image)
|
|
|
|
+ err := graph.walkAll(func(image *image.Image) {
|
|
images[image.ID] = image
|
|
images[image.ID] = image
|
|
})
|
|
})
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -344,7 +345,7 @@ func (graph *Graph) Map() (map[string]*Image, error) {
|
|
|
|
|
|
// walkAll iterates over each image in the graph, and passes it to a handler.
|
|
// walkAll iterates over each image in the graph, and passes it to a handler.
|
|
// The walking order is undetermined.
|
|
// The walking order is undetermined.
|
|
-func (graph *Graph) walkAll(handler func(*Image)) error {
|
|
|
|
|
|
+func (graph *Graph) walkAll(handler func(*image.Image)) error {
|
|
files, err := ioutil.ReadDir(graph.Root)
|
|
files, err := ioutil.ReadDir(graph.Root)
|
|
if err != nil {
|
|
if err != nil {
|
|
return err
|
|
return err
|
|
@@ -364,17 +365,17 @@ func (graph *Graph) walkAll(handler func(*Image)) error {
|
|
// If an image of id ID has 3 children images, then the value for key ID
|
|
// If an image of id ID has 3 children images, then the value for key ID
|
|
// will be a list of 3 images.
|
|
// will be a list of 3 images.
|
|
// If an image has no children, it will not have an entry in the table.
|
|
// If an image has no children, it will not have an entry in the table.
|
|
-func (graph *Graph) ByParent() (map[string][]*Image, error) {
|
|
|
|
- byParent := make(map[string][]*Image)
|
|
|
|
- err := graph.walkAll(func(image *Image) {
|
|
|
|
- parent, err := graph.Get(image.Parent)
|
|
|
|
|
|
+func (graph *Graph) ByParent() (map[string][]*image.Image, error) {
|
|
|
|
+ byParent := make(map[string][]*image.Image)
|
|
|
|
+ err := graph.walkAll(func(img *image.Image) {
|
|
|
|
+ parent, err := graph.Get(img.Parent)
|
|
if err != nil {
|
|
if err != nil {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
if children, exists := byParent[parent.ID]; exists {
|
|
if children, exists := byParent[parent.ID]; exists {
|
|
- byParent[parent.ID] = append(children, image)
|
|
|
|
|
|
+ byParent[parent.ID] = append(children, img)
|
|
} else {
|
|
} else {
|
|
- byParent[parent.ID] = []*Image{image}
|
|
|
|
|
|
+ byParent[parent.ID] = []*image.Image{img}
|
|
}
|
|
}
|
|
})
|
|
})
|
|
return byParent, err
|
|
return byParent, err
|
|
@@ -382,13 +383,13 @@ func (graph *Graph) ByParent() (map[string][]*Image, error) {
|
|
|
|
|
|
// Heads returns all heads in the graph, keyed by id.
|
|
// Heads returns all heads in the graph, keyed by id.
|
|
// A head is an image which is not the parent of another image in the graph.
|
|
// A head is an image which is not the parent of another image in the graph.
|
|
-func (graph *Graph) Heads() (map[string]*Image, error) {
|
|
|
|
- heads := make(map[string]*Image)
|
|
|
|
|
|
+func (graph *Graph) Heads() (map[string]*image.Image, error) {
|
|
|
|
+ heads := make(map[string]*image.Image)
|
|
byParent, err := graph.ByParent()
|
|
byParent, err := graph.ByParent()
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
- err = graph.walkAll(func(image *Image) {
|
|
|
|
|
|
+ err = graph.walkAll(func(image *image.Image) {
|
|
// If it's not in the byParent lookup table, then
|
|
// If it's not in the byParent lookup table, then
|
|
// it's not a parent -> so it's a head!
|
|
// it's not a parent -> so it's a head!
|
|
if _, exists := byParent[image.ID]; !exists {
|
|
if _, exists := byParent[image.ID]; !exists {
|
|
@@ -398,7 +399,7 @@ func (graph *Graph) Heads() (map[string]*Image, error) {
|
|
return heads, err
|
|
return heads, err
|
|
}
|
|
}
|
|
|
|
|
|
-func (graph *Graph) imageRoot(id string) string {
|
|
|
|
|
|
+func (graph *Graph) ImageRoot(id string) string {
|
|
return path.Join(graph.Root, id)
|
|
return path.Join(graph.Root, id)
|
|
}
|
|
}
|
|
|
|
|