func main() { fname := flag.String("from", "", "name of container to clone from or create before cloning") bname := flag.String("to", "", "name to use for clone") if *fname == "" || *bname == "" { log.Println("Unacceptable for names to be empty!") return } var err error cl := &lxc.CloneOptions{ Backend: lxc.Aufs, KeepName: true, Snapshot: true, } tl := &lxc.TemplateOptions{ Template: "download", Distro: "ubuntu", Release: "trusty", Arch: "amd64", Backend: lxc.Directory, } c, err := lxc.NewContainer(*fname, lxc.DefaultConfigPath()) if err != nil { log.Printf("Allocating Container %s error %s", *fname, err) panic("Unable to get container") } lxc.Release(c) if !c.Defined() { err := c.Create(*tl) if err != nil { log.Printf("Allocating Container %s error %s", *fname, err) panic("Unable to create container") } } err = c.Clone(*bname, *cl) if err != nil { log.Println("Unable to clone", *bname) return } cloned, err := lxc.NewContainer(*bname, lxc.DefaultConfigPath()) if err != nil { log.Println("Unable to locate clone", *bname) return } switch cloned.State() { case lxc.FROZEN: err = cloned.Unfreeze() log.Printf("Container in current State: %+s", cloned.State()) case lxc.STOPPED: err = cloned.Start() log.Printf("Container in current State: %+s", cloned.State()) case lxc.RUNNING: log.Printf("Container in current State: %+s", cloned.State()) return default: log.Printf("Container in current State: %+s", cloned.State()) err = fmt.Errorf("Bad controller") } if err != nil { return } if !cloned.Wait(lxc.RUNNING, 60) { log.Printf("Unable to get it running (%+v)", cloned.State()) return } // var dest string // // log.Printf("Begin IP Acquisition process for container") // // for { // ip, err := con.IPAddress("eth0") // // if err != nil { // log.Printf("Waiting for Container (%s) IP to settle", err.Error()) // time.Sleep(time.Millisecond * time.Duration(1000)) // continue // } // // break // } // cloned.Freeze() if !cloned.Wait(lxc.FROZEN, 60) { log.Printf("Unable to freeze it (%+s)", *bname) return } var durs int fmt.Scan(&durs) time.Sleep(time.Duration(durs) * time.Second) lxc.Release(cloned) time.Sleep(time.Duration(durs) * time.Second) }
// Start starts the LXC Driver func (d *LxcDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) { var driverConfig LxcDriverConfig if err := mapstructure.WeakDecode(task.Config, &driverConfig); err != nil { return nil, err } lxcPath := lxc.DefaultConfigPath() if path := d.config.Read("driver.lxc.path"); path != "" { lxcPath = path } containerName := fmt.Sprintf("%s-%s", task.Name, ctx.AllocID) c, err := lxc.NewContainer(containerName, lxcPath) if err != nil { return nil, fmt.Errorf("unable to initialize container: %v", err) } var verbosity lxc.Verbosity switch driverConfig.Verbosity { case "verbose": verbosity = lxc.Verbose case "", "quiet": verbosity = lxc.Quiet default: return nil, fmt.Errorf("lxc driver config 'verbosity' can only be either quiet or verbose") } c.SetVerbosity(verbosity) var logLevel lxc.LogLevel switch driverConfig.LogLevel { case "trace": logLevel = lxc.TRACE case "debug": logLevel = lxc.DEBUG case "info": logLevel = lxc.INFO case "warn": logLevel = lxc.WARN case "", "error": logLevel = lxc.ERROR default: return nil, fmt.Errorf("lxc driver config 'log_level' can only be trace, debug, info, warn or error") } c.SetLogLevel(logLevel) logFile := filepath.Join(ctx.AllocDir.LogDir(), fmt.Sprintf("%v-lxc.log", task.Name)) c.SetLogFile(logFile) options := lxc.TemplateOptions{ Template: driverConfig.Template, Distro: driverConfig.Distro, Release: driverConfig.Release, Arch: driverConfig.Arch, FlushCache: driverConfig.FlushCache, DisableGPGValidation: driverConfig.DisableGPGValidation, ExtraArgs: driverConfig.TemplateArgs, } if err := c.Create(options); err != nil { return nil, fmt.Errorf("unable to create container: %v", err) } // Set the network type to none if err := c.SetConfigItem("lxc.network.type", "none"); err != nil { return nil, fmt.Errorf("error setting network type configuration: %v", err) } // Bind mount the shared alloc dir and task local dir in the container taskDir, ok := ctx.AllocDir.TaskDirs[task.Name] if !ok { return nil, fmt.Errorf("failed to find task local directory: %v", task.Name) } secretdir, err := ctx.AllocDir.GetSecretDir(task.Name) if err != nil { return nil, fmt.Errorf("faild getting secret path for task: %v", err) } taskLocalDir := filepath.Join(taskDir, allocdir.TaskLocal) mounts := []string{ fmt.Sprintf("%s local none rw,bind,create=dir", taskLocalDir), fmt.Sprintf("%s alloc none rw,bind,create=dir", ctx.AllocDir.SharedDir), fmt.Sprintf("%s secret none rw,bind,create=dir", secretdir), } for _, mnt := range mounts { if err := c.SetConfigItem("lxc.mount.entry", mnt); err != nil { return nil, fmt.Errorf("error setting bind mount %q error: %v", mnt, err) } } // Start the container if err := c.Start(); err != nil { return nil, fmt.Errorf("unable to start container: %v", err) } // Set the resource limits if err := c.SetMemoryLimit(lxc.ByteSize(task.Resources.MemoryMB) * lxc.MB); err != nil { return nil, fmt.Errorf("unable to set memory limits: %v", err) } if err := c.SetCgroupItem("cpu.shares", strconv.Itoa(task.Resources.CPU)); err != nil { return nil, fmt.Errorf("unable to set cpu shares: %v", err) } handle := lxcDriverHandle{ container: c, initPid: c.InitPid(), lxcPath: lxcPath, logger: d.logger, killTimeout: GetKillTimeout(task.KillTimeout, d.DriverContext.config.MaxKillTimeout), maxKillTimeout: d.DriverContext.config.MaxKillTimeout, totalCpuStats: stats.NewCpuStats(), userCpuStats: stats.NewCpuStats(), systemCpuStats: stats.NewCpuStats(), waitCh: make(chan *dstructs.WaitResult, 1), doneCh: make(chan bool, 1), } go handle.run() return &handle, nil }