Skip to content

Support publishing as Docker Engine managed plugin #103

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*
!/plugin/
!/etc/docker/docker-lvm-plugin
!/docker-lvm-plugin
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ _testmain.go
*.prof

.vagrant/
plugin/rootfs
docker-lvm-plugin
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ This plugin can be used to create lvm volumes of specified size, which can
then be bind mounted into the container using `docker run` command.

## Setup
### Using Docker
docker plugin install --alias lvm containers/docker-lvm-plugin/docker-lvm-plugin VOLUME_GROUP=vg0

### Manual
1) git clone [email protected]:projectatomic/docker-lvm-plugin.git (You can also use HTTPS to clone: git clone https://github.com/projectatomic/docker-lvm-plugin.git)
2) cd docker-lvm-plugin
3) export GO111MODULE=on
Expand Down
48 changes: 24 additions & 24 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"log/syslog"
"log"
"os"
"os/exec"
"sync"
Expand All @@ -19,7 +19,7 @@ type lvmDriver struct {
volumes map[string]*vol
count map[string]int
mu sync.RWMutex
logger *syslog.Writer
logger *log.Logger
}

type vol struct {
Expand All @@ -32,10 +32,10 @@ type vol struct {
}

func newDriver(home, vgConfig string) (*lvmDriver, error) {
logger, err := syslog.New(syslog.LOG_ERR, "docker-lvm-plugin")
if err != nil {
return nil, err
}
logger := log.New(os.Stdout, "docker-lvm-plugin", 1)
//if err != nil {
// return nil, err
//}

return &lvmDriver{
home: home,
Expand Down Expand Up @@ -82,7 +82,7 @@ func (l *lvmDriver) Create(req *volume.CreateRequest) error {
return fmt.Errorf("Please don't specify --opt keyfile= for snapshots")
}
if isThinSnap, _, err = isThinlyProvisioned(vgName, snap); err != nil {
l.logger.Err(fmt.Sprintf("Create: lvdisplayGrep error: %v", err))
l.logger.Print(fmt.Sprintf("Create: lvdisplayGrep error: %v", err))
return fmt.Errorf("Error creating volume")
}
}
Expand Down Expand Up @@ -123,7 +123,7 @@ func (l *lvmDriver) Create(req *volume.CreateRequest) error {
}
cmd := exec.Command("lvcreate", cmdArgs...)
if out, err := cmd.CombinedOutput(); err != nil {
l.logger.Err(fmt.Sprintf("Create: lvcreate error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Create: lvcreate error: %s output %s", err, string(out)))
return fmt.Errorf("Error creating volume")
}

Expand All @@ -139,19 +139,19 @@ func (l *lvmDriver) Create(req *volume.CreateRequest) error {
if hasKeyFile {
cmd = exec.Command("cryptsetup", "-q", "-d", keyFile, "luksFormat", device)
if out, err := cmd.CombinedOutput(); err != nil {
l.logger.Err(fmt.Sprintf("Create: cryptsetup error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Create: cryptsetup error: %s output %s", err, string(out)))
return fmt.Errorf("Error encrypting volume")
}

if out, err := luksOpen(vgName, req.Name, keyFile); err != nil {
l.logger.Err(fmt.Sprintf("Create: cryptsetup error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Create: cryptsetup error: %s output %s", err, string(out)))
return fmt.Errorf("Error opening encrypted volume")
}

defer func() {
if err != nil {
if out, err := luksClose(req.Name); err != nil {
l.logger.Err(fmt.Sprintf("Create: cryptsetup error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Create: cryptsetup error: %s output %s", err, string(out)))
}
}
}()
Expand All @@ -161,13 +161,13 @@ func (l *lvmDriver) Create(req *volume.CreateRequest) error {

cmd = exec.Command("mkfs.xfs", device)
if out, err := cmd.CombinedOutput(); err != nil {
l.logger.Err(fmt.Sprintf("Create: mkfs.xfs error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Create: mkfs.xfs error: %s output %s", err, string(out)))
return fmt.Errorf("Error partitioning volume")
}

if hasKeyFile {
if out, err := luksClose(req.Name); err != nil {
l.logger.Err(fmt.Sprintf("Create: cryptsetup error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Create: cryptsetup error: %s output %s", err, string(out)))
return fmt.Errorf("Error closing encrypted volume")
}
}
Expand Down Expand Up @@ -237,7 +237,7 @@ func (l *lvmDriver) Get(req *volume.GetRequest) (*volume.GetResponse, error) {

createdAt, err := getVolumeCreationDateTime(v.VgName, v.Name)
if err != nil {
l.logger.Err(fmt.Sprintf("Get: %v", err))
l.logger.Print(fmt.Sprintf("Get: %v", err))
return nil, err
}

Expand Down Expand Up @@ -287,7 +287,7 @@ func (l *lvmDriver) Remove(req *volume.RemoveRequest) error {
}

if out, err := removeLogicalVolume(req.Name, vol.VgName); err != nil {
l.logger.Err(fmt.Sprintf("Remove: removeLogicalVolume error %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Remove: removeLogicalVolume error %s output %s", err, string(out)))
return fmt.Errorf("error removing volume")
}

Expand Down Expand Up @@ -334,21 +334,21 @@ func (l *lvmDriver) Mount(req *volume.MountRequest) (*volume.MountResponse, erro

if keyFile != "" {
if err := keyFileExists(keyFile); err != nil {
l.logger.Err(fmt.Sprintf("Mount: %s", err))
l.logger.Print(fmt.Sprintf("Mount: %s", err))
return &volume.MountResponse{}, err
}
if err := cryptsetupInstalled(); err != nil {
l.logger.Err(fmt.Sprintf("Mount: %s", err))
l.logger.Print(fmt.Sprintf("Mount: %s", err))
return &volume.MountResponse{}, err
}
if out, err := luksOpen(vol.VgName, req.Name, keyFile); err != nil {
l.logger.Err(fmt.Sprintf("Mount: cryptsetup error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Mount: cryptsetup error: %s output %s", err, string(out)))
return &volume.MountResponse{}, fmt.Errorf("Error opening encrypted volume")
}
defer func() {
if err != nil {
if out, err := luksClose(req.Name); err != nil {
l.logger.Err(fmt.Sprintf("Mount: cryptsetup error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Mount: cryptsetup error: %s output %s", err, string(out)))
}
}
}()
Expand All @@ -361,7 +361,7 @@ func (l *lvmDriver) Mount(req *volume.MountRequest) (*volume.MountResponse, erro
}
cmd := exec.Command("mount", mountArgs...)
if out, err := cmd.CombinedOutput(); err != nil {
l.logger.Err(fmt.Sprintf("Mount: mount error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Mount: mount error: %s output %s", err, string(out)))
return &volume.MountResponse{}, fmt.Errorf("Error mouting volume")
}
}
Expand All @@ -379,22 +379,22 @@ func (l *lvmDriver) Unmount(req *volume.UnmountRequest) error {
mp := getMountpoint(l.home, req.Name)
isVolMounted, err := mount.Mounted(mp)
if err != nil {
l.logger.Err(fmt.Sprintf("Unmount: %s", err))
l.logger.Print(fmt.Sprintf("Unmount: %s", err))
return fmt.Errorf("error unmounting volume")
}
if isVolMounted {
cmd := exec.Command("umount", mp)
if out, err := cmd.CombinedOutput(); err != nil {
l.logger.Err(fmt.Sprintf("Unmount: unmount error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Unmount: unmount error: %s output %s", err, string(out)))
return fmt.Errorf("error unmounting volume")
}
if v, ok := l.volumes[req.Name]; ok && v.KeyFile != "" {
if err := cryptsetupInstalled(); err != nil {
l.logger.Err(fmt.Sprintf("Unmount: %s", err))
l.logger.Print(fmt.Sprintf("Unmount: %s", err))
return err
}
if out, err := luksClose(req.Name); err != nil {
l.logger.Err(fmt.Sprintf("Unmount: cryptsetup error: %s output %s", err, string(out)))
l.logger.Print(fmt.Sprintf("Unmount: cryptsetup error: %s output %s", err, string(out)))
return fmt.Errorf("Error closing encrypted volume")
}
}
Expand Down
2 changes: 1 addition & 1 deletion etc/docker/docker-lvm-plugin
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
# OR create a new volume group using `vgcreate` command.
# e.g. vgcreate volume_group_one /dev/hda where /dev/hda is your partition or
# whole disk on which physical volumes were created.
VOLUME_GROUP=
VOLUME_GROUP=foo
5 changes: 5 additions & 0 deletions plugin/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM alpine
RUN apk update && apk add lvm2 xfsprogs cryptsetup thin-provisioning-tools
RUN mkdir -p /var/lib/docker-lvm-plugin
COPY etc/docker/docker-lvm-plugin /etc/docker/docker-lvm-plugin
COPY docker-lvm-plugin /
38 changes: 38 additions & 0 deletions plugin/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name := containers/docker-lvm-plugin

.PHONY: build
build: docker-lvm-plugin

docker-lvm-plugin: main.go driver.go utils.go go.mod go.sum
docker run --rm --tmpfs /tmp -v $(shell pwd):/tmp/docker-lvm-plugin -w /tmp/docker-lvm-plugin golang:alpine go build

.PHONY: create
create: plugin/config.json plugin/rootfs
docker plugin rm --force $(name) || true
docker plugin create $(name) plugin

.PHONY: install
install: create
docker plugin rm --force $(name) || true
docker plugin install $(name) --alias lvm --grant-all-permissions

.PHONY: push
push: create
docker plugin push $(name)

.PHONY: enable
enable: create
docker plugin enable $(name)

.PHONY: clean
clean:
rm -rf plugin/rootfs

plugin/rootfs: .dockerignore plugin/Dockerfile docker-lvm-plugin
docker build --tag $(name):rootfs -f plugin/Dockerfile .
docker rm --force --volumes rootfs || true
docker create --name rootfs $(name):rootfs
rm -rf $@
mkdir -p $@
docker export rootfs | tar -x -C $@
docker rm --force --volumes rootfs
36 changes: 36 additions & 0 deletions plugin/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"Description": "LVM volume plugin for Docker",
"Documentation": "https://docs.docker.com/engine/extend/plugins/",
"Entrypoint": ["/docker-lvm-plugin"],
"Env": [
{
"Name": "VOLUME_GROUP",
"Description": "LVM volume group to create volumes in.",
"Settable": ["value"],
"Value": null
}
],
"Interface": {
"Socket": "lvm.sock",
"Types": ["docker.volumedriver/1.0"]
},
"Linux": {
"Capabilities": ["CAP_SYS_ADMIN"],
"AllowAllDevices": true,
"Devices": null
},
"Mounts": [
{
"description": "Device access for devicemapper (/dev/mapper/*, /dev/*/*)",
"destination": "/dev",
"options": ["rbind"],
"name": "dev",
"source": "/dev",
"type": "bind"
}
],
"Network": {
"Type": "host"
},
"PropagatedMount": "/var/lib/docker-lvm-plugin"
}