-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit allows virter to create new virtual networks, optionally with DHCP and NAT. It also allows adding interfaces when creating VMs, similar to the way additional disks can be provisioned. The following new commands are introduced: * network ls, showing all currently started networks * network add, adding a new virtual network * network rm, removing an existing network * network list-attached, listing VMs attached to a network The following commands are updated: * vm run: added the `--nic` flag to add network interfaces (like `--disk`) The main motivation for adding this was work on a multinode openstack CI system, which work best if openstack has complete control over a single interface.
- Loading branch information
Showing
26 changed files
with
812 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package cmd | ||
|
||
import ( | ||
libvirtxml "github.com/libvirt/libvirt-go-xml" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
"net" | ||
) | ||
|
||
func networkAddCommand() *cobra.Command { | ||
var forward string | ||
var dhcp bool | ||
var network string | ||
var domain string | ||
|
||
addCmd := &cobra.Command{ | ||
Use: "add <name>", | ||
Short: "Add a new network", | ||
Long: `Add a new network. VMs can be attached to such a network in addition to the default network used by virter.`, | ||
Args: cobra.ExactArgs(1), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
v, err := InitVirter() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
defer v.ForceDisconnect() | ||
|
||
var forwardDesc *libvirtxml.NetworkForward | ||
if forward != "" { | ||
forwardDesc = &libvirtxml.NetworkForward{ | ||
Mode: forward, | ||
} | ||
} | ||
|
||
var addressesDesc []libvirtxml.NetworkIP | ||
if network != "" { | ||
ip, n, err := net.ParseCIDR(network) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
var dhcpDesc *libvirtxml.NetworkDHCP | ||
if dhcp { | ||
start := nextIP(ip) | ||
end := previousIP(broadcastAddress(n)) | ||
|
||
n.Network() | ||
dhcpDesc = &libvirtxml.NetworkDHCP{ | ||
Ranges: []libvirtxml.NetworkDHCPRange{{Start: start.String(), End: end.String()}}, | ||
} | ||
} | ||
|
||
addressesDesc = append(addressesDesc, libvirtxml.NetworkIP{ | ||
Address: ip.String(), | ||
Netmask: net.IP(n.Mask).String(), | ||
DHCP: dhcpDesc, | ||
}) | ||
} | ||
|
||
var domainDesc *libvirtxml.NetworkDomain | ||
if domain != "" { | ||
domainDesc = &libvirtxml.NetworkDomain{ | ||
Name: domain, | ||
LocalOnly: "yes", | ||
} | ||
} | ||
|
||
desc := libvirtxml.Network{ | ||
Name: args[0], | ||
Forward: forwardDesc, | ||
IPs: addressesDesc, | ||
Domain: domainDesc, | ||
} | ||
|
||
err = v.NetworkAdd(desc) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
}, | ||
} | ||
|
||
addCmd.Flags().StringVarP(&forward, "forward-mode", "m", "", "Set the forward mode, for example 'nat'") | ||
addCmd.Flags().StringVarP(&network, "network-cidr", "n", "", "Configure the network range (IPv4) in CIDR notation. The IP will be assigned to the host device.") | ||
addCmd.Flags().BoolVarP(&dhcp, "dhcp", "p", false, "Configure DHCP. Use together with '--network-cidr'. DHCP range is configured starting from --network-cidr+1 until the broadcast address") | ||
addCmd.Flags().StringVarP(&domain, "domain", "d", "", "Configure DNS names for the network") | ||
return addCmd | ||
} | ||
|
||
func nextIP(ip net.IP) net.IP { | ||
dup := make(net.IP, len(ip)) | ||
copy(dup, ip) | ||
for j := len(dup) - 1; j >= 0; j-- { | ||
dup[j]++ | ||
if dup[j] > 0 { | ||
break | ||
} | ||
} | ||
return dup | ||
} | ||
|
||
func previousIP(ip net.IP) net.IP { | ||
dup := make(net.IP, len(ip)) | ||
copy(dup, ip) | ||
for j := len(dup) - 1; j >= 0; j-- { | ||
dup[j]-- | ||
if dup[j] < 255 { | ||
break | ||
} | ||
} | ||
return dup | ||
} | ||
|
||
func broadcastAddress(ipnet *net.IPNet) net.IP { | ||
dup := make(net.IP, len(ipnet.IP)) | ||
copy(dup, ipnet.IP) | ||
for i := range dup { | ||
dup[i] = dup[i] | ^ipnet.Mask[i] | ||
} | ||
return dup | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/rodaine/table" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func networkListAttachedCommand() *cobra.Command { | ||
listAttachedCmd := &cobra.Command{ | ||
Use: "list-attached <network-name>", | ||
Short: "List VMs attached to a network", | ||
Long: `List VMs attached to a network. Includes IP address and hostname if available.`, | ||
Args: cobra.ExactArgs(1), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
v, err := InitVirter() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
defer v.ForceDisconnect() | ||
|
||
vmnics, err := v.NetworkListAttached(args[0]) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
tbl := table.New("VM", "MAC", "IP", "Hostname", "Host Device") | ||
for _, vmnic := range vmnics { | ||
tbl.AddRow(vmnic.VMName, vmnic.MAC, vmnic.IP, vmnic.HostName, vmnic.HostDevice) | ||
} | ||
tbl.Print() | ||
}, | ||
} | ||
|
||
return listAttachedCmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"github.com/rodaine/table" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/viper" | ||
"net" | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
func networkLsCommand() *cobra.Command { | ||
lsCmd := &cobra.Command{ | ||
Use: "ls", | ||
Short: "List available networks", | ||
Long: `List available networks that VMs can be attached to.`, | ||
Args: cobra.NoArgs, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
v, err := InitVirter() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
defer v.ForceDisconnect() | ||
|
||
xmls, err := v.NetworkList() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
virterNet := viper.GetString("libvirt.network") | ||
|
||
tbl := table.New("Name", "Forward-Type", "IP-Range", "Domain", "DHCP", "Bridge") | ||
for _, desc := range xmls { | ||
name := desc.Name | ||
if name == virterNet { | ||
name = fmt.Sprintf("%s (virter default)", name) | ||
} | ||
ty := "" | ||
if desc.Forward != nil { | ||
ty = desc.Forward.Mode | ||
} | ||
|
||
var ranges []string | ||
netrg := make([]string, len(desc.IPs)) | ||
for i, n := range desc.IPs { | ||
ip := net.ParseIP(n.Address) | ||
mask := net.ParseIP(n.Netmask) | ||
netrg[i] = (&net.IPNet{IP: ip, Mask: net.IPMask(mask)}).String() | ||
|
||
if n.DHCP != nil { | ||
for _, r := range n.DHCP.Ranges { | ||
ranges = append(ranges, fmt.Sprintf("%s-%s", r.Start, r.End)) | ||
} | ||
} | ||
} | ||
netranges := strings.Join(netrg, ",") | ||
|
||
domain := "" | ||
if desc.Domain != nil { | ||
domain = desc.Domain.Name | ||
} | ||
|
||
dhcp := strings.Join(ranges, ",") | ||
|
||
bridge := "" | ||
if desc.Bridge != nil { | ||
bridge = desc.Bridge.Name | ||
} | ||
|
||
tbl.AddRow(name, ty, netranges, domain, dhcp, bridge) | ||
} | ||
|
||
tbl.Print() | ||
}, | ||
} | ||
|
||
return lsCmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package cmd | ||
|
||
import ( | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func networkRmCommand() *cobra.Command { | ||
rmCmd := &cobra.Command{ | ||
Use: "rm <name>", | ||
Short: "Remove a network", | ||
Long: `Remove the named network.`, | ||
Args: cobra.ExactArgs(1), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
v, err := InitVirter() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
defer v.ForceDisconnect() | ||
|
||
err = v.NetworkRemove(args[0]) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
}, | ||
} | ||
return rmCmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/LINBIT/virter/pkg/cliutils" | ||
) | ||
|
||
type NICArg struct { | ||
NicType string `arg:"type"` | ||
Source string `arg:"source"` | ||
Model string `arg:"model,virtio"` | ||
MAC string `arg:"mac,"` | ||
} | ||
|
||
func (n *NICArg) GetType() string { | ||
return n.NicType | ||
} | ||
|
||
func (n *NICArg) GetSource() string { | ||
return n.Source | ||
} | ||
|
||
func (n *NICArg) GetModel() string { | ||
return n.Model | ||
} | ||
|
||
func (n *NICArg) GetMAC() string { | ||
return n.MAC | ||
} | ||
|
||
func (n *NICArg) Set(str string) error { | ||
return cliutils.Parse(str, n) | ||
} | ||
|
||
func (n *NICArg) Type() string { | ||
return "nic" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.