diff --git a/cmd/containerd/builtins_linux.go b/cmd/containerd/builtins_linux.go index 6c56744df..bd7269861 100644 --- a/cmd/containerd/builtins_linux.go +++ b/cmd/containerd/builtins_linux.go @@ -17,12 +17,14 @@ package main import ( - _ "github.com/containerd/aufs" + // TODO: Needs updated snapshotter interface + //_ "github.com/containerd/aufs" _ "github.com/containerd/containerd/metrics/cgroups" _ "github.com/containerd/containerd/runtime/v1/linux" _ "github.com/containerd/containerd/runtime/v2" _ "github.com/containerd/containerd/runtime/v2/runc/options" _ "github.com/containerd/containerd/snapshots/native" _ "github.com/containerd/containerd/snapshots/overlay" - _ "github.com/containerd/zfs" + // TODO: Needs updated snapshotter interface + //_ "github.com/containerd/zfs" ) diff --git a/contrib/snapshotservice/service.go b/contrib/snapshotservice/service.go index aebc69ed2..c1d1a4230 100644 --- a/contrib/snapshotservice/service.go +++ b/contrib/snapshotservice/service.go @@ -136,7 +136,7 @@ func (s service) List(sr *snapshotsapi.ListSnapshotsRequest, ss snapshotsapi.Sna } return nil - }) + }, sr.Filters...) if err != nil { return err } diff --git a/metadata/adaptors.go b/metadata/adaptors.go index 4fd4c8243..5c6983be2 100644 --- a/metadata/adaptors.go +++ b/metadata/adaptors.go @@ -24,6 +24,7 @@ import ( "github.com/containerd/containerd/filters" "github.com/containerd/containerd/images" "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/snapshots" ) func adaptImage(o interface{}) filters.Adaptor { @@ -139,6 +140,36 @@ func adaptLease(lease leases.Lease) filters.Adaptor { }) } +func adaptSnapshot(info snapshots.Info) filters.Adaptor { + return filters.AdapterFunc(func(fieldpath []string) (string, bool) { + if len(fieldpath) == 0 { + return "", false + } + + switch fieldpath[0] { + case "kind": + switch info.Kind { + case snapshots.KindActive: + return "active", true + case snapshots.KindView: + return "view", true + case snapshots.KindCommitted: + return "committed", true + } + case "name": + return info.Name, true + case "parent": + if info.Parent != "" { + return info.Parent, true + } + case "labels": + return checkMap(fieldpath[1:], info.Labels) + } + + return "", false + }) +} + func checkMap(fieldpath []string, m map[string]string) (string, bool) { if len(m) == 0 { return "", false diff --git a/metadata/snapshot.go b/metadata/snapshot.go index 1ed42c31f..31dfc3bd9 100644 --- a/metadata/snapshot.go +++ b/metadata/snapshot.go @@ -25,6 +25,7 @@ import ( "time" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/filters" "github.com/containerd/containerd/labels" "github.com/containerd/containerd/log" "github.com/containerd/containerd/metadata/boltutil" @@ -530,7 +531,7 @@ type infoPair struct { info snapshots.Info } -func (s *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error, filters ...string) error { +func (s *snapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { ns, err := namespaces.NamespaceRequired(ctx) if err != nil { return err @@ -542,6 +543,11 @@ func (s *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapsho lastKey string ) + filter, err := filters.ParseAll(fs...) + if err != nil { + return err + } + for { if err := view(ctx, s.db, func(tx *bolt.Tx) error { bkt := getSnapshotterBucket(tx, ns, s.name) @@ -604,8 +610,11 @@ func (s *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapsho return err } - if err := fn(ctx, overlayInfo(info, pair.info)); err != nil { - return err + info = overlayInfo(info, pair.info) + if filter.Match(adaptSnapshot(info)) { + if err := fn(ctx, info); err != nil { + return err + } } } diff --git a/services/snapshots/service.go b/services/snapshots/service.go index 8ef7a47f5..d37a96585 100644 --- a/services/snapshots/service.go +++ b/services/snapshots/service.go @@ -227,7 +227,7 @@ func (s *service) List(sr *snapshotsapi.ListSnapshotsRequest, ss snapshotsapi.Sn } return nil - }) + }, sr.Filters...) if err != nil { return err } diff --git a/snapshots/btrfs/btrfs.go b/snapshots/btrfs/btrfs.go index 6fd80172b..ea90853da 100644 --- a/snapshots/btrfs/btrfs.go +++ b/snapshots/btrfs/btrfs.go @@ -186,13 +186,13 @@ func (b *snapshotter) usage(ctx context.Context, key string) (snapshots.Usage, e } // Walk the committed snapshots. -func (b *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error, filters ...string) error { +func (b *snapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { ctx, t, err := b.ms.TransactionContext(ctx, false) if err != nil { return err } defer t.Rollback() - return storage.WalkInfo(ctx, fn) + return storage.WalkInfo(ctx, fn, fs...) } func (b *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) { diff --git a/snapshots/devmapper/snapshotter.go b/snapshots/devmapper/snapshotter.go index c1332897a..f9a809863 100644 --- a/snapshots/devmapper/snapshotter.go +++ b/snapshots/devmapper/snapshotter.go @@ -312,10 +312,10 @@ func (s *Snapshotter) removeDevice(ctx context.Context, key string) error { } // Walk iterates through all metadata Info for the stored snapshots and calls the provided function for each. -func (s *Snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error, filters ...string) error { +func (s *Snapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { log.G(ctx).Debug("walk") return s.withTransaction(ctx, false, func(ctx context.Context) error { - return storage.WalkInfo(ctx, fn) + return storage.WalkInfo(ctx, fn, fs...) }) } diff --git a/snapshots/lcow/lcow.go b/snapshots/lcow/lcow.go index 0c08d5c69..2bb05ff8c 100644 --- a/snapshots/lcow/lcow.go +++ b/snapshots/lcow/lcow.go @@ -241,7 +241,7 @@ func (s *snapshotter) Remove(ctx context.Context, key string) error { } // Walk the committed snapshots. -func (s *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error, filters ...string) error { +func (s *snapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { log.G(ctx).Debug("Starting Walk") ctx, t, err := s.ms.TransactionContext(ctx, false) if err != nil { @@ -249,7 +249,7 @@ func (s *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapsho } defer t.Rollback() - return storage.WalkInfo(ctx, fn) + return storage.WalkInfo(ctx, fn, fs...) } // Close closes the snapshotter diff --git a/snapshots/native/native.go b/snapshots/native/native.go index cfe443c5a..50d87577c 100644 --- a/snapshots/native/native.go +++ b/snapshots/native/native.go @@ -232,13 +232,13 @@ func (o *snapshotter) Remove(ctx context.Context, key string) (err error) { } // Walk the committed snapshots. -func (o *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error, filters ...string) error { +func (o *snapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { ctx, t, err := o.ms.TransactionContext(ctx, false) if err != nil { return err } defer t.Rollback() - return storage.WalkInfo(ctx, fn) + return storage.WalkInfo(ctx, fn, fs...) } func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, key, parent string, opts []snapshots.Opt) (_ []mount.Mount, err error) { diff --git a/snapshots/overlay/overlay.go b/snapshots/overlay/overlay.go index c99c47554..31c9968eb 100644 --- a/snapshots/overlay/overlay.go +++ b/snapshots/overlay/overlay.go @@ -282,14 +282,14 @@ func (o *snapshotter) Remove(ctx context.Context, key string) (err error) { return t.Commit() } -// Walk the committed snapshots. -func (o *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error, filters ...string) error { +// Walk the snapshots. +func (o *snapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { ctx, t, err := o.ms.TransactionContext(ctx, false) if err != nil { return err } defer t.Rollback() - return storage.WalkInfo(ctx, fn) + return storage.WalkInfo(ctx, fn, fs...) } // Cleanup cleans up disk resources from removed or abandoned snapshots diff --git a/snapshots/proxy/proxy.go b/snapshots/proxy/proxy.go index 080067ec4..d9803c7c8 100644 --- a/snapshots/proxy/proxy.go +++ b/snapshots/proxy/proxy.go @@ -153,9 +153,10 @@ func (p *proxySnapshotter) Remove(ctx context.Context, key string) error { return errdefs.FromGRPC(err) } -func (p *proxySnapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error, filters ...string) error { +func (p *proxySnapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { sc, err := p.client.List(ctx, &snapshotsapi.ListSnapshotsRequest{ Snapshotter: p.snapshotterName, + Filters: fs, }) if err != nil { return errdefs.FromGRPC(err) diff --git a/snapshots/snapshotter.go b/snapshots/snapshotter.go index c7470a594..3a0a6589e 100644 --- a/snapshots/snapshotter.go +++ b/snapshots/snapshotter.go @@ -118,6 +118,9 @@ func (u *Usage) Add(other Usage) { u.Inodes += other.Inodes } +// WalkFunc defines the callback for a snapshot walk. +type WalkFunc func(context.Context, Info) error + // Snapshotter defines the methods required to implement a snapshot snapshotter for // allocating, snapshotting and mounting filesystem changesets. The model works // by building up sets of changes with parent-child relationships. @@ -314,12 +317,15 @@ type Snapshotter interface { // removed before proceeding. Remove(ctx context.Context, key string) error - // Walk all snapshots in the snapshotter. For each snapshot in the - // snapshotter, the function will be called, unless filters were used. - // Zero or more filters may be provided as strings. Only events that match - // *any* of the provided filters will be sent on the channel. The filters use - // the standard containerd filters package syntax. - Walk(ctx context.Context, fn func(context.Context, Info) error, filters ...string) error + // Walk will call the provided function for each snapshot in the + // snapshotter which match the provided filters. If no filters are + // given all items will be walked. + // Filters: + // name + // parent + // kind (active,view,committed) + // labels.(label) + Walk(ctx context.Context, fn WalkFunc, filters ...string) error // Close releases the internal resources. // diff --git a/snapshots/storage/bolt.go b/snapshots/storage/bolt.go index 7716a591e..1277a4abc 100644 --- a/snapshots/storage/bolt.go +++ b/snapshots/storage/bolt.go @@ -24,6 +24,7 @@ import ( "time" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/filters" "github.com/containerd/containerd/metadata/boltutil" "github.com/containerd/containerd/snapshots" "github.com/pkg/errors" @@ -144,7 +145,12 @@ func UpdateInfo(ctx context.Context, info snapshots.Info, fieldpaths ...string) // WalkInfo iterates through all metadata Info for the stored snapshots and // calls the provided function for each. Requires a context with a storage // transaction. -func WalkInfo(ctx context.Context, fn func(context.Context, snapshots.Info) error) error { +func WalkInfo(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { + filter, err := filters.ParseAll(fs...) + if err != nil { + return err + } + // TODO: allow indexes (name, parent, specific labels) return withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error { return bkt.ForEach(func(k, v []byte) error { // skip non buckets @@ -160,6 +166,9 @@ func WalkInfo(ctx context.Context, fn func(context.Context, snapshots.Info) erro if err := readSnapshot(sbkt, nil, &si); err != nil { return err } + if !filter.Match(adaptSnapshot(si)) { + return nil + } return fn(ctx, si) }) @@ -604,3 +613,38 @@ func encodeID(id uint64) ([]byte, error) { } return idEncoded, nil } + +func adaptSnapshot(info snapshots.Info) filters.Adaptor { + return filters.AdapterFunc(func(fieldpath []string) (string, bool) { + if len(fieldpath) == 0 { + return "", false + } + + switch fieldpath[0] { + case "kind": + switch info.Kind { + case snapshots.KindActive: + return "active", true + case snapshots.KindView: + return "view", true + case snapshots.KindCommitted: + return "committed", true + } + case "name": + return info.Name, true + case "parent": + if info.Parent != "" { + return info.Parent, true + } + case "labels": + if len(info.Labels) == 0 { + return "", false + } + + v, ok := info.Labels[strings.Join(fieldpath[1:], ".")] + return v, ok + } + + return "", false + }) +} diff --git a/snapshots/testsuite/testsuite.go b/snapshots/testsuite/testsuite.go index ee64e30a5..63f7eb711 100644 --- a/snapshots/testsuite/testsuite.go +++ b/snapshots/testsuite/testsuite.go @@ -23,6 +23,7 @@ import ( "math/rand" "os" "path/filepath" + "sort" "testing" "time" @@ -49,6 +50,7 @@ func SnapshotterSuite(t *testing.T, name string, snapshotterFn func(ctx context. t.Run("PreareViewFailingtest", makeTest(name, snapshotterFn, checkSnapshotterPrepareView)) t.Run("Update", makeTest(name, snapshotterFn, checkUpdate)) t.Run("Remove", makeTest(name, snapshotterFn, checkRemove)) + t.Run("Walk", makeTest(name, snapshotterFn, checkWalk)) t.Run("LayerFileupdate", makeTest(name, snapshotterFn, checkLayerFileUpdate)) t.Run("RemoveDirectoryInLowerLayer", makeTest(name, snapshotterFn, checkRemoveDirectoryInLowerLayer)) @@ -961,3 +963,135 @@ func check128LayersMount(name string) func(ctx context.Context, t *testing.T, sn } } } + +func checkWalk(ctx context.Context, t *testing.T, snapshotter snapshots.Snapshotter, work string) { + opt := snapshots.WithLabels(map[string]string{ + "containerd.io/gc.root": "check-walk", + }) + + // No parent active + if _, err := snapshotter.Prepare(ctx, "a-np", "", opt); err != nil { + t.Fatal(err) + } + + // Base parent + if _, err := snapshotter.Prepare(ctx, "p-tmp", "", opt); err != nil { + t.Fatal(err) + } + if err := snapshotter.Commit(ctx, "p", "p-tmp", opt); err != nil { + t.Fatal(err) + } + + // Active + if _, err := snapshotter.Prepare(ctx, "a", "p", opt); err != nil { + t.Fatal(err) + } + + // View + if _, err := snapshotter.View(ctx, "v", "p", opt); err != nil { + t.Fatal(err) + } + + // Base parent with label=1 + if _, err := snapshotter.Prepare(ctx, "p-wl-tmp", "", opt); err != nil { + t.Fatal(err) + } + if err := snapshotter.Commit(ctx, "p-wl", "p-wl-tmp", snapshots.WithLabels(map[string]string{ + "l": "1", + "containerd.io/gc.root": "check-walk", + })); err != nil { + t.Fatal(err) + } + + // active with label=2 + if _, err := snapshotter.Prepare(ctx, "a-wl", "p-wl", snapshots.WithLabels(map[string]string{ + "l": "2", + "containerd.io/gc.root": "check-walk", + })); err != nil { + t.Fatal(err) + } + + // view with label=3 + if _, err := snapshotter.View(ctx, "v-wl", "p-wl", snapshots.WithLabels(map[string]string{ + "l": "3", + "containerd.io/gc.root": "check-walk", + })); err != nil { + t.Fatal(err) + } + + // no parent active with label=2 + if _, err := snapshotter.Prepare(ctx, "a-np-wl", "", snapshots.WithLabels(map[string]string{ + "l": "2", + "containerd.io/gc.root": "check-walk", + })); err != nil { + t.Fatal(err) + } + + for i, tc := range []struct { + matches []string + filters []string + }{ + { + matches: []string{"a-np", "p", "a", "v", "p-wl", "a-wl", "v-wl", "a-np-wl"}, + filters: []string{"labels.\"containerd.io/gc.root\"==check-walk"}, + }, + { + matches: []string{"a-np", "a", "a-wl", "a-np-wl"}, + filters: []string{"kind==active,labels.\"containerd.io/gc.root\"==check-walk"}, + }, + { + matches: []string{"v", "v-wl"}, + filters: []string{"kind==view,labels.\"containerd.io/gc.root\"==check-walk"}, + }, + { + matches: []string{"p", "p-wl"}, + filters: []string{"kind==committed,labels.\"containerd.io/gc.root\"==check-walk"}, + }, + { + matches: []string{"p", "a-np-wl"}, + filters: []string{"name==p", "name==a-np-wl"}, + }, + { + matches: []string{"a-wl"}, + filters: []string{"name==a-wl,labels.l"}, + }, + { + matches: []string{"a", "v"}, + filters: []string{"parent==p"}, + }, + { + matches: []string{"a", "v", "a-wl", "v-wl"}, + filters: []string{"parent,labels.\"containerd.io/gc.root\"==check-walk"}, + }, + { + matches: []string{"p-wl", "a-wl", "v-wl", "a-np-wl"}, + filters: []string{"labels.l"}, + }, + { + matches: []string{"a-wl", "a-np-wl"}, + filters: []string{"labels.l==2"}, + }, + } { + actual := []string{} + err := snapshotter.Walk(ctx, func(ctx context.Context, si snapshots.Info) error { + actual = append(actual, si.Name) + return nil + }, tc.filters...) + if err != nil { + t.Fatal(err) + } + + sort.Strings(tc.matches) + sort.Strings(actual) + if len(actual) != len(tc.matches) { + t.Errorf("[%d] Unexpected result (size):\nActual:\n\t%#v\nExpected:\n\t%#v", i, actual, tc.matches) + continue + } + for j := range actual { + if actual[j] != tc.matches[j] { + t.Errorf("[%d] Unexpected result @%d:\nActual:\n\t%#vExpected:\n\t%#v", i, j, actual, tc.matches) + break + } + } + } +} diff --git a/snapshots/windows/windows.go b/snapshots/windows/windows.go index 74573405e..cc9894735 100644 --- a/snapshots/windows/windows.go +++ b/snapshots/windows/windows.go @@ -238,14 +238,14 @@ func (s *snapshotter) Remove(ctx context.Context, key string) error { } // Walk the committed snapshots. -func (s *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error, filters ...string) error { +func (s *snapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { ctx, t, err := s.ms.TransactionContext(ctx, false) if err != nil { return err } defer t.Rollback() - return storage.WalkInfo(ctx, fn) + return storage.WalkInfo(ctx, fn, fs...) } // Close closes the snapshotter diff --git a/vendor.conf b/vendor.conf index 3cef3d4ae..692007ece 100644 --- a/vendor.conf +++ b/vendor.conf @@ -49,6 +49,7 @@ go.opencensus.io v0.22.0 github.com/imdario/mergo v0.3.7 github.com/cpuguy83/go-md2man v1.0.10 github.com/russross/blackfriday v1.5.2 +github.com/google/uuid v1.1.1 # cri dependencies github.com/containerd/cri 0ebf032aac5f6029f95a94e42161e9db7a7e84df # release/1.3+ @@ -82,10 +83,9 @@ k8s.io/kubernetes v1.16.0-rc.2 k8s.io/utils c2654d5206da6b7b6ace12841e8f359bb89b443c sigs.k8s.io/yaml v1.1.0 -# zfs dependencies -github.com/containerd/zfs 2ceb2dbb8154202ed1b8fd32e4ea25b491d7b251 -github.com/mistifyio/go-zfs f784269be439d704d3dfa1906f45dd848fed2beb -github.com/google/uuid v1.1.1 +# zfs dependencies (temporarily removed) +# github.com/containerd/zfs 2ceb2dbb8154202ed1b8fd32e4ea25b491d7b251 +# github.com/mistifyio/go-zfs f784269be439d704d3dfa1906f45dd848fed2beb -# aufs dependencies -github.com/containerd/aufs f894a800659b6e11c1a13084abd1712f346e349c +# aufs dependencies (temporarily removed) +# github.com/containerd/aufs f894a800659b6e11c1a13084abd1712f346e349c diff --git a/vendor/github.com/containerd/aufs/LICENSE b/vendor/github.com/containerd/aufs/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/vendor/github.com/containerd/aufs/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/containerd/aufs/README.md b/vendor/github.com/containerd/aufs/README.md deleted file mode 100644 index 0f871b36d..000000000 --- a/vendor/github.com/containerd/aufs/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# aufs snapshotter - -[![Build Status](https://travis-ci.org/containerd/aufs.svg?branch=master)](https://travis-ci.org/containerd/aufs) - -[![codecov](https://codecov.io/gh/containerd/aufs/branch/master/graph/badge.svg)](https://codecov.io/gh/containerd/aufs) - - -AUFS implementation of the snapshot interface for containerd. - -## Compile - -To compile containerd with aufs support add the import into the `cmd/containerd/builtins_linux.go` file. - -```go -package main - -import ( - _ "github.com/containerd/aufs" - _ "github.com/containerd/containerd/linux" - _ "github.com/containerd/containerd/metrics/cgroups" - _ "github.com/containerd/containerd/snapshot/overlay" -) -``` - -## Project details - -aufs is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). -As a containerd sub-project, you will find the: - * [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md), - * [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS), - * and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md) - -information in our [`containerd/project`](https://github.com/containerd/project) repository. diff --git a/vendor/github.com/containerd/aufs/aufs.go b/vendor/github.com/containerd/aufs/aufs.go deleted file mode 100644 index ed4e28fec..000000000 --- a/vendor/github.com/containerd/aufs/aufs.go +++ /dev/null @@ -1,452 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package aufs - -import ( - "bufio" - "context" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "strings" - "sync" - "syscall" - - "golang.org/x/sys/unix" - - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/platforms" - "github.com/containerd/containerd/plugin" - "github.com/containerd/containerd/snapshots" - "github.com/containerd/containerd/snapshots/storage" - "github.com/containerd/continuity/fs" - "github.com/pkg/errors" -) - -func init() { - plugin.Register(&plugin.Registration{ - Type: plugin.SnapshotPlugin, - ID: "aufs", - InitFn: func(ic *plugin.InitContext) (interface{}, error) { - ic.Meta.Platforms = append(ic.Meta.Platforms, platforms.DefaultSpec()) - ic.Meta.Exports["root"] = ic.Root - return New(ic.Root) - }, - }) - -} - -var ( - dirperm sync.Once - dirpermEnabled bool -) - -type snapshotter struct { - root string - ms *storage.MetaStore -} - -// New creates a new snapshotter using aufs -func New(root string) (snapshots.Snapshotter, error) { - if err := supported(); err != nil { - return nil, errors.Wrap(plugin.ErrSkipPlugin, err.Error()) - } - if err := os.MkdirAll(root, 0700); err != nil { - return nil, err - } - ms, err := storage.NewMetaStore(filepath.Join(root, "metadata.db")) - if err != nil { - return nil, err - } - if err := os.Mkdir(filepath.Join(root, "snapshots"), 0700); err != nil && !os.IsExist(err) { - return nil, err - } - return &snapshotter{ - root: root, - ms: ms, - }, nil -} - -func (o *snapshotter) Stat(ctx context.Context, key string) (snapshots.Info, error) { - ctx, t, err := o.ms.TransactionContext(ctx, false) - if err != nil { - return snapshots.Info{}, err - } - defer t.Rollback() - _, info, _, err := storage.GetInfo(ctx, key) - if err != nil { - return snapshots.Info{}, err - } - return info, nil -} - -func (o *snapshotter) Update(ctx context.Context, info snapshots.Info, fieldpaths ...string) (snapshots.Info, error) { - ctx, t, err := o.ms.TransactionContext(ctx, true) - if err != nil { - return snapshots.Info{}, err - } - info, err = storage.UpdateInfo(ctx, info, fieldpaths...) - if err != nil { - t.Rollback() - return snapshots.Info{}, err - } - if err := t.Commit(); err != nil { - return snapshots.Info{}, err - } - return info, nil -} - -// Usage returns the resources taken by the snapshot identified by key. -// -// For active snapshots, this will scan the usage of directory and may take some time. -// -// For committed snapshots, the value is returned from the metadata database. -func (o *snapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) { - ctx, t, err := o.ms.TransactionContext(ctx, false) - if err != nil { - return snapshots.Usage{}, err - } - id, info, usage, err := storage.GetInfo(ctx, key) - if err != nil { - return snapshots.Usage{}, err - } - - upperPath := o.upperPath(id) - t.Rollback() // transaction no longer needed at this point. - - if info.Kind == snapshots.KindActive { - du, err := fs.DiskUsage(ctx, upperPath) - if err != nil { - // TODO(stevvooe): Consider not reporting an error in this case. - return snapshots.Usage{}, err - } - - usage = snapshots.Usage(du) - } - - return usage, nil -} - -func (o *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) { - return o.createSnapshot(ctx, snapshots.KindActive, key, parent, opts) -} - -func (o *snapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) { - return o.createSnapshot(ctx, snapshots.KindView, key, parent, opts) -} - -// Mounts returns the mounts for the transaction identified by key. Can be -// called on an read-write or readonly transaction. -// -// This can be used to recover mounts after calling View or Prepare. -func (o *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) { - ctx, t, err := o.ms.TransactionContext(ctx, false) - if err != nil { - return nil, err - } - s, err := storage.GetSnapshot(ctx, key) - t.Rollback() - if err != nil { - return nil, errors.Wrap(err, "failed to get active mount") - } - return o.mounts(s), nil -} - -func (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) error { - ctx, t, err := o.ms.TransactionContext(ctx, true) - if err != nil { - return err - } - - defer func() { - if err != nil { - if rerr := t.Rollback(); rerr != nil { - log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") - } - } - }() - - // grab the existing id - id, _, _, err := storage.GetInfo(ctx, key) - if err != nil { - return err - } - - usage, err := fs.DiskUsage(ctx, o.upperPath(id)) - if err != nil { - return err - } - - if _, err = storage.CommitActive(ctx, key, name, snapshots.Usage(usage), opts...); err != nil { - return errors.Wrap(err, "failed to commit snapshot") - } - return t.Commit() -} - -// Remove abandons the transaction identified by key. All resources -// associated with the key will be removed. -func (o *snapshotter) Remove(ctx context.Context, key string) (err error) { - ctx, t, err := o.ms.TransactionContext(ctx, true) - if err != nil { - return err - } - defer func() { - if err != nil && t != nil { - if rerr := t.Rollback(); rerr != nil { - log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") - } - } - }() - - id, _, err := storage.Remove(ctx, key) - if err != nil { - return errors.Wrap(err, "failed to remove") - } - - path := filepath.Join(o.root, "snapshots", id) - renamed := filepath.Join(o.root, "snapshots", "rm-"+id) - if err := os.Rename(path, renamed); err != nil { - return errors.Wrap(err, "failed to rename") - } - - err = t.Commit() - t = nil - if err != nil { - if err1 := os.Rename(renamed, path); err1 != nil { - // May cause inconsistent data on disk - log.G(ctx).WithError(err1).WithField("path", renamed).Errorf("Failed to rename after failed commit") - } - return errors.Wrap(err, "failed to commit") - } - if err := os.RemoveAll(renamed); err != nil { - // Must be cleaned up, any "rm-*" could be removed if no active transactions - log.G(ctx).WithError(err).WithField("path", renamed).Warnf("Failed to remove root filesystem") - } - - return nil -} - -// Walk the committed snapshots. -func (o *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error) error { - ctx, t, err := o.ms.TransactionContext(ctx, false) - if err != nil { - return err - } - defer t.Rollback() - return storage.WalkInfo(ctx, fn) -} - -func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, key, parent string, opts []snapshots.Opt) ([]mount.Mount, error) { - var ( - path string - snapshotDir = filepath.Join(o.root, "snapshots") - ) - - td, err := ioutil.TempDir(snapshotDir, "new-") - if err != nil { - return nil, errors.Wrap(err, "failed to create temp dir") - } - defer func() { - if err != nil { - if td != "" { - if err1 := os.RemoveAll(td); err1 != nil { - err = errors.Wrapf(err, "remove failed: %v", err1) - } - } - if path != "" { - if err1 := os.RemoveAll(path); err1 != nil { - err = errors.Wrapf(err, "failed to remove path: %v", err1) - } - } - } - }() - - fs := filepath.Join(td, "fs") - if err = os.MkdirAll(fs, 0755); err != nil { - return nil, err - } - - ctx, t, err := o.ms.TransactionContext(ctx, true) - if err != nil { - return nil, err - } - - s, err := storage.CreateSnapshot(ctx, kind, key, parent, opts...) - if err != nil { - if rerr := t.Rollback(); rerr != nil { - log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") - } - return nil, errors.Wrap(err, "failed to create active") - } - - if len(s.ParentIDs) > 0 { - st, err := os.Stat(filepath.Join(o.upperPath(s.ParentIDs[0]))) - if err != nil { - if rerr := t.Rollback(); rerr != nil { - log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") - } - return nil, errors.Wrap(err, "failed to stat parent") - } - - stat := st.Sys().(*syscall.Stat_t) - - if err := os.Lchown(fs, int(stat.Uid), int(stat.Gid)); err != nil { - if rerr := t.Rollback(); rerr != nil { - log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") - } - return nil, errors.Wrap(err, "failed to chown") - } - } - - path = filepath.Join(snapshotDir, s.ID) - if err = os.Rename(td, path); err != nil { - if rerr := t.Rollback(); rerr != nil { - log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") - } - return nil, errors.Wrap(err, "failed to rename") - } - td = "" - - if err = t.Commit(); err != nil { - return nil, errors.Wrap(err, "commit failed") - } - - return o.mounts(s), nil -} - -func (o *snapshotter) mounts(s storage.Snapshot) []mount.Mount { - if len(s.ParentIDs) == 0 { - // if we only have one layer/no parents then just return a bind mount - roFlag := "rw" - if s.Kind == snapshots.KindView { - roFlag = "ro" - } - - return []mount.Mount{ - { - Source: o.upperPath(s.ID), - Type: "bind", - Options: []string{ - roFlag, - "rbind", - }, - }, - } - } - - aufsOptions := []string{ - "br", - } - - if s.Kind == snapshots.KindActive { - aufsOptions = append(aufsOptions, - fmt.Sprintf("%s=rw", o.upperPath(s.ID)), - ) - } else if len(s.ParentIDs) == 1 { - return []mount.Mount{ - { - Source: o.upperPath(s.ParentIDs[0]), - Type: "bind", - Options: []string{ - "ro", - "rbind", - }, - }, - } - } - - for i := range s.ParentIDs { - aufsOptions = append(aufsOptions, fmt.Sprintf("%s=ro+wh", o.upperPath(s.ParentIDs[i]))) - } - options := []string{ - "dio", - "xino=/dev/shm/aufs.xino", - } - if useDirperm() { - options = append(options, "dirperm1") - } - - options = append(options, strings.Join(aufsOptions, ":")) - return []mount.Mount{ - { - Type: "aufs", - Source: "none", - Options: options, - }, - } - -} - -func (o *snapshotter) upperPath(id string) string { - return filepath.Join(o.root, "snapshots", id, "fs") -} - -func supported() error { - // modprobe the aufs module before checking - cmd := exec.Command("modprobe", "aufs") - out, err := cmd.CombinedOutput() - if err != nil { - return errors.Wrapf(err, "modprobe aufs failed: %q", out) - } - - f, err := os.Open("/proc/filesystems") - if err != nil { - return err - } - defer f.Close() - - s := bufio.NewScanner(f) - for s.Scan() { - if strings.Contains(s.Text(), "aufs") { - return nil - } - } - return errors.Errorf("aufs is not supported") -} - -// useDirperm checks dirperm1 mount option can be used with the current -// version of aufs. -func useDirperm() bool { - dirperm.Do(func() { - base, err := ioutil.TempDir("", "docker-aufs-base") - if err != nil { - return - } - defer os.RemoveAll(base) - - union, err := ioutil.TempDir("", "docker-aufs-union") - if err != nil { - return - } - defer os.RemoveAll(union) - - opts := fmt.Sprintf("br:%s,dirperm1,xino=/dev/shm/aufs.xino", base) - if err := unix.Mount("none", union, "aufs", 0, opts); err != nil { - return - } - dirpermEnabled = true - unix.Unmount(union, 0) - }) - return dirpermEnabled -} - -func (o *snapshotter) Close() error { - return o.ms.Close() -} diff --git a/vendor/github.com/containerd/zfs/LICENSE b/vendor/github.com/containerd/zfs/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/vendor/github.com/containerd/zfs/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/containerd/zfs/README.md b/vendor/github.com/containerd/zfs/README.md deleted file mode 100644 index 5f8e5bad3..000000000 --- a/vendor/github.com/containerd/zfs/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# [containerd](https://github.com/containerd/containerd) ZFS snapshotter plugin - -[![Build Status](https://travis-ci.org/containerd/zfs.svg)](https://travis-ci.org/containerd/zfs) -[![codecov](https://codecov.io/gh/containerd/zfs/branch/master/graph/badge.svg)](https://codecov.io/gh/containerd/zfs) - -ZFS snapshotter plugin for containerd. - -This plugin is tested on Linux with Ubuntu. It should be compatible with FreeBSD. - - -## Compile - -To compile containerd with ZFS support, add the import into the `$GOPATH/src/github.com/containerd/containerd/cmd/containerd/builtins_zfs.go` file. - -```go -// +build linux freebsd - -package main - -import ( - _ "github.com/containerd/zfs" -) -``` - -Please refer to [`.travis.yml`](.travis.yml) for the latest containerd version known to work with. - - -## Usage - -1. Set up a ZFS filesystem. -The ZFS filesystem name is arbitrary but the mount point needs to be `/var/lib/containerd/io.containerd.snapshotter.v1.zfs`, when the containerd root is set to `/var/lib/containerd`. -```console -$ zfs create -o mountpoint=/var/lib/containerd/io.containerd.snapshotter.v1.zfs your-zpool/containerd -``` - -2. Start containerd. - -3. e.g. `ctr pull --snapshotter=zfs ...` - -## Project details - -The zfs plugin is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). -As a containerd sub-project, you will find the: - * [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md), - * [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS), - * and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md) - -information in our [`containerd/project`](https://github.com/containerd/project) repository. diff --git a/vendor/github.com/containerd/zfs/zfs.go b/vendor/github.com/containerd/zfs/zfs.go deleted file mode 100644 index 5a08fda6e..000000000 --- a/vendor/github.com/containerd/zfs/zfs.go +++ /dev/null @@ -1,343 +0,0 @@ -// +build linux freebsd - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package zfs - -import ( - "context" - "path/filepath" - - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/platforms" - "github.com/containerd/containerd/plugin" - "github.com/containerd/containerd/snapshots" - "github.com/containerd/containerd/snapshots/storage" - zfs "github.com/mistifyio/go-zfs" - "github.com/pkg/errors" -) - -const ( - // snapshotSuffix is used as follows: - // active := filepath.Join(dataset.Name, id) - // committed := active + "@" + snapshotSuffix - snapshotSuffix = "snapshot" -) - -func init() { - plugin.Register(&plugin.Registration{ - Type: plugin.SnapshotPlugin, - ID: "zfs", - InitFn: func(ic *plugin.InitContext) (interface{}, error) { - ic.Meta.Platforms = append(ic.Meta.Platforms, platforms.DefaultSpec()) - ic.Meta.Exports["root"] = ic.Root - return NewSnapshotter(ic.Root) - }, - }) -} - -type snapshotter struct { - dataset *zfs.Dataset - ms *storage.MetaStore -} - -// NewSnapshotter returns a Snapshotter using zfs. Uses the provided -// root directory for snapshots and stores the metadata in -// a file in the provided root. -// root needs to be a mount point of zfs. -func NewSnapshotter(root string) (snapshots.Snapshotter, error) { - m, err := mount.Lookup(root) - if err != nil { - return nil, err - } - if m.FSType != "zfs" { - return nil, errors.Wrapf(plugin.ErrSkipPlugin, "path %s must be a zfs filesystem to be used with the zfs snapshotter", root) - } - dataset, err := zfs.GetDataset(m.Source) - if err != nil { - return nil, err - } - - ms, err := storage.NewMetaStore(filepath.Join(root, "metadata.db")) - if err != nil { - return nil, err - } - - b := &snapshotter{ - dataset: dataset, - ms: ms, - } - return b, nil -} - -var ( - zfsCreateProperties = map[string]string{ - "mountpoint": "legacy", - } -) - -// createFilesystem creates but not mount. -func createFilesystem(datasetName string) (*zfs.Dataset, error) { - return zfs.CreateFilesystem(datasetName, zfsCreateProperties) -} - -// cloneFilesystem clones but not mount. -func cloneFilesystem(datasetName string, snapshot *zfs.Dataset) (*zfs.Dataset, error) { - return snapshot.Clone(datasetName, zfsCreateProperties) -} - -func destroy(dataset *zfs.Dataset) error { - return dataset.Destroy(zfs.DestroyDefault) -} - -func destroySnapshot(dataset *zfs.Dataset) error { - return dataset.Destroy(zfs.DestroyDeferDeletion) -} - -// Stat returns the info for an active or committed snapshot by name or -// key. -// -// Should be used for parent resolution, existence checks and to discern -// the kind of snapshot. -func (z *snapshotter) Stat(ctx context.Context, key string) (snapshots.Info, error) { - ctx, t, err := z.ms.TransactionContext(ctx, false) - if err != nil { - return snapshots.Info{}, err - } - defer t.Rollback() - _, info, _, err := storage.GetInfo(ctx, key) - if err != nil { - return snapshots.Info{}, err - } - - return info, nil -} - -// Usage retrieves the disk usage of the top-level snapshot. -func (z *snapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) { - return snapshots.Usage{}, errors.New("zfs does not implement Usage() yet") -} - -// Walk the committed snapshots. -func (z *snapshotter) Walk(ctx context.Context, fn func(context.Context, snapshots.Info) error) error { - ctx, t, err := z.ms.TransactionContext(ctx, false) - if err != nil { - return err - } - defer t.Rollback() - return storage.WalkInfo(ctx, fn) -} - -func (z *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) { - return z.createSnapshot(ctx, snapshots.KindActive, key, parent, opts...) -} - -func (z *snapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) { - return z.createSnapshot(ctx, snapshots.KindView, key, parent, opts...) -} - -func (z *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) { - ctx, t, err := z.ms.TransactionContext(ctx, true) - if err != nil { - return nil, err - } - defer func() { - if err != nil && t != nil { - if rerr := t.Rollback(); rerr != nil { - log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") - } - } - }() - - a, err := storage.CreateSnapshot(ctx, kind, key, parent, opts...) - if err != nil { - return nil, err - } - - targetName := filepath.Join(z.dataset.Name, a.ID) - var target *zfs.Dataset - if len(a.ParentIDs) == 0 { - target, err = createFilesystem(targetName) - if err != nil { - return nil, err - } - } else { - parent0Name := filepath.Join(z.dataset.Name, a.ParentIDs[0]) + "@" + snapshotSuffix - parent0, err := zfs.GetDataset(parent0Name) - if err != nil { - return nil, err - } - target, err = cloneFilesystem(targetName, parent0) - if err != nil { - return nil, err - } - } - - err = t.Commit() - t = nil - if err != nil { - if derr := destroy(target); derr != nil { - log.G(ctx).WithError(derr).WithField("targetName", targetName).Error("failed to delete dataset") - } - return nil, err - } - readonly := kind == snapshots.KindView - return z.mounts(target, readonly) -} - -func (z *snapshotter) mounts(dataset *zfs.Dataset, readonly bool) ([]mount.Mount, error) { - var options []string - if readonly { - options = append(options, "ro") - } - return []mount.Mount{ - { - Type: "zfs", - Source: dataset.Name, - Options: options, - }, - }, nil -} - -func (z *snapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) (err error) { - ctx, t, err := z.ms.TransactionContext(ctx, true) - if err != nil { - return err - } - defer func() { - if err != nil && t != nil { - if rerr := t.Rollback(); rerr != nil { - log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") - } - } - }() - - id, err := storage.CommitActive(ctx, key, name, snapshots.Usage{}) - if err != nil { - return errors.Wrap(err, "failed to commit") - } - - activeName := filepath.Join(z.dataset.Name, id) - active, err := zfs.GetDataset(activeName) - if err != nil { - return err - } - snapshot, err := active.Snapshot(snapshotSuffix, false) - if err != nil { - return err - } - err = t.Commit() - t = nil - if err != nil { - snapshotName := activeName + "@" + snapshotSuffix - if derr := destroySnapshot(snapshot); derr != nil { - log.G(ctx).WithError(derr).WithField("snapshotName", snapshotName).Error("failed to delete dataset") - } - return err - } - return nil -} - -// Mounts returns the mounts for the transaction identified by key. Can be -// called on an read-write or readonly transaction. -// -// This can be used to recover mounts after calling View or Prepare. -func (z *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) { - ctx, t, err := z.ms.TransactionContext(ctx, false) - if err != nil { - return nil, err - } - s, err := storage.GetSnapshot(ctx, key) - t.Rollback() - if err != nil { - return nil, errors.Wrap(err, "failed to get active snapshot") - } - sName := filepath.Join(z.dataset.Name, s.ID) - sDataset, err := zfs.GetDataset(sName) - if err != nil { - return nil, err - } - return z.mounts(sDataset, false) -} - -// Remove abandons the transaction identified by key. All resources -// associated with the key will be removed. -func (z *snapshotter) Remove(ctx context.Context, key string) (err error) { - ctx, t, err := z.ms.TransactionContext(ctx, true) - if err != nil { - return err - } - defer func() { - if err != nil && t != nil { - if rerr := t.Rollback(); rerr != nil { - log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") - } - } - // FIXME: rolling back the removed ZFS dataset is unsupported yet - }() - - id, k, err := storage.Remove(ctx, key) - if err != nil { - return errors.Wrap(err, "failed to remove snapshot") - } - - datasetName := filepath.Join(z.dataset.Name, id) - if k == snapshots.KindCommitted { - snapshotName := datasetName + "@" + snapshotSuffix - snapshot, err := zfs.GetDataset(snapshotName) - if err != nil { - return err - } - if err = destroySnapshot(snapshot); err != nil { - return err - } - } - dataset, err := zfs.GetDataset(datasetName) - if err != nil { - return err - } - if err = destroy(dataset); err != nil { - return err - } - err = t.Commit() - t = nil - return err -} - -func (o *snapshotter) Update(ctx context.Context, info snapshots.Info, fieldpaths ...string) (snapshots.Info, error) { - ctx, t, err := o.ms.TransactionContext(ctx, true) - if err != nil { - return snapshots.Info{}, err - } - - info, err = storage.UpdateInfo(ctx, info, fieldpaths...) - if err != nil { - t.Rollback() - return snapshots.Info{}, err - } - - if err := t.Commit(); err != nil { - return snapshots.Info{}, err - } - - return info, nil -} - -func (o *snapshotter) Close() error { - return o.ms.Close() -} diff --git a/vendor/github.com/mistifyio/go-zfs/LICENSE b/vendor/github.com/mistifyio/go-zfs/LICENSE deleted file mode 100644 index f4c265cfe..000000000 --- a/vendor/github.com/mistifyio/go-zfs/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright (c) 2014, OmniTI Computer Consulting, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/vendor/github.com/mistifyio/go-zfs/README.md b/vendor/github.com/mistifyio/go-zfs/README.md deleted file mode 100644 index fef80d727..000000000 --- a/vendor/github.com/mistifyio/go-zfs/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# Go Wrapper for ZFS # - -Simple wrappers for ZFS command line tools. - -[![GoDoc](https://godoc.org/github.com/mistifyio/go-zfs?status.svg)](https://godoc.org/github.com/mistifyio/go-zfs) - -## Requirements ## - -You need a working ZFS setup. To use on Ubuntu 14.04, setup ZFS: - - sudo apt-get install python-software-properties - sudo apt-add-repository ppa:zfs-native/stable - sudo apt-get update - sudo apt-get install ubuntu-zfs libzfs-dev - -Developed using Go 1.3, but currently there isn't anything 1.3 specific. Don't use Ubuntu packages for Go, use http://golang.org/doc/install - -Generally you need root privileges to use anything zfs related. - -## Status ## - -This has been only been tested on Ubuntu 14.04 - -In the future, we hope to work directly with libzfs. - -# Hacking # - -The tests have decent examples for most functions. - -```go -//assuming a zpool named test -//error handling omitted - - -f, err := zfs.CreateFilesystem("test/snapshot-test", nil) -ok(t, err) - -s, err := f.Snapshot("test", nil) -ok(t, err) - -// snapshot is named "test/snapshot-test@test" - -c, err := s.Clone("test/clone-test", nil) - -err := c.Destroy() -err := s.Destroy() -err := f.Destroy() - -``` - -# Contributing # - -See the [contributing guidelines](./CONTRIBUTING.md) - diff --git a/vendor/github.com/mistifyio/go-zfs/error.go b/vendor/github.com/mistifyio/go-zfs/error.go deleted file mode 100644 index 5408ccdb5..000000000 --- a/vendor/github.com/mistifyio/go-zfs/error.go +++ /dev/null @@ -1,18 +0,0 @@ -package zfs - -import ( - "fmt" -) - -// Error is an error which is returned when the `zfs` or `zpool` shell -// commands return with a non-zero exit code. -type Error struct { - Err error - Debug string - Stderr string -} - -// Error returns the string representation of an Error. -func (e Error) Error() string { - return fmt.Sprintf("%s: %q => %s", e.Err, e.Debug, e.Stderr) -} diff --git a/vendor/github.com/mistifyio/go-zfs/utils.go b/vendor/github.com/mistifyio/go-zfs/utils.go deleted file mode 100644 index c18c2c3da..000000000 --- a/vendor/github.com/mistifyio/go-zfs/utils.go +++ /dev/null @@ -1,360 +0,0 @@ -package zfs - -import ( - "bytes" - "errors" - "fmt" - "io" - "os/exec" - "regexp" - "runtime" - "strconv" - "strings" - - "github.com/google/uuid" -) - -type command struct { - Command string - Stdin io.Reader - Stdout io.Writer -} - -func (c *command) Run(arg ...string) ([][]string, error) { - - cmd := exec.Command(c.Command, arg...) - - var stdout, stderr bytes.Buffer - - if c.Stdout == nil { - cmd.Stdout = &stdout - } else { - cmd.Stdout = c.Stdout - } - - if c.Stdin != nil { - cmd.Stdin = c.Stdin - - } - cmd.Stderr = &stderr - - id := uuid.New().String() - joinedArgs := strings.Join(cmd.Args, " ") - - logger.Log([]string{"ID:" + id, "START", joinedArgs}) - err := cmd.Run() - logger.Log([]string{"ID:" + id, "FINISH"}) - - if err != nil { - return nil, &Error{ - Err: err, - Debug: strings.Join([]string{cmd.Path, joinedArgs[1:]}, " "), - Stderr: stderr.String(), - } - } - - // assume if you passed in something for stdout, that you know what to do with it - if c.Stdout != nil { - return nil, nil - } - - lines := strings.Split(stdout.String(), "\n") - - //last line is always blank - lines = lines[0 : len(lines)-1] - output := make([][]string, len(lines)) - - for i, l := range lines { - output[i] = strings.Fields(l) - } - - return output, nil -} - -func setString(field *string, value string) { - v := "" - if value != "-" { - v = value - } - *field = v -} - -func setUint(field *uint64, value string) error { - var v uint64 - if value != "-" { - var err error - v, err = strconv.ParseUint(value, 10, 64) - if err != nil { - return err - } - } - *field = v - return nil -} - -func (ds *Dataset) parseLine(line []string) error { - var err error - - if len(line) != len(dsPropList) { - return errors.New("Output does not match what is expected on this platform") - } - setString(&ds.Name, line[0]) - setString(&ds.Origin, line[1]) - - if err = setUint(&ds.Used, line[2]); err != nil { - return err - } - if err = setUint(&ds.Avail, line[3]); err != nil { - return err - } - - setString(&ds.Mountpoint, line[4]) - setString(&ds.Compression, line[5]) - setString(&ds.Type, line[6]) - - if err = setUint(&ds.Volsize, line[7]); err != nil { - return err - } - if err = setUint(&ds.Quota, line[8]); err != nil { - return err - } - if err = setUint(&ds.Referenced, line[9]); err != nil { - return err - } - - if runtime.GOOS == "solaris" { - return nil - } - - if err = setUint(&ds.Written, line[10]); err != nil { - return err - } - if err = setUint(&ds.Logicalused, line[11]); err != nil { - return err - } - if err = setUint(&ds.Usedbydataset, line[12]); err != nil { - return err - } - - return nil -} - -/* - * from zfs diff`s escape function: - * - * Prints a file name out a character at a time. If the character is - * not in the range of what we consider "printable" ASCII, display it - * as an escaped 3-digit octal value. ASCII values less than a space - * are all control characters and we declare the upper end as the - * DELete character. This also is the last 7-bit ASCII character. - * We choose to treat all 8-bit ASCII as not printable for this - * application. - */ -func unescapeFilepath(path string) (string, error) { - buf := make([]byte, 0, len(path)) - llen := len(path) - for i := 0; i < llen; { - if path[i] == '\\' { - if llen < i+4 { - return "", fmt.Errorf("Invalid octal code: too short") - } - octalCode := path[(i + 1):(i + 4)] - val, err := strconv.ParseUint(octalCode, 8, 8) - if err != nil { - return "", fmt.Errorf("Invalid octal code: %v", err) - } - buf = append(buf, byte(val)) - i += 4 - } else { - buf = append(buf, path[i]) - i++ - } - } - return string(buf), nil -} - -var changeTypeMap = map[string]ChangeType{ - "-": Removed, - "+": Created, - "M": Modified, - "R": Renamed, -} -var inodeTypeMap = map[string]InodeType{ - "B": BlockDevice, - "C": CharacterDevice, - "/": Directory, - ">": Door, - "|": NamedPipe, - "@": SymbolicLink, - "P": EventPort, - "=": Socket, - "F": File, -} - -// matches (+1) or (-1) -var referenceCountRegex = regexp.MustCompile("\\(([+-]\\d+?)\\)") - -func parseReferenceCount(field string) (int, error) { - matches := referenceCountRegex.FindStringSubmatch(field) - if matches == nil { - return 0, fmt.Errorf("Regexp does not match") - } - return strconv.Atoi(matches[1]) -} - -func parseInodeChange(line []string) (*InodeChange, error) { - llen := len(line) - if llen < 1 { - return nil, fmt.Errorf("Empty line passed") - } - - changeType := changeTypeMap[line[0]] - if changeType == 0 { - return nil, fmt.Errorf("Unknown change type '%s'", line[0]) - } - - switch changeType { - case Renamed: - if llen != 4 { - return nil, fmt.Errorf("Mismatching number of fields: expect 4, got: %d", llen) - } - case Modified: - if llen != 4 && llen != 3 { - return nil, fmt.Errorf("Mismatching number of fields: expect 3..4, got: %d", llen) - } - default: - if llen != 3 { - return nil, fmt.Errorf("Mismatching number of fields: expect 3, got: %d", llen) - } - } - - inodeType := inodeTypeMap[line[1]] - if inodeType == 0 { - return nil, fmt.Errorf("Unknown inode type '%s'", line[1]) - } - - path, err := unescapeFilepath(line[2]) - if err != nil { - return nil, fmt.Errorf("Failed to parse filename: %v", err) - } - - var newPath string - var referenceCount int - switch changeType { - case Renamed: - newPath, err = unescapeFilepath(line[3]) - if err != nil { - return nil, fmt.Errorf("Failed to parse filename: %v", err) - } - case Modified: - if llen == 4 { - referenceCount, err = parseReferenceCount(line[3]) - if err != nil { - return nil, fmt.Errorf("Failed to parse reference count: %v", err) - } - } - default: - newPath = "" - } - - return &InodeChange{ - Change: changeType, - Type: inodeType, - Path: path, - NewPath: newPath, - ReferenceCountChange: referenceCount, - }, nil -} - -// example input -//M / /testpool/bar/ -//+ F /testpool/bar/hello.txt -//M / /testpool/bar/hello.txt (+1) -//M / /testpool/bar/hello-hardlink -func parseInodeChanges(lines [][]string) ([]*InodeChange, error) { - changes := make([]*InodeChange, len(lines)) - - for i, line := range lines { - c, err := parseInodeChange(line) - if err != nil { - return nil, fmt.Errorf("Failed to parse line %d of zfs diff: %v, got: '%s'", i, err, line) - } - changes[i] = c - } - return changes, nil -} - -func listByType(t, filter string) ([]*Dataset, error) { - args := []string{"list", "-rHp", "-t", t, "-o", dsPropListOptions} - - if filter != "" { - args = append(args, filter) - } - out, err := zfs(args...) - if err != nil { - return nil, err - } - - var datasets []*Dataset - - name := "" - var ds *Dataset - for _, line := range out { - if name != line[0] { - name = line[0] - ds = &Dataset{Name: name} - datasets = append(datasets, ds) - } - if err := ds.parseLine(line); err != nil { - return nil, err - } - } - - return datasets, nil -} - -func propsSlice(properties map[string]string) []string { - args := make([]string, 0, len(properties)*3) - for k, v := range properties { - args = append(args, "-o") - args = append(args, fmt.Sprintf("%s=%s", k, v)) - } - return args -} - -func (z *Zpool) parseLine(line []string) error { - prop := line[1] - val := line[2] - - var err error - - switch prop { - case "name": - setString(&z.Name, val) - case "health": - setString(&z.Health, val) - case "allocated": - err = setUint(&z.Allocated, val) - case "size": - err = setUint(&z.Size, val) - case "free": - err = setUint(&z.Free, val) - case "fragmentation": - // Trim trailing "%" before parsing uint - i := strings.Index(val, "%") - if i < 0 { - i = len(val) - } - err = setUint(&z.Fragmentation, val[:i]) - case "readonly": - z.ReadOnly = val == "on" - case "freeing": - err = setUint(&z.Freeing, val) - case "leaked": - err = setUint(&z.Leaked, val) - case "dedupratio": - // Trim trailing "x" before parsing float64 - z.DedupRatio, err = strconv.ParseFloat(val[:len(val)-1], 64) - } - return err -} diff --git a/vendor/github.com/mistifyio/go-zfs/utils_notsolaris.go b/vendor/github.com/mistifyio/go-zfs/utils_notsolaris.go deleted file mode 100644 index a46f73060..000000000 --- a/vendor/github.com/mistifyio/go-zfs/utils_notsolaris.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build !solaris - -package zfs - -import ( - "strings" -) - -// List of ZFS properties to retrieve from zfs list command on a non-Solaris platform -var dsPropList = []string{"name", "origin", "used", "available", "mountpoint", "compression", "type", "volsize", "quota", "referenced", "written", "logicalused", "usedbydataset"} - -var dsPropListOptions = strings.Join(dsPropList, ",") - -// List of Zpool properties to retrieve from zpool list command on a non-Solaris platform -var zpoolPropList = []string{"name", "health", "allocated", "size", "free", "readonly", "dedupratio", "fragmentation", "freeing", "leaked"} -var zpoolPropListOptions = strings.Join(zpoolPropList, ",") -var zpoolArgs = []string{"get", "-p", zpoolPropListOptions} diff --git a/vendor/github.com/mistifyio/go-zfs/utils_solaris.go b/vendor/github.com/mistifyio/go-zfs/utils_solaris.go deleted file mode 100644 index 0a7e90f22..000000000 --- a/vendor/github.com/mistifyio/go-zfs/utils_solaris.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build solaris - -package zfs - -import ( - "strings" -) - -// List of ZFS properties to retrieve from zfs list command on a Solaris platform -var dsPropList = []string{"name", "origin", "used", "available", "mountpoint", "compression", "type", "volsize", "quota", "referenced"} - -var dsPropListOptions = strings.Join(dsPropList, ",") - -// List of Zpool properties to retrieve from zpool list command on a non-Solaris platform -var zpoolPropList = []string{"name", "health", "allocated", "size", "free", "readonly", "dedupratio"} -var zpoolPropListOptions = strings.Join(zpoolPropList, ",") -var zpoolArgs = []string{"get", "-p", zpoolPropListOptions} diff --git a/vendor/github.com/mistifyio/go-zfs/zfs.go b/vendor/github.com/mistifyio/go-zfs/zfs.go deleted file mode 100644 index 4e5087ffe..000000000 --- a/vendor/github.com/mistifyio/go-zfs/zfs.go +++ /dev/null @@ -1,452 +0,0 @@ -// Package zfs provides wrappers around the ZFS command line tools. -package zfs - -import ( - "errors" - "fmt" - "io" - "strconv" - "strings" -) - -// ZFS dataset types, which can indicate if a dataset is a filesystem, -// snapshot, or volume. -const ( - DatasetFilesystem = "filesystem" - DatasetSnapshot = "snapshot" - DatasetVolume = "volume" -) - -// Dataset is a ZFS dataset. A dataset could be a clone, filesystem, snapshot, -// or volume. The Type struct member can be used to determine a dataset's type. -// -// The field definitions can be found in the ZFS manual: -// http://www.freebsd.org/cgi/man.cgi?zfs(8). -type Dataset struct { - Name string - Origin string - Used uint64 - Avail uint64 - Mountpoint string - Compression string - Type string - Written uint64 - Volsize uint64 - Logicalused uint64 - Usedbydataset uint64 - Quota uint64 - Referenced uint64 -} - -// InodeType is the type of inode as reported by Diff -type InodeType int - -// Types of Inodes -const ( - _ = iota // 0 == unknown type - BlockDevice InodeType = iota - CharacterDevice - Directory - Door - NamedPipe - SymbolicLink - EventPort - Socket - File -) - -// ChangeType is the type of inode change as reported by Diff -type ChangeType int - -// Types of Changes -const ( - _ = iota // 0 == unknown type - Removed ChangeType = iota - Created - Modified - Renamed -) - -// DestroyFlag is the options flag passed to Destroy -type DestroyFlag int - -// Valid destroy options -const ( - DestroyDefault DestroyFlag = 1 << iota - DestroyRecursive = 1 << iota - DestroyRecursiveClones = 1 << iota - DestroyDeferDeletion = 1 << iota - DestroyForceUmount = 1 << iota -) - -// InodeChange represents a change as reported by Diff -type InodeChange struct { - Change ChangeType - Type InodeType - Path string - NewPath string - ReferenceCountChange int -} - -// Logger can be used to log commands/actions -type Logger interface { - Log(cmd []string) -} - -type defaultLogger struct{} - -func (*defaultLogger) Log(cmd []string) { - return -} - -var logger Logger = &defaultLogger{} - -// SetLogger set a log handler to log all commands including arguments before -// they are executed -func SetLogger(l Logger) { - if l != nil { - logger = l - } -} - -// zfs is a helper function to wrap typical calls to zfs. -func zfs(arg ...string) ([][]string, error) { - c := command{Command: "zfs"} - return c.Run(arg...) -} - -// Datasets returns a slice of ZFS datasets, regardless of type. -// A filter argument may be passed to select a dataset with the matching name, -// or empty string ("") may be used to select all datasets. -func Datasets(filter string) ([]*Dataset, error) { - return listByType("all", filter) -} - -// Snapshots returns a slice of ZFS snapshots. -// A filter argument may be passed to select a snapshot with the matching name, -// or empty string ("") may be used to select all snapshots. -func Snapshots(filter string) ([]*Dataset, error) { - return listByType(DatasetSnapshot, filter) -} - -// Filesystems returns a slice of ZFS filesystems. -// A filter argument may be passed to select a filesystem with the matching name, -// or empty string ("") may be used to select all filesystems. -func Filesystems(filter string) ([]*Dataset, error) { - return listByType(DatasetFilesystem, filter) -} - -// Volumes returns a slice of ZFS volumes. -// A filter argument may be passed to select a volume with the matching name, -// or empty string ("") may be used to select all volumes. -func Volumes(filter string) ([]*Dataset, error) { - return listByType(DatasetVolume, filter) -} - -// GetDataset retrieves a single ZFS dataset by name. This dataset could be -// any valid ZFS dataset type, such as a clone, filesystem, snapshot, or volume. -func GetDataset(name string) (*Dataset, error) { - out, err := zfs("list", "-Hp", "-o", dsPropListOptions, name) - if err != nil { - return nil, err - } - - ds := &Dataset{Name: name} - for _, line := range out { - if err := ds.parseLine(line); err != nil { - return nil, err - } - } - - return ds, nil -} - -// Clone clones a ZFS snapshot and returns a clone dataset. -// An error will be returned if the input dataset is not of snapshot type. -func (d *Dataset) Clone(dest string, properties map[string]string) (*Dataset, error) { - if d.Type != DatasetSnapshot { - return nil, errors.New("can only clone snapshots") - } - args := make([]string, 2, 4) - args[0] = "clone" - args[1] = "-p" - if properties != nil { - args = append(args, propsSlice(properties)...) - } - args = append(args, []string{d.Name, dest}...) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(dest) -} - -// Unmount unmounts currently mounted ZFS file systems. -func (d *Dataset) Unmount(force bool) (*Dataset, error) { - if d.Type == DatasetSnapshot { - return nil, errors.New("cannot unmount snapshots") - } - args := make([]string, 1, 3) - args[0] = "umount" - if force { - args = append(args, "-f") - } - args = append(args, d.Name) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(d.Name) -} - -// Mount mounts ZFS file systems. -func (d *Dataset) Mount(overlay bool, options []string) (*Dataset, error) { - if d.Type == DatasetSnapshot { - return nil, errors.New("cannot mount snapshots") - } - args := make([]string, 1, 5) - args[0] = "mount" - if overlay { - args = append(args, "-O") - } - if options != nil { - args = append(args, "-o") - args = append(args, strings.Join(options, ",")) - } - args = append(args, d.Name) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(d.Name) -} - -// ReceiveSnapshot receives a ZFS stream from the input io.Reader, creates a -// new snapshot with the specified name, and streams the input data into the -// newly-created snapshot. -func ReceiveSnapshot(input io.Reader, name string) (*Dataset, error) { - c := command{Command: "zfs", Stdin: input} - _, err := c.Run("receive", name) - if err != nil { - return nil, err - } - return GetDataset(name) -} - -// SendSnapshot sends a ZFS stream of a snapshot to the input io.Writer. -// An error will be returned if the input dataset is not of snapshot type. -func (d *Dataset) SendSnapshot(output io.Writer) error { - if d.Type != DatasetSnapshot { - return errors.New("can only send snapshots") - } - - c := command{Command: "zfs", Stdout: output} - _, err := c.Run("send", d.Name) - return err -} - -// CreateVolume creates a new ZFS volume with the specified name, size, and -// properties. -// A full list of available ZFS properties may be found here: -// https://www.freebsd.org/cgi/man.cgi?zfs(8). -func CreateVolume(name string, size uint64, properties map[string]string) (*Dataset, error) { - args := make([]string, 4, 5) - args[0] = "create" - args[1] = "-p" - args[2] = "-V" - args[3] = strconv.FormatUint(size, 10) - if properties != nil { - args = append(args, propsSlice(properties)...) - } - args = append(args, name) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(name) -} - -// Destroy destroys a ZFS dataset. If the destroy bit flag is set, any -// descendents of the dataset will be recursively destroyed, including snapshots. -// If the deferred bit flag is set, the snapshot is marked for deferred -// deletion. -func (d *Dataset) Destroy(flags DestroyFlag) error { - args := make([]string, 1, 3) - args[0] = "destroy" - if flags&DestroyRecursive != 0 { - args = append(args, "-r") - } - - if flags&DestroyRecursiveClones != 0 { - args = append(args, "-R") - } - - if flags&DestroyDeferDeletion != 0 { - args = append(args, "-d") - } - - if flags&DestroyForceUmount != 0 { - args = append(args, "-f") - } - - args = append(args, d.Name) - _, err := zfs(args...) - return err -} - -// SetProperty sets a ZFS property on the receiving dataset. -// A full list of available ZFS properties may be found here: -// https://www.freebsd.org/cgi/man.cgi?zfs(8). -func (d *Dataset) SetProperty(key, val string) error { - prop := strings.Join([]string{key, val}, "=") - _, err := zfs("set", prop, d.Name) - return err -} - -// GetProperty returns the current value of a ZFS property from the -// receiving dataset. -// A full list of available ZFS properties may be found here: -// https://www.freebsd.org/cgi/man.cgi?zfs(8). -func (d *Dataset) GetProperty(key string) (string, error) { - out, err := zfs("get", "-H", key, d.Name) - if err != nil { - return "", err - } - - return out[0][2], nil -} - -// Rename renames a dataset. -func (d *Dataset) Rename(name string, createParent bool, recursiveRenameSnapshots bool) (*Dataset, error) { - args := make([]string, 3, 5) - args[0] = "rename" - args[1] = d.Name - args[2] = name - if createParent { - args = append(args, "-p") - } - if recursiveRenameSnapshots { - args = append(args, "-r") - } - _, err := zfs(args...) - if err != nil { - return d, err - } - - return GetDataset(name) -} - -// Snapshots returns a slice of all ZFS snapshots of a given dataset. -func (d *Dataset) Snapshots() ([]*Dataset, error) { - return Snapshots(d.Name) -} - -// CreateFilesystem creates a new ZFS filesystem with the specified name and -// properties. -// A full list of available ZFS properties may be found here: -// https://www.freebsd.org/cgi/man.cgi?zfs(8). -func CreateFilesystem(name string, properties map[string]string) (*Dataset, error) { - args := make([]string, 1, 4) - args[0] = "create" - - if properties != nil { - args = append(args, propsSlice(properties)...) - } - - args = append(args, name) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(name) -} - -// Snapshot creates a new ZFS snapshot of the receiving dataset, using the -// specified name. Optionally, the snapshot can be taken recursively, creating -// snapshots of all descendent filesystems in a single, atomic operation. -func (d *Dataset) Snapshot(name string, recursive bool) (*Dataset, error) { - args := make([]string, 1, 4) - args[0] = "snapshot" - if recursive { - args = append(args, "-r") - } - snapName := fmt.Sprintf("%s@%s", d.Name, name) - args = append(args, snapName) - _, err := zfs(args...) - if err != nil { - return nil, err - } - return GetDataset(snapName) -} - -// Rollback rolls back the receiving ZFS dataset to a previous snapshot. -// Optionally, intermediate snapshots can be destroyed. A ZFS snapshot -// rollback cannot be completed without this option, if more recent -// snapshots exist. -// An error will be returned if the input dataset is not of snapshot type. -func (d *Dataset) Rollback(destroyMoreRecent bool) error { - if d.Type != DatasetSnapshot { - return errors.New("can only rollback snapshots") - } - - args := make([]string, 1, 3) - args[0] = "rollback" - if destroyMoreRecent { - args = append(args, "-r") - } - args = append(args, d.Name) - - _, err := zfs(args...) - return err -} - -// Children returns a slice of children of the receiving ZFS dataset. -// A recursion depth may be specified, or a depth of 0 allows unlimited -// recursion. -func (d *Dataset) Children(depth uint64) ([]*Dataset, error) { - args := []string{"list"} - if depth > 0 { - args = append(args, "-d") - args = append(args, strconv.FormatUint(depth, 10)) - } else { - args = append(args, "-r") - } - args = append(args, "-t", "all", "-Hp", "-o", dsPropListOptions) - args = append(args, d.Name) - - out, err := zfs(args...) - if err != nil { - return nil, err - } - - var datasets []*Dataset - name := "" - var ds *Dataset - for _, line := range out { - if name != line[0] { - name = line[0] - ds = &Dataset{Name: name} - datasets = append(datasets, ds) - } - if err := ds.parseLine(line); err != nil { - return nil, err - } - } - return datasets[1:], nil -} - -// Diff returns changes between a snapshot and the given ZFS dataset. -// The snapshot name must include the filesystem part as it is possible to -// compare clones with their origin snapshots. -func (d *Dataset) Diff(snapshot string) ([]*InodeChange, error) { - args := []string{"diff", "-FH", snapshot, d.Name}[:] - out, err := zfs(args...) - if err != nil { - return nil, err - } - inodeChanges, err := parseInodeChanges(out) - if err != nil { - return nil, err - } - return inodeChanges, nil -} diff --git a/vendor/github.com/mistifyio/go-zfs/zpool.go b/vendor/github.com/mistifyio/go-zfs/zpool.go deleted file mode 100644 index d8db945d7..000000000 --- a/vendor/github.com/mistifyio/go-zfs/zpool.go +++ /dev/null @@ -1,112 +0,0 @@ -package zfs - -// ZFS zpool states, which can indicate if a pool is online, offline, -// degraded, etc. More information regarding zpool states can be found here: -// https://docs.oracle.com/cd/E19253-01/819-5461/gamno/index.html. -const ( - ZpoolOnline = "ONLINE" - ZpoolDegraded = "DEGRADED" - ZpoolFaulted = "FAULTED" - ZpoolOffline = "OFFLINE" - ZpoolUnavail = "UNAVAIL" - ZpoolRemoved = "REMOVED" -) - -// Zpool is a ZFS zpool. A pool is a top-level structure in ZFS, and can -// contain many descendent datasets. -type Zpool struct { - Name string - Health string - Allocated uint64 - Size uint64 - Free uint64 - Fragmentation uint64 - ReadOnly bool - Freeing uint64 - Leaked uint64 - DedupRatio float64 -} - -// zpool is a helper function to wrap typical calls to zpool. -func zpool(arg ...string) ([][]string, error) { - c := command{Command: "zpool"} - return c.Run(arg...) -} - -// GetZpool retrieves a single ZFS zpool by name. -func GetZpool(name string) (*Zpool, error) { - args := zpoolArgs - args = append(args, name) - out, err := zpool(args...) - if err != nil { - return nil, err - } - - // there is no -H - out = out[1:] - - z := &Zpool{Name: name} - for _, line := range out { - if err := z.parseLine(line); err != nil { - return nil, err - } - } - - return z, nil -} - -// Datasets returns a slice of all ZFS datasets in a zpool. -func (z *Zpool) Datasets() ([]*Dataset, error) { - return Datasets(z.Name) -} - -// Snapshots returns a slice of all ZFS snapshots in a zpool. -func (z *Zpool) Snapshots() ([]*Dataset, error) { - return Snapshots(z.Name) -} - -// CreateZpool creates a new ZFS zpool with the specified name, properties, -// and optional arguments. -// A full list of available ZFS properties and command-line arguments may be -// found here: https://www.freebsd.org/cgi/man.cgi?zfs(8). -func CreateZpool(name string, properties map[string]string, args ...string) (*Zpool, error) { - cli := make([]string, 1, 4) - cli[0] = "create" - if properties != nil { - cli = append(cli, propsSlice(properties)...) - } - cli = append(cli, name) - cli = append(cli, args...) - _, err := zpool(cli...) - if err != nil { - return nil, err - } - - return &Zpool{Name: name}, nil -} - -// Destroy destroys a ZFS zpool by name. -func (z *Zpool) Destroy() error { - _, err := zpool("destroy", z.Name) - return err -} - -// ListZpools list all ZFS zpools accessible on the current system. -func ListZpools() ([]*Zpool, error) { - args := []string{"list", "-Ho", "name"} - out, err := zpool(args...) - if err != nil { - return nil, err - } - - var pools []*Zpool - - for _, line := range out { - z, err := GetZpool(line[0]) - if err != nil { - return nil, err - } - pools = append(pools, z) - } - return pools, nil -}