Skip to content

Commit 287606b

Browse files
authored
feat(zfspv): adding snapshot and clone support for ZFSPV (#39)
This commits support snapshot and clone commands via CSI driver. User can create snap and clone using the following steps. Note: - Snapshot is created via reconciliation CR - Cloned volume will be on the same zpool where the snapshot is taken - Cloned volume will have same properties as source volume. ----------------------------------- Create a Snapshotclass ``` kind: VolumeSnapshotClass apiVersion: snapshot.storage.k8s.io/v1beta1 metadata: name: zfspv-snapclass annotations: snapshot.storage.kubernetes.io/is-default-class: "true" driver: zfs.csi.openebs.io deletionPolicy: Delete ``` Once snapshotclass is created, we can use this class to create a Snapshot ``` apiVersion: snapshot.storage.k8s.io/v1beta1 kind: VolumeSnapshot metadata: name: zfspv-snap spec: volumeSnapshotClassName: zfspv-snapclass source: persistentVolumeClaimName: csi-zfspv ``` ``` $ kubectl get volumesnapshot NAME AGE zfspv-snap 7m52s ``` ``` $ kubectl get volumesnapshot -o yaml apiVersion: v1 items: - apiVersion: snapshot.storage.k8s.io/v1beta1 kind: VolumeSnapshot metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"snapshot.storage.k8s.io/v1beta1","kind":"VolumeSnapshot","metadata":{"annotations":{},"name":"zfspv-snap","namespace":"default"},"spec":{"source":{"persistentVolumeClaimName":"csi-zfspv"},"volumeSnapshotClassName":"zfspv-snapclass"}} creationTimestamp: "2020-01-30T10:31:24Z" finalizers: - snapshot.storage.kubernetes.io/volumesnapshot-as-source-protection - snapshot.storage.kubernetes.io/volumesnapshot-bound-protection generation: 1 name: zfspv-snap namespace: default resourceVersion: "30040" selfLink: /apis/snapshot.storage.k8s.io/v1beta1/namespaces/default/volumesnapshots/zfspv-snap uid: 1a5cf166-c599-4f58-9f3c-f1148be47fca spec: source: persistentVolumeClaimName: csi-zfspv volumeSnapshotClassName: zfspv-snapclass status: boundVolumeSnapshotContentName: snapcontent-1a5cf166-c599-4f58-9f3c-f1148be47fca creationTime: "2020-01-30T10:31:24Z" readyToUse: true restoreSize: "0" kind: List metadata: resourceVersion: "" selfLink: "" ``` Openebs resource for the created snapshot ``` $ kubectl get snap -n openebs -o yaml apiVersion: v1 items: - apiVersion: openebs.io/v1alpha1 kind: ZFSSnapshot metadata: creationTimestamp: "2020-01-30T10:31:24Z" finalizers: - zfs.openebs.io/finalizer generation: 2 labels: kubernetes.io/nodename: pawan-2 openebs.io/persistent-volume: pvc-18cab7c3-ec5e-4264-8507-e6f7df4c789a name: snapshot-1a5cf166-c599-4f58-9f3c-f1148be47fca namespace: openebs resourceVersion: "30035" selfLink: /apis/openebs.io/v1alpha1/namespaces/openebs/zfssnapshots/snapshot-1a5cf166-c599-4f58-9f3c-f1148be47fca uid: e29d571c-42b5-4fb7-9110-e1cfc9b96641 spec: capacity: "4294967296" fsType: zfs ownerNodeID: pawan-2 poolName: zfspv-pool status: Ready volumeType: DATASET kind: List metadata: resourceVersion: "" selfLink: "" ``` Create a clone volume We can provide a datasource as snapshot name to create a clone volume ```yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: zfspv-clone spec: storageClassName: openebs-zfspv dataSource: name: zfspv-snap kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.io accessModes: - ReadWriteOnce resources: requests: storage: 4Gi ``` It will create a ZFS clone volume from the mentioned snapshot and create the PV on the same node where original volume is there. Here, As resize is not supported yet, the clone PVC size should match the size of the snapshot. Also, all the properties from the storageclass will not be considered for the clone case, it will take the properties from the snapshot and create the clone volume. One thing to note here is that, the storageclass in clone PVC should have the same poolname as that of the original volume as across the pool, clone is not supported. Signed-off-by: Pawan <[email protected]>
1 parent b0434bb commit 287606b

40 files changed

+2994
-122
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ cscope*
44
tags
55
*.swp
66
*.swo
7+
*.swn

deploy/sample/zfsclone.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
kind: PersistentVolumeClaim
2+
apiVersion: v1
3+
metadata:
4+
name: zfspv-clone
5+
spec:
6+
storageClassName: openebs-zfspv
7+
dataSource:
8+
name: zfspv-snap
9+
kind: VolumeSnapshot
10+
apiGroup: snapshot.storage.k8s.io
11+
accessModes:
12+
- ReadWriteOnce
13+
resources:
14+
requests:
15+
storage: 4Gi
16+

deploy/sample/zfssnapshot.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
kind: VolumeSnapshotClass
2+
apiVersion: snapshot.storage.k8s.io/v1beta1
3+
metadata:
4+
name: zfspv-snapclass
5+
annotations:
6+
snapshot.storage.kubernetes.io/is-default-class: "true"
7+
driver: zfs.csi.openebs.io
8+
deletionPolicy: Delete
9+
---
10+
apiVersion: snapshot.storage.k8s.io/v1beta1
11+
kind: VolumeSnapshot
12+
metadata:
13+
name: zfspv-snap
14+
spec:
15+
volumeSnapshotClassName: zfspv-snapclass
16+
source:
17+
persistentVolumeClaimName: csi-zfspv
18+

deploy/zfs-operator.yaml

Lines changed: 470 additions & 3 deletions
Large diffs are not rendered by default.

pkg/apis/openebs.io/core/v1alpha1/register.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
7171
SchemeGroupVersion,
7272
&ZFSVolume{},
7373
&ZFSVolumeList{},
74+
&ZFSSnapshot{},
75+
&ZFSSnapshotList{},
7476
)
7577
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
7678
return nil
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright © 2019 The OpenEBS Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
// +genclient
24+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
25+
// +resource:path=zfssnapshot
26+
27+
// ZFSSnapshot represents a ZFS Snapshot of the zfsvolume
28+
type ZFSSnapshot struct {
29+
metav1.TypeMeta `json:",inline"`
30+
metav1.ObjectMeta `json:"metadata,omitempty"`
31+
32+
Spec VolumeInfo `json:"spec"`
33+
Status SnapStatus `json:"status"`
34+
}
35+
36+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
37+
// +resource:path=zfssnapshots
38+
39+
// ZFSSnapshotList is a list of ZFSSnapshot resources
40+
type ZFSSnapshotList struct {
41+
metav1.TypeMeta `json:",inline"`
42+
metav1.ListMeta `json:"metadata"`
43+
44+
Items []ZFSSnapshot `json:"items"`
45+
}
46+
47+
type SnapStatus struct {
48+
State string `json:"state,omitempty"`
49+
}

