forked from libopenstorage/stork
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rule.go
137 lines (126 loc) · 4.21 KB
/
rule.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package snapshot
import (
crdv1 "github.com/kubernetes-incubator/external-storage/snapshot/pkg/apis/crd/v1"
"github.com/libopenstorage/stork/pkg/rule"
k8sextops "github.com/portworx/sched-ops/k8s/externalstorage"
storkops "github.com/portworx/sched-ops/k8s/stork"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
)
const (
storkRuleAnnotationPrefixDeprecated = "stork.rule"
storkRuleAnnotationPrefix = "stork.libopenstorage.org"
preSnapRuleAnnotationKey = storkRuleAnnotationPrefix + "/pre-snapshot-rule"
postSnapRuleAnnotationKey = storkRuleAnnotationPrefix + "/post-snapshot-rule"
preSnapRuleAnnotationKeyDeprecated = storkRuleAnnotationPrefixDeprecated + "/pre-snapshot"
postSnapRuleAnnotationKeyDeprecated = storkRuleAnnotationPrefixDeprecated + "/post-snapshot"
)
var ruleAnnotationKeyTypes = map[string]rule.Type{
preSnapRuleAnnotationKey: rule.PreExecRule,
postSnapRuleAnnotationKey: rule.PostExecRule,
preSnapRuleAnnotationKeyDeprecated: rule.PreExecRule,
postSnapRuleAnnotationKeyDeprecated: rule.PostExecRule,
}
// validateSnapRules validates the rules if they are present in the given snapshot's annotations
func validateSnapRules(snap *crdv1.VolumeSnapshot) error {
if snap.Metadata.Annotations != nil {
ruleAnnotations := []string{
preSnapRuleAnnotationKey,
postSnapRuleAnnotationKey,
preSnapRuleAnnotationKeyDeprecated,
preSnapRuleAnnotationKeyDeprecated,
}
for _, annotation := range ruleAnnotations {
ruleName, present := snap.Metadata.Annotations[annotation]
if present && len(ruleName) > 0 {
r, err := storkops.Instance().GetRule(ruleName, snap.Metadata.Namespace)
if err != nil {
return err
}
err = rule.ValidateRule(r, ruleAnnotationKeyTypes[annotation])
if err != nil {
return err
}
}
}
}
return nil
}
func setKind(snap *crdv1.VolumeSnapshot) {
snap.Kind = "VolumeSnapshot"
snap.APIVersion = crdv1.SchemeGroupVersion.String()
}
// ExecutePreSnapRule executes the pre snapshot rule. pvcs is a list of PVCs that are associated
// with the snapshot. It returns a channel which the caller can trigger to delete the termination of background commands
func ExecutePreSnapRule(snap *crdv1.VolumeSnapshot, pvcs []v1.PersistentVolumeClaim) (chan bool, error) {
setKind(snap)
if err := validateSnapRules(snap); err != nil {
return nil, err
}
if snap.Metadata.Annotations != nil {
ruleName, present := snap.Metadata.Annotations[preSnapRuleAnnotationKey]
if !present {
ruleName, present = snap.Metadata.Annotations[preSnapRuleAnnotationKeyDeprecated]
if !present {
return nil, nil
}
}
if ruleName == "" {
return nil, nil
}
r, err := storkops.Instance().GetRule(ruleName, snap.Metadata.Namespace)
if err != nil {
return nil, err
}
return rule.ExecuteRule(r, rule.PreExecRule, snap, snap.Metadata.Namespace)
}
return nil, nil
}
// ExecutePostSnapRule executes the post snapshot rule for the given snapshot. pvcs is a list of PVCs
// that are associated with the snapshot
func ExecutePostSnapRule(pvcs []v1.PersistentVolumeClaim, snap *crdv1.VolumeSnapshot) error {
setKind(snap)
if err := validateSnapRules(snap); err != nil {
return err
}
if snap.Metadata.Annotations != nil {
ruleName, present := snap.Metadata.Annotations[postSnapRuleAnnotationKey]
if !present {
ruleName, present = snap.Metadata.Annotations[postSnapRuleAnnotationKeyDeprecated]
if !present {
return nil
}
}
if ruleName == "" {
return nil
}
r, err := storkops.Instance().GetRule(ruleName, snap.Metadata.Namespace)
if err != nil {
return err
}
_, err = rule.ExecuteRule(r, rule.PostExecRule, snap, snap.Metadata.Namespace)
return err
}
return nil
}
// performRuleRecovery terminates potential background commands running pods for
// the given snapshot
func performRuleRecovery() error {
allSnaps, err := k8sextops.Instance().ListSnapshots(v1.NamespaceAll)
if err != nil {
logrus.Errorf("Failed to list all snapshots due to: %v. Will retry.", err)
return err
}
if allSnaps == nil {
return nil
}
var lastError error
for _, snap := range allSnaps.Items {
setKind(&snap)
err := rule.PerformRuleRecovery(&snap)
if err != nil {
lastError = err
}
}
return lastError
}