|
@@ -48,6 +48,7 @@ type Container struct {
|
|
runtime *Runtime
|
|
runtime *Runtime
|
|
|
|
|
|
waitLock chan struct{}
|
|
waitLock chan struct{}
|
|
|
|
+ Volumes map[string]string
|
|
}
|
|
}
|
|
|
|
|
|
type Config struct {
|
|
type Config struct {
|
|
@@ -66,6 +67,8 @@ type Config struct {
|
|
Cmd []string
|
|
Cmd []string
|
|
Dns []string
|
|
Dns []string
|
|
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
|
|
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
|
|
|
|
+ Volumes map[string]struct{}
|
|
|
|
+ VolumesFrom string
|
|
}
|
|
}
|
|
|
|
|
|
func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Config, error) {
|
|
func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Config, error) {
|
|
@@ -97,6 +100,11 @@ func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Con
|
|
var flDns ListOpts
|
|
var flDns ListOpts
|
|
cmd.Var(&flDns, "dns", "Set custom dns servers")
|
|
cmd.Var(&flDns, "dns", "Set custom dns servers")
|
|
|
|
|
|
|
|
+ flVolumes := NewPathOpts()
|
|
|
|
+ cmd.Var(flVolumes, "v", "Attach a data volume")
|
|
|
|
+
|
|
|
|
+ flVolumesFrom := cmd.String("volumes-from", "", "Mount volumes from the specified container")
|
|
|
|
+
|
|
if err := cmd.Parse(args); err != nil {
|
|
if err := cmd.Parse(args); err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
@@ -136,6 +144,8 @@ func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Con
|
|
Cmd: runCmd,
|
|
Cmd: runCmd,
|
|
Dns: flDns,
|
|
Dns: flDns,
|
|
Image: image,
|
|
Image: image,
|
|
|
|
+ Volumes: flVolumes,
|
|
|
|
+ VolumesFrom: *flVolumesFrom,
|
|
}
|
|
}
|
|
|
|
|
|
if *flMemory > 0 && !capabilities.SwapLimit {
|
|
if *flMemory > 0 && !capabilities.SwapLimit {
|
|
@@ -394,10 +404,40 @@ func (container *Container) Start() error {
|
|
log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
|
log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
|
container.Config.MemorySwap = -1
|
|
container.Config.MemorySwap = -1
|
|
}
|
|
}
|
|
|
|
+ container.Volumes = make(map[string]string)
|
|
|
|
+
|
|
|
|
+ // Create the requested volumes volumes
|
|
|
|
+ for volPath := range container.Config.Volumes {
|
|
|
|
+ if c, err := container.runtime.volumes.Create(nil, container, "", "", nil); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ } else {
|
|
|
|
+ if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ container.Volumes[volPath] = c.Id
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if container.Config.VolumesFrom != "" {
|
|
|
|
+ c := container.runtime.Get(container.Config.VolumesFrom)
|
|
|
|
+ if c == nil {
|
|
|
|
+ return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.Id)
|
|
|
|
+ }
|
|
|
|
+ for volPath, id := range c.Volumes {
|
|
|
|
+ if _, exists := container.Volumes[volPath]; exists {
|
|
|
|
+ return fmt.Errorf("The requested volume %s overlap one of the volume of the container %s", volPath, c.Id)
|
|
|
|
+ }
|
|
|
|
+ if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ container.Volumes[volPath] = id
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
if err := container.generateLXCConfig(); err != nil {
|
|
if err := container.generateLXCConfig(); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
|
|
+
|
|
params := []string{
|
|
params := []string{
|
|
"-n", container.Id,
|
|
"-n", container.Id,
|
|
"-f", container.lxcConfigPath(),
|
|
"-f", container.lxcConfigPath(),
|
|
@@ -456,6 +496,7 @@ func (container *Container) Start() error {
|
|
|
|
|
|
// Init the lock
|
|
// Init the lock
|
|
container.waitLock = make(chan struct{})
|
|
container.waitLock = make(chan struct{})
|
|
|
|
+
|
|
container.ToDisk()
|
|
container.ToDisk()
|
|
go container.monitor()
|
|
go container.monitor()
|
|
return nil
|
|
return nil
|
|
@@ -787,6 +828,22 @@ func (container *Container) RootfsPath() string {
|
|
return path.Join(container.root, "rootfs")
|
|
return path.Join(container.root, "rootfs")
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (container *Container) GetVolumes() (map[string]string, error) {
|
|
|
|
+ ret := make(map[string]string)
|
|
|
|
+ for volPath, id := range container.Volumes {
|
|
|
|
+ volume, err := container.runtime.volumes.Get(id)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ root, err := volume.root()
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ ret[volPath] = path.Join(root, "layer")
|
|
|
|
+ }
|
|
|
|
+ return ret, nil
|
|
|
|
+}
|
|
|
|
+
|
|
func (container *Container) rwPath() string {
|
|
func (container *Container) rwPath() string {
|
|
return path.Join(container.root, "rw")
|
|
return path.Join(container.root, "rw")
|
|
}
|
|
}
|