Skip to content

Commit 2e5a26d

Browse files
committed
implement rbd lock related commands
Signed-off-by: Yuji Ito <[email protected]>
1 parent 4c48c13 commit 2e5a26d

File tree

9 files changed

+283
-39
lines changed

9 files changed

+283
-39
lines changed

Makefile

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,12 @@ clean-test:
9292
rm -f $(TEST_XFS_IMG); \
9393
fi
9494

95+
.PHONY: mock
96+
mock: mockgen
97+
$(MOCKGEN) -source=internal/infrastructure/ceph/command.go -destination=internal/infrastructure/ceph/command_mock.go -package=ceph
98+
9599
.PHONY: test
96-
test: manifests generate fmt vet envtest ## Run tests.
100+
test: manifests generate fmt vet envtest mock ## Run tests.
97101
$(MAKE) prepare-test
98102
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" \
99103
TEST_BLOCK_DEV=$(TEST_BLOCK_DEV) \
@@ -193,11 +197,12 @@ $(LOCALBIN):
193197
mkdir -p $(LOCALBIN)
194198

195199
## Tool Binaries
196-
KUBECTL ?= kubectl
197-
KUSTOMIZE ?= $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION)
198-
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION)
199-
ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)
200+
KUBECTL = kubectl
201+
KUSTOMIZE = $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION)
202+
CONTROLLER_GEN = $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION)
203+
ENVTEST = $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)
200204
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION)
205+
MOCKGEN = $(LOCALBIN)/mockgen-$(MOCKGEN_VERSION)
201206

202207
.PHONY: kustomize
203208
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
@@ -217,7 +222,12 @@ $(ENVTEST): $(LOCALBIN)
217222
.PHONY: golangci-lint
218223
golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
219224
$(GOLANGCI_LINT): $(LOCALBIN)
220-
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,${GOLANGCI_LINT_VERSION})
225+
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))
226+
227+
.PHONY: mockgen
228+
mockgen: $(MOCKGEN) ## Download mockgen locally if necessary.
229+
$(MOCKGEN): $(LOCALBIN)
230+
$(call go-install-tool,$(MOCKGEN),go.uber.org/mock/mockgen,$(MOCKGEN_VERSION))
221231

222232
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
223233
# $1 - target path with name of binary (ideally with version)

go.mod

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ module github.com/cybozu-go/fin
33
go 1.24
44

