Skip to content

Commit ff87f17

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

File tree

3 files changed

+103
-2
lines changed

3 files changed

+103
-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: 38 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,45 @@ 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+
return true, strings.TrimSuffix(file, snapshotExt)
142+
}
143+
return false, ""
144+
}
145+
146+
func discoverExistingSnapshots() {
147+
glog.V(4).Infof("discovering existing snapshots in %s", dataRoot)
148+
err := filepath.Walk(dataRoot, func(p string, i os.FileInfo, e error) error {
149+
isSnapshot, snapshotID := getSnapshotID(p)
150+
if isSnapshot {
151+
glog.V(4).Infof("adding snapshot %s from file %s", snapshotID, p)
152+
hostPathVolumeSnapshots[snapshotID] = hostPathSnapshot{
153+
Id: snapshotID,
154+
Path: p,
155+
ReadyToUse: true,
156+
}
157+
}
158+
return nil
159+
})
160+
161+
if err != nil {
162+
glog.Errorf("failed to discover snapshots under %s", dataRoot)
163+
return
164+
}
165+
}
166+
130167
func (hp *hostPath) Run() {
131168
// Create GRPC servers
132169
hp.ids = NewIdentityServer(hp.name, hp.version)
133170
hp.ns = NewNodeServer(hp.nodeID, hp.ephemeral, hp.maxVolumesPerNode)
134171
hp.cs = NewControllerServer(hp.ephemeral, hp.nodeID)
135172

173+
discoverExistingSnapshots()
136174
s := NewNonBlockingGRPCServer()
137175
s.Start(hp.endpoint, hp.ids, hp.cs, hp.ns)
138176
s.Wait()

pkg/hostpath/hostpath_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
inputPath: "foo/bar/baz.tar.snap.snap",
49+
expectedIsSnapshot: true,
50+
expectedSnapshotID: "baz.tar.snap",
51+
},
52+
}
53+
54+
for _, tc := range testCases {
55+
actualIsSnapshot, actualSnapshotID := getSnapshotID(tc.inputPath)
56+
if actualIsSnapshot != tc.expectedIsSnapshot {
57+
t.Fatalf("getSnapshotID failed, unexpected result for path %s, Want: %t, Got: %t", tc.inputPath, tc.expectedIsSnapshot, actualIsSnapshot)
58+
}
59+
if actualSnapshotID != tc.expectedSnapshotID {
60+
t.Fatalf("getSnapshotID failed, unexpected snapshotID for path %s, Want: %s; Got :%s", tc.inputPath, tc.expectedSnapshotID, actualSnapshotID)
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)