Skip to content

Commit f59edba

Browse files
committed
bugfix: add attach volume when container start
Add attach volume when container start. Now volume attaching is at container create stage, but if host have been restarted, container won't be created, so volume can't be attached. Add Config() for volume driver, it makes volume driver can use the configure of volume in daemon. Now set `volume-meta-dir` and `volume-timeout` into driver config. Signed-off-by: Rudy Zhang <[email protected]>
1 parent 4782518 commit f59edba

File tree

7 files changed

+91
-11
lines changed

7 files changed

+91
-11
lines changed

daemon/mgr/container.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -446,18 +446,48 @@ func (mgr *ContainerManager) Start(ctx context.Context, id, detachKeys string) (
446446
}
447447

448448
func (mgr *ContainerManager) start(ctx context.Context, c *Container, detachKeys string) error {
449+
var err error
450+
449451
c.Lock()
450452
if c.Config == nil || c.State == nil {
451453
c.Unlock()
452454
return errors.Wrapf(errtypes.ErrNotfound, "container %s", c.ID)
453455
}
454456
c.DetachKeys = detachKeys
455457

458+
// attach volume
459+
for _, mp := range c.Mounts {
460+
if mp.Name == "" {
461+
continue
462+
}
463+
464+
attachedVolumes := map[string]struct{}{}
465+
defer func() {
466+
if err != nil {
467+
for name := range attachedVolumes {
468+
_, err = mgr.VolumeMgr.Detach(ctx, name, map[string]string{volumetypes.OptionRef: c.ID})
469+
if err != nil {
470+
logrus.Errorf("failed to detach volume(%s) when start container(%s) rollback",
471+
name, c.ID)
472+
}
473+
}
474+
}
475+
}()
476+
477+
_, err = mgr.VolumeMgr.Attach(ctx, mp.Name, map[string]string{volumetypes.OptionRef: c.ID})
478+
if err != nil {
479+
c.Unlock()
480+
return errors.Wrapf(err, "failed to attach volume(%s)", mp.Name)
481+
}
482+
attachedVolumes[mp.Name] = struct{}{}
483+
}
484+
456485
// initialise container network mode
457486
networkMode := c.HostConfig.NetworkMode
458487

459488
if IsContainer(networkMode) {
460-
origContainer, err := mgr.Get(ctx, strings.SplitN(networkMode, ":", 2)[1])
489+
var origContainer *Container
490+
origContainer, err = mgr.Get(ctx, strings.SplitN(networkMode, ":", 2)[1])
461491
if err != nil {
462492
c.Unlock()
463493
return err
@@ -471,7 +501,8 @@ func (mgr *ContainerManager) start(ctx context.Context, c *Container, detachKeys
471501
} else {
472502
// initialise host network mode
473503
if IsHost(networkMode) {
474-
hostname, err := os.Hostname()
504+
var hostname string
505+
hostname, err = os.Hostname()
475506
if err != nil {
476507
c.Unlock()
477508
return err
@@ -480,7 +511,7 @@ func (mgr *ContainerManager) start(ctx context.Context, c *Container, detachKeys
480511
}
481512

482513
// build the network related path.
483-
if err := mgr.buildNetworkRelatedPath(c); err != nil {
514+
if err = mgr.buildNetworkRelatedPath(c); err != nil {
484515
c.Unlock()
485516
return err
486517
}
@@ -491,7 +522,7 @@ func (mgr *ContainerManager) start(ctx context.Context, c *Container, detachKeys
491522
endpoint := mgr.buildContainerEndpoint(c)
492523
endpoint.Name = name
493524
endpoint.EndpointConfig = endpointSetting
494-
if _, err := mgr.NetworkMgr.EndpointCreate(ctx, endpoint); err != nil {
525+
if _, err = mgr.NetworkMgr.EndpointCreate(ctx, endpoint); err != nil {
495526
logrus.Errorf("failed to create endpoint: %v", err)
496527
c.Unlock()
497528
return err
@@ -501,7 +532,11 @@ func (mgr *ContainerManager) start(ctx context.Context, c *Container, detachKeys
501532
}
502533
c.Unlock()
503534

504-
return mgr.createContainerdContainer(ctx, c)
535+
if err = mgr.createContainerdContainer(ctx, c); err != nil {
536+
return errors.Wrapf(err, "failed to create container(%s) on containerd", c.ID)
537+
}
538+
539+
return nil
505540
}
506541

507542
// buildNetworkRelatedPath builds the network related path.

daemon/mgr/volume.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func (vm *VolumeManager) Attach(ctx context.Context, name string, options map[st
164164
ref := v.Option(types.OptionRef)
165165
if ref == "" {
166166
options[types.OptionRef] = cid
167-
} else {
167+
} else if !strings.Contains(ref, cid) {
168168
options[types.OptionRef] = strings.Join([]string{ref, cid}, ",")
169169
}
170170
}
@@ -199,7 +199,6 @@ func (vm *VolumeManager) Detach(ctx context.Context, name string, options map[st
199199
for i, id := range ids {
200200
if id == cid {
201201
ids = append(ids[:i], ids[i+1:]...)
202-
break
203202
}
204203
}
205204

storage/volume/core.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package volume
22

33
import (
44
"fmt"
5+
"path"
56
"reflect"
67
"strings"
78

@@ -24,6 +25,7 @@ type Core struct {
2425
func NewCore(cfg Config) (*Core, error) {
2526
c := &Core{Config: cfg}
2627

28+
// initialize volume driver alias.
2729
if cfg.DriverAlias != "" {
2830
parts := strings.Split(cfg.DriverAlias, ";")
2931
for _, p := range parts {
@@ -38,6 +40,7 @@ func NewCore(cfg Config) (*Core, error) {
3840
}
3941
}
4042

43+
// initialize volume metadata store.
4144
volumeStore, err := metastore.NewStore(metastore.Config{
4245
Driver: "boltdb",
4346
BaseDir: cfg.VolumeMetaPath,
@@ -52,9 +55,23 @@ func NewCore(cfg Config) (*Core, error) {
5255
logrus.Errorf("failed to create volume meta store: %v", err)
5356
return nil, err
5457
}
55-
5658
c.store = volumeStore
5759

60+
// set configure into each driver
61+
driverConfig := map[string]interface{}{
62+
"volume-meta-dir": path.Dir(cfg.VolumeMetaPath),
63+
"volume-timeout": cfg.Timeout,
64+
}
65+
drivers, err := driver.GetAll()
66+
if err != nil {
67+
return nil, errors.Wrapf(err, "failed to get all volume driver")
68+
}
69+
for _, dv := range drivers {
70+
if d, ok := dv.(driver.Opt); ok {
71+
d.Config(driver.Contexts(), driverConfig)
72+
}
73+
}
74+
5875
return c, nil
5976
}
6077

storage/volume/driver/driver_interface.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ type Driver interface {
2626
type Opt interface {
2727
// Options return module customize volume options.
2828
Options() map[string]types.Option
29+
30+
// Config is used to pass the daemon volume configure into driver.
31+
Config(Context, map[string]interface{}) error
2932
}
3033

3134
// AttachDetach represents volume attach/detach interface.

storage/volume/driver/remote.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ func (r *remoteDriverWrapper) Options() map[string]types.Option {
109109
return map[string]types.Option{}
110110
}
111111

112+
// Config is used to pass the daemon volume configure for remote driver.
113+
func (r *remoteDriverWrapper) Config(ctx Context, cfg map[string]interface{}) error {
114+
return nil
115+
}
116+
112117
// Attach a remote volume.
113118
func (r *remoteDriverWrapper) Attach(ctx Context, v *types.Volume) error {
114119
ctx.Log.Debugf("driver wrapper [%s] attach volume: %s", r.Name(ctx), v.Name)

storage/volume/modules/local/local.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
)
1616

1717
var (
18-
dataDir = "/var/lib/pouch/volume"
18+
defaultDataPath = "/var/lib/pouch/volume"
1919
)
2020

2121
func init() {
@@ -26,6 +26,7 @@ func init() {
2626

2727
// Local represents local volume driver.
2828
type Local struct {
29+
DataPath string
2930
}
3031

3132
// Name returns local volume driver's name.
@@ -42,8 +43,13 @@ func (p *Local) StoreMode(ctx driver.Context) driver.VolumeStoreMode {
4243
func (p *Local) Create(ctx driver.Context, id types.VolumeID) (*types.Volume, error) {
4344
ctx.Log.Debugf("Local create volume: %s", id.Name)
4445

46+
dataPath := defaultDataPath
47+
if p.DataPath != "" {
48+
dataPath = p.DataPath
49+
}
50+
4551
var (
46-
mountPath = path.Join(dataDir, id.Name)
52+
mountPath = path.Join(dataPath, id.Name)
4753
size string
4854
)
4955

@@ -91,7 +97,10 @@ func (p *Local) Path(ctx driver.Context, v *types.Volume) (string, error) {
9197

9298
mountPath := v.Option("mount")
9399
if mountPath == "" {
94-
mountPath = dataDir
100+
mountPath = defaultDataPath
101+
if p.DataPath != "" {
102+
mountPath = p.DataPath
103+
}
95104
}
96105

97106
return path.Join(mountPath, v.Name), nil
@@ -104,6 +113,13 @@ func (p *Local) Options() map[string]types.Option {
104113
}
105114
}
106115

116+
// Config is used to pass the daemon volume configure for local driver.
117+
func (p *Local) Config(ctx driver.Context, cfg map[string]interface{}) error {
118+
p.DataPath = cfg["volume-meta-dir"].(string)
119+
120+
return nil
121+
}
122+
107123
// Attach a local volume.
108124
func (p *Local) Attach(ctx driver.Context, v *types.Volume) error {
109125
ctx.Log.Debugf("Local attach volume: %s", v.Name)

storage/volume/modules/tmpfs/tmpfs.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ func (p *Tmpfs) Options() map[string]types.Option {
7272
}
7373
}
7474

75+
// Config is used to pass the daemon volume configure for tmpfs driver.
76+
func (p *Tmpfs) Config(ctx driver.Context, cfg map[string]interface{}) error {
77+
return nil
78+
}
79+
7580
// Attach a tmpfs volume.
7681
func (p *Tmpfs) Attach(ctx driver.Context, v *types.Volume) error {
7782
ctx.Log.Debugf("Tmpfs attach volume: %s", v.Name)

0 commit comments

Comments
 (0)