55
require (
6+
github.com/cespare/xxhash/v2 v2.3.0
67
github.com/google/uuid v1.6.0
78
github.com/mattn/go-sqlite3 v1.14.28
89
github.com/onsi/ginkgo/v2 v2.23.4
910
github.com/onsi/gomega v1.37.0
1011
github.com/prometheus/client_golang v1.22.0
1112
github.com/spf13/cobra v1.9.1
1213
github.com/stretchr/testify v1.10.0
13-
golang.org/x/sys v0.32.0
14+
go.uber.org/mock v0.6.0
15+
golang.org/x/sys v0.35.0
1416
k8s.io/api v0.32.7
1517
k8s.io/apimachinery v0.32.7
1618
k8s.io/client-go v0.32.7
@@ -22,7 +24,6 @@ require (
2224

2325
require (
2426
github.com/beorn7/perks v1.0.1 // indirect
25-
github.com/cespare/xxhash/v2 v2.3.0 // indirect
2627
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
2728
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
2829
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
@@ -59,13 +60,13 @@ require (
5960
go.uber.org/multierr v1.11.0 // indirect
6061
go.uber.org/zap v1.27.0 // indirect
6162
go.yaml.in/yaml/v2 v2.4.2 // indirect
62-
golang.org/x/net v0.38.0 // indirect
63+
golang.org/x/net v0.43.0 // indirect
6364
golang.org/x/oauth2 v0.27.0 // indirect
64-
golang.org/x/sync v0.12.0 // indirect
65-
golang.org/x/term v0.30.0 // indirect
66-
golang.org/x/text v0.23.0 // indirect
65+
golang.org/x/sync v0.16.0 // indirect
66+
golang.org/x/term v0.34.0 // indirect
67+
golang.org/x/text v0.28.0 // indirect
6768
golang.org/x/time v0.9.0 // indirect
68-
golang.org/x/tools v0.31.0 // indirect
69+
golang.org/x/tools v0.36.0 // indirect
6970
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
7071
google.golang.org/protobuf v1.36.5 // indirect
7172
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect

go.sum

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
123123
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
124124
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
125125
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
126+
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
127+
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
126128
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
127129
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
128130
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
@@ -140,34 +142,34 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
140142
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
141143
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
142144
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
143-
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
144-
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
145+
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
146+
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
145147
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
146148
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
147149
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
148150
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
149151
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
150-
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
151-
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
152+
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
153+
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
152154
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
153155
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
154156
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
155-
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
156-
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
157-
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
158-
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
157+
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
158+
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
159+
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
160+
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
159161
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
160162
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
161-
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
162-
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
163+
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
164+
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
163165
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
164166
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
165167
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
166168
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
167169
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
168170
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
169-
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
170-
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
171+
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
172+
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
171173
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
172174
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
173175
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

internal/infrastructure/ceph/command.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,19 @@ import (
55
"os/exec"
66
)
77

8-
func execute(command string, args ...string) ([]byte, []byte, error) {
9-
cmd := exec.Command(command, args...)
8+
type Command interface {
9+
execute(command ...string) ([]byte, []byte, error)
10+
}
11+
12+
type commandImpl struct {
13+
}
14+
15+
func newCommand() Command {
16+
return &commandImpl{}
17+
}
18+
19+
func (c *commandImpl) execute(command ...string) ([]byte, []byte, error) {
20+
cmd := exec.Command(command[0], command[1:]...)
1021

1122
var stdoutBuf, stderrBuf bytes.Buffer
1223
cmd.Stdout = &stdoutBuf
@@ -15,7 +26,3 @@ func execute(command string, args ...string) ([]byte, []byte, error) {
1526
err := cmd.Run()
1627
return stdoutBuf.Bytes(), stderrBuf.Bytes(), err
1728
}
18-
19-
func runRBDCommand(args ...string) ([]byte, []byte, error) {
20-
return execute("rbd", args...)
21-
}

internal/infrastructure/ceph/command_mock.go

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/infrastructure/ceph/rbd.go

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,20 @@ var (
3131
)
3232

3333
type RBDRepository struct {
34+
command Command
3435
}
3536

3637
var _ model.RBDRepository = &RBDRepository{}
38+
var _ model.RBDImageLocker = &RBDRepository{}
3739

38-
func NewRBDRepository() *RBDRepository {
39-
return &RBDRepository{}
40+
func NewRBDRepository() model.RBDRepository {
41+
return &RBDRepository{
42+
command: newCommand(),
43+
}
4044
}
4145

4246
func (r *RBDRepository) CreateSnapshot(poolName, imageName, snapName string) error {
43-
args := []string{"snap", "create", fmt.Sprintf("%s/%s@%s", poolName, imageName, snapName)}
44-
_, stderr, err := runRBDCommand(args...)
47+
_, stderr, err := r.command.execute("rbd", "snap", "create", fmt.Sprintf("%s/%s@%s", poolName, imageName, snapName))
4548
if err != nil {
4649
return fmt.Errorf("failed to create RBD snapshot: %w, stderr: %s", err, string(stderr))
4750
}
@@ -50,8 +53,7 @@ func (r *RBDRepository) CreateSnapshot(poolName, imageName, snapName string) err
5053
}
5154

5255
func (r *RBDRepository) RemoveSnapshot(poolName, imageName, snapName string) error {
53-
args := []string{"snap", "rm", "--force", fmt.Sprintf("%s/%s@%s", poolName, imageName, snapName)}
54-
_, stderr, err := runRBDCommand(args...)
56+
_, stderr, err := r.command.execute("rbd", "snap", "rm", "--force", fmt.Sprintf("%s/%s@%s", poolName, imageName, snapName))
5557
if err != nil {
5658
return fmt.Errorf("failed to delete RBD snapshot: %w, stderr: %s", err, string(stderr))
5759
}
@@ -60,8 +62,7 @@ func (r *RBDRepository) RemoveSnapshot(poolName, imageName, snapName string) err
6062
}
6163

6264
func (r *RBDRepository) ListSnapshots(poolName, imageName string) ([]*model.RBDSnapshot, error) {
63-
args := []string{"snap", "ls", "--format", "json", fmt.Sprintf("%s/%s", poolName, imageName)}
64-
stdout, stderr, err := runRBDCommand(args...)
65+
stdout, stderr, err := r.command.execute("rbd", "snap", "ls", "--format", "json", fmt.Sprintf("%s/%s", poolName, imageName))
6566
if err != nil {
6667
return nil, fmt.Errorf("failed to list RBD snapshots: %w, stderr: %s", err, string(stderr))
6768
}
@@ -75,6 +76,39 @@ func (r *RBDRepository) ListSnapshots(poolName, imageName string) ([]*model.RBDS
7576
return snapshots, nil
7677
}
7778

79+
func (r *RBDRepository) LockAdd(pool, image, lockID string) error {
80+
_, stderr, err := r.command.execute("rbd", "-p", pool, "lock", "add", image, lockID)
81+
if err != nil {
82+
return fmt.Errorf("failed to add lock to RBD image: %w, stderr: %s", err, string(stderr))
83+
}
84+
85+
return nil
86+
}
87+
88+
func (r *RBDRepository) LockRm(pool, image string, lock *model.RBDLock) error {
89+
_, stderr, err := r.command.execute("rbd", "-p", pool, "lock", "rm", image, lock.LockID, lock.Locker)
90+
if err != nil {
91+
return fmt.Errorf("failed to remove lock from RBD image: %w, stderr: %s", err, string(stderr))
92+
}
93+
94+
return nil
95+
}
96+
97+
func (r *RBDRepository) LockLs(pool, image string) ([]*model.RBDLock, error) {
98+
stdout, stderr, err := r.command.execute("rbd", "-p", pool, "--format", "json", "lock", "ls", image)
99+
if err != nil {
100+
return nil, fmt.Errorf("failed to list locks on RBD image: %w, stderr: %s", err, string(stderr))
101+
}
102+
103+
var locks []*model.RBDLock
104+
err = json.Unmarshal(stdout, &locks)
105+
if err != nil {
106+
return nil, fmt.Errorf("failed to unmarshal RBD locks: %w", err)
107+
}
108+
109+
return locks, nil
110+
}
111+
78112
func (r *RBDRepository) ExportDiff(input *model.ExportDiffInput) (io.ReadCloser, error) {
79113
args := []string{
80114
"export-diff",

0 commit comments

Comments
 (0)