forked from kubernetes-retired/external-storage
/
reconciler.go
130 lines (112 loc) · 4.8 KB
/
reconciler.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
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package reconciler implements interfaces that attempt to reconcile the
// desired state of the with the actual state of the world by triggering
// actions.
package reconciler
import (
"time"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/util/wait"
"github.com/kubernetes-incubator/external-storage/snapshot/pkg/controller/cache"
"github.com/kubernetes-incubator/external-storage/snapshot/pkg/controller/snapshotter"
)
// Reconciler runs a periodic loop to reconcile the desired state of the with
// the actual state of the world by triggering the volume snapshot operations.
type Reconciler interface {
// Starts running the reconciliation loop which executes periodically, creates
// and deletes VolumeSnapshotData for the user created and deleted VolumeSnapshot
// objects and triggers the actual snapshot creation in the volume backends.
Run(stopCh <-chan struct{})
}
type reconciler struct {
loopPeriod time.Duration
syncDuration time.Duration
desiredStateOfWorld cache.DesiredStateOfWorld
actualStateOfWorld cache.ActualStateOfWorld
snapshotter snapshotter.VolumeSnapshotter
timeOfLastSync time.Time
disableReconciliationSync bool
}
// NewReconciler is the constructor of Reconciler
func NewReconciler(
loopPeriod time.Duration,
syncDuration time.Duration,
disableReconciliationSync bool,
desiredStateOfWorld cache.DesiredStateOfWorld,
actualStateOfWorld cache.ActualStateOfWorld,
snapshotter snapshotter.VolumeSnapshotter) Reconciler {
return &reconciler{
loopPeriod: loopPeriod,
syncDuration: syncDuration,
disableReconciliationSync: disableReconciliationSync,
desiredStateOfWorld: desiredStateOfWorld,
actualStateOfWorld: actualStateOfWorld,
snapshotter: snapshotter,
timeOfLastSync: time.Now(),
}
}
func (rc *reconciler) Run(stopCh <-chan struct{}) {
wait.Until(rc.reconciliationLoopFunc(), rc.loopPeriod, stopCh)
}
// reconciliationLoopFunc this can be disabled via cli option disableReconciliation.
// It periodically checks whether the VolumeSnapshots have corresponding SnapshotData
// and creates or deletes the snapshots when required.
func (rc *reconciler) reconciliationLoopFunc() func() {
return func() {
rc.reconcile()
if rc.disableReconciliationSync {
glog.V(5).Info("Skipping reconciling volume snapshots it is disabled via the command line.")
} else if rc.syncDuration < time.Second {
glog.V(5).Info("Skipping reconciling volume snapshots since it is set to less than one second via the command line.")
} else if time.Since(rc.timeOfLastSync) > rc.syncDuration {
glog.V(5).Info("Starting reconciling volume snapshots")
rc.sync()
}
}
}
func (rc *reconciler) sync() {
defer rc.updateSyncTime()
rc.syncStates()
}
func (rc *reconciler) updateSyncTime() {
rc.timeOfLastSync = time.Now()
}
func (rc *reconciler) syncStates() {
// volumesPerNode := rc.actualStateOfWorld.GetAttachedVolumesPerNode()
// rc.attacherDetacher.VerifyVolumesAreAttached(volumesPerNode, rc.actualStateOfWorld)
}
func (rc *reconciler) reconcile() {
//glog.Infof("Volume snapshots are being reconciled")
// Ensure the snapshots that should be deleted are deleted
for name, snapshot := range rc.actualStateOfWorld.GetSnapshots() {
if !rc.desiredStateOfWorld.SnapshotExists(name) {
// Call snapshotter to start deleting the snapshot: it should
// use the volume plugin to actually remove the on-disk snapshot.
// It's likely that the operation exists already: it should be fired by the controller right
// after the event has arrived.
rc.snapshotter.DeleteVolumeSnapshot(snapshot)
}
}
// Ensure the snapshots that should be created are created
for name, snapshot := range rc.desiredStateOfWorld.GetSnapshots() {
if !rc.actualStateOfWorld.SnapshotExists(name) {
// Call snapshotter to start creating the snapshot: it should use the volume
// plugin to create the on-disk snapshot, create the SnapshotData object for it
// and update and put the Snapshot object to the actualStateOfWorld once the operation finishes.
// It's likely that the operation exists already: it should be fired by the controller right
// after the event has arrived.
rc.snapshotter.CreateVolumeSnapshot(snapshot)
}
}
}