diff options
author | Flavio Castelli <fcastelli@suse.com> | 2016-07-04 19:03:45 +0200 |
---|---|---|
committer | Flavio Castelli <fcastelli@suse.com> | 2016-07-20 13:11:13 +0200 |
commit | c5661d890f83f2e118f89867a0edf73dc1da282e (patch) | |
tree | fd1e488f769a2c01a318e75ff542216b9f43df3a /libvirt/qemu_agent.go | |
parent | 0cc42cc992323bcd42db36536227d8616dca3189 (diff) | |
download | terraform-provider-libvirt-c5661d890f83f2e118f89867a0edf73dc1da282e.tar terraform-provider-libvirt-c5661d890f83f2e118f89867a0edf73dc1da282e.tar.gz |
Discover IP address of the network cards attached to a LAN
When a network card is attached to a LAN the `domain.ListAllInterfaceAddresses`
API cannot be used to get the IP address associated with the interfaces.
The only solution to this problem is to use the [Qemu guest agent](http://wiki.libvirt.org/page/Qemu_guest_agent)
to fetch this information.
This PR will take advantage of the qemu guest ageint (when installed
inside of the domain) to workaround the limitations of the
`domain.ListAllInterfaceAddresses`.
In theory this PR could also allow to relax the required version of
libvirt.
Signed-off-by: Flavio Castelli <fcastelli@suse.com>
Diffstat (limited to 'libvirt/qemu_agent.go')
-rw-r--r-- | libvirt/qemu_agent.go | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/libvirt/qemu_agent.go b/libvirt/qemu_agent.go new file mode 100644 index 00000000..10bf45cc --- /dev/null +++ b/libvirt/qemu_agent.go @@ -0,0 +1,90 @@ +package libvirt + +import ( + "encoding/json" + "log" + "strings" + + libvirt "github.com/dmacvicar/libvirt-go" +) + +type QemuAgentInterfacesResponse struct { + Interfaces []QemuAgentInterface `json:"return"` +} + +type QemuAgentInterface struct { + Name string `json:"name"` + Hwaddr string `json:"hardware-address"` + IpAddresses []struct { + Type string `json:"ip-address-type"` + Address string `json:"ip-address"` + Prefix uint `json:"prefix"` + } `json:"ip-addresses"` +} + +// Retrieve all the interfaces attached to a domain and their addresses. Only +// the interfaces with at least an IP address are returned. +// When wait4ipv4 is turned on the code will not report interfaces that don't +// have a ipv4 address set. This is useful when a domain gets the ipv6 address +// before the ipv4 one. +func getDomainInterfacesViaQemuAgent(domain *libvirt.VirDomain, wait4ipv4 bool) []libvirt.VirDomainInterface { + log.Print("[DEBUG] get network interfaces using qemu agent") + + var interfaces []libvirt.VirDomainInterface + + result := domain.QemuAgentCommand( + "{\"execute\":\"guest-network-get-interfaces\"}", + libvirt.VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, + 0) + + log.Printf("[DEBUG] qemu-agent response: %s", result) + + response := QemuAgentInterfacesResponse{} + if err := json.Unmarshal([]byte(result), &response); err != nil { + log.Printf("[DEBUG] Error converting Qemu agent response about domain interfaces: %s", err) + log.Printf("[DEBUG] Original message: %s", response) + log.Print("[DEBUG] Returning an empty list of interfaces") + return interfaces + } + log.Printf("[DEBUG] Parsed response %+v", response) + + for _, iface := range response.Interfaces { + if iface.Name == "lo" { + // ignore loopback interface + continue + } + + libVirtIface := libvirt.VirDomainInterface{} + libVirtIface.Name = iface.Name + libVirtIface.Hwaddr = iface.Hwaddr + + ipv4Assigned := false + for _, addr := range iface.IpAddresses { + if addr.Address == "" { + // ignore interfaces without an address (eg. waiting for dhcp lease) + continue + } + + libVirtAddr := libvirt.VirDomainIPAddress{} + libVirtAddr.Addr = addr.Address + libVirtAddr.Prefix = addr.Prefix + switch strings.ToLower(addr.Type) { + case "ipv4": + libVirtAddr.Type = libvirt.VIR_IP_ADDR_TYPE_IPV4 + ipv4Assigned = true + case "ipv6": + libVirtAddr.Type = libvirt.VIR_IP_ADDR_TYPE_IPV6 + default: + log.Printf("[ERROR] Cannot handle unknown address type %s", addr.Type) + } + libVirtIface.Addrs = append(libVirtIface.Addrs, libVirtAddr) + } + if len(libVirtIface.Addrs) > 0 && (ipv4Assigned || !wait4ipv4) { + interfaces = append(interfaces, libVirtIface) + } + } + + log.Printf("[DEBUG] Interfaces obtained via qemu Agent: %+v", interfaces) + + return interfaces +} |