Beispiel #1
0
func (c *profileCmd) doProfileRemove(client *lxd.Client, d string, p string) error {
	ct, err := client.ContainerInfo(d)
	if err != nil {
		return err
	}

	if !shared.StringInSlice(p, ct.Profiles) {
		return fmt.Errorf("Profile %s isn't currently applied to %s", p, d)
	}

	profiles := []string{}
	for _, profile := range ct.Profiles {
		if profile == p {
			continue
		}

		profiles = append(profiles, profile)
	}

	ct.Profiles = profiles

	err = client.UpdateContainerConfig(d, ct.Brief())
	if err != nil {
		return err
	}

	fmt.Printf(i18n.G("Profile %s removed from %s")+"\n", p, d)

	return err
}
Beispiel #2
0
func (c *networkCmd) doNetworkDetach(client *lxd.Client, name string, args []string) error {
	if len(args) < 1 || len(args) > 2 {
		return errArgs
	}

	containerName := args[0]
	devName := ""
	if len(args) > 1 {
		devName = args[1]
	}

	container, err := client.ContainerInfo(containerName)
	if err != nil {
		return err
	}

	if devName == "" {
		for n, d := range container.Devices {
			if d["type"] == "nic" && d["parent"] == name {
				if devName != "" {
					return fmt.Errorf(i18n.G("More than one device matches, specify the device name."))
				}

				devName = n
			}
		}
	}

	if devName == "" {
		return fmt.Errorf(i18n.G("No device found for this network"))
	}

	device, ok := container.Devices[devName]
	if !ok {
		return fmt.Errorf(i18n.G("The specified device doesn't exist"))
	}

	if device["type"] != "nic" || device["parent"] != name {
		return fmt.Errorf(i18n.G("The specified device doesn't match the network"))
	}

	resp, err := client.ContainerDeviceDelete(containerName, devName)
	if err != nil {
		return err
	}

	return client.WaitForSuccess(resp.Operation)
}
Beispiel #3
0
Datei: init.go Projekt: vahe/lxd
func (c *initCmd) checkNetwork(d *lxd.Client, name string) {
	ct, err := d.ContainerInfo(name)
	if err != nil {
		return
	}

	for _, d := range ct.ExpandedDevices {
		if d["type"] == "nic" {
			return
		}
	}

	fmt.Fprintf(os.Stderr, "\n"+i18n.G("The container you are starting doesn’t have any network attached to it.")+"\n")
	fmt.Fprintf(os.Stderr, "  "+i18n.G("To create a new network, use: lxc network create")+"\n")
	fmt.Fprintf(os.Stderr, "  "+i18n.G("To assign a network to a container, use: lxc network assign")+"\n\n")
}
Beispiel #4
0
func (c *profileCmd) doProfileAdd(client *lxd.Client, d string, p string) error {
	ct, err := client.ContainerInfo(d)
	if err != nil {
		return err
	}

	ct.Profiles = append(ct.Profiles, p)

	err = client.UpdateContainerConfig(d, ct.Brief())
	if err != nil {
		return err
	}

	fmt.Printf(i18n.G("Profile %s added to %s")+"\n", p, d)

	return err
}
Beispiel #5
0
func (c *configCmd) doContainerConfigEdit(client *lxd.Client, cont 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.BriefContainerInfo{}
		err = yaml.Unmarshal(contents, &newdata)
		if err != nil {
			return err
		}
		return client.UpdateContainerConfig(cont, newdata)
	}

	// Extract the current value
	config, err := client.ContainerInfo(cont)
	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.configEditHelp()+"\n\n"+string(data)))
	if err != nil {
		return err
	}

	for {
		// Parse the text received from the editor
		newdata := shared.BriefContainerInfo{}
		err = yaml.Unmarshal(content, &newdata)
		if err == nil {
			err = client.UpdateContainerConfig(cont, 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
}
Beispiel #6
0
func (c *infoCmd) containerInfo(d *lxd.Client, name string, showLog bool) error {
	ct, err := d.ContainerInfo(name)
	if err != nil {
		return err
	}

	cs, err := d.ContainerState(name)
	if err != nil {
		return err
	}

	const layout = "2006/01/02 15:04 UTC"

	fmt.Printf(i18n.G("Name: %s")+"\n", ct.Name)
	fmt.Printf(i18n.G("Architecture: %s")+"\n", ct.Architecture)
	if ct.CreationDate.UTC().Unix() != 0 {
		fmt.Printf(i18n.G("Created: %s")+"\n", ct.CreationDate.UTC().Format(layout))
	}

	fmt.Printf(i18n.G("Status: %s")+"\n", ct.Status)
	if ct.Ephemeral {
		fmt.Printf(i18n.G("Type: ephemeral") + "\n")
	} else {
		fmt.Printf(i18n.G("Type: persistent") + "\n")
	}
	fmt.Printf(i18n.G("Profiles: %s")+"\n", strings.Join(ct.Profiles, ", "))
	if cs.Pid != 0 {
		fmt.Printf(i18n.G("Pid: %d")+"\n", cs.Pid)
		fmt.Printf(i18n.G("Processes: %d")+"\n", cs.Processes)

		ipInfo := ""
		for netName, net := range cs.Network {
			vethStr := ""
			if net.HostName != "" {
				vethStr = fmt.Sprintf("\t%s", net.HostName)
			}

			for _, addr := range net.Addresses {
				ipInfo += fmt.Sprintf("  %s:\t%s\t%s%s\n", netName, addr.Family, addr.Address, vethStr)
			}
		}

		if ipInfo != "" {
			fmt.Printf(i18n.G("Ips:") + "\n")
			fmt.Printf(ipInfo)
		}
	}

	// List snapshots
	first_snapshot := true
	snaps, err := d.ListSnapshots(name)
	if err != nil {
		return nil
	}

	for _, snap := range snaps {
		if first_snapshot {
			fmt.Println(i18n.G("Snapshots:"))
		}
		fmt.Printf("  %s", snap.Name)

		if snap.CreationDate.UTC().Unix() != 0 {
			fmt.Printf(" ("+i18n.G("taken at %s")+")", snap.CreationDate.UTC().Format(layout))
		}

		if snap.Stateful {
			fmt.Printf(" (" + i18n.G("stateful") + ")")
		} else {
			fmt.Printf(" (" + i18n.G("stateless") + ")")
		}
		fmt.Printf("\n")

		first_snapshot = false
	}

	if showLog {
		log, err := d.GetLog(name, "lxc.log")
		if err != nil {
			return err
		}

		stuff, err := ioutil.ReadAll(log)
		if err != nil {
			return err
		}

		fmt.Printf("\n"+i18n.G("Log:")+"\n\n%s\n", string(stuff))
	}

	return nil
}
Beispiel #7
0
Datei: info.go Projekt: vahe/lxd
func (c *infoCmd) containerInfo(d *lxd.Client, name string, showLog bool) error {
	ct, err := d.ContainerInfo(name)
	if err != nil {
		return err
	}

	cs, err := d.ContainerState(name)
	if err != nil {
		return err
	}

	const layout = "2006/01/02 15:04 UTC"

	fmt.Printf(i18n.G("Name: %s")+"\n", ct.Name)
	if d.Remote != nil && d.Remote.Addr != "" {
		fmt.Printf(i18n.G("Remote: %s")+"\n", d.Remote.Addr)
	}
	fmt.Printf(i18n.G("Architecture: %s")+"\n", ct.Architecture)
	if ct.CreationDate.UTC().Unix() != 0 {
		fmt.Printf(i18n.G("Created: %s")+"\n", ct.CreationDate.UTC().Format(layout))
	}

	fmt.Printf(i18n.G("Status: %s")+"\n", ct.Status)
	if ct.Ephemeral {
		fmt.Printf(i18n.G("Type: ephemeral") + "\n")
	} else {
		fmt.Printf(i18n.G("Type: persistent") + "\n")
	}
	fmt.Printf(i18n.G("Profiles: %s")+"\n", strings.Join(ct.Profiles, ", "))
	if cs.Pid != 0 {
		fmt.Printf(i18n.G("Pid: %d")+"\n", cs.Pid)

		// IP addresses
		ipInfo := ""
		if cs.Network != nil {
			for netName, net := range cs.Network {
				vethStr := ""
				if net.HostName != "" {
					vethStr = fmt.Sprintf("\t%s", net.HostName)
				}

				for _, addr := range net.Addresses {
					ipInfo += fmt.Sprintf("  %s:\t%s\t%s%s\n", netName, addr.Family, addr.Address, vethStr)
				}
			}
		}

		if ipInfo != "" {
			fmt.Println(i18n.G("Ips:"))
			fmt.Printf(ipInfo)
		}
		fmt.Println(i18n.G("Resources:"))

		// Processes
		fmt.Printf("  "+i18n.G("Processes: %d")+"\n", cs.Processes)

		// Disk usage
		diskInfo := ""
		if cs.Disk != nil {
			for entry, disk := range cs.Disk {
				if disk.Usage != 0 {
					diskInfo += fmt.Sprintf("    %s: %s\n", entry, shared.GetByteSizeString(disk.Usage))
				}
			}
		}

		if diskInfo != "" {
			fmt.Println(i18n.G("  Disk usage:"))
			fmt.Printf(diskInfo)
		}

		// CPU usage
		cpuInfo := ""
		if cs.CPU.Usage != 0 {
			cpuInfo += fmt.Sprintf("    %s: %v\n", i18n.G("CPU usage (in seconds)"), cs.CPU.Usage/1000000000)
		}

		if cpuInfo != "" {
			fmt.Println(i18n.G("  CPU usage:"))
			fmt.Printf(cpuInfo)
		}

		// Memory usage
		memoryInfo := ""
		if cs.Memory.Usage != 0 {
			memoryInfo += fmt.Sprintf("    %s: %s\n", i18n.G("Memory (current)"), shared.GetByteSizeString(cs.Memory.Usage))
		}

		if cs.Memory.UsagePeak != 0 {
			memoryInfo += fmt.Sprintf("    %s: %s\n", i18n.G("Memory (peak)"), shared.GetByteSizeString(cs.Memory.UsagePeak))
		}

		if cs.Memory.SwapUsage != 0 {
			memoryInfo += fmt.Sprintf("    %s: %s\n", i18n.G("Swap (current)"), shared.GetByteSizeString(cs.Memory.SwapUsage))
		}

		if cs.Memory.SwapUsagePeak != 0 {
			memoryInfo += fmt.Sprintf("    %s: %s\n", i18n.G("Swap (peak)"), shared.GetByteSizeString(cs.Memory.SwapUsagePeak))
		}

		if memoryInfo != "" {
			fmt.Println(i18n.G("  Memory usage:"))
			fmt.Printf(memoryInfo)
		}

		// Network usage
		networkInfo := ""
		if cs.Network != nil {
			for netName, net := range cs.Network {
				networkInfo += fmt.Sprintf("    %s:\n", netName)
				networkInfo += fmt.Sprintf("      %s: %s\n", i18n.G("Bytes received"), shared.GetByteSizeString(net.Counters.BytesReceived))
				networkInfo += fmt.Sprintf("      %s: %s\n", i18n.G("Bytes sent"), shared.GetByteSizeString(net.Counters.BytesSent))
				networkInfo += fmt.Sprintf("      %s: %d\n", i18n.G("Packets received"), net.Counters.PacketsReceived)
				networkInfo += fmt.Sprintf("      %s: %d\n", i18n.G("Packets sent"), net.Counters.PacketsSent)
			}
		}

		if networkInfo != "" {
			fmt.Println(i18n.G("  Network usage:"))
			fmt.Printf(networkInfo)
		}
	}

	// List snapshots
	first_snapshot := true
	snaps, err := d.ListSnapshots(name)
	if err != nil {
		return nil
	}

	for _, snap := range snaps {
		if first_snapshot {
			fmt.Println(i18n.G("Snapshots:"))
		}

		fields := strings.Split(snap.Name, shared.SnapshotDelimiter)
		fmt.Printf("  %s", fields[len(fields)-1])

		if snap.CreationDate.UTC().Unix() != 0 {
			fmt.Printf(" ("+i18n.G("taken at %s")+")", snap.CreationDate.UTC().Format(layout))
		}

		if snap.Stateful {
			fmt.Printf(" (" + i18n.G("stateful") + ")")
		} else {
			fmt.Printf(" (" + i18n.G("stateless") + ")")
		}
		fmt.Printf("\n")

		first_snapshot = false
	}

	if showLog {
		log, err := d.GetLog(name, "lxc.log")
		if err != nil {
			return err
		}

		stuff, err := ioutil.ReadAll(log)
		if err != nil {
			return err
		}

		fmt.Printf("\n"+i18n.G("Log:")+"\n\n%s\n", string(stuff))
	}

	return nil
}
Beispiel #8
0
func cmdCreate(c *lxd.Client, args []string) error {
	var wgBatch sync.WaitGroup

	// A path must be provided
	if len(args) < 1 {
		return fmt.Errorf("A path must be passed to create.")
	}

	// Load the simulation
	routersMap, err := importFromCSV(args[0])
	if err != nil {
		return err
	}

	routers := []*Router{}
	for _, v := range routersMap {
		if v.Tier < 1 {
			continue
		}

		routers = append(routers, v)
	}

	// Clear any existing images
	fp := c.GetAlias("internet-router")
	if fp != "" {
		logf("Deleting the existing router image: %s", fp)
		err = c.DeleteImage(fp)
		if err != nil {
			return err
		}
	}

	// Load the image
	logf("Importing the router image")
	_, err = c.PostImage("image/image-meta.tar.xz", "image/image-rootfs.tar.xz", nil, false, []string{"internet-router"}, nil)
	if err != nil {
		return err
	}
	logf("New router image imported: %s", fp)

	// Create the profile
	_, err = c.ProfileConfig("internet-base")
	if err != nil {
		logf("Creating the profile")
		err := c.ProfileCreate("internet-base")
		if err != nil {
			return err
		}
	}

	// Helper function
	createContainer := func(router *Router) {
		defer wgBatch.Done()

		var interfaces string
		var bgpd string

		// Configuration
		config := map[string]string{}
		devices := map[string]map[string]string{}

		config["user.internet.type"] = "router"
		config["user.internet.organization"] = router.Organization
		config["user.internet.priority"] = fmt.Sprintf("%d", router.Priority)
		config["user.internet.tier"] = fmt.Sprintf("%d", router.Tier)
		config["user.internet.location"] = router.Location

		for i, r := range router.DNS {
			config[fmt.Sprintf("user.internet.dns.%d", i)] = r
		}

		config["user.internet.router.fqdn"] = router.Configuration.FQDN
		config["user.internet.router.asn"] = fmt.Sprintf("%d", router.Configuration.ASN)
		config["user.internet.router.password.login"] = router.Configuration.PasswordLogin
		config["user.internet.router.password.enable"] = router.Configuration.PasswordEnable
		if router.Configuration.RouterID != nil {
			config["user.internet.router.routerid"] = router.Configuration.RouterID.String()
		}

		if router.Internal {
			config["user.internet.internal"] = "true"
		} else {
			config["user.internet.internal"] = "false"
		}

		if router.Tier >= 1 && router.Tier <= 3 {
			interfaces = fmt.Sprintf(`auto lo
iface lo inet loopback
    pre-up echo 0 > /proc/sys/net/ipv6/conf/all/accept_dad || true
    post-up echo 1 > /proc/sys/net/ipv6/conf/all/forwarding || true

auto local
iface local inet6 manual
    pre-up ip link add local type dummy || true
    pre-up ip link set local up || true
`)
		}

		for i, r := range router.Configuration.Loopback.Addresses {
			config[fmt.Sprintf("user.internet.router.loopback.address.%d", i)] = r.String()
			if router.Tier >= 1 && router.Tier <= 3 {
				interfaces += fmt.Sprintf("    post-up ip -6 addr add dev local %s/128 || true\n", r.String())
			}
		}

		for i, r := range router.Configuration.Loopback.Routes {
			config[fmt.Sprintf("user.internet.router.loopback.route.%d.subnet", i)] = r.Subnet.String()
			if router.Tier >= 1 && router.Tier <= 3 {
				interfaces += fmt.Sprintf("    post-up sleep 10 ; ip -6 route add dev local %s || true\n", r.Subnet.String())
			}
		}

		if router.Tier >= 1 && router.Tier <= 3 {
			bgpd = fmt.Sprintf(fmt.Sprintf(`hostname %s
password %s
enable password %s

router bgp %d
 bgp router-id %s
 no bgp default ipv4-unicast
`, router.Name, router.Configuration.PasswordLogin, router.Configuration.PasswordEnable, router.Configuration.ASN, router.Configuration.RouterID.String()))
		}

		if router.Peers != nil {
			for _, p := range router.Peers {
				if strings.HasPrefix(p.Interface, "v") {
					device := map[string]string{
						"type":    "nic",
						"nictype": "physical",
						"name":    p.Interface,
						"parent":  p.Interface,
						"hwaddr":  p.MAC,
					}
					devices[p.Interface] = device
				} else if strings.HasPrefix(p.Interface, "br") {
					device := map[string]string{
						"type":    "nic",
						"nictype": "bridged",
						"name":    p.Interface,
						"parent":  p.Interface,
						"hwaddr":  p.MAC,
					}
					devices[p.Interface] = device
				} else {
					logf("Failed to configure container '%s': Bad interface name: %s", router.Name, p.Interface)
					return
				}

				if router.Tier >= 1 && router.Tier <= 3 {
					interfaces += fmt.Sprintf(`
auto %s
iface %s inet6 manual
    post-up tc qdisc add dev %s root netem delay %dms || true
    post-up tc qdisc add dev %s root netem rate %dmbit || true
`, p.Interface, p.Interface, p.Interface, p.Delay, p.Interface, p.Speed)

					if p.ASN != 0 {
						bgpd += fmt.Sprintf(`
 neighbor %s remote-as %d
 neighbor %s weight %d
 neighbor %s interface %s

`, p.Remote, p.ASN, p.Remote, p.Weight, p.Remote, p.Interface)
					}
				}

				config[fmt.Sprintf("user.internet.peer.%s.interface", p.Name)] = p.Interface
				config[fmt.Sprintf("user.internet.peer.%s.mac", p.Name)] = p.MAC
				config[fmt.Sprintf("user.internet.peer.%s.remote", p.Name)] = p.Remote
				config[fmt.Sprintf("user.internet.peer.%s.speed", p.Name)] = fmt.Sprintf("%d", p.Speed)
				config[fmt.Sprintf("user.internet.peer.%s.delay", p.Name)] = fmt.Sprintf("%d", p.Delay)
				config[fmt.Sprintf("user.internet.peer.%s.asn", p.Name)] = fmt.Sprintf("%d", p.ASN)
				config[fmt.Sprintf("user.internet.peer.%s.weight", p.Name)] = fmt.Sprintf("%d", p.Weight)

				if p.Routes != nil {
					for i, r := range p.Routes {
						config[fmt.Sprintf("user.internet.peer.%s.route.%d.subnet", p.Name, i)] = r.Subnet.String()
						if r.Gateway != nil {
							config[fmt.Sprintf("user.internet.peer.%s.route.%d.gateway", p.Name, i)] = r.Gateway.String()
							if router.Tier >= 1 && router.Tier <= 3 {
								interfaces += fmt.Sprintf("    post-up sleep 10 ; ip -6 route add dev %s %s via %s || true\n", p.Interface, r.Subnet.String(), r.Gateway.String())
							}
						} else {
							if router.Tier >= 1 && router.Tier <= 3 {
								interfaces += fmt.Sprintf("    post-up sleep 10 ; ip -6 route add dev %s %s via %s || true\n", p.Interface, r.Subnet.String(), p.Remote)
							}
						}
					}
				}
			}
		}

		if router.Tier >= 1 && router.Tier <= 3 {
			bgpd += " address-family ipv6\n"

			if router.Peers != nil {
				for _, p := range router.Peers {
					if p.ASN != 0 {
						bgpd += fmt.Sprintf("  neighbor %s activate\n", p.Remote)
					}
				}
			}

			bgpd += `  redistribute connected
  redistribute kernel
 exit-address-family
`

			config["user.internet.config.interfaces"] = interfaces
			config["user.internet.config.bgpd"] = bgpd
		}

		// Config-only containers
		if router.Tier > 3 {
			ct, err := c.ContainerInfo(router.Name)
			if err != nil {
				logf("Failed to configure container '%s': %s", router.Name, err)
				return
			}

			for k, _ := range ct.Config {
				if strings.HasPrefix(k, "user.internet.") {
					delete(ct.Config, k)
				}
			}

			for k, v := range config {
				ct.Config[k] = v
			}

			err = c.UpdateContainerConfig(router.Name, ct.Writable())
			if err != nil {
				logf("Failed to configure container '%s': %s", router.Name, err)
				return
			}

			return
		}

		// Create the container
		resp, err := c.Init(router.Name, "local", "internet-router", &[]string{"internet-base"}, config, nil, false)
		if err != nil {
			logf("Failed to create container '%s': %s", router.Name, err)
			return
		}

		err = c.WaitForSuccess(resp.Operation)
		if err != nil {
			logf("Failed to create container '%s': %s", router.Name, err)
			return
		}

		// Setup the devices
		ct, err := c.ContainerInfo(router.Name)
		if err != nil {
			logf("Failed to configure container '%s': %s", router.Name, err)
			return
		}

		for k, v := range devices {
			ct.Devices[k] = v
		}

		err = c.UpdateContainerConfig(router.Name, ct.Writable())
		if err != nil {
			logf("Failed to configure container '%s': %s", router.Name, err)
			return
		}
	}

	// Create the containers
	batch := 8
	batches := len(routers) / batch
	remainder := len(routers) % batch

	logf("Creating the containers")
	current := 0
	for i := 0; i < batches; i++ {
		for j := 0; j < batch; j++ {
			wgBatch.Add(1)
			go createContainer(routers[current])
			current += 1
		}
		wgBatch.Wait()
	}

	for k := 0; k < remainder; k++ {
		wgBatch.Add(1)
		go createContainer(routers[current])
		current += 1
	}
	wgBatch.Wait()
	logf("%d containers created", len(routers))

	return nil
}