9
9
"github.com/appscode/go/types"
10
10
vs_cs "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned"
11
11
"github.com/spf13/cobra"
12
- corev1 "k8s.io/api/core/v1"
12
+ core "k8s.io/api/core/v1"
13
13
storage_api_v1 "k8s.io/api/storage/v1"
14
14
kerr "k8s.io/apimachinery/pkg/api/errors"
15
15
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -24,12 +24,6 @@ import (
24
24
"stash.appscode.dev/stash/pkg/util"
25
25
)
26
26
27
- type PVC struct {
28
- podOrdinal * int32
29
- pvcName string
30
- pvc corev1.PersistentVolumeClaim
31
- }
32
-
33
27
func NewCmdRestoreVolumeSnapshot () * cobra.Command {
34
28
var (
35
29
masterURL string
@@ -85,40 +79,56 @@ func (opt *VSoption) RestoreVolumeSnapshot() error {
85
79
return fmt .Errorf ("restoreSession Target is nil" )
86
80
}
87
81
88
- pvcData := [] PVC {}
82
+ pvcList := make ([]core. PersistentVolumeClaim , 0 )
89
83
90
84
if restoreSession .Spec .Target .Replicas == nil {
91
- for _ , vol := range restoreSession .Spec .Target .VolumeClaimTemplates {
92
- pvcData = append ( pvcData , PVC { pvcName : vol . Name , pvc : vol })
93
-
85
+ pvcs , err := opt . getPVCFromVolumeClaimTemplates ( - 1 , restoreSession .Spec .Target .VolumeClaimTemplates , startTime )
86
+ if err != nil {
87
+ return err
94
88
}
89
+ pvcList = append (pvcList , pvcs ... )
95
90
} else {
96
- for i := int32 (0 ); i < * restoreSession .Spec .Target .Replicas ; i ++ {
97
- for _ , vol := range restoreSession .Spec .Target .VolumeClaimTemplates {
98
- pvcData = append (pvcData , PVC {pvcName : vol .Name , podOrdinal : types .Int32P (i ), pvc : vol })
91
+ for ordinal := int32 (0 ); ordinal < * restoreSession .Spec .Target .Replicas ; ordinal ++ {
92
+ pvcs , err := opt .getPVCFromVolumeClaimTemplates (ordinal , restoreSession .Spec .Target .VolumeClaimTemplates , startTime )
93
+ if err != nil {
94
+ return err
99
95
}
96
+ pvcList = append (pvcList , pvcs ... )
100
97
}
101
-
102
98
}
103
99
104
- objectMeta := []metav1.ObjectMeta {}
105
100
pvcAllReadyExists := false
101
+ volumeSnapshotExists := false
106
102
107
- for _ , data := range pvcData {
108
- pvc := opt .getPVCDefinition (data )
103
+ for _ , pvc := range pvcList {
109
104
105
+ _ , err = opt .snapshotClient .VolumesnapshotV1alpha1 ().VolumeSnapshots (opt .namespace ).Get (pvc .Spec .DataSource .Name , metav1.GetOptions {})
106
+ if err != nil {
107
+ volumeSnapshotExists = true
108
+ // write failure event for not existing volumeSnapshot
109
+ restoreOutput := restic.RestoreOutput {
110
+ HostRestoreStats : v1beta1.HostRestoreStats {
111
+ Hostname : pvc .Name ,
112
+ Phase : v1beta1 .HostRestoreFailed ,
113
+ Error : fmt .Sprintf ("%s not exixts" , pvc .Spec .DataSource .Name ),
114
+ },
115
+ }
116
+ err := opt .updateRestoreSessionStatus (restoreOutput , startTime )
117
+ if err != nil {
118
+ return err
119
+ }
120
+ continue
121
+ }
110
122
_ , err = opt .kubeClient .CoreV1 ().PersistentVolumeClaims (opt .namespace ).Get (pvc .Name , metav1.GetOptions {})
111
123
if err != nil {
112
124
if kerr .IsNotFound (err ) {
113
- pvc , err := opt .kubeClient .CoreV1 ().PersistentVolumeClaims (opt .namespace ).Create (pvc )
125
+ _ , err := opt .kubeClient .CoreV1 ().PersistentVolumeClaims (opt .namespace ).Create (& pvc )
114
126
if err != nil {
115
127
return err
116
128
}
117
- objectMeta = append (objectMeta , pvc .ObjectMeta )
118
129
} else {
119
130
return err
120
131
}
121
-
122
132
} else {
123
133
// write failure event for existing PVC
124
134
pvcAllReadyExists = true
@@ -135,20 +145,21 @@ func (opt *VSoption) RestoreVolumeSnapshot() error {
135
145
}
136
146
}
137
147
}
138
- if pvcAllReadyExists {
148
+
149
+ if pvcAllReadyExists || volumeSnapshotExists {
139
150
return nil
140
151
}
141
152
142
- for i , data := range pvcData {
143
- storageClass , err := opt .kubeClient .StorageV1 ().StorageClasses ().Get (types .String (data . pvc .Spec .StorageClassName ), metav1.GetOptions {})
153
+ for _ , pvc := range pvcList {
154
+ storageClass , err := opt .kubeClient .StorageV1 ().StorageClasses ().Get (types .String (pvc .Spec .StorageClassName ), metav1.GetOptions {})
144
155
if err != nil {
145
156
return err
146
157
}
147
158
if * storageClass .VolumeBindingMode != storage_api_v1 .VolumeBindingImmediate {
148
159
// write failure event because of VolumeBindingMode is WaitForFirstConsumer
149
160
restoreOutput := restic.RestoreOutput {
150
161
HostRestoreStats : v1beta1.HostRestoreStats {
151
- Hostname : objectMeta [ i ] .Name ,
162
+ Hostname : pvc .Name ,
152
163
Phase : v1beta1 .HostRestoreUnknown ,
153
164
Error : fmt .Sprintf ("VolumeBindingMode is 'WaitForFirstConsumer'. Stash is unable to decide wheather the restore has succeeded or not as the PVC will not bind with respective PV until any workload mount it." ),
154
165
},
@@ -160,13 +171,13 @@ func (opt *VSoption) RestoreVolumeSnapshot() error {
160
171
continue
161
172
}
162
173
163
- err = util .WaitUntilPVCReady (opt .kubeClient , objectMeta [ i ] )
174
+ err = util .WaitUntilPVCReady (opt .kubeClient , pvc . ObjectMeta )
164
175
if err != nil {
165
176
return err
166
177
}
167
178
restoreOutput := restic.RestoreOutput {
168
179
HostRestoreStats : v1beta1.HostRestoreStats {
169
- Hostname : objectMeta [ i ] .Name ,
180
+ Hostname : pvc .Name ,
170
181
Phase : v1beta1 .HostRestoreSucceeded ,
171
182
},
172
183
}
@@ -178,20 +189,40 @@ func (opt *VSoption) RestoreVolumeSnapshot() error {
178
189
return nil
179
190
}
180
191
181
- func (opt * VSoption ) getPVCDefinition (data PVC ) * corev1.PersistentVolumeClaim {
182
- inputs := make (map [string ]string )
183
- if data .podOrdinal == nil {
184
- data .pvc .Name = data .pvcName
185
- } else {
186
- data .pvc .Name = fmt .Sprintf ("%v-%v" , data .pvcName , * data .podOrdinal )
187
- inputs ["POD_ORDINAL" ] = strconv .Itoa (int (* data .podOrdinal ))
192
+ func (opt * VSoption ) getPVCFromVolumeClaimTemplates (ordinal int32 , claimTemplates []core.PersistentVolumeClaim , startTime time.Time ) ([]core.PersistentVolumeClaim , error ) {
193
+ pvcList := make ([]core.PersistentVolumeClaim , 0 )
194
+
195
+ for _ , claim := range claimTemplates {
196
+ pvc , err := opt .getPVCDefinition (ordinal , claim )
197
+ if err != nil {
198
+ // write failure event
199
+ restoreOutput := restic.RestoreOutput {
200
+ HostRestoreStats : v1beta1.HostRestoreStats {
201
+ Hostname : pvc .Name ,
202
+ Phase : v1beta1 .HostRestoreFailed ,
203
+ Error : err .Error (),
204
+ },
205
+ }
206
+ err := opt .updateRestoreSessionStatus (restoreOutput , startTime )
207
+ return pvcList , err
208
+ }
209
+ pvc .Namespace = opt .namespace
210
+ pvcList = append (pvcList , pvc )
188
211
}
189
- inputs ["CLAIM_NAME" ] = data .pvcName
190
- err := resolve .ResolvePVCSpec (& data .pvc , inputs )
191
- if err != nil {
192
- return nil
212
+ return pvcList , nil
213
+ }
214
+
215
+ func (opt * VSoption ) getPVCDefinition (ordinal int32 , claim core.PersistentVolumeClaim ) (core.PersistentVolumeClaim , error ) {
216
+ inputs := make (map [string ]string )
217
+ inputs ["POD_ORDINAL" ] = strconv .Itoa (int (ordinal ))
218
+ inputs ["CLAIM_NAME" ] = claim .Name
219
+ if ordinal != int32 (- 1 ) {
220
+ claim .Name = fmt .Sprintf ("%v-%v" , claim .Name , ordinal )
193
221
}
194
- return & data .pvc
222
+ dataSource := claim .Spec .DataSource
223
+ err := resolve .ResolvePVCSpec (& claim , inputs )
224
+ claim .Spec .DataSource = dataSource
225
+ return claim , err
195
226
}
196
227
197
228
func (opt * VSoption ) updateRestoreSessionStatus (restoreOutput restic.RestoreOutput , startTime time.Time ) error {
0 commit comments