Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add snapshot creation, deletion and restore from snapshot, Clone from PVC support for CephFS volumes. #394

Merged
merged 27 commits into from
Aug 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fe74c03
deploy: add csi-cephfsplugin provisioner deployment and role
humblec Aug 3, 2020
2d86457
helm: add deployment charts for cephfs csi snapshotter and roles
humblec Aug 3, 2020
6259a4b
e2e: add/modify deployment files for cephfs snapshot/clone tests
humblec Aug 3, 2020
340a15d
deploy: update external provisioner version to v1.6.0 from v1.4.0
humblec Aug 3, 2020
038071e
e2e: introduce writeDataInPod() to write data to an attached PVC
humblec Aug 3, 2020
e0def3c
e2e: introduce createCephFSSnapshotClass creation
humblec Aug 3, 2020
d243e97
e2e: add test cases for cephfs snapshot creation,deletion and restore
humblec Aug 3, 2020
b3d1d90
cephfs: make use of expand operation lock in ControllerExpandVolume
humblec Aug 3, 2020
e1ea1ac
cephfs: add snapshotlock and operationlock to controllerserver
humblec Aug 3, 2020
3460375
cephfs: change createBackingVolume to accomodate clone operations
humblec Aug 3, 2020
bf03614
cephfs: add checkContentSource() to validate the data source
humblec Aug 3, 2020
0268a8c
cephfs: add various error strings for command validation
humblec Aug 3, 2020
62fa5ef
cephfs: retrieve NewCSISnapshotJournal with namespace set
humblec Aug 3, 2020
ab71114
cephfs: introduce newSnapshotOptionsFromID to generate volOpt and sid
humblec Aug 3, 2020
b8fe1b0
cephfs: add snapshot create/delete capabilities in controllerserver
humblec Aug 4, 2020
7e84873
cephfs: use delete operation lock in delete volume
humblec Aug 4, 2020
7d59196
cephfs: change createvolume for snapshot/clone workflow
humblec Aug 4, 2020
13885cb
cephfs: add snapshot and clone helper functions
humblec Aug 7, 2020
9daa0ea
cephfs: Change checkVolExist for snapshot and clone workflow
humblec Aug 7, 2020
3bb069a
cephfs: validate create volume request
humblec Aug 4, 2020
c820f3a
cephfs: add snap reserve/unreserve and snap exist functionalities
humblec Aug 4, 2020
211ca6f
cephfs: remove inValidCommmand and errNotFoundString
humblec Aug 4, 2020
09b9db8
cephfs: add subvolume struct and getSubvolumeInfo calls
humblec Aug 4, 2020
cc2c616
cephfs: getVolumeRootPathCeph and purgeVolume use new error strings
humblec Aug 4, 2020
1fa7308
cephfs: add snapshot create and delete functionalilies
humblec Aug 4, 2020
9f65173
cephfs: introduce parsetime() to parse createdAt field in snap return
humblec Aug 7, 2020
36babba
e2e: remove volume populate test case and also change writeDataInPod()
humblec Aug 4, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion charts/ceph-csi-cephfs/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: v1
appVersion: canary
description: "Container Storage Interface (CSI) driver,
provisioner, and attacher for Ceph cephfs"
provisioner, snapshotter and attacher for Ceph cephfs"
name: ceph-csi-cephfs
version: 1.3.0-canary
keywords:
Expand Down
18 changes: 18 additions & 0 deletions charts/ceph-csi-cephfs/templates/provisioner-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ spec:
mountPath: /csi
resources:
{{ toYaml .Values.provisioner.provisioner.resources | indent 12 }}
- name: csi-snapshotter
image: {{ .Values.provisioner.snapshotter.image.repository }}:{{ .Values.provisioner.snapshotter.image.tag }}
imagePullPolicy: {{ .Values.provisioner.snapshotter.image.pullPolicy }}
args:
- "--csi-address=$(ADDRESS)"
- "--v=5"
- "--timeout={{ .Values.provisioner.timeout }}"
- "--leader-election=true"
env:
- name: ADDRESS
value: "unix:///csi/{{ .Values.provisionerSocketFile }}"
securityContext:
privileged: true
volumeMounts:
- name: socket-dir
mountPath: /csi
resources:
{{ toYaml .Values.provisioner.snapshotter.resources | indent 12 }}
{{- if .Values.provisioner.attacher.enabled }}
- name: csi-attacher
image: "{{ .Values.provisioner.attacher.image.repository }}:{{ .Values.provisioner.attacher.image.tag }}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ rules:
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshots"]
verbs: ["get", "list"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["create", "get", "list", "watch", "update", "delete"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents/status"]
verbs: ["update"]
{{- if .Values.provisioner.attacher.enabled }}
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
Expand Down
9 changes: 8 additions & 1 deletion charts/ceph-csi-cephfs/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ provisioner:
provisioner:
image:
repository: quay.io/k8scsi/csi-provisioner
tag: v1.4.0
tag: v1.6.0
pullPolicy: IfNotPresent
resources: {}

Expand All @@ -156,6 +156,13 @@ provisioner:
pullPolicy: IfNotPresent
resources: {}

snapshotter:
image:
repository: quay.io/k8scsi/csi-snapshotter
tag: v2.1.1
pullPolicy: IfNotPresent
resources: {}

nodeSelector: {}

tolerations: []
Expand Down
18 changes: 17 additions & 1 deletion deploy/cephfs/kubernetes/csi-cephfsplugin-provisioner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ spec:
serviceAccount: cephfs-csi-provisioner
containers:
- name: csi-provisioner
image: quay.io/k8scsi/csi-provisioner:v1.4.0
image: quay.io/k8scsi/csi-provisioner:v1.6.0
args:
- "--csi-address=$(ADDRESS)"
- "--v=5"
Expand Down Expand Up @@ -63,6 +63,22 @@ spec:
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-snapshotter
image: quay.io/k8scsi/csi-snapshotter:v2.1.1
args:
- "--csi-address=$(ADDRESS)"
- "--v=5"
- "--timeout=150s"
- "--leader-election=true"
env:
- name: ADDRESS
value: unix:///csi/csi-provisioner.sock
imagePullPolicy: "IfNotPresent"
securityContext:
privileged: true
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-cephfsplugin-attacher
image: quay.io/k8scsi/csi-attacher:v2.1.1
args:
Expand Down
13 changes: 12 additions & 1 deletion deploy/cephfs/kubernetes/csi-provisioner-rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ rules:
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshots"]
verbs: ["get", "list"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["create", "get", "list", "watch", "update", "delete"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch", "update", "patch"]
Expand All @@ -49,7 +58,9 @@ rules:
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get", "list", "watch"]

- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents/status"]
verbs: ["update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
238 changes: 238 additions & 0 deletions e2e/cephfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package e2e
import (
"fmt"
"strings"
"sync"

vs "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1"
. "github.com/onsi/ginkgo" // nolint
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -163,6 +165,11 @@ var _ = Describe("cephfs", func() {
It("Test cephfs CSI", func() {
pvcPath := cephfsExamplePath + "pvc.yaml"
appPath := cephfsExamplePath + "pod.yaml"
pvcClonePath := cephfsExamplePath + "pvc-restore.yaml"
pvcSmartClonePath := cephfsExamplePath + "pvc-clone.yaml"
appClonePath := cephfsExamplePath + "pod-restore.yaml"
appSmartClonePath := cephfsExamplePath + "pod-clone.yaml"
snapshotPath := cephfsExamplePath + "snapshot.yaml"

By("checking provisioner deployment is running")
var err error
Expand Down Expand Up @@ -362,6 +369,237 @@ var _ = Describe("cephfs", func() {
}
})

By("create a PVC clone and bind it to an app", func() {
v, err := f.ClientSet.Discovery().ServerVersion()
if err != nil {
e2elog.Logf("failed to get server version with error %v", err)
Fail(err.Error())
}
// snapshot beta is only supported from v1.17+
if v.Major > "1" || (v.Major == "1" && v.Minor >= "17") {
humblec marked this conversation as resolved.
Show resolved Hide resolved
var wg sync.WaitGroup
totalCount := 3
wg.Add(totalCount)
createCephFSSnapshotClass(f)
pvc, err := loadPVC(pvcPath)
if err != nil {
Fail(err.Error())
}

pvc.Namespace = f.UniqueName
e2elog.Logf("The PVC template %+v", pvc)
err = createPVCAndvalidatePV(f.ClientSet, pvc, deployTimeout)
if err != nil {
Fail(err.Error())
}
humblec marked this conversation as resolved.
Show resolved Hide resolved

app, err := loadApp(appPath)
if err != nil {
Fail(err.Error())
}

app.Namespace = f.UniqueName
app.Spec.Volumes[0].PersistentVolumeClaim.ClaimName = pvc.Name
wErr := writeDataInPod(app, f)
if wErr != nil {
Fail(wErr.Error())
}

snap := getSnapshot(snapshotPath)
snap.Namespace = f.UniqueName
snap.Spec.Source.PersistentVolumeClaimName = &pvc.Name
// create snapshot
for i := 0; i < totalCount; i++ {
go func(w *sync.WaitGroup, n int, s vs.VolumeSnapshot) {
s.Name = fmt.Sprintf("%s%d", f.UniqueName, n)
err = createSnapshot(&s, deployTimeout)
if err != nil {
e2elog.Logf("failed to create snapshot %v", err)
Fail(err.Error())
}
w.Done()
}(&wg, i, snap)
}
wg.Wait()

humblec marked this conversation as resolved.
Show resolved Hide resolved
pvcClone, err := loadPVC(pvcClonePath)
if err != nil {
Fail(err.Error())
}
appClone, err := loadApp(appClonePath)
if err != nil {
Fail(err.Error())
}
pvcClone.Namespace = f.UniqueName
appClone.Namespace = f.UniqueName
pvcClone.Spec.DataSource.Name = fmt.Sprintf("%s%d", f.UniqueName, 0)

// create multiple PVC from same snapshot
wg.Add(totalCount)
for i := 0; i < totalCount; i++ {

go func(w *sync.WaitGroup, n int, p v1.PersistentVolumeClaim, a v1.Pod) {
name := fmt.Sprintf("%s%d", f.UniqueName, n)
err = createPVCAndApp(name, f, &p, &a, deployTimeout)
if err != nil {
e2elog.Logf("failed to create pvc and app %v", err)
Fail(err.Error())
}
w.Done()
}(&wg, i, *pvcClone, *appClone)
}
wg.Wait()

wg.Add(totalCount)
// delete clone and app
for i := 0; i < totalCount; i++ {
go func(w *sync.WaitGroup, n int, p v1.PersistentVolumeClaim, a v1.Pod) {
name := fmt.Sprintf("%s%d", f.UniqueName, n)
p.Spec.DataSource.Name = name
err = deletePVCAndApp(name, f, &p, &a)
if err != nil {
e2elog.Logf("failed to delete pvc and app %v", err)
Fail(err.Error())
}
w.Done()
}(&wg, i, *pvcClone, *appClone)
}
wg.Wait()

// create clones from different snapshosts and bind it to an
// app
wg.Add(totalCount)
for i := 0; i < totalCount; i++ {
go func(w *sync.WaitGroup, n int, p v1.PersistentVolumeClaim, a v1.Pod) {
name := fmt.Sprintf("%s%d", f.UniqueName, n)
p.Spec.DataSource.Name = name
err = createPVCAndApp(name, f, &p, &a, deployTimeout)
if err != nil {
e2elog.Logf("failed to create pvc and app %v", err)
Fail(err.Error())
}
w.Done()
}(&wg, i, *pvcClone, *appClone)
}
wg.Wait()

wg.Add(totalCount)
// delete snapshot
for i := 0; i < totalCount; i++ {
go func(w *sync.WaitGroup, n int, s vs.VolumeSnapshot) {
s.Name = fmt.Sprintf("%s%d", f.UniqueName, n)
err = deleteSnapshot(&s, deployTimeout)
if err != nil {
e2elog.Logf("failed to delete snapshot %v", err)
Fail(err.Error())
}
w.Done()
}(&wg, i, snap)
}
wg.Wait()

wg.Add(totalCount)
// delete clone and app
for i := 0; i < totalCount; i++ {
go func(w *sync.WaitGroup, n int, p v1.PersistentVolumeClaim, a v1.Pod) {
name := fmt.Sprintf("%s%d", f.UniqueName, n)
p.Spec.DataSource.Name = name
err = deletePVCAndApp(name, f, &p, &a)
if err != nil {
e2elog.Logf("failed to delete pvc and app %v", err)
Fail(err.Error())
}
w.Done()
}(&wg, i, *pvcClone, *appClone)
}
wg.Wait()

humblec marked this conversation as resolved.
Show resolved Hide resolved
// delete parent pvc
err = deletePVCAndApp("", f, pvc, app)
if err != nil {
Fail(err.Error())
}
}
})

By("create a PVC-PVC clone and bind it to an app", func() {
v, err := f.ClientSet.Discovery().ServerVersion()
if err != nil {
e2elog.Logf("failed to get server version with error %v", err)
Fail(err.Error())
}
// pvc clone is only supported from v1.16+
if v.Major > "1" || (v.Major == "1" && v.Minor >= "16") {
humblec marked this conversation as resolved.
Show resolved Hide resolved
var wg sync.WaitGroup
totalCount := 3
pvc, err := loadPVC(pvcPath)
if err != nil {
Fail(err.Error())
}

pvc.Namespace = f.UniqueName
err = createPVCAndvalidatePV(f.ClientSet, pvc, deployTimeout)
if err != nil {
Fail(err.Error())
}
app, err := loadApp(appPath)
if err != nil {
Fail(err.Error())
}
app.Namespace = f.UniqueName
app.Spec.Volumes[0].PersistentVolumeClaim.ClaimName = pvc.Name
wErr := writeDataInPod(app, f)
if wErr != nil {
Fail(wErr.Error())
}

pvcClone, err := loadPVC(pvcSmartClonePath)
if err != nil {
Fail(err.Error())
}
pvcClone.Spec.DataSource.Name = pvc.Name
pvcClone.Namespace = f.UniqueName
appClone, err := loadApp(appSmartClonePath)
if err != nil {
Fail(err.Error())
}
appClone.Namespace = f.UniqueName
wg.Add(totalCount)
// create clone and bind it to an app
for i := 0; i < totalCount; i++ {
go func(w *sync.WaitGroup, n int, p v1.PersistentVolumeClaim, a v1.Pod) {
name := fmt.Sprintf("%s%d", f.UniqueName, n)
err = createPVCAndApp(name, f, &p, &a, deployTimeout)
if err != nil {
Fail(err.Error())
}
w.Done()
}(&wg, i, *pvcClone, *appClone)
}
wg.Wait()
// delete parent pvc
err = deletePVCAndApp("", f, pvc, app)
if err != nil {
Fail(err.Error())
}

wg.Add(totalCount)
// delete clone and app
for i := 0; i < totalCount; i++ {
go func(w *sync.WaitGroup, n int, p v1.PersistentVolumeClaim, a v1.Pod) {
name := fmt.Sprintf("%s%d", f.UniqueName, n)
p.Spec.DataSource.Name = name
err = deletePVCAndApp(name, f, &p, &a)
if err != nil {
Fail(err.Error())
}
w.Done()
}(&wg, i, *pvcClone, *appClone)
}
wg.Wait()
}
})

By("Create ROX PVC and Bind it to an app", func() {
// create pvc and bind it to an app
pvc, err := loadPVC(pvcPath)
Expand Down
Loading