Skip to content

Commit f15d26f

Browse files
committed
Improve Plugin
1 parent 757eb58 commit f15d26f

File tree

11 files changed

+390
-44
lines changed

11 files changed

+390
-44
lines changed

.gitignore

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
1-
*~
1+
# Binaries for programs and plugins
2+
*.exe
3+
*.exe~
4+
*.dll
5+
*.so
6+
*.dylib
27
docker-volume-moosefs
3-
*.rpm
8+
9+
# Test binary, built with `go test -c`
10+
*.test
11+
12+
# Output of the go coverage tool
13+
*.out
14+
15+
# Dependency directories (remove the comment below to include it)
16+
vendor/
17+
18+
# Plugin build artifacts
19+
plugin/rootfs/
420
*.deb
5-
obj
6-
.idea
7-
vendor/*/
21+
*.rpm
22+
obj/
23+
24+
# IDE specific files
25+
.idea/
26+
.vscode/
27+
*.swp
28+
*.swo
29+
30+
# OS generated files
31+
.DS_Store
32+
.DS_Store?
33+
._*
34+
.Spotlight-V100
35+
.Trashes
36+
ehthumbs.db
37+
Thumbs.db
38+

Makefile

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,19 @@ deb: compile
4444
clean:
4545
rm -fr obj *.deb *.rpm docker-volume-moosefs
4646

47-
.PHONY: clean rpm-deps deb-deps fmt deps compile
47+
plugin: compile
48+
mkdir -p plugin/rootfs
49+
docker build -t moosefs-plugin-build -f plugin/Dockerfile .
50+
docker create --name tmp moosefs-plugin-build
51+
docker export tmp | tar -x -C plugin/rootfs
52+
docker rm -vf tmp
53+
docker rmi moosefs-plugin-build
54+
55+
plugin-enable:
56+
docker plugin create moosefs/docker-volume-moosefs:$(VERSION) plugin
57+
docker plugin enable moosefs/docker-volume-moosefs:$(VERSION)
58+
59+
plugin-push: plugin plugin-enable
60+
docker plugin push moosefs/docker-volume-moosefs:$(VERSION)
61+
62+
.PHONY: clean rpm-deps deb-deps fmt deps compile plugin plugin-enable plugin-push

build.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env bash
2+
3+
# Colors for output
4+
RED='\033[0;31m'
5+
GREEN='\033[0;32m'
6+
YELLOW='\033[1;33m'
7+
NC='\033[0m'
8+
9+
# Version
10+
VERSION="0.2.0"
11+
PLUGIN_NAME="moosefs/docker-volume-moosefs:${VERSION}"
12+
13+
# Function to print step
14+
print_step() {
15+
echo -e "${YELLOW}[*] $1${NC}"
16+
}
17+
18+
# Function to print success
19+
print_success() {
20+
echo -e "${GREEN}[+] $1${NC}"
21+
}
22+
23+
# Function to print error and exit
24+
print_error() {
25+
echo -e "${RED}[-] $1${NC}"
26+
exit 1
27+
}
28+
29+
# Clean previous build
30+
print_step "Cleaning previous build..."
31+
rm -rf plugin/rootfs *.deb *.rpm docker-volume-moosefs obj
32+
print_success "Clean completed"
33+
34+
# Clean existing plugin if it exists
35+
print_step "Checking for existing plugin..."
36+
if docker plugin inspect ${PLUGIN_NAME} >/dev/null 2>&1; then
37+
print_step "Disabling existing plugin..."
38+
docker plugin disable ${PLUGIN_NAME} >/dev/null 2>&1
39+
print_step "Removing existing plugin..."
40+
docker plugin rm ${PLUGIN_NAME} >/dev/null 2>&1
41+
fi
42+
print_success "Plugin cleanup completed"
43+
44+
# Build Go binary
45+
print_step "Building Go binary..."
46+
go build || print_error "Go build failed"
47+
print_success "Binary built successfully"
48+
49+
# Create plugin
50+
print_step "Creating Docker plugin..."
51+
mkdir -p plugin/rootfs || print_error "Failed to create plugin directory"
52+
53+
# Build Docker image
54+
print_step "Building Docker image..."
55+
docker build -t moosefs-plugin-build -f plugin/Dockerfile . || print_error "Docker build failed"
56+
57+
print_step "Creating temporary container..."
58+
docker create --name tmp moosefs-plugin-build || print_error "Failed to create temporary container"
59+
60+
print_step "Extracting rootfs..."
61+
docker export tmp | tar -x -C plugin/rootfs || print_error "Failed to extract rootfs"
62+
63+
print_step "Cleaning up temporary container..."
64+
docker rm -vf tmp
65+
docker rmi moosefs-plugin-build
66+
67+
# Create and enable plugin
68+
print_step "Creating Docker plugin..."
69+
docker plugin create ${PLUGIN_NAME} plugin || print_error "Failed to create plugin"
70+
71+
print_step "Enabling Docker plugin..."
72+
docker plugin enable ${PLUGIN_NAME} || print_error "Failed to enable plugin"
73+
74+
print_success "Build completed successfully!"
75+
echo -e "${GREEN}Plugin ${PLUGIN_NAME} is now ready to use${NC}"
76+
echo -e "${YELLOW}You can create a volume with:${NC}"
77+
echo -e "docker volume create -d ${PLUGIN_NAME} --name test_volume"

driver.go

Lines changed: 80 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,29 @@ package main
33
import (
44
"errors"
55
"fmt"
6-
"os"
7-
"path"
6+
"os"
7+
"strings"
88
"path/filepath"
99
"sync"
10-
"syscall"
1110

12-
log "github.com/Sirupsen/logrus"
11+
log "github.com/sirupsen/logrus"
1312

1413
"github.com/davecgh/go-spew/spew"
1514
"github.com/docker/go-plugins-helpers/volume"
1615
)
1716

17+
// Configuration structure
18+
type MoosefsConfig struct {
19+
MasterHost string
20+
MasterPort string
21+
RootDir string
22+
MountOptions []string
23+
}
24+
1825
// A single volume instance
1926
type moosefsMount struct {
2027
name string
21-
path string
28+
path string
2229
root string
2330
}
2431

@@ -27,16 +34,21 @@ type moosefsDriver struct {
2734
m *sync.Mutex
2835
}
2936

30-
func newMooseFSDriver(root string) moosefsDriver {
31-
d := moosefsDriver{
37+
func newMooseFSDriver(root string) (*moosefsDriver, error) {
38+
d := &moosefsDriver{
3239
mounts: make(map[string]*moosefsMount),
3340
m: &sync.Mutex{},
3441
}
35-
return d
42+
43+
if err := d.loadState(); err != nil {
44+
return nil, err
45+
}
46+
47+
return d, nil
3648
}
3749

3850
func (d moosefsDriver) Create(r *volume.CreateRequest) error {
39-
var volumeRoot string
51+
var volumeRoot string
4052

4153
d.m.Lock()
4254
defer d.m.Unlock()
@@ -45,15 +57,15 @@ func (d moosefsDriver) Create(r *volume.CreateRequest) error {
4557
volumeRoot = optsRoot
4658
} else {
4759
// Assume the default root
48-
volumeRoot = *root
60+
volumeRoot = *root
4961
}
5062

51-
volumePath := filepath.Join(volumeRoot, r.Name)
63+
volumePath := filepath.Join(volumeRoot, r.Name)
5264

53-
if err := mkdir(volumePath); err != nil {
65+
if err := mkdir(volumePath); err != nil {
5466
return err
5567
}
56-
68+
5769
if !ismoosefs(volumePath) {
5870
emsg := fmt.Sprintf("Cannot create volume %s as it's not a valid MooseFS mount", volumePath)
5971
log.Error(emsg)
@@ -66,19 +78,22 @@ func (d moosefsDriver) Create(r *volume.CreateRequest) error {
6678
return errors.New(emsg)
6779
}
6880

69-
if err := mkdir(volumePath); err != nil {
70-
return err
71-
}
7281
d.mounts[r.Name] = &moosefsMount{
7382
name: r.Name,
74-
path: volumePath,
83+
path: volumePath,
7584
root: volumeRoot,
7685
}
7786

7887
if *verbose {
7988
spew.Dump(d.mounts)
8089
}
8190

91+
if err := d.saveState(); err != nil {
92+
// If we can't save state, remove the volume from memory
93+
delete(d.mounts, r.Name)
94+
return err
95+
}
96+
8297
return nil
8398
}
8499

@@ -87,6 +102,9 @@ func (d moosefsDriver) Remove(r *volume.RemoveRequest) error {
87102
defer d.m.Unlock()
88103
if _, ok := d.mounts[r.Name]; ok {
89104
delete(d.mounts, r.Name)
105+
if err := d.saveState(); err != nil {
106+
return err
107+
}
90108
}
91109
return nil
92110
}
@@ -99,16 +117,16 @@ func (d moosefsDriver) Path(r *volume.PathRequest) (*volume.PathResponse, error)
99117
}
100118

101119
func (d moosefsDriver) Mount(r *volume.MountRequest) (*volume.MountResponse, error) {
102-
volumePath := filepath.Join(d.mounts[r.Name].root, r.Name)
103-
if !ismoosefs(volumePath) {
104-
emsg := fmt.Sprintf("Cannot mount volume %s as it's not a valid MooseFS mount", volumePath)
105-
log.Error(emsg)
106-
return &volume.MountResponse{}, errors.New(emsg)
107-
}
108-
if _, ok := d.mounts[r.Name]; ok {
109-
return &volume.MountResponse{Mountpoint: d.mounts[r.Name].path}, nil
110-
}
111-
return &volume.MountResponse{}, nil
120+
volumePath := filepath.Join(d.mounts[r.Name].root, r.Name)
121+
if !ismoosefs(volumePath) {
122+
emsg := fmt.Sprintf("Cannot mount volume %s as it's not a valid MooseFS mount", volumePath)
123+
log.Error(emsg)
124+
return &volume.MountResponse{}, errors.New(emsg)
125+
}
126+
if _, ok := d.mounts[r.Name]; ok {
127+
return &volume.MountResponse{Mountpoint: d.mounts[r.Name].path}, nil
128+
}
129+
return &volume.MountResponse{}, nil
112130
}
113131

114132
func (d moosefsDriver) Unmount(r *volume.UnmountRequest) error {
@@ -137,15 +155,41 @@ func (d moosefsDriver) Capabilities() *volume.CapabilitiesResponse {
137155
return &res
138156
}
139157

140-
// Check if MooseFS is mounted in mountpoint using the .masterinfo file
141-
func ismoosefs(mountpoint string) bool {
142-
stat := syscall.Statfs_t{}
143-
err := syscall.Statfs(path.Join(mountpoint, ".masterinfo"), &stat)
144-
if err != nil {
145-
log.Errorf("Could not determine filesystem type for %s: %s", mountpoint, err)
146-
return false
147-
}
148-
return true
158+
// Check if path is under a MooseFS mount
159+
func ismoosefs(checkPath string) bool {
160+
absPath, err := filepath.Abs(checkPath)
161+
if err != nil {
162+
log.Errorf("Cannot get absolute path for %s: %s", checkPath, err)
163+
return false
164+
}
165+
166+
data, err := os.ReadFile("/proc/mounts")
167+
if err != nil {
168+
log.Errorf("Cannot read /proc/mounts: %s", err)
169+
return false
170+
}
171+
172+
mounts := strings.Split(string(data), "\n")
173+
for _, mount := range mounts {
174+
fields := strings.Fields(mount)
175+
if len(fields) < 3 {
176+
continue
177+
}
178+
179+
mountPoint := fields[1]
180+
fsType := fields[2]
181+
182+
if fsType == "fuse.mfs" {
183+
log.Infof("Found MooseFS mount at %s", mountPoint)
184+
if strings.HasPrefix(absPath, mountPoint) {
185+
log.Infof("Path %s is under MooseFS mount %s", absPath, mountPoint)
186+
return true
187+
}
188+
}
189+
}
190+
191+
log.Infof("Path %s is not under any MooseFS mount", absPath)
192+
return false
149193
}
150194

151195
func mkdir(path string) error {

go.mod

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module github.com/liberodark/docker-volume-moosefs
2+
3+
go 1.21
4+
5+
toolchain go1.23.3
6+
7+
require (
8+
github.com/davecgh/go-spew v1.1.1
9+
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
10+
github.com/sirupsen/logrus v1.9.3
11+
)
12+
13+
require (
14+
github.com/Microsoft/go-winio v0.6.2 // indirect
15+
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
16+
github.com/docker/go-connections v0.5.0 // indirect
17+
golang.org/x/sys v0.10.0 // indirect
18+
)

go.sum

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
2+
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
3+
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
4+
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
5+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
7+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8+
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
9+
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
10+
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651 h1:YcvzLmdrP/b8kLAGJ8GT7bdncgCAiWxJZIlt84D+RJg=
11+
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651/go.mod h1:LFyLie6XcDbyKGeVK6bHe+9aJTYCxWLBg5IrJZOaXKA=
12+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
13+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
14+
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
15+
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
16+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
17+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
18+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
19+
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
20+
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
21+
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
22+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
23+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
24+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)