Skip to content

Commit 7dc4613

Browse files
committed
Sorting functions for common use
Signed-off-by: Yuji Ito <llamerada.jp@gmail.com>
1 parent d709325 commit 7dc4613

3 files changed

Lines changed: 88 additions & 65 deletions

File tree

internal/controller/mantlebackup_controller.go

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,11 +1918,23 @@ func (r *MantleBackupReconciler) reconcileZeroOutJob(
19181918
return ctrl.Result{}, nil
19191919
}
19201920

1921-
if err := r.createOrUpdateZeroOutPV(ctx, backup, snapshotTarget.pv); err != nil {
1921+
if err := r.createOrUpdateStaticPV(
1922+
ctx,
1923+
snapshotTarget.pv,
1924+
snapshotTarget.pv.Spec.CSI.VolumeAttributes["imageName"],
1925+
snapshotTarget.pv.Spec.Capacity,
1926+
MakeZeroOutPVName(backup),
1927+
labelComponentZeroOutVolume,
1928+
); err != nil {
19221929
return ctrl.Result{}, err
19231930
}
19241931

1925-
if err := r.createOrUpdateZeroOutPVC(ctx, backup, snapshotTarget.pvc); err != nil {
1932+
if err := r.createOrUpdateStaticPVC(
1933+
ctx,
1934+
MakeZeroOutPVCName(backup),
1935+
MakeZeroOutPVName(backup),
1936+
snapshotTarget.pvc.Spec.Resources,
1937+
); err != nil {
19261938
return ctrl.Result{}, err
19271939
}
19281940

@@ -1940,24 +1952,26 @@ func (r *MantleBackupReconciler) reconcileZeroOutJob(
19401952
return requeueReconciliation(), nil
19411953
}
19421954

1943-
func (r *MantleBackupReconciler) createOrUpdateZeroOutPV(
1955+
func (r *MantleBackupReconciler) createOrUpdateStaticPV(
19441956
ctx context.Context,
1945-
backup *mantlev1.MantleBackup,
1946-
targetPV *corev1.PersistentVolume,
1957+
basePV *corev1.PersistentVolume,
1958+
volume string,
1959+
capacity corev1.ResourceList,
1960+
newPvName, componentName string,
19471961
) error {
19481962
var pv corev1.PersistentVolume
1949-
pv.SetName(MakeZeroOutPVName(backup))
1963+
pv.SetName(newPvName)
19501964
_, err := ctrl.CreateOrUpdate(ctx, r.Client, &pv, func() error {
19511965
labels := pv.GetLabels()
19521966
if labels == nil {
19531967
labels = map[string]string{}
19541968
}
19551969
labels["app.kubernetes.io/name"] = labelAppNameValue
1956-
labels["app.kubernetes.io/component"] = labelComponentZeroOutVolume
1970+
labels["app.kubernetes.io/component"] = componentName
19571971
pv.SetLabels(labels)
19581972

19591973
pv.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}
1960-
pv.Spec.Capacity = targetPV.Spec.Capacity
1974+
pv.Spec.Capacity = capacity
19611975
pv.Spec.PersistentVolumeReclaimPolicy = corev1.PersistentVolumeReclaimRetain
19621976
pv.Spec.StorageClassName = ""
19631977

@@ -1967,32 +1981,32 @@ func (r *MantleBackupReconciler) createOrUpdateZeroOutPV(
19671981
if pv.Spec.CSI == nil {
19681982
pv.Spec.CSI = &corev1.CSIPersistentVolumeSource{}
19691983
}
1970-
pv.Spec.CSI.Driver = targetPV.Spec.CSI.Driver
1971-
pv.Spec.CSI.ControllerExpandSecretRef = targetPV.Spec.CSI.ControllerExpandSecretRef
1972-
pv.Spec.CSI.NodeStageSecretRef = targetPV.Spec.CSI.NodeStageSecretRef
1973-
pv.Spec.CSI.VolumeHandle = targetPV.Spec.CSI.VolumeAttributes["imageName"]
1984+
pv.Spec.CSI.Driver = basePV.Spec.CSI.Driver
1985+
pv.Spec.CSI.ControllerExpandSecretRef = basePV.Spec.CSI.ControllerExpandSecretRef
1986+
pv.Spec.CSI.NodeStageSecretRef = basePV.Spec.CSI.NodeStageSecretRef
1987+
pv.Spec.CSI.VolumeHandle = volume
19741988

19751989
if pv.Spec.CSI.VolumeAttributes == nil {
19761990
pv.Spec.CSI.VolumeAttributes = map[string]string{}
19771991
}
1978-
pv.Spec.CSI.VolumeAttributes["clusterID"] = targetPV.Spec.CSI.VolumeAttributes["clusterID"]
1979-
pv.Spec.CSI.VolumeAttributes["imageFeatures"] = targetPV.Spec.CSI.VolumeAttributes["imageFeatures"]
1980-
pv.Spec.CSI.VolumeAttributes["imageFormat"] = targetPV.Spec.CSI.VolumeAttributes["imageFormat"]
1981-
pv.Spec.CSI.VolumeAttributes["pool"] = targetPV.Spec.CSI.VolumeAttributes["pool"]
1992+
pv.Spec.CSI.VolumeAttributes["clusterID"] = basePV.Spec.CSI.VolumeAttributes["clusterID"]
1993+
pv.Spec.CSI.VolumeAttributes["imageFeatures"] = basePV.Spec.CSI.VolumeAttributes["imageFeatures"]
1994+
pv.Spec.CSI.VolumeAttributes["imageFormat"] = basePV.Spec.CSI.VolumeAttributes["imageFormat"]
1995+
pv.Spec.CSI.VolumeAttributes["pool"] = basePV.Spec.CSI.VolumeAttributes["pool"]
19821996
pv.Spec.CSI.VolumeAttributes["staticVolume"] = "true"
19831997

19841998
return nil
19851999
})
19862000
return err
19872001
}
19882002

1989-
func (r *MantleBackupReconciler) createOrUpdateZeroOutPVC(
2003+
func (r *MantleBackupReconciler) createOrUpdateStaticPVC(
19902004
ctx context.Context,
1991-
backup *mantlev1.MantleBackup,
1992-
targetPVC *corev1.PersistentVolumeClaim,
2005+
pvcName, pvName string,
2006+
resources corev1.VolumeResourceRequirements,
19932007
) error {
19942008
var pvc corev1.PersistentVolumeClaim
1995-
pvc.SetName(MakeZeroOutPVCName(backup))
2009+
pvc.SetName(pvcName)
19962010
pvc.SetNamespace(r.managedCephClusterID)
19972011
_, err := ctrl.CreateOrUpdate(ctx, r.Client, &pvc, func() error {
19982012
labels := pvc.GetLabels()
@@ -2006,8 +2020,8 @@ func (r *MantleBackupReconciler) createOrUpdateZeroOutPVC(
20062020
storageClassName := ""
20072021
pvc.Spec.StorageClassName = &storageClassName
20082022
pvc.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}
2009-
pvc.Spec.Resources = targetPVC.Spec.Resources
2010-
pvc.Spec.VolumeName = MakeZeroOutPVName(backup)
2023+
pvc.Spec.Resources = resources
2024+
pvc.Spec.VolumeName = pvName
20112025

20122026
volumeMode := corev1.PersistentVolumeBlock
20132027
pvc.Spec.VolumeMode = &volumeMode

internal/controller/mantlerestore_controller.go

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7-
"slices"
87

98
mantlev1 "github.com/cybozu-go/mantle/api/v1"
109
"github.com/cybozu-go/mantle/internal/ceph"
@@ -183,54 +182,13 @@ func (r *MantleRestoreReconciler) restoringPVName(restore *mantlev1.MantleRestor
183182
}
184183

185184
func (r *MantleRestoreReconciler) cloneImageFromBackup(ctx context.Context, restore *mantlev1.MantleRestore, backup *mantlev1.MantleBackup) error {
186-
logger := log.FromContext(ctx)
187185
pv := corev1.PersistentVolume{}
188186
err := json.Unmarshal([]byte(backup.Status.PVManifest), &pv)
189187
if err != nil {
190188
return fmt.Errorf("failed to unmarshal PV manifest: %w", err)
191189
}
192190

193-
bkImage := pv.Spec.CSI.VolumeAttributes["imageName"]
194-
if bkImage == "" {
195-
return fmt.Errorf("imageName not found in PV manifest")
196-
}
197-
pool := pv.Spec.CSI.VolumeAttributes["pool"]
198-
if pool == "" {
199-
return fmt.Errorf("pool not found in PV manifest")
200-
}
201-
202-
images, err := r.ceph.RBDLs(pool)
203-
if err != nil {
204-
return fmt.Errorf("failed to list RBD images: %w", err)
205-
}
206-
207-
// check if the image already exists
208-
if slices.Contains(images, r.restoringRBDImageName(restore)) {
209-
info, err := r.ceph.RBDInfo(pool, r.restoringRBDImageName(restore))
210-
if err != nil {
211-
return fmt.Errorf("failed to get RBD info: %w", err)
212-
}
213-
if info.Parent == nil {
214-
return fmt.Errorf("failed to get RBD info: parent field is empty")
215-
}
216-
217-
if info.Parent.Pool == pool && info.Parent.Image == bkImage && info.Parent.Snapshot == backup.Name {
218-
logger.Info("image already exists", "image", r.restoringRBDImageName(restore))
219-
return nil
220-
} else {
221-
return fmt.Errorf("image already exists but not a clone of the backup: %s", r.restoringRBDImageName(restore))
222-
}
223-
}
224-
225-
features := pv.Spec.CSI.VolumeAttributes["imageFeatures"]
226-
if features == "" {
227-
features = "deep-flatten"
228-
} else {
229-
features += ",deep-flatten"
230-
}
231-
232-
// create a clone image from the backup
233-
return r.ceph.RBDClone(pool, bkImage, backup.Name, r.restoringRBDImageName(restore), features)
191+
return createCloneByPV(ctx, r.ceph, &pv, backup.Name, r.restoringRBDImageName(restore))
234192
}
235193

236194
func (r *MantleRestoreReconciler) createOrUpdateRestoringPV(ctx context.Context, restore *mantlev1.MantleRestore, backup *mantlev1.MantleBackup) error {

internal/controller/util.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import (
55
"errors"
66
"fmt"
77
"os"
8+
"slices"
89
"strings"
910
"time"
1011

12+
"github.com/cybozu-go/mantle/internal/ceph"
1113
batchv1 "k8s.io/api/batch/v1"
1214
corev1 "k8s.io/api/core/v1"
1315
storagev1 "k8s.io/api/storage/v1"
@@ -19,6 +21,55 @@ import (
1921

2022
var errEmptyClusterID error = errors.New("cluster ID is empty")
2123

24+
// createCloneByPV creates a clone RBD image from the snapshot of the volume bound to PV.
25+
// If the clone image already exists and is a clone of the snapshot, it does nothing.
26+
func createCloneByPV(ctx context.Context, cephCmd ceph.CephCmd, pv *corev1.PersistentVolume, snapshotName, cloneName string) error {
27+
logger := log.FromContext(ctx)
28+
29+
bkImage := pv.Spec.CSI.VolumeAttributes["imageName"]
30+
if bkImage == "" {
31+
return fmt.Errorf("imageName not found in PV manifest")
32+
}
33+
pool := pv.Spec.CSI.VolumeAttributes["pool"]
34+
if pool == "" {
35+
return fmt.Errorf("pool not found in PV manifest")
36+
}
37+
38+
images, err := cephCmd.RBDLs(pool)
39+
if err != nil {
40+
return fmt.Errorf("failed to list RBD images: %w", err)
41+
}
42+
43+
// check if the image already exists
44+
if slices.Contains(images, cloneName) {
45+
info, err := cephCmd.RBDInfo(pool, cloneName)
46+
if err != nil {
47+
return fmt.Errorf("failed to get RBD info: %w", err)
48+
}
49+
if info.Parent == nil {
50+
return fmt.Errorf("failed to get RBD info: parent field is empty")
51+
}
52+
53+
if info.Parent.Pool == pool && info.Parent.Image == bkImage && info.Parent.Snapshot == snapshotName {
54+
logger.Info("image already exists", "image", cloneName)
55+
return nil
56+
} else {
57+
// If the clone image already exists but is not a clone of the snapshot, it returns an error.
58+
return fmt.Errorf("image already exists but not a clone of the backup: %s", cloneName)
59+
}
60+
}
61+
62+
features := pv.Spec.CSI.VolumeAttributes["imageFeatures"]
63+
if features == "" {
64+
features = "deep-flatten"
65+
} else {
66+
features += ",deep-flatten"
67+
}
68+
69+
// create a clone image from the backup
70+
return cephCmd.RBDClone(pool, bkImage, snapshotName, cloneName, features)
71+
}
72+
2273
func getCephClusterIDFromSCName(ctx context.Context, k8sClient client.Client, storageClassName string) (string, error) {
2374
var storageClass storagev1.StorageClass
2475
err := k8sClient.Get(ctx, types.NamespacedName{Name: storageClassName}, &storageClass)

0 commit comments

Comments
 (0)