Skip to content

Commit

Permalink
Improve Plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
liberodark committed Dec 30, 2024
1 parent 757eb58 commit f15d26f
Show file tree
Hide file tree
Showing 11 changed files with 390 additions and 44 deletions.
41 changes: 36 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,38 @@
*~
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
docker-volume-moosefs
*.rpm

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool
*.out

# Dependency directories (remove the comment below to include it)
vendor/

# Plugin build artifacts
plugin/rootfs/
*.deb
obj
.idea
vendor/*/
*.rpm
obj/

# IDE specific files
.idea/
.vscode/
*.swp
*.swo

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

17 changes: 16 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,19 @@ deb: compile
clean:
rm -fr obj *.deb *.rpm docker-volume-moosefs

.PHONY: clean rpm-deps deb-deps fmt deps compile
plugin: compile
mkdir -p plugin/rootfs
docker build -t moosefs-plugin-build -f plugin/Dockerfile .
docker create --name tmp moosefs-plugin-build
docker export tmp | tar -x -C plugin/rootfs
docker rm -vf tmp
docker rmi moosefs-plugin-build

plugin-enable:
docker plugin create moosefs/docker-volume-moosefs:$(VERSION) plugin
docker plugin enable moosefs/docker-volume-moosefs:$(VERSION)

plugin-push: plugin plugin-enable
docker plugin push moosefs/docker-volume-moosefs:$(VERSION)

.PHONY: clean rpm-deps deb-deps fmt deps compile plugin plugin-enable plugin-push
77 changes: 77 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env bash

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

# Version
VERSION="0.2.0"
PLUGIN_NAME="moosefs/docker-volume-moosefs:${VERSION}"

# Function to print step
print_step() {
echo -e "${YELLOW}[*] $1${NC}"
}

# Function to print success
print_success() {
echo -e "${GREEN}[+] $1${NC}"
}

# Function to print error and exit
print_error() {
echo -e "${RED}[-] $1${NC}"
exit 1
}

# Clean previous build
print_step "Cleaning previous build..."
rm -rf plugin/rootfs *.deb *.rpm docker-volume-moosefs obj
print_success "Clean completed"

# Clean existing plugin if it exists
print_step "Checking for existing plugin..."
if docker plugin inspect ${PLUGIN_NAME} >/dev/null 2>&1; then
print_step "Disabling existing plugin..."
docker plugin disable ${PLUGIN_NAME} >/dev/null 2>&1
print_step "Removing existing plugin..."
docker plugin rm ${PLUGIN_NAME} >/dev/null 2>&1
fi
print_success "Plugin cleanup completed"

# Build Go binary
print_step "Building Go binary..."
go build || print_error "Go build failed"
print_success "Binary built successfully"

# Create plugin
print_step "Creating Docker plugin..."
mkdir -p plugin/rootfs || print_error "Failed to create plugin directory"

# Build Docker image
print_step "Building Docker image..."
docker build -t moosefs-plugin-build -f plugin/Dockerfile . || print_error "Docker build failed"

print_step "Creating temporary container..."
docker create --name tmp moosefs-plugin-build || print_error "Failed to create temporary container"

print_step "Extracting rootfs..."
docker export tmp | tar -x -C plugin/rootfs || print_error "Failed to extract rootfs"

print_step "Cleaning up temporary container..."
docker rm -vf tmp
docker rmi moosefs-plugin-build

# Create and enable plugin
print_step "Creating Docker plugin..."
docker plugin create ${PLUGIN_NAME} plugin || print_error "Failed to create plugin"

print_step "Enabling Docker plugin..."
docker plugin enable ${PLUGIN_NAME} || print_error "Failed to enable plugin"

print_success "Build completed successfully!"
echo -e "${GREEN}Plugin ${PLUGIN_NAME} is now ready to use${NC}"
echo -e "${YELLOW}You can create a volume with:${NC}"
echo -e "docker volume create -d ${PLUGIN_NAME} --name test_volume"
116 changes: 80 additions & 36 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,29 @@ package main
import (
"errors"
"fmt"
"os"
"path"
"os"
"strings"
"path/filepath"
"sync"
"syscall"

log "github.com/Sirupsen/logrus"
log "github.com/sirupsen/logrus"

"github.com/davecgh/go-spew/spew"
"github.com/docker/go-plugins-helpers/volume"
)

// Configuration structure
type MoosefsConfig struct {
MasterHost string
MasterPort string
RootDir string
MountOptions []string
}

// A single volume instance
type moosefsMount struct {
name string
path string
path string
root string
}

Expand All @@ -27,16 +34,21 @@ type moosefsDriver struct {
m *sync.Mutex
}

func newMooseFSDriver(root string) moosefsDriver {
d := moosefsDriver{
func newMooseFSDriver(root string) (*moosefsDriver, error) {
d := &moosefsDriver{
mounts: make(map[string]*moosefsMount),
m: &sync.Mutex{},
}
return d

if err := d.loadState(); err != nil {
return nil, err
}

return d, nil
}

func (d moosefsDriver) Create(r *volume.CreateRequest) error {
var volumeRoot string
var volumeRoot string

d.m.Lock()
defer d.m.Unlock()
Expand All @@ -45,15 +57,15 @@ func (d moosefsDriver) Create(r *volume.CreateRequest) error {
volumeRoot = optsRoot
} else {
// Assume the default root
volumeRoot = *root
volumeRoot = *root
}

volumePath := filepath.Join(volumeRoot, r.Name)
volumePath := filepath.Join(volumeRoot, r.Name)

if err := mkdir(volumePath); err != nil {
if err := mkdir(volumePath); err != nil {
return err
}

if !ismoosefs(volumePath) {
emsg := fmt.Sprintf("Cannot create volume %s as it's not a valid MooseFS mount", volumePath)
log.Error(emsg)
Expand All @@ -66,19 +78,22 @@ func (d moosefsDriver) Create(r *volume.CreateRequest) error {
return errors.New(emsg)
}

if err := mkdir(volumePath); err != nil {
return err
}
d.mounts[r.Name] = &moosefsMount{
name: r.Name,
path: volumePath,
path: volumePath,
root: volumeRoot,
}

if *verbose {
spew.Dump(d.mounts)
}

if err := d.saveState(); err != nil {
// If we can't save state, remove the volume from memory
delete(d.mounts, r.Name)
return err
}

return nil
}

Expand All @@ -87,6 +102,9 @@ func (d moosefsDriver) Remove(r *volume.RemoveRequest) error {
defer d.m.Unlock()
if _, ok := d.mounts[r.Name]; ok {
delete(d.mounts, r.Name)
if err := d.saveState(); err != nil {
return err
}
}
return nil
}
Expand All @@ -99,16 +117,16 @@ func (d moosefsDriver) Path(r *volume.PathRequest) (*volume.PathResponse, error)
}

func (d moosefsDriver) Mount(r *volume.MountRequest) (*volume.MountResponse, error) {
volumePath := filepath.Join(d.mounts[r.Name].root, r.Name)
if !ismoosefs(volumePath) {
emsg := fmt.Sprintf("Cannot mount volume %s as it's not a valid MooseFS mount", volumePath)
log.Error(emsg)
return &volume.MountResponse{}, errors.New(emsg)
}
if _, ok := d.mounts[r.Name]; ok {
return &volume.MountResponse{Mountpoint: d.mounts[r.Name].path}, nil
}
return &volume.MountResponse{}, nil
volumePath := filepath.Join(d.mounts[r.Name].root, r.Name)
if !ismoosefs(volumePath) {
emsg := fmt.Sprintf("Cannot mount volume %s as it's not a valid MooseFS mount", volumePath)
log.Error(emsg)
return &volume.MountResponse{}, errors.New(emsg)
}
if _, ok := d.mounts[r.Name]; ok {
return &volume.MountResponse{Mountpoint: d.mounts[r.Name].path}, nil
}
return &volume.MountResponse{}, nil
}

func (d moosefsDriver) Unmount(r *volume.UnmountRequest) error {
Expand Down Expand Up @@ -137,15 +155,41 @@ func (d moosefsDriver) Capabilities() *volume.CapabilitiesResponse {
return &res
}

// Check if MooseFS is mounted in mountpoint using the .masterinfo file
func ismoosefs(mountpoint string) bool {
stat := syscall.Statfs_t{}
err := syscall.Statfs(path.Join(mountpoint, ".masterinfo"), &stat)
if err != nil {
log.Errorf("Could not determine filesystem type for %s: %s", mountpoint, err)
return false
}
return true
// Check if path is under a MooseFS mount
func ismoosefs(checkPath string) bool {
absPath, err := filepath.Abs(checkPath)
if err != nil {
log.Errorf("Cannot get absolute path for %s: %s", checkPath, err)
return false
}

data, err := os.ReadFile("/proc/mounts")
if err != nil {
log.Errorf("Cannot read /proc/mounts: %s", err)
return false
}

mounts := strings.Split(string(data), "\n")
for _, mount := range mounts {
fields := strings.Fields(mount)
if len(fields) < 3 {
continue
}

mountPoint := fields[1]
fsType := fields[2]

if fsType == "fuse.mfs" {
log.Infof("Found MooseFS mount at %s", mountPoint)
if strings.HasPrefix(absPath, mountPoint) {
log.Infof("Path %s is under MooseFS mount %s", absPath, mountPoint)
return true
}
}
}

log.Infof("Path %s is not under any MooseFS mount", absPath)
return false
}

func mkdir(path string) error {
Expand Down
18 changes: 18 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module github.com/liberodark/docker-volume-moosefs

go 1.21

toolchain go1.23.3

require (
github.com/davecgh/go-spew v1.1.1
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
github.com/sirupsen/logrus v1.9.3
)

require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
github.com/docker/go-connections v0.5.0 // indirect
golang.org/x/sys v0.10.0 // indirect
)
24 changes: 24 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651 h1:YcvzLmdrP/b8kLAGJ8GT7bdncgCAiWxJZIlt84D+RJg=
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651/go.mod h1:LFyLie6XcDbyKGeVK6bHe+9aJTYCxWLBg5IrJZOaXKA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading

0 comments on commit f15d26f

Please sign in to comment.