func (c *initCmd) guessImage(config *lxd.Config, d *lxd.Client, remote string, iremote string, image string) (string, string) { if remote != iremote { return iremote, image } _, ok := config.Remotes[image] if !ok { return iremote, image } target := d.GetAlias(image) if target != "" { return iremote, image } _, err := d.GetImageInfo(image) if err == nil { return iremote, image } fmt.Fprintf(os.Stderr, i18n.G("The local image '%s' couldn't be found, trying '%s:' instead.")+"\n", image, image) return image, "default" }
func spawnContainers(c *lxd.Client, count int, image string, privileged bool) error { batch := *argParallel if batch < 1 { // Detect the number of parallel actions cpus, err := ioutil.ReadDir("/sys/bus/cpu/devices") if err != nil { return err } batch = len(cpus) } batches := count / batch remainder := count % batch // Print the test header st, err := c.ServerStatus() if err != nil { return err } privilegedStr := "unprivileged" if privileged { privilegedStr = "privileged" } mode := "normal startup" if *argFreeze { mode = "start and freeze" } fmt.Printf("Test environment:\n") fmt.Printf(" Server backend: %s\n", st.Environment.Server) fmt.Printf(" Server version: %s\n", st.Environment.ServerVersion) fmt.Printf(" Kernel: %s\n", st.Environment.Kernel) fmt.Printf(" Kernel architecture: %s\n", st.Environment.KernelArchitecture) fmt.Printf(" Kernel version: %s\n", st.Environment.KernelVersion) fmt.Printf(" Storage backend: %s\n", st.Environment.Storage) fmt.Printf(" Storage version: %s\n", st.Environment.StorageVersion) fmt.Printf(" Container backend: %s\n", st.Environment.Driver) fmt.Printf(" Container version: %s\n", st.Environment.DriverVersion) fmt.Printf("\n") fmt.Printf("Test variables:\n") fmt.Printf(" Container count: %d\n", count) fmt.Printf(" Container mode: %s\n", privilegedStr) fmt.Printf(" Startup mode: %s\n", mode) fmt.Printf(" Image: %s\n", image) fmt.Printf(" Batches: %d\n", batches) fmt.Printf(" Batch size: %d\n", batch) fmt.Printf(" Remainder: %d\n", remainder) fmt.Printf("\n") // Pre-load the image var fingerprint string if strings.Contains(image, ":") { var remote string remote, fingerprint = lxd.DefaultConfig.ParseRemoteAndContainer(image) if fingerprint == "" { fingerprint = "default" } d, err := lxd.NewClient(&lxd.DefaultConfig, remote) if err != nil { return err } target := d.GetAlias(fingerprint) if target != "" { fingerprint = target } _, err = c.GetImageInfo(fingerprint) if err != nil { logf("Importing image into local store: %s", fingerprint) err := d.CopyImage(fingerprint, c, false, nil, false, false, nil) if err != nil { return err } } else { logf("Found image in local store: %s", fingerprint) } } else { fingerprint = image logf("Found image in local store: %s", fingerprint) } // Start the containers spawnedCount := 0 nameFormat := "benchmark-%." + fmt.Sprintf("%d", len(fmt.Sprintf("%d", count))) + "d" wgBatch := sync.WaitGroup{} nextStat := batch startContainer := func(name string) { defer wgBatch.Done() // Configure config := map[string]string{} if privileged { config["security.privileged"] = "true" } config["user.lxd-benchmark"] = "true" // Create resp, err := c.Init(name, "local", fingerprint, nil, config, nil, false) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } // Start resp, err = c.Action(name, "start", -1, false, false) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } // Freeze if *argFreeze { resp, err = c.Action(name, "freeze", -1, false, false) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf(fmt.Sprintf("Failed to spawn container '%s': %s", name, err)) return } } } logf("Starting the test") timeStart := time.Now() for i := 0; i < batches; i++ { for j := 0; j < batch; j++ { spawnedCount = spawnedCount + 1 name := fmt.Sprintf(nameFormat, spawnedCount) wgBatch.Add(1) go startContainer(name) } wgBatch.Wait() if spawnedCount >= nextStat { interval := time.Since(timeStart).Seconds() logf("Started %d containers in %.3fs (%.3f/s)", spawnedCount, interval, float64(spawnedCount)/interval) nextStat = nextStat * 2 } } for k := 0; k < remainder; k++ { spawnedCount = spawnedCount + 1 name := fmt.Sprintf(nameFormat, spawnedCount) wgBatch.Add(1) go startContainer(name) } wgBatch.Wait() logf("Test completed in %.3fs", time.Since(timeStart).Seconds()) return nil }
func (c *imageCmd) doImageEdit(client *lxd.Client, image string) error { // If stdin isn't a terminal, read text from it if !termios.IsTerminal(int(syscall.Stdin)) { contents, err := ioutil.ReadAll(os.Stdin) if err != nil { return err } newdata := shared.BriefImageInfo{} err = yaml.Unmarshal(contents, &newdata) if err != nil { return err } return client.PutImageInfo(image, newdata) } // Extract the current value config, err := client.GetImageInfo(image) if err != nil { return err } brief := config.Brief() data, err := yaml.Marshal(&brief) if err != nil { return err } // Spawn the editor content, err := shared.TextEditor("", []byte(c.imageEditHelp()+"\n\n"+string(data))) if err != nil { return err } for { // Parse the text received from the editor newdata := shared.BriefImageInfo{} err = yaml.Unmarshal(content, &newdata) if err == nil { err = client.PutImageInfo(image, newdata) } // Respawn the editor if err != nil { fmt.Fprintf(os.Stderr, i18n.G("Config parsing error: %s")+"\n", err) fmt.Println(i18n.G("Press enter to start the editor again")) _, err := os.Stdin.Read(make([]byte, 1)) if err != nil { return err } content, err = shared.TextEditor("", content) if err != nil { return err } continue } break } return nil }