func lxdForceDelete(d *lxd.Client, name string) error { resp, err := d.Action(name, "stop", -1, true, false) if err == nil { d.WaitForSuccess(resp.Operation) } resp, err = d.Delete(name) if err != nil { return err } return d.WaitForSuccess(resp.Operation) }
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 deleteContainers(c *lxd.Client) 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) } // List all the containers allContainers, err := c.ListContainers() if err != nil { return err } containers := []shared.ContainerInfo{} for _, container := range allContainers { if container.Config["user.lxd-benchmark"] != "true" { continue } containers = append(containers, container) } // Delete them all count := len(containers) logf("%d containers to delete", count) batches := count / batch deletedCount := 0 wgBatch := sync.WaitGroup{} nextStat := batch deleteContainer := func(ct shared.ContainerInfo) { defer wgBatch.Done() // Stop if ct.IsActive() { resp, err := c.Action(ct.Name, "stop", -1, true, false) if err != nil { logf("Failed to delete container: %s", ct.Name) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf("Failed to delete container: %s", ct.Name) return } } // Delete resp, err := c.Delete(ct.Name) if err != nil { logf("Failed to delete container: %s", ct.Name) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf("Failed to delete container: %s", ct.Name) return } } logf("Starting the cleanup") timeStart := time.Now() for i := 0; i < batches; i++ { for j := 0; j < batch; j++ { wgBatch.Add(1) go deleteContainer(containers[deletedCount]) deletedCount = deletedCount + 1 } wgBatch.Wait() if deletedCount >= nextStat { interval := time.Since(timeStart).Seconds() logf("Deleted %d containers in %.3fs (%.3f/s)", deletedCount, interval, float64(deletedCount)/interval) nextStat = nextStat * 2 } } for k := deletedCount; k < count; k++ { wgBatch.Add(1) go deleteContainer(containers[deletedCount]) deletedCount = deletedCount + 1 } wgBatch.Wait() logf("Cleanup completed") return nil }
func cmdStop(c *lxd.Client, args []string) error { var wgBatch sync.WaitGroup if os.Getuid() != 0 { return fmt.Errorf("Container stop must be run as root.") } // Load the simulation routersMap, err := importFromLXD(c) if err != nil { return err } routers := []*Router{} for _, v := range routersMap { if v.Tier < 1 || v.Tier > 3 { continue } routers = append(routers, v) } // Helper function stopContainer := func(name string) { defer wgBatch.Done() resp, err := c.Action(name, "stop", -1, true, false) if err != nil { return } err = c.WaitForSuccess(resp.Operation) if err != nil { return } } // Stop the containers batch := 8 batches := len(routers) / batch remainder := len(routers) % batch current := 0 for i := 0; i < batches; i++ { for j := 0; j < batch; j++ { wgBatch.Add(1) go stopContainer(routers[current].Name) current += 1 } wgBatch.Wait() } for k := 0; k < remainder; k++ { wgBatch.Add(1) go stopContainer(routers[current].Name) current += 1 } wgBatch.Wait() // Destroy all the interfaces err = networkDestroy(routersMap) if err != nil { return err } return nil }
func cmdStart(c *lxd.Client, args []string) error { var wgBatch sync.WaitGroup if os.Getuid() != 0 { return fmt.Errorf("Container startup must be run as root.") } // Load the simulation routersMap, err := importFromLXD(c) if err != nil { return err } routers := []*Router{} for _, v := range routersMap { if v.Tier < 1 || v.Tier > 3 { continue } routers = append(routers, v) } // Create all the needed interfaces logf("Creating the network interfaces") err = networkCreate(routersMap) if err != nil { return err } // Helper function startContainer := func(name string) { defer wgBatch.Done() resp, err := c.Action(name, "start", -1, false, false) if err != nil { logf("Failed to start container '%s': %s", name, err) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf("Failed to start container '%s': %s", name, err) return } } // Start the containers batch := 8 batches := len(routers) / batch remainder := len(routers) % batch logf("Starting the containers") current := 0 for i := 0; i < batches; i++ { for j := 0; j < batch; j++ { wgBatch.Add(1) go startContainer(routers[current].Name) current += 1 } wgBatch.Wait() } for k := 0; k < remainder; k++ { wgBatch.Add(1) go startContainer(routers[current].Name) current += 1 } wgBatch.Wait() logf("%d containers started", len(routers)) return nil }
func cmdDestroy(c *lxd.Client, args []string) error { var wgBatch sync.WaitGroup if os.Getuid() != 0 { return fmt.Errorf("Container destruction must be run as root.") } // Load the simulation routersMap, err := importFromLXD(c) if err != nil { return err } routers := []*Router{} for _, v := range routersMap { if v.Tier < 1 || v.Tier > 3 { continue } routers = append(routers, v) } // Load the LXD container list containers, err := c.ListContainers() if err != nil { return err } containersMap := map[string]api.Container{} for _, ctn := range containers { containersMap[ctn.Name] = ctn } // Helper function deleteContainer := func(name string) { defer wgBatch.Done() ct, ok := containersMap[name] if !ok { logf("Failed to delete container: %s: Doesn't exist", ct.Name) return } // Stop if ct.IsActive() { resp, err := c.Action(ct.Name, "stop", -1, true, false) if err != nil { logf("Failed to delete container: %s: %s", ct.Name, err) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf("Failed to delete container: %s: %s", ct.Name, err) return } } // Delete resp, err := c.Delete(ct.Name) if err != nil { logf("Failed to delete container: %s: %s", ct.Name, err) return } err = c.WaitForSuccess(resp.Operation) if err != nil { logf("Failed to delete container: %s: %s", ct.Name, err) return } } // Delete all the containers batch := 8 batches := len(routers) / batch remainder := len(routers) % batch current := 0 for i := 0; i < batches; i++ { for j := 0; j < batch; j++ { wgBatch.Add(1) go deleteContainer(routers[current].Name) current += 1 } wgBatch.Wait() } for k := 0; k < remainder; k++ { wgBatch.Add(1) go deleteContainer(routers[current].Name) current += 1 } wgBatch.Wait() // Destroy all the interfaces err = networkDestroy(routersMap) if err != nil { return err } return nil }