Merge pull request #971 from stevvooe/namespace-snapshotters

snapshot/storage: namespace snapshot drivers
This commit is contained in:
Michael Crosby 2017-06-08 13:37:16 -07:00 committed by GitHub
commit a6314cad65
5 changed files with 57 additions and 12 deletions

View File

@ -12,6 +12,7 @@ import (
"testing" "testing"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/snapshot/testsuite" "github.com/containerd/containerd/snapshot/testsuite"
"github.com/containerd/containerd/testutil" "github.com/containerd/containerd/testutil"
@ -42,7 +43,7 @@ func TestBtrfs(t *testing.T) {
func TestBtrfsMounts(t *testing.T) { func TestBtrfsMounts(t *testing.T) {
testutil.RequiresRoot(t) testutil.RequiresRoot(t)
ctx := context.Background() ctx := namespaces.WithNamespace(context.Background(), "snapshotter-btrfs-test")
// create temporary directory for mount point // create temporary directory for mount point
mountPoint, err := ioutil.TempDir("", "containerd-btrfs-test") mountPoint, err := ioutil.TempDir("", "containerd-btrfs-test")

View File

@ -12,6 +12,7 @@ import (
"testing" "testing"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/snapshot/storage" "github.com/containerd/containerd/snapshot/storage"
"github.com/containerd/containerd/snapshot/testsuite" "github.com/containerd/containerd/snapshot/testsuite"
@ -33,7 +34,7 @@ func TestOverlay(t *testing.T) {
} }
func TestOverlayMounts(t *testing.T) { func TestOverlayMounts(t *testing.T) {
ctx := context.TODO() ctx := namespaces.WithNamespace(context.Background(), "snapshotter-overlay-test")
root, err := ioutil.TempDir("", "overlay") root, err := ioutil.TempDir("", "overlay")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -69,7 +70,7 @@ func TestOverlayMounts(t *testing.T) {
} }
func TestOverlayCommit(t *testing.T) { func TestOverlayCommit(t *testing.T) {
ctx := context.TODO() ctx := namespaces.WithNamespace(context.Background(), "snapshotter-overlay-test")
root, err := ioutil.TempDir("", "overlay") root, err := ioutil.TempDir("", "overlay")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -98,7 +99,7 @@ func TestOverlayCommit(t *testing.T) {
} }
func TestOverlayOverlayMount(t *testing.T) { func TestOverlayOverlayMount(t *testing.T) {
ctx := context.TODO() ctx := namespaces.WithNamespace(context.Background(), "snapshotter-overlay-test")
root, err := ioutil.TempDir("", "overlay") root, err := ioutil.TempDir("", "overlay")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -186,7 +187,7 @@ func getParents(ctx context.Context, sn snapshot.Snapshotter, root, key string)
func TestOverlayOverlayRead(t *testing.T) { func TestOverlayOverlayRead(t *testing.T) {
testutil.RequiresRoot(t) testutil.RequiresRoot(t)
ctx := context.TODO() ctx := namespaces.WithNamespace(context.Background(), "snapshotter-overlay-test")
root, err := ioutil.TempDir("", "overlay") root, err := ioutil.TempDir("", "overlay")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -238,7 +239,7 @@ func TestOverlayOverlayRead(t *testing.T) {
} }
func TestOverlayView(t *testing.T) { func TestOverlayView(t *testing.T) {
ctx := context.TODO() ctx := namespaces.WithNamespace(context.Background(), "snapshotter-overlay-test")
root, err := ioutil.TempDir("", "overlay") root, err := ioutil.TempDir("", "overlay")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github.com/boltdb/bolt" "github.com/boltdb/bolt"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
db "github.com/containerd/containerd/snapshot/storage/proto" db "github.com/containerd/containerd/snapshot/storage/proto"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
@ -136,7 +137,7 @@ func CreateActive(ctx context.Context, key, parent string, readonly bool) (a Act
return snapshot.ErrSnapshotExist return snapshot.ErrSnapshotExist
} }
id, err := bkt.NextSequence() id, err := nextSequence(ctx)
if err != nil { if err != nil {
return errors.Wrap(err, "unable to get identifier") return errors.Wrap(err, "unable to get identifier")
} }
@ -309,28 +310,68 @@ func CommitActive(ctx context.Context, key, name string, usage snapshot.Usage) (
return return
} }
// nextSequence maintains the snapshot ids in the same space across namespaces
// to avoid collisions on the filesystem, which is typically not namespace
// aware. This will also be useful to ensure that snapshots can be used across
// namespaces in the future, by projecting parent relationships into an
// alternate namespace without fixing up identifiers.
func nextSequence(ctx context.Context) (uint64, error) {
t, ok := ctx.Value(transactionKey{}).(*boltFileTransactor)
if !ok {
return 0, ErrNoTransaction
}
bkt := t.tx.Bucket(bucketKeyStorageVersion)
if bkt == nil {
return 0, errors.New("version bucket required for sequence")
}
return bkt.NextSequence()
}
func withBucket(ctx context.Context, fn func(context.Context, *bolt.Bucket, *bolt.Bucket) error) error { func withBucket(ctx context.Context, fn func(context.Context, *bolt.Bucket, *bolt.Bucket) error) error {
namespace, err := namespaces.NamespaceRequired(ctx)
if err != nil {
return err
}
t, ok := ctx.Value(transactionKey{}).(*boltFileTransactor) t, ok := ctx.Value(transactionKey{}).(*boltFileTransactor)
if !ok { if !ok {
return ErrNoTransaction return ErrNoTransaction
} }
bkt := t.tx.Bucket(bucketKeyStorageVersion) nbkt := t.tx.Bucket(bucketKeyStorageVersion)
if bkt == nil { if nbkt == nil {
return errors.Wrap(snapshot.ErrSnapshotNotExist, "bucket does not exist") return errors.Wrap(snapshot.ErrSnapshotNotExist, "bucket does not exist")
} }
bkt := nbkt.Bucket([]byte(namespace))
if bkt == nil {
return errors.Wrap(snapshot.ErrSnapshotNotExist, "namespace not available in snapshotter")
}
return fn(ctx, bkt.Bucket(bucketKeySnapshot), bkt.Bucket(bucketKeyParents)) return fn(ctx, bkt.Bucket(bucketKeySnapshot), bkt.Bucket(bucketKeyParents))
} }
func createBucketIfNotExists(ctx context.Context, fn func(context.Context, *bolt.Bucket, *bolt.Bucket) error) error { func createBucketIfNotExists(ctx context.Context, fn func(context.Context, *bolt.Bucket, *bolt.Bucket) error) error {
namespace, err := namespaces.NamespaceRequired(ctx)
if err != nil {
return err
}
t, ok := ctx.Value(transactionKey{}).(*boltFileTransactor) t, ok := ctx.Value(transactionKey{}).(*boltFileTransactor)
if !ok { if !ok {
return ErrNoTransaction return ErrNoTransaction
} }
bkt, err := t.tx.CreateBucketIfNotExists(bucketKeyStorageVersion) nbkt, err := t.tx.CreateBucketIfNotExists(bucketKeyStorageVersion)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to create version bucket") return errors.Wrap(err, "failed to create version bucket")
} }
bkt, err := nbkt.CreateBucketIfNotExists([]byte(namespace))
if err != nil {
return err
}
sbkt, err := bkt.CreateBucketIfNotExists(bucketKeySnapshot) sbkt, err := bkt.CreateBucketIfNotExists(bucketKeySnapshot)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to create snapshots bucket") return errors.Wrap(err, "failed to create snapshots bucket")

View File

@ -6,6 +6,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -44,7 +45,7 @@ func MetaStoreSuite(t *testing.T, name string, meta func(root string) (*MetaStor
// makeTest creates a testsuite with a writable transaction // makeTest creates a testsuite with a writable transaction
func makeTest(t *testing.T, name string, metaFn metaFactory, fn testFunc) func(t *testing.T) { func makeTest(t *testing.T, name string, metaFn metaFactory, fn testFunc) func(t *testing.T) {
return func(t *testing.T) { return func(t *testing.T) {
ctx := context.Background() ctx := namespaces.WithNamespace(context.Background(), "testing-snapshot-metadata")
tmpDir, err := ioutil.TempDir("", "metastore-test-"+name+"-") tmpDir, err := ioutil.TempDir("", "metastore-test-"+name+"-")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View File

@ -10,6 +10,7 @@ import (
"github.com/containerd/containerd/fs/fstest" "github.com/containerd/containerd/fs/fstest"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/testutil" "github.com/containerd/containerd/testutil"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -26,7 +27,7 @@ func SnapshotterSuite(t *testing.T, name string, snapshotterFn func(ctx context.
func makeTest(t *testing.T, name string, snapshotterFn func(ctx context.Context, root string) (snapshot.Snapshotter, func(), error), fn func(ctx context.Context, t *testing.T, snapshotter snapshot.Snapshotter, work string)) func(t *testing.T) { func makeTest(t *testing.T, name string, snapshotterFn func(ctx context.Context, root string) (snapshot.Snapshotter, func(), error), fn func(ctx context.Context, t *testing.T, snapshotter snapshot.Snapshotter, work string)) func(t *testing.T) {
return func(t *testing.T) { return func(t *testing.T) {
ctx := context.Background() ctx := namespaces.WithNamespace(context.Background(), "snapshotter-test")
restoreMask := clearMask() restoreMask := clearMask()
defer restoreMask() defer restoreMask()
// Make two directories: a snapshotter root and a play area for the tests: // Make two directories: a snapshotter root and a play area for the tests: