Skip to content

Commit

Permalink
vm rm: try releasing the VMs DHCP lease
Browse files Browse the repository at this point in the history
We have seen some strange effects when IP/MAC addresses are reused. A
solution for this problem is to get rid of the DHCP lease when
destroying the VM.
In order to do that, we have to run dhcp_release, which can only run as
root. We try running it with sudo when removing the machine. If it
doesn't work, we don't complain either.

Note that this requires passwordless sudo for the executing user, at
least for the dhcp_release command. Something along the lines of:

    %libvirt ALL=(ALL) NOPASSWD: /usr/bin/dhcp_release

To allow all users in the libvirt group to execute it.
  • Loading branch information
chrboe committed Jul 29, 2020
1 parent 1915d11 commit d0c20c8
Showing 1 changed file with 33 additions and 0 deletions.
33 changes: 33 additions & 0 deletions internal/virter/dhcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package virter
import (
"fmt"
"net"
"os/exec"

libvirt "github.com/digitalocean/go-libvirt"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -146,6 +147,11 @@ func (v *Virter) rmDHCPEntry(domain libvirt.Domain) error {
}
}

err = v.tryReleaseDHCP(mac, ips, network)
if err != nil {
log.Debugf("Could not release DHCP lease: %v", err)
}

return nil
}

Expand Down Expand Up @@ -283,3 +289,30 @@ func (v *Virter) getVMID(wantedID uint) (uint, error) {

return 0, fmt.Errorf("could not find unused VM id")
}

func (v *Virter) tryReleaseDHCP(mac string, addrs []string, network libvirt.Network) error {
networkDescription, err := getNetworkDescription(v.libvirt, network)
if err != nil {
return err
}

if networkDescription.Bridge == nil {
return fmt.Errorf("network %q is not a bridge, cannot release dhcp", networkDescription.Name)
}
iface := networkDescription.Bridge.Name

for _, addr := range addrs {
log.Debugf("Releasing DHCP lease from %v to %v", mac, addr)
cmd := exec.Command("sudo", "--non-interactive", "dhcp_release", iface, addr, mac)
_, err = cmd.Output()
if err != nil {
if e, ok := err.(*exec.ExitError); ok {
log.Debugf("dhcp_release stderr:\n%s", string(e.Stderr))
}

return fmt.Errorf("failed to run dhcp_release: %w", err)
}
}

return nil
}

0 comments on commit d0c20c8

Please sign in to comment.