aaf18b5962
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
117 lines
3 KiB
Go
117 lines
3 KiB
Go
package naive
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/docker/containerd"
|
|
"github.com/docker/containerd/fs"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type Naive struct {
|
|
root string
|
|
|
|
// TODO(stevvooe): Very lazy copying from the overlay driver. We'll have to
|
|
// put *all* of this on disk in an easy to access format.
|
|
active map[string]activeNaiveSnapshot
|
|
parents map[string]string // mirror of what is on disk
|
|
}
|
|
|
|
type activeNaiveSnapshot struct {
|
|
parent string
|
|
metadata string
|
|
}
|
|
|
|
func NewNaive(root string) (*Naive, error) {
|
|
if err := os.MkdirAll(root, 0777); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO(stevvooe): Recover active transactions.
|
|
|
|
return &Naive{
|
|
root: root,
|
|
active: make(map[string]activeNaiveSnapshot),
|
|
parents: make(map[string]string),
|
|
}, nil
|
|
}
|
|
|
|
// Prepare works per the snapshot specification.
|
|
//
|
|
// For the naive driver, the data is checked out directly into dst and no
|
|
// mounts are returned.
|
|
func (n *Naive) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
|
metadataRoot, err := ioutil.TempDir(n.root, "active-")
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to created transaction dir")
|
|
}
|
|
|
|
// TODO(stevvooe): Write in driver metadata so it can be identified,
|
|
// probably part of common manager type.
|
|
|
|
if err := ioutil.WriteFile(filepath.Join(metadataRoot, "target"), []byte(dst), 0777); err != nil {
|
|
return nil, errors.Wrap(err, "failed to write target to disk")
|
|
}
|
|
|
|
if parent != "" {
|
|
if _, ok := n.parents[parent]; !ok {
|
|
return nil, errors.Wrap(err, "specified parent does not exist")
|
|
}
|
|
|
|
if err := ioutil.WriteFile(filepath.Join(metadataRoot, "parent"), []byte(parent), 0777); err != nil {
|
|
return nil, errors.Wrap(err, "error specifying parent")
|
|
}
|
|
|
|
// Now, we copy the parent filesystem, just a directory, into dst.
|
|
if err := fs.CopyDir(dst, filepath.Join(parent, "data")); err != nil {
|
|
return nil, errors.Wrap(err, "copying of parent failed")
|
|
}
|
|
}
|
|
|
|
n.active[dst] = activeNaiveSnapshot{
|
|
parent: parent,
|
|
metadata: metadataRoot,
|
|
}
|
|
|
|
return nil, nil // no mounts!!
|
|
}
|
|
|
|
// Commit just moves the metadata directory to the diff location.
|
|
func (n *Naive) Commit(diff, dst string) error {
|
|
active, ok := n.active[dst]
|
|
if !ok {
|
|
return errors.Errorf("%v is not an active transaction", dst)
|
|
}
|
|
|
|
// Move the data into our metadata directory, we could probably save disk
|
|
// space if we just saved the diff, but let's get something working.
|
|
if err := fs.CopyDir(filepath.Join(active.metadata, "data"), dst); err != nil {
|
|
return errors.Wrap(err, "copying of parent failed")
|
|
}
|
|
|
|
if err := os.Rename(active.metadata, diff); err != nil {
|
|
return errors.Wrap(err, "failed to rename metadata into diff")
|
|
}
|
|
|
|
n.parents[diff] = active.parent
|
|
delete(n.active, dst)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (n *Naive) Rollback(dst string) error {
|
|
active, ok := n.active[dst]
|
|
if !ok {
|
|
return fmt.Errorf("%q must be an active snapshot", dst)
|
|
}
|
|
|
|
delete(n.active, dst)
|
|
return os.RemoveAll(active.metadata)
|
|
}
|
|
|
|
func (n *Naive) Parent(diff string) string {
|
|
return n.parents[diff]
|
|
}
|