pkg/apis/openebs.io/core/v1alpha1/zfsvolume.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ type MountInfo struct {
5858
}
5959

6060
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
61-
// +resource:path=csivolumes
61+
// +resource:path=zfsvolumes
6262

6363
// ZFSVolumeList is a list of ZFSVolume resources
6464
type ZFSVolumeList struct {
@@ -79,6 +79,10 @@ type VolumeInfo struct {
7979
// pool where this volume should be created
8080
PoolName string `json:"poolName"`
8181

82+
// SnapName specifies the name of the
83+
// snapshot where this volume should be cloned
84+
SnapName string `json:"snapname,omitempty"`
85+
8286
// Capacity of the volume
8387
Capacity string `json:"capacity"`
8488

pkg/apis/openebs.io/core/v1alpha1/zz_generated.deepcopy.go

Lines changed: 77 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/builder/snapbuilder/build.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
Copyright 2020 The OpenEBS Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package snapbuilder
18+
19+
import (
20+
apis "github.com/openebs/zfs-localpv/pkg/apis/openebs.io/core/v1alpha1"
21+
"github.com/openebs/zfs-localpv/pkg/common/errors"
22+
)
23+
24+
// Builder is the builder object for ZFSSnapshot
25+
type Builder struct {
26+
snap *ZFSSnapshot
27+
errs []error
28+
}
29+
30+
// NewBuilder returns new instance of Builder
31+
func NewBuilder() *Builder {
32+
return &Builder{
33+
snap: &ZFSSnapshot{
34+
Object: &apis.ZFSSnapshot{},
35+
},
36+
}
37+
}
38+
39+
// BuildFrom returns new instance of Builder
40+
// from the provided api instance
41+
func BuildFrom(snap *apis.ZFSSnapshot) *Builder {
42+
if snap == nil {
43+
b := NewBuilder()
44+
b.errs = append(
45+
b.errs,
46+
errors.New("failed to build snap object: nil snap"),
47+
)
48+
return b
49+
}
50+
return &Builder{
51+
snap: &ZFSSnapshot{
52+
Object: snap,
53+
},
54+
}
55+
}
56+
57+
// WithNamespace sets the namespace of ZFSSnapshot
58+
func (b *Builder) WithNamespace(namespace string) *Builder {
59+
if namespace == "" {
60+
b.errs = append(
61+
b.errs,
62+
errors.New(
63+
"failed to build csi snap object: missing namespace",
64+
),
65+
)
66+
return b
67+
}
68+
b.snap.Object.Namespace = namespace
69+
return b
70+
}
71+
72+
// WithName sets the name of ZFSSnapshot
73+
func (b *Builder) WithName(name string) *Builder {
74+
if name == "" {
75+
b.errs = append(
76+
b.errs,
77+
errors.New(
78+
"failed to build csi snap object: missing name",
79+
),
80+
)
81+
return b
82+
}
83+
b.snap.Object.Name = name
84+
return b
85+
}
86+
87+
// WithLabels merges existing labels if any
88+
// with the ones that are provided here
89+
func (b *Builder) WithLabels(labels map[string]string) *Builder {
90+
if len(labels) == 0 {
91+
return b
92+
}
93+
94+
if b.snap.Object.Labels == nil {
95+
b.snap.Object.Labels = map[string]string{}
96+
}
97+
98+
for key, value := range labels {
99+
b.snap.Object.Labels[key] = value
100+
}
101+
return b
102+
}
103+
104+
func (b *Builder) WithFinalizer(finalizer []string) *Builder {
105+
b.snap.Object.Finalizers = append(b.snap.Object.Finalizers, finalizer...)
106+
return b
107+
}
108+
109+
// Build returns ZFSSnapshot API object
110+
func (b *Builder) Build() (*apis.ZFSSnapshot, error) {
111+
if len(b.errs) > 0 {
112+
return nil, errors.Errorf("%+v", b.errs)
113+
}
114+
115+
return b.snap.Object, nil
116+
}

0 commit comments

Comments
 (0)