summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Saurin <alvaro.saurin@gmail.com>2017-08-21 18:23:13 +0200
committerAlvaro <alvaro.saurin@gmail.com>2017-11-27 13:04:37 +0100
commit39b7567db8477cebf98ca7ff225c2a356b42bd98 (patch)
tree9d474ca7643c0763710fd827ea22813f66d0d43d
parenta4e19162a53ec97402eba79aa1a5b28b55743cf3 (diff)
downloadterraform-provider-libvirt-39b7567db8477cebf98ca7ff225c2a356b42bd98.tar
terraform-provider-libvirt-39b7567db8477cebf98ca7ff225c2a356b42bd98.tar.gz
Retry the query about interfaces to the qemu-agent
-rw-r--r--libvirt/qemu_agent.go135
-rw-r--r--libvirt/resource_libvirt_domain.go4
2 files changed, 81 insertions, 58 deletions
diff --git a/libvirt/qemu_agent.go b/libvirt/qemu_agent.go
index b884f7c4..fd7cef39 100644
--- a/libvirt/qemu_agent.go
+++ b/libvirt/qemu_agent.go
@@ -4,7 +4,9 @@ import (
"encoding/json"
"log"
"strings"
+ "time"
+ "github.com/hashicorp/terraform/helper/resource"
libvirt "github.com/libvirt/libvirt-go"
)
@@ -27,75 +29,96 @@ type QemuAgentInterfaceIPAddress struct {
Prefix uint `json:"prefix"`
}
-// 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 Domain, wait4ipv4 bool) []libvirt.DomainInterface {
- log.Print("[DEBUG] get network interfaces using qemu agent")
+func qemuAgentInterfacesRefreshFunc(domain LibVirtDomain, wait4ipv4 bool) resource.StateRefreshFunc {
+ return func() (interface{}, string, error) {
- var interfaces []libvirt.DomainInterface
+ var interfaces []libvirt.DomainInterface
- result, err := domain.QemuAgentCommand(
- "{\"execute\":\"guest-network-get-interfaces\"}",
- libvirt.DOMAIN_QEMU_AGENT_COMMAND_DEFAULT,
- 0)
- if err != nil {
- return interfaces
- }
-
- log.Printf("[DEBUG] qemu-agent response: %s", result)
+ log.Printf("[DEBUG] sending command to qemu-agent in %s", domain)
+ result, err := domain.QemuAgentCommand(
+ "{\"execute\":\"guest-network-get-interfaces\"}",
+ libvirt.DOMAIN_QEMU_AGENT_COMMAND_DEFAULT,
+ 0)
+ if err != nil {
+ log.Printf("[DEBUG] command error: %s", err)
+ return interfaces, "failed", nil
+ }
- 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: %v", response)
- log.Print("[DEBUG] Returning an empty list of interfaces")
- return interfaces
- }
- log.Printf("[DEBUG] Parsed response %+v", response)
+ log.Printf("[DEBUG] qemu-agent response: %s", result)
- for _, iface := range response.Interfaces {
- if iface.Name == "lo" {
- // ignore loopback interface
- continue
+ 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, "fatal", nil
}
+ log.Printf("[DEBUG] Parsed response %+v", response)
- libVirtIface := libvirt.DomainInterface{
- Name: iface.Name,
- Hwaddr: iface.Hwaddr}
-
- ipv4Assigned := false
- for _, addr := range iface.IPAddresses {
- if addr.Address == "" {
- // ignore interfaces without an address (eg. waiting for dhcp lease)
+ for _, iface := range response.Interfaces {
+ if iface.Name == "lo" {
+ // ignore loopback interface
continue
}
- libVirtAddr := libvirt.DomainIPAddress{
- Addr: addr.Address,
- Prefix: addr.Prefix,
+ libVirtIface := libvirt.DomainInterface{
+ Name: iface.Name,
+ 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.DomainIPAddress{
+ Addr: addr.Address,
+ Prefix: addr.Prefix,
+ }
+
+ switch strings.ToLower(addr.Type) {
+ case "ipv4":
+ libVirtAddr.Type = int(libvirt.IP_ADDR_TYPE_IPV4)
+ ipv4Assigned = true
+ case "ipv6":
+ libVirtAddr.Type = int(libvirt.IP_ADDR_TYPE_IPV6)
+ default:
+ log.Printf("[ERROR] Cannot handle unknown address type %s", addr.Type)
+ continue
+ }
+ libVirtIface.Addrs = append(libVirtIface.Addrs, libVirtAddr)
}
-
- switch strings.ToLower(addr.Type) {
- case "ipv4":
- libVirtAddr.Type = int(libvirt.IP_ADDR_TYPE_IPV4)
- ipv4Assigned = true
- case "ipv6":
- libVirtAddr.Type = int(libvirt.IP_ADDR_TYPE_IPV6)
- default:
- log.Printf("[ERROR] Cannot handle unknown address type %s", addr.Type)
- continue
+ if len(libVirtIface.Addrs) > 0 && (ipv4Assigned || !wait4ipv4) {
+ interfaces = append(interfaces, libVirtIface)
}
- 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, "success", nil
+ }
+}
+
+// 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 LibVirtDomain, wait4ipv4 bool) []libvirt.DomainInterface {
+
+ qemuAgentQuery := &resource.StateChangeConf{
+ Pending: []string{"failed"},
+ Target: []string{"success"},
+ Refresh: qemuAgentInterfacesRefreshFunc(domain, wait4ipv4),
+ MinTimeout: 4 * time.Second,
+ Delay: 4 * time.Second, // Wait this time before starting checks
+ Timeout: 16 * time.Second,
}
- log.Printf("[DEBUG] Interfaces obtained via qemu Agent: %+v", interfaces)
+ interfaces, err := qemuAgentQuery.WaitForState()
+ if err != nil {
+ return []libvirt.DomainInterface{}
+ }
- return interfaces
+ return interfaces.([]libvirt.DomainInterface)
}
diff --git a/libvirt/resource_libvirt_domain.go b/libvirt/resource_libvirt_domain.go
index b5d0fb6d..25829f35 100644
--- a/libvirt/resource_libvirt_domain.go
+++ b/libvirt/resource_libvirt_domain.go
@@ -1300,6 +1300,7 @@ func getDomainInterfaces(domain libvirt.Domain) ([]libvirt.DomainInterface, erro
// get all the interfaces using the qemu-agent, this includes also
// interfaces that are not attached to networks managed by libvirt
// (eg. bridges, macvtap,...)
+ log.Print("[DEBUG] fetching networking interfaces using qemu-agent")
interfaces := getDomainInterfacesViaQemuAgent(&domain, true)
if len(interfaces) > 0 {
// the agent will always return all the interfaces, both the
@@ -1308,9 +1309,8 @@ func getDomainInterfaces(domain libvirt.Domain) ([]libvirt.DomainInterface, erro
return interfaces, nil
}
- log.Print("[DEBUG] fetching networking interfaces using libvirt API")
-
// get all the interfaces attached to libvirt networks
+ log.Print("[DEBUG] fetching networking interfaces using libvirt API")
interfaces, err := domain.ListAllInterfaceAddresses(libvirt.DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE)
if err != nil {
switch err.(type) {