Example #1
0
func importFromLXD(c *lxd.Client) (Routers, error) {
	// Load the LXD container list
	containers, err := c.ListContainers()
	if err != nil {
		return nil, err
	}

	// Build the routers map
	routers := Routers{}
	for _, ctn := range containers {
		// Skip the container we don't care about
		if ctn.ExpandedConfig["user.internet.type"] != "router" {
			continue
		}

		config := ctn.ExpandedConfig

		// Generate the new record
		router := Router{}
		router.Configuration = &RouterConfiguration{}

		// Text fields
		router.Organization = config["user.internet.organization"]
		router.Name = ctn.Name
		router.Location = config["user.internet.location"]

		router.Configuration.PasswordLogin = config["user.internet.router.password.login"]
		router.Configuration.PasswordEnable = config["user.internet.router.password.enable"]
		router.Configuration.FQDN = config["user.internet.router.fqdn"]

		routerid := net.ParseIP(config["user.internet.router.routerid"])
		router.Configuration.RouterID = &routerid

		// Integers
		tier, err := strconv.Atoi(config["user.internet.tier"])
		if err != nil {
			return nil, fmt.Errorf("Invalid tier: %s\n", config["user.internet.tier"])
		}
		router.Tier = tier

		asn, err := strconv.Atoi(config["user.internet.router.asn"])
		if err != nil {
			return nil, fmt.Errorf("Invalid ASN: %s\n", config["user.internet.router.asn"])
		}
		router.Configuration.ASN = asn

		priority, err := strconv.Atoi(config["user.internet.priority"])
		if err != nil {
			return nil, fmt.Errorf("Invalid priority: %s\n", config["user.internet.priority"])
		}
		router.Priority = priority

		// Booleans
		if config["user.internet.internal"] == "true" {
			router.Internal = true
		}

		// DNS
		dns := []string{}
		for k, v := range config {
			if !strings.HasPrefix(k, "user.internet.dns.") {
				continue
			}

			dns = append(dns, v)
		}
		router.DNS = dns

		// Loopback
		addresses := []net.IP{}
		routes := []RouterInterfaceRoute{}
		for k, v := range config {
			if strings.HasPrefix(k, "user.internet.router.loopback.address.") {
				addresses = append(addresses, net.ParseIP(v))
				continue
			}

			if strings.HasPrefix(k, "user.internet.router.loopback.route.") {
				_, subnet, err := net.ParseCIDR(v)
				if err != nil {
					return nil, err
				}

				routes = append(routes, RouterInterfaceRoute{Subnet: subnet})
				continue
			}
		}

		// Peers
		peersMap := map[string]*Peer{}

		for k, v := range config {
			if !strings.HasPrefix(k, "user.internet.peer.") {
				continue
			}

			fields := strings.Split(k, ".")
			name := fields[3]
			key := fields[4]

			peer, ok := peersMap[name]
			if !ok {
				peer = &Peer{Name: name}
			}

			switch key {
			case "interface":
				peer.Interface = v
			case "mac":
				peer.MAC = v
			case "remote":
				peer.Remote = v
			case "speed":
				speed, err := strconv.Atoi(v)
				if err != nil {
					return nil, err
				}

				peer.Speed = speed
			case "delay":
				delay, err := strconv.Atoi(v)
				if err != nil {
					return nil, err
				}

				peer.Delay = delay
			case "asn":
				asn, err := strconv.Atoi(v)
				if err != nil {
					return nil, err
				}

				peer.ASN = asn
			case "weight":
				weight, err := strconv.Atoi(v)
				if err != nil {
					return nil, err
				}

				peer.Weight = weight
			}

			peersMap[name] = peer
		}

		peers := []Peer{}

		for _, p := range peersMap {
			i := 0

			routes := []RouterInterfaceRoute{}
			for {
				found := false
				route := RouterInterfaceRoute{}

				v, ok := config[fmt.Sprintf("user.internet.peer.%s.route.%d.subnet", p.Name, i)]
				if ok {
					found = true
					_, subnet, err := net.ParseCIDR(v)
					if err != nil {
						return nil, err
					}

					route.Subnet = subnet
				}

				v, ok = config[fmt.Sprintf("user.internet.peer.%s.route.%d.gateway", p.Name, i)]
				if ok {
					found = true
					gateway := net.ParseIP(v)
					route.Gateway = &gateway
				}

				if !found {
					break
				}

				i += 1

				routes = append(routes, route)
			}

			p.Routes = routes

			peers = append(peers, *p)
		}

		router.Peers = peers
		routers[router.Name] = &router
	}

	return routers, nil
}
Example #2
0
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
}
Example #3
0
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
}