Skip to content

Commit 577cf76

Browse files
discover existing on-disk snapshotsk
Signed-off-by: Ashish Amarnath <[email protected]>
1 parent ee6beea commit 577cf76

File tree

3 files changed

+99
-2
lines changed

3 files changed

+99
-2
lines changed

pkg/hostpath/controllerserver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,8 @@ func (cs *controllerServer) ListVolumes(ctx context.Context, req *csi.ListVolume
281281
}
282282

283283
// getSnapshotPath returns the full path to where the snapshot is stored
284-
func getSnapshotPath(snapshotId string) string {
285-
return filepath.Join(dataRoot, fmt.Sprintf("%s.snap", snapshotId))
284+
func getSnapshotPath(snapshotID string) string {
285+
return filepath.Join(dataRoot, fmt.Sprintf("%s%s", snapshotID, snapshotExt))
286286
}
287287

288288
// CreateSnapshot uses tar command to create snapshot for hostpath volume. The tar command can quickly create

pkg/hostpath/hostpath.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import (
2121
"fmt"
2222
"io"
2323
"os"
24+
"path"
2425
"path/filepath"
26+
"strings"
2527

2628
"github.com/golang/glog"
2729
"google.golang.org/grpc/codes"
@@ -87,6 +89,9 @@ const (
8789
// This can be ephemeral within the container or persisted if
8890
// backed by a Pod volume.
8991
dataRoot = "/csi-data-dir"
92+
93+
// Extension with which snapshot files will be saved.
94+
snapshotExt = ".snap"
9095
)
9196

9297
func init() {
@@ -127,12 +132,46 @@ func NewHostPathDriver(driverName, nodeID, endpoint string, ephemeral bool, maxV
127132
}, nil
128133
}
129134

135+
func getSnapshotID(p string) (bool, string) {
136+
dir, file := path.Split(p)
137+
glog.V(4).Infof("dir: %s, file: %s", dir, file)
138+
// Files with .snap extension are volumesnapshot files.
139+
// e.g. foo.snap, foo.bar.snap
140+
if filepath.Ext(file) == snapshotExt {
141+
snapshotID := strings.Split(file, snapshotExt)[0]
142+
return true, snapshotID
143+
}
144+
return false, ""
145+
}
146+
147+
func discoverExistingSnapshots() {
148+
glog.V(4).Infof("discovering existing snapshots in %s", dataRoot)
149+
err := filepath.Walk(dataRoot, func(p string, i os.FileInfo, e error) error {
150+
isSnapshot, snapshotID := getSnapshotID(p)
151+
if isSnapshot {
152+
glog.V(4).Infof("adding snapshot %s from file %s", snapshotID, p)
153+
hostPathVolumeSnapshots[snapshotID] = hostPathSnapshot{
154+
Id: snapshotID,
155+
Path: p,
156+
ReadyToUse: true,
157+
}
158+
}
159+
return nil
160+
})
161+
162+
if err != nil {
163+
glog.Errorf("failed to discover snapshots under %s", dataRoot)
164+
return
165+
}
166+
}
167+
130168
func (hp *hostPath) Run() {
131169
// Create GRPC servers
132170
hp.ids = NewIdentityServer(hp.name, hp.version)
133171
hp.ns = NewNodeServer(hp.nodeID, hp.ephemeral, hp.maxVolumesPerNode)
134172
hp.cs = NewControllerServer(hp.ephemeral, hp.nodeID)
135173

174+
discoverExistingSnapshots()
136175
s := NewNonBlockingGRPCServer()
137176
s.Start(hp.endpoint, hp.ids, hp.cs, hp.ns)
138177
s.Wait()

pkg/hostpath/hostpath_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package hostpath
18+
19+
import "testing"
20+
21+
func TestGetSnapshotID(t *testing.T) {
22+
testCases := []struct {
23+
inputPath string
24+
expectedIsSnapshot bool
25+
expectedSnapshotID string
26+
}{
27+
{
28+
inputPath: "foo.snap",
29+
expectedIsSnapshot: true,
30+
expectedSnapshotID: "foo",
31+
},
32+
{
33+
inputPath: "foo/bar/baz.snap",
34+
expectedIsSnapshot: true,
35+
expectedSnapshotID: "baz",
36+
},
37+
{
38+
inputPath: "foo/bar/baz.tar.gz",
39+
expectedIsSnapshot: false,
40+
expectedSnapshotID: "",
41+
},
42+
{
43+
inputPath: "foo/bar/baz.tar.snap",
44+
expectedIsSnapshot: true,
45+
expectedSnapshotID: "baz.tar",
46+
},
47+
}
48+
49+
for _, tc := range testCases {
50+
actualIsSnapshot, actualSnapshotID := getSnapshotID(tc.inputPath)
51+
if actualIsSnapshot != tc.expectedIsSnapshot {
52+
t.Fatalf("getSnapshotID failed, unexpected result for path %s, Want: %t, Got: %t", tc.inputPath, tc.expectedIsSnapshot, actualIsSnapshot)
53+
}
54+
if actualSnapshotID != tc.expectedSnapshotID {
55+
t.Fatalf("getSnapshotID failed, unexpected snapshotID for path %s, Want: %s; Got :%s", tc.inputPath, tc.expectedSnapshotID, actualSnapshotID)
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)