Skip to content

Commit

Permalink
Merge pull request #28 from gondor/Issue21_25
Browse files Browse the repository at this point in the history
Issue #21, #25 and #30
  • Loading branch information
gondor committed Apr 9, 2016
2 parents 88ee83d + 56f989d commit 124fec9
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 282 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION = 0.15
VERSION = 0.16
GO_FMT = gofmt -s -w -l .
GO_XC = goxc -os="linux" -tasks-="rmbin"

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ The method below will install the sysvinit and /etc/default options that can be
1. Install the Package

```
$ wget https://github.com/gondor/docker-volume-netshare/releases/download/v0.15/docker-volume-netshare_0.15_amd64.deb
$ sudo dpkg -i docker-volume-netshare_0.15_amd64.deb
$ wget https://github.com/gondor/docker-volume-netshare/releases/download/v0.16/docker-volume-netshare_0.16_amd64.deb
$ sudo dpkg -i docker-volume-netshare_0.16_amd64.deb
```

2. Modify the startup options in `/etc/default/docker-volume-netshare`
Expand Down
126 changes: 51 additions & 75 deletions netshare/drivers/cifs.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"os"
"path/filepath"
"strings"
"sync"
)

const (
Expand All @@ -20,11 +19,9 @@ const (
)

type cifsDriver struct {
root string
creds *cifsCreds
netrc *netrc.Netrc
mountm *mountManager
m *sync.Mutex
volumeDriver
creds *cifsCreds
netrc *netrc.Netrc
}

type cifsCreds struct {
Expand All @@ -36,11 +33,9 @@ type cifsCreds struct {

func NewCIFSDriver(root, user, pass, domain, security, netrc string) cifsDriver {
d := cifsDriver{
root: root,
creds: &cifsCreds{user: user, pass: pass, domain: domain, security: security},
netrc: parseNetRC(netrc),
mountm: NewVolumeManager(),
m: &sync.Mutex{},
volumeDriver: newVolumeDriver(root),
creds: &cifsCreds{user: user, pass: pass, domain: domain, security: security},
netrc: parseNetRC(netrc),
}
return d
}
Expand All @@ -54,104 +49,85 @@ func parseNetRC(path string) *netrc.Netrc {
return nil
}

func (s cifsDriver) Create(r volume.Request) volume.Response {
log.Debugf("Create: %s, %v", r.Name, r.Options)
dest := mountpoint(s.root, r.Name)
if err := createDest(dest); err != nil {
return volume.Response{Err: err.Error()}
}
s.mountm.Create(dest, r.Name, r.Options)
return volume.Response{}
}

func (s cifsDriver) Remove(r volume.Request) volume.Response {
log.Debugf("Removing volume %s", r.Name)
return volume.Response{}
}

func (s cifsDriver) Path(r volume.Request) volume.Response {
log.Debugf("Path for %s is at %s", r.Name, mountpoint(s.root, r.Name))
return volume.Response{Mountpoint: mountpoint(s.root, r.Name)}
}
func (c cifsDriver) Mount(r volume.Request) volume.Response {
c.m.Lock()
defer c.m.Unlock()
hostdir := mountpoint(c.root, r.Name)
source := c.fixSource(r)
host := c.parseHost(r)

func (s cifsDriver) Get(r volume.Request) volume.Response {
log.Debugf("Get for %s is at %s", r.Name, mountpoint(s.root, r.Name))
return volume.Response{Volume: &volume.Volume{Name: r.Name, Mountpoint: mountpoint(s.root, r.Name)}}
}

func (s cifsDriver) List(r volume.Request) volume.Response {
log.Debugf("List Volumes")
return volume.Response{Volumes: s.mountm.GetVolumes(s.root)}
}

func (s cifsDriver) Mount(r volume.Request) volume.Response {
s.m.Lock()
defer s.m.Unlock()
dest := mountpoint(s.root, r.Name)
source := s.fixSource(r.Name)
host := parseHost(r.Name)
log.Infof("Mount: %s, %v", r.Name, r.Options)

if s.mountm.HasMount(dest) && s.mountm.Count(dest) > 0 {
log.Infof("Using existing CIFS volume mount: %s", dest)
s.mountm.Increment(dest)
return volume.Response{Mountpoint: dest}
if c.mountm.HasMount(r.Name) && c.mountm.Count(r.Name) > 0 {
log.Infof("Using existing CIFS volume mount: %s", hostdir)
c.mountm.Increment(r.Name)
return volume.Response{Mountpoint: hostdir}
}

log.Infof("Mounting CIFS volume %s on %s", source, dest)
log.Infof("Mounting CIFS volume %s on %s", source, hostdir)

if err := createDest(dest); err != nil {
if err := createDest(hostdir); err != nil {
return volume.Response{Err: err.Error()}
}

if err := s.mountVolume(source, dest, s.getCreds(host)); err != nil {
if err := c.mountVolume(r.Name, source, hostdir, c.getCreds(host)); err != nil {
return volume.Response{Err: err.Error()}
}
s.mountm.Add(dest, r.Name)
return volume.Response{Mountpoint: dest}
c.mountm.Add(r.Name, hostdir)
return volume.Response{Mountpoint: hostdir}
}

func (s cifsDriver) Unmount(r volume.Request) volume.Response {
s.m.Lock()
defer s.m.Unlock()
dest := mountpoint(s.root, r.Name)
source := s.fixSource(r.Name)
func (c cifsDriver) Unmount(r volume.Request) volume.Response {
c.m.Lock()
defer c.m.Unlock()
hostdir := mountpoint(c.root, r.Name)
source := c.fixSource(r)

if s.mountm.HasMount(dest) {
if s.mountm.Count(dest) > 1 {
log.Infof("Skipping unmount for %s - in use by other containers", dest)
s.mountm.Decrement(dest)
if c.mountm.HasMount(r.Name) {
if c.mountm.Count(r.Name) > 1 {
log.Infof("Skipping unmount for %s - in use by other containers", r.Name)
c.mountm.Decrement(r.Name)
return volume.Response{}
}
s.mountm.Decrement(dest)
c.mountm.Decrement(r.Name)
}

log.Infof("Unmounting volume %s from %s", source, dest)
log.Infof("Unmounting volume %s from %s", source, hostdir)

if err := run(fmt.Sprintf("umount %s", dest)); err != nil {
if err := run(fmt.Sprintf("umount %s", hostdir)); err != nil {
return volume.Response{Err: err.Error()}
}

if err := os.RemoveAll(dest); err != nil {
c.mountm.DeleteIfNotManaged(r.Name)

if err := os.RemoveAll(hostdir); err != nil {
return volume.Response{Err: err.Error()}
}

return volume.Response{}
}

func (s cifsDriver) fixSource(name string) string {
return "//" + name
func (c cifsDriver) fixSource(r volume.Request) string {
if c.mountm.HasOption(r.Name, ShareOpt) {
return "//" + c.mountm.GetOption(r.Name, ShareOpt)
}
return "//" + r.Name
}

func parseHost(name string) string {
func (c cifsDriver) parseHost(r volume.Request) string {
name := r.Name
if c.mountm.HasOption(r.Name, ShareOpt) {
name = c.mountm.GetOption(r.Name, ShareOpt)
}

if strings.ContainsAny(name, "/") {
s := strings.Split(name, "/")
return s[0]
}
return name
}

func (s cifsDriver) mountVolume(source, dest string, creds *cifsCreds) error {
func (s cifsDriver) mountVolume(name, source, dest string, creds *cifsCreds) error {
var opts bytes.Buffer

opts.WriteString("-o ")
Expand All @@ -160,8 +136,8 @@ func (s cifsDriver) mountVolume(source, dest string, creds *cifsCreds) error {
var domain = creds.domain
var security = creds.security

if s.mountm.HasOptions(dest) {
mopts := s.mountm.GetOptions(dest)
if s.mountm.HasOptions(name) {
mopts := s.mountm.GetOptions(name)
if v, found := mopts[UsernameOpt]; found {
user = v
}
Expand Down Expand Up @@ -197,7 +173,7 @@ func (s cifsDriver) mountVolume(source, dest string, creds *cifsCreds) error {

opts.WriteString(fmt.Sprintf("%s %s", source, dest))
cmd := fmt.Sprintf("mount -t cifs %s", opts.String())
log.Debugf("Executing: %s\n", strings.Replace(cmd, pass, "", 1))
log.Debugf("Executing: %s\n", strings.Replace(cmd, "password="+pass, "password=****", 1))
return run(cmd)
}

Expand Down
89 changes: 52 additions & 37 deletions netshare/drivers/driver.go
Original file line number Diff line number Diff line change
@@ -1,56 +1,71 @@
package drivers

import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
log "github.com/Sirupsen/logrus"
"github.com/docker/go-plugins-helpers/volume"
"sync"
)

type DriverType int

const (
CIFS DriverType = iota
NFS
EFS
)

var driverTypes = []string{
"cifs",
"nfs",
"efs",
type volumeDriver struct {
root string
mountm *mountManager
m *sync.Mutex
}

func (dt DriverType) String() string {
return driverTypes[dt]
func newVolumeDriver(root string) volumeDriver {
return volumeDriver{
root: root,
mountm: NewVolumeManager(),
m: &sync.Mutex{},
}
}

func createDest(dest string) error {
fi, err := os.Lstat(dest)
func (v volumeDriver) Create(r volume.Request) volume.Response {
log.Debugf("Entering Create: name: %s, options %v", r.Name, r.Options)

v.m.Lock()
defer v.m.Unlock()

log.Debugf("Create volume -> name: %s, %v", r.Name, r.Options)

if os.IsNotExist(err) {
if err := os.MkdirAll(dest, 0755); err != nil {
return err
}
} else if err != nil {
return err
dest := mountpoint(v.root, r.Name)
if err := createDest(dest); err != nil {
return volume.Response{Err: err.Error()}
}
v.mountm.Create(r.Name, dest, r.Options)
return volume.Response{}
}

func (v volumeDriver) Remove(r volume.Request) volume.Response {
log.Debugf("Entering Remove: name: %s, options %v", r.Name, r.Options)
v.m.Lock()
defer v.m.Unlock()

if fi != nil && !fi.IsDir() {
return fmt.Errorf("%v already exist and it's not a directory", dest)
if err := v.mountm.Delete(r.Name); err != nil {
return volume.Response{Err: err.Error()}
}
return nil
return volume.Response{}
}

func mountpoint(root, name string) string {
return filepath.Join(root, name)
func (v volumeDriver) Path(r volume.Request) volume.Response {
log.Debugf("Host path for %s is at %s", r.Name, mountpoint(v.root, r.Name))
return volume.Response{Mountpoint: mountpoint(v.root, r.Name)}
}

func run(cmd string) error {
if out, err := exec.Command("sh", "-c", cmd).CombinedOutput(); err != nil {
log.Println(string(out))
return err
func (v volumeDriver) Get(r volume.Request) volume.Response {
log.Debugf("Entering Get: %v", r)
v.m.Lock()
defer v.m.Unlock()
hostdir := mountpoint(v.root, r.Name)

if v.mountm.HasMount(r.Name) {
log.Debugf("Get: mount found for %s, host directory: %s", r.Name, hostdir)
return volume.Response{Volume: &volume.Volume{Name: r.Name, Mountpoint: hostdir}}
}
return nil
return volume.Response{}
}

func (v volumeDriver) List(r volume.Request) volume.Response {
log.Debugf("Entering List: %v", r)
return volume.Response{Volumes: v.mountm.GetVolumes(v.root)}
}
19 changes: 19 additions & 0 deletions netshare/drivers/driver_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package drivers

type DriverType int

const (
CIFS DriverType = iota
NFS
EFS
)

var driverTypes = []string{
"cifs",
"nfs",
"efs",
}

func (dt DriverType) String() string {
return driverTypes[dt]
}
Loading

0 comments on commit 124fec9

Please sign in to comment.