Files
docker-cli/components/engine/runtime/graphdriver/aufs/migrate.go
Dan Walsh f757666ccd This patch adds SELinux labeling support.
docker will run the process(es) within the container with an SELinux label and will label
all of  the content within the container with mount label.  Any temporary file systems
created within the container need to be mounted with the same mount label.

The user can override the process label by specifying

-Z With a string of space separated options.

-Z "user=unconfined_u role=unconfined_r type=unconfined_t level=s0"

Would cause the process label to run with unconfined_u:unconfined_r:unconfined_t:s0"

By default the processes will run execute within the container as svirt_lxc_net_t.
All of the content in the container as svirt_sandbox_file_t.

The process mcs level is based of the PID of the docker process that is creating the container.

If you run the container in --priv mode, the labeling will be disabled.

Docker-DCO-1.1-Signed-off-by: Dan Walsh <dwalsh@redhat.com> (github: rhatdan)
Upstream-commit: 4c4356692580afb3971094e322aea64abe0e2500
Component: engine
2014-03-26 15:30:40 -04:00

195 lines
4.6 KiB
Go

package aufs
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
)
type metadata struct {
ID string `json:"id"`
ParentID string `json:"parent,omitempty"`
Image string `json:"Image,omitempty"`
parent *metadata
}
func pathExists(pth string) bool {
if _, err := os.Stat(pth); err != nil {
return false
}
return true
}
// Migrate existing images and containers from docker < 0.7.x
//
// The format pre 0.7 is for docker to store the metadata and filesystem
// content in the same directory. For the migration to work we need to move Image layer
// data from /var/lib/docker/graph/<id>/layers to the diff of the registered id.
//
// Next we need to migrate the container's rw layer to diff of the driver. After the
// contents are migrated we need to register the image and container ids with the
// driver.
//
// For the migration we try to move the folder containing the layer files, if that
// fails because the data is currently mounted we will fallback to creating a
// symlink.
func (a *Driver) Migrate(pth string, setupInit func(p string) error) error {
if pathExists(path.Join(pth, "graph")) {
if err := a.migrateRepositories(pth); err != nil {
return err
}
if err := a.migrateImages(path.Join(pth, "graph")); err != nil {
return err
}
return a.migrateContainers(path.Join(pth, "containers"), setupInit)
}
return nil
}
func (a *Driver) migrateRepositories(pth string) error {
name := path.Join(pth, "repositories")
if err := os.Rename(name, name+"-aufs"); err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
func (a *Driver) migrateContainers(pth string, setupInit func(p string) error) error {
fis, err := ioutil.ReadDir(pth)
if err != nil {
return err
}
for _, fi := range fis {
if id := fi.Name(); fi.IsDir() && pathExists(path.Join(pth, id, "rw")) {
if err := tryRelocate(path.Join(pth, id, "rw"), path.Join(a.rootPath(), "diff", id)); err != nil {
return err
}
if !a.Exists(id) {
metadata, err := loadMetadata(path.Join(pth, id, "config.json"))
if err != nil {
return err
}
initID := fmt.Sprintf("%s-init", id)
if err := a.Create(initID, metadata.Image, ""); err != nil {
return err
}
initPath, err := a.Get(initID)
if err != nil {
return err
}
// setup init layer
if err := setupInit(initPath); err != nil {
return err
}
if err := a.Create(id, initID, ""); err != nil {
return err
}
}
}
}
return nil
}
func (a *Driver) migrateImages(pth string) error {
fis, err := ioutil.ReadDir(pth)
if err != nil {
return err
}
var (
m = make(map[string]*metadata)
current *metadata
exists bool
)
for _, fi := range fis {
if id := fi.Name(); fi.IsDir() && pathExists(path.Join(pth, id, "layer")) {
if current, exists = m[id]; !exists {
current, err = loadMetadata(path.Join(pth, id, "json"))
if err != nil {
return err
}
m[id] = current
}
}
}
for _, v := range m {
v.parent = m[v.ParentID]
}
migrated := make(map[string]bool)
for _, v := range m {
if err := a.migrateImage(v, pth, migrated); err != nil {
return err
}
}
return nil
}
func (a *Driver) migrateImage(m *metadata, pth string, migrated map[string]bool) error {
if !migrated[m.ID] {
if m.parent != nil {
a.migrateImage(m.parent, pth, migrated)
}
if err := tryRelocate(path.Join(pth, m.ID, "layer"), path.Join(a.rootPath(), "diff", m.ID)); err != nil {
return err
}
if !a.Exists(m.ID) {
if err := a.Create(m.ID, m.ParentID, ""); err != nil {
return err
}
}
migrated[m.ID] = true
}
return nil
}
// tryRelocate will try to rename the old path to the new pack and if
// the operation fails, it will fallback to a symlink
func tryRelocate(oldPath, newPath string) error {
s, err := os.Lstat(newPath)
if err != nil && !os.IsNotExist(err) {
return err
}
// If the destination is a symlink then we already tried to relocate once before
// and it failed so we delete it and try to remove
if s != nil && s.Mode()&os.ModeSymlink == os.ModeSymlink {
if err := os.RemoveAll(newPath); err != nil {
return err
}
}
if err := os.Rename(oldPath, newPath); err != nil {
if sErr := os.Symlink(oldPath, newPath); sErr != nil {
return fmt.Errorf("Unable to relocate %s to %s: Rename err %s Symlink err %s", oldPath, newPath, err, sErr)
}
}
return nil
}
func loadMetadata(pth string) (*metadata, error) {
f, err := os.Open(pth)
if err != nil {
return nil, err
}
defer f.Close()
var (
out = &metadata{}
dec = json.NewDecoder(f)
)
if err := dec.Decode(out); err != nil {
return nil, err
}
return out, nil
}