Skip to content

Improve Plugin #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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