Skip to content

Nat Network Support #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,16 @@ func (m *Machine) Poweroff() error {
case Poweroff, Aborted, Saved:
return nil
}
return Manage().run("controlvm", m.Name, "poweroff")
for m.State != Poweroff { // busy wait until the machine is stopped, because it can lock machine deletion otherwise
if err := Manage().run("controlvm", m.Name, "poweroff"); err != nil {
return err
}
time.Sleep(1 * time.Second)
if err := m.Refresh(); err != nil {
return err
}
}
return nil
}

// Restart gracefully restarts the machine.
Expand Down Expand Up @@ -283,6 +292,8 @@ func GetMachine(id string) (*Machine, error) {
nic.HostInterface = propMap[fmt.Sprintf("hostonlyadapter%d", i)]
} else if nic.Network == NICNetBridged {
nic.HostInterface = propMap[fmt.Sprintf("bridgeadapter%d", i)]
} else if nic.Network == NICNetNATNetwork {
nic.NatNetwork = propMap[fmt.Sprintf("nat-network%d", i)]
}
m.NICs = append(m.NICs, nic)
}
Expand Down Expand Up @@ -405,6 +416,8 @@ func (m *Machine) Modify() error {
args = append(args, fmt.Sprintf("--hostonlyadapter%d", n), nic.HostInterface)
} else if nic.Network == NICNetBridged {
args = append(args, fmt.Sprintf("--bridgeadapter%d", n), nic.HostInterface)
} else if nic.Network == NICNetNATNetwork {
args = append(args, fmt.Sprintf("--nat-network%d", n), nic.NatNetwork)
}
}

Expand Down Expand Up @@ -437,6 +450,8 @@ func (m *Machine) SetNIC(n int, nic NIC) error {
args = append(args, fmt.Sprintf("--hostonlyadapter%d", n), nic.HostInterface)
} else if nic.Network == NICNetBridged {
args = append(args, fmt.Sprintf("--bridgeadapter%d", n), nic.HostInterface)
} else if nic.Network == NICNetNATNetwork {
args = append(args, fmt.Sprintf("--nat-network%d", n), nic.NatNetwork)
}
return Manage().run(args...)
}
Expand Down
61 changes: 58 additions & 3 deletions natnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import (
"bufio"
"net"
"strings"
"errors"
)
var (
ErrNoSuchNet = errors.New("No such NAT network")
)

// A NATNet defines a NAT network.
type NATNet struct {
Name string
Expand All @@ -15,6 +18,59 @@ type NATNet struct {
Enabled bool
}

func (n *NATNet) Delete() error {
err := Manage().run("natnetwork", "remove", "--netname", n.Name)
if err != nil {
return err
}
return nil
}

func (n *NATNet) Config() error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config sounds like a function which will return some configuration. I think making it a verb Configure would portray the effect of this function better.

if n.IPv4.IP != nil && n.IPv4.Mask != nil {
if err := Manage().run("natnetwork", "modify", "--netname", n.Name, "--network", n.IPv4.String()); err != nil {
return err
}
}

if err := Manage().run("natnetwork", "modify", "--netname", n.Name, "--dhcp", bool2string(n.DHCP)); err != nil {
return err
}

if n.Enabled {
if err := Manage().run("natnetwork", "modify", "--netname", n.Name, "--enable"); err != nil {
return err
}
} else {
if err := Manage().run("natnetwork", "modify", "--netname", n.Name, "--disable"); err != nil {
return err
}
}

return nil
}

func CreateNATNet(name string, network string, dhcp bool) (*NATNet, error) {
err := Manage().run("natnetwork", "add", "--netname", name, "--network", network, "--dhcp", bool2string(dhcp))
if err != nil {
return nil, err
}
_, ipnet, err := net.ParseCIDR(network)
return &NATNet{Name: name, IPv4: *ipnet, DHCP: dhcp, Enabled: true}, nil
}

func GetNATNetwork(name string) (*NATNet, error) {
natnets, err := NATNets()
if err != nil {
return nil, err
}
natnet, ok := natnets[name]
if !ok {
return nil, ErrNoSuchNet
}
return &natnet, nil
}

// NATNets gets all NAT networks in a map keyed by NATNet.Name.
func NATNets() (map[string]NATNet, error) {
out, err := Manage().runOut("list", "natnets")
Expand All @@ -38,13 +94,12 @@ func NATNets() (map[string]NATNet, error) {
switch key, val := res[1], res[2]; key {
case "NetworkName":
n.Name = val
case "IP":
n.IPv4.IP = net.ParseIP(val)
case "Network":
_, ipnet, err := net.ParseCIDR(val)
if err != nil {
return nil, err
}
n.IPv4.IP = ipnet.IP
n.IPv4.Mask = ipnet.Mask
case "IPv6 Prefix":
// TODO: IPv6 CIDR parsing works fine on macOS, check on Windows
Expand Down
3 changes: 3 additions & 0 deletions nic.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type NIC struct {
Network NICNetwork
Hardware NICHardware
HostInterface string // The host interface name to bind to in 'hostonly' and 'bridged' mode
NatNetwork string // The nat network to use in 'natnetwork' mode
MacAddr string
}

Expand All @@ -18,6 +19,8 @@ const (
NICNetDisconnected = NICNetwork("null")
// NICNetNAT when the NIC is NAT-ed to access the external network.
NICNetNAT = NICNetwork("nat")
// NICNetNATNetwork when the NIC is on an internal network, with NATed external access.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a potential go fmt error. I have merged a change to update the linting on the CI. I think if you rebase this PR it should show up.

NICNetNATNetwork = NICNetwork("natnetwork")
// NICNetBridged when the NIC is the bridge to the external network.
NICNetBridged = NICNetwork("bridged")
// NICNetInternal when the NIC does not have access to the external network.
Expand Down