Skip to content

Commit

Permalink
Windows: Graph driver implementation
Browse files Browse the repository at this point in the history
Signed-off-by: John Howard <[email protected]>
  • Loading branch information
John Howard committed Jul 10, 2015
1 parent b7e8169 commit 52f4d09
Show file tree
Hide file tree
Showing 29 changed files with 850 additions and 145 deletions.
13 changes: 10 additions & 3 deletions builder/internals.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/docker/docker/cliconfig"
"github.com/docker/docker/daemon"
"github.com/docker/docker/graph"
imagepkg "github.com/docker/docker/image"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/httputils"
Expand Down Expand Up @@ -229,12 +228,20 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowDecomp
}
defer container.Unmount()

if err := container.PrepareStorage(); err != nil {
return err
}

for _, ci := range copyInfos {
if err := b.addContext(container, ci.origPath, ci.destPath, ci.decompress); err != nil {
return err
}
}

if err := container.CleanupStorage(); err != nil {
return err
}

if err := b.commit(container.ID, cmd, fmt.Sprintf("%s %s in %s", cmdName, origPaths, dest)); err != nil {
return err
}
Expand Down Expand Up @@ -455,7 +462,7 @@ func ContainsWildcards(name string) bool {
return false
}

func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
func (b *Builder) pullImage(name string) (*graph.Image, error) {
remote, tag := parsers.ParseRepositoryTag(name)
if tag == "" {
tag = "latest"
Expand Down Expand Up @@ -493,7 +500,7 @@ func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
return image, nil
}

func (b *Builder) processImageFrom(img *imagepkg.Image) error {
func (b *Builder) processImageFrom(img *graph.Image) error {
b.image = img.ID

if img.Config != nil {
Expand Down
3 changes: 2 additions & 1 deletion cliconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strings"

"github.com/docker/docker/pkg/homedir"
"github.com/docker/docker/pkg/system"
)

const (
Expand Down Expand Up @@ -177,7 +178,7 @@ func (configFile *ConfigFile) Save() error {
return err
}

if err := os.MkdirAll(filepath.Dir(configFile.filename), 0700); err != nil {
if err := system.MkdirAll(filepath.Dir(configFile.filename), 0700); err != nil {
return err
}

Expand Down
4 changes: 2 additions & 2 deletions daemon/commit.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package daemon

import (
"github.com/docker/docker/image"
"github.com/docker/docker/graph"
"github.com/docker/docker/runconfig"
)

Expand All @@ -16,7 +16,7 @@ type ContainerCommitConfig struct {

// Commit creates a new filesystem image from the current state of a container.
// The image can optionally be tagged into a repository
func (daemon *Daemon) Commit(container *Container, c *ContainerCommitConfig) (*image.Image, error) {
func (daemon *Daemon) Commit(container *Container, c *ContainerCommitConfig) (*graph.Image, error) {
if c.Pause && !container.IsPaused() {
container.Pause()
defer container.Unpause()
Expand Down
22 changes: 20 additions & 2 deletions daemon/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"github.com/docker/docker/daemon/logger"
"github.com/docker/docker/daemon/logger/jsonfilelog"
"github.com/docker/docker/daemon/network"
"github.com/docker/docker/image"
"github.com/docker/docker/graph"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/broadcastwriter"
"github.com/docker/docker/pkg/fileutils"
Expand Down Expand Up @@ -259,6 +259,13 @@ func (container *Container) Start() (err error) {
if err := container.Mount(); err != nil {
return err
}

// No-op if non-Windows. Once the container filesystem is mounted,
// prepare the layer to boot using the Windows driver.
if err := container.PrepareStorage(); err != nil {
return err
}

if err := container.initializeNetworking(); err != nil {
return err
}
Expand Down Expand Up @@ -350,6 +357,10 @@ func (container *Container) cleanup() {

disableAllActiveLinks(container)

if err := container.CleanupStorage(); err != nil {
logrus.Errorf("%v: Failed to cleanup storage: %v", container.ID, err)
}

if err := container.Unmount(); err != nil {
logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
}
Expand Down Expand Up @@ -573,7 +584,7 @@ func (container *Container) Changes() ([]archive.Change, error) {
return container.changes()
}

func (container *Container) GetImage() (*image.Image, error) {
func (container *Container) GetImage() (*graph.Image, error) {
if container.daemon == nil {
return nil, fmt.Errorf("Can't get image of unregistered container")
}
Expand Down Expand Up @@ -666,8 +677,15 @@ func (container *Container) Copy(resource string) (io.ReadCloser, error) {
if err != nil {
return nil, err
}

if err := container.PrepareStorage(); err != nil {
container.Unmount()
return nil, err
}

reader := ioutils.NewReadCloserWrapper(archive, func() error {
err := archive.Close()
container.CleanupStorage()
container.UnmountVolumes(true)
container.Unmount()
return err
Expand Down
13 changes: 11 additions & 2 deletions daemon/container_linux.go → daemon/container_unix.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build linux
// +build !windows

package daemon

Expand All @@ -23,6 +23,7 @@ import (
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/nat"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/system"
"github.com/docker/docker/pkg/ulimit"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/utils"
Expand Down Expand Up @@ -970,7 +971,7 @@ func (container *Container) setupWorkingDirectory() error {
return err
}

if err := os.MkdirAll(pth, 0755); err != nil {
if err := system.MkdirAll(pth, 0755); err != nil {
return err
}
}
Expand Down Expand Up @@ -1109,3 +1110,11 @@ func (container *Container) UnmountVolumes(forceSyscall bool) error {

return nil
}

func (container *Container) PrepareStorage() error {
return nil
}

func (container *Container) CleanupStorage() error {
return nil
}
56 changes: 56 additions & 0 deletions daemon/container_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ package daemon

import (
"fmt"
"path/filepath"
"strings"

"github.com/docker/docker/daemon/execdriver"
"github.com/docker/docker/daemon/graphdriver/windows"
"github.com/docker/docker/graph"
"github.com/docker/docker/pkg/archive"
"github.com/microsoft/hcsshim"
)

// This is deliberately empty on Windows as the default path will be set by
Expand Down Expand Up @@ -102,6 +106,26 @@ func populateCommand(c *Container, env []string) error {

processConfig.Env = env

var layerFolder string
var layerPaths []string

// The following is specific to the Windows driver. We do this to
// enable VFS to continue operating for development purposes.
if wd, ok := c.daemon.driver.(*windows.WindowsGraphDriver); ok {
var err error
var img *graph.Image
var ids []string

if img, err = c.daemon.graph.Get(c.ImageID); err != nil {
return fmt.Errorf("Failed to graph.Get on ImageID %s - %s", c.ImageID, err)
}
if ids, err = c.daemon.graph.ParentLayerIds(img); err != nil {
return fmt.Errorf("Failed to get parentlayer ids %s", img.ID)
}
layerPaths = wd.LayerIdsToPaths(ids)
layerFolder = filepath.Join(wd.Info().HomeDir, filepath.Base(c.ID))
}

// TODO Windows: Factor out remainder of unused fields.
c.command = &execdriver.Command{
ID: c.ID,
Expand All @@ -118,6 +142,8 @@ func populateCommand(c *Container, env []string) error {
ProcessLabel: c.GetProcessLabel(),
MountLabel: c.GetMountLabel(),
FirstStart: !c.HasBeenStartedBefore,
LayerFolder: layerFolder,
LayerPaths: layerPaths,
}

return nil
Expand Down Expand Up @@ -165,3 +191,33 @@ func (container *Container) DisableLink(name string) {
func (container *Container) UnmountVolumes(forceSyscall bool) error {
return nil
}

func (container *Container) PrepareStorage() error {
if wd, ok := container.daemon.driver.(*windows.WindowsGraphDriver); ok {
// Get list of paths to parent layers.
var ids []string
if container.ImageID != "" {
img, err := container.daemon.graph.Get(container.ImageID)
if err != nil {
return err
}

ids, err = container.daemon.graph.ParentLayerIds(img)
if err != nil {
return err
}
}

if err := hcsshim.PrepareLayer(wd.Info(), container.ID, wd.LayerIdsToPaths(ids)); err != nil {
return err
}
}
return nil
}

func (container *Container) CleanupStorage() error {
if wd, ok := container.daemon.driver.(*windows.WindowsGraphDriver); ok {
return hcsshim.UnprepareLayer(wd.Info(), container.ID)
}
return nil
}
3 changes: 1 addition & 2 deletions daemon/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/Sirupsen/logrus"
"github.com/docker/docker/graph"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/runconfig"
Expand Down Expand Up @@ -47,7 +46,7 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos
var (
container *Container
warnings []string
img *image.Image
img *graph.Image
imgID string
err error
)
Expand Down
7 changes: 3 additions & 4 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/docker/docker/daemon/logger"
"github.com/docker/docker/daemon/network"
"github.com/docker/docker/graph"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/broadcastwriter"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/graphdb"
Expand Down Expand Up @@ -338,7 +337,7 @@ func (daemon *Daemon) restore() error {
return nil
}

func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error {
func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *graph.Image) error {
if img != nil && img.Config != nil {
if err := runconfig.Merge(config, img.Config); err != nil {
return err
Expand Down Expand Up @@ -879,7 +878,7 @@ func (daemon *Daemon) ContainerGraph() *graphdb.Database {
return daemon.containerGraph
}

func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) {
func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*graph.Image, error) {
// Retrieve all images
images, err := daemon.Graph().Map()
if err != nil {
Expand All @@ -896,7 +895,7 @@ func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*i
}

// Loop on the children of the given image and check the config
var match *image.Image
var match *graph.Image
for elem := range imageMap[imgID] {
img, ok := images[elem]
if !ok {
Expand Down
35 changes: 33 additions & 2 deletions daemon/daemon_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import (
"runtime"
"syscall"

"github.com/Sirupsen/logrus"
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/daemon/graphdriver/windows"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/runconfig"
"github.com/docker/libnetwork"
"github.com/microsoft/hcsshim"
)

func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) {
Expand All @@ -31,8 +34,36 @@ func (daemon *Daemon) createRootfs(container *Container) error {
if err := os.Mkdir(container.root, 0700); err != nil {
return err
}
if err := daemon.driver.Create(container.ID, container.ImageID); err != nil {
return err

if wd, ok := daemon.driver.(*windows.WindowsGraphDriver); ok {
if container.ImageID != "" {
// Get list of paths to parent layers.
logrus.Debugln("createRootfs: Container has parent image:", container.ImageID)
img, err := daemon.graph.Get(container.ImageID)
if err != nil {
return err
}

ids, err := daemon.graph.ParentLayerIds(img)
if err != nil {
return err
}
logrus.Debugf("Got image ids: %d", len(ids))

if err := hcsshim.CreateSandboxLayer(wd.Info(), container.ID, container.ImageID, wd.LayerIdsToPaths(ids)); err != nil {
return err
}
} else {
if err := daemon.driver.Create(container.ID, container.ImageID); err != nil {
return err
}
}
} else {
// Fall-back code path to allow the use of the VFS driver for development
if err := daemon.driver.Create(container.ID, container.ImageID); err != nil {
return err
}

}
return nil
}
Expand Down
1 change: 1 addition & 0 deletions daemon/graphdriver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ func GetDriver(name, home string, options []string) (Driver, error) {
if initFunc, exists := drivers[name]; exists {
return initFunc(filepath.Join(home, name), options)
}
logrus.Errorf("Failed to GetDriver graph %s %s", name, home)
return nil, ErrNotSupported
}

Expand Down
Loading

0 comments on commit 52f4d09

Please sign in to comment.