aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Saurin <alvaro.saurin@gmail.com>2017-10-19 17:39:31 +0200
committerAlvaro <alvaro.saurin@gmail.com>2017-11-27 13:04:37 +0100
commitc7cc7221d46e8fa7ee7d64c7eab64f5515980fc1 (patch)
tree94f923062c9ff708b7f5c80621a6f6634befd0b2
parent39b7567db8477cebf98ca7ff225c2a356b42bd98 (diff)
downloadterraform-provider-libvirt-c7cc7221d46e8fa7ee7d64c7eab64f5515980fc1.tar
terraform-provider-libvirt-c7cc7221d46e8fa7ee7d64c7eab64f5515980fc1.tar.gz
Simplify the wait_for_leases mechanism
-rw-r--r--.travis.yml8
-rw-r--r--Makefile10
-rw-r--r--README.md2
-rw-r--r--libvirt/domain.go179
-rw-r--r--libvirt/network_interface_def.go14
-rw-r--r--libvirt/qemu_agent.go25
-rw-r--r--libvirt/qemu_agent_test.go12
-rw-r--r--libvirt/resource_libvirt_domain.go206
-rwxr-xr-x[-rw-r--r--]travis/run-gofmt (renamed from travis/gofmtcheck.sh)0
-rwxr-xr-xtravis/run-tests-acceptance (renamed from travis/run_acceptance_test.sh)1
-rwxr-xr-xtravis/run-tests-inside-guest18
-rwxr-xr-xtravis/setup-host1
12 files changed, 246 insertions, 230 deletions
diff --git a/.travis.yml b/.travis.yml
index 1048239f..e870d5d2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,17 +1,17 @@
-dist: trusty
-language: go
+dist: trusty
+language: go
go:
- 1.9
go_import_path: github.com/dmacvicar/terraform-provider-libvirt
-install: true
+install: true
before_script:
- go get github.com/mattn/goveralls
- go get github.com/golang/lint/golint
- sudo bash ./travis/setup-host
- sudo lxc exec libvirt -- bash /code/travis/setup-guest
script:
- - bash ./travis/gofmtcheck.sh
+ - make gofmtcheck
- make vet
- golint -set_exit_status libvirt/
- sudo lxc exec libvirt -- bash /code/travis/run-tests-inside-guest
diff --git a/Makefile b/Makefile
index 72b45f91..317970d8 100644
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,12 @@ default: build
build: gofmtcheck golint vet
go build
-install:
+install:
go install
-test:
- bash travis/run_acceptance_test.sh
+test:
+ bash travis/run-tests-acceptance
+
vet:
@echo "go vet ."
@go vet $$(go list ./... | grep -v vendor/) ; if [ $$? -eq 1 ]; then \
@@ -19,7 +20,8 @@ vet:
golint:
golint ./libvirt
+
gofmtcheck:
- bash travis/gofmtcheck.sh
+ bash travis/run-gofmt
.PHONY: build install test vet fmt golint
diff --git a/README.md b/README.md
index 23fed4ce..1d94e350 100644
--- a/README.md
+++ b/README.md
@@ -77,7 +77,7 @@ resource "libvirt_domain" "terraform_test" {
Now you can see the plan, apply it, and then destroy the infrastructure:
```console
-$ terraform init
+$ terraform init
$ terraform plan
$ terraform apply
$ terraform destroy
diff --git a/libvirt/domain.go b/libvirt/domain.go
new file mode 100644
index 00000000..9991dc42
--- /dev/null
+++ b/libvirt/domain.go
@@ -0,0 +1,179 @@
+package libvirt
+
+import (
+ "errors"
+ "fmt"
+ "log"
+ "os"
+ "strings"
+ "time"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/hashicorp/terraform/helper/resource"
+ libvirt "github.com/libvirt/libvirt-go"
+ "github.com/libvirt/libvirt-go-xml"
+)
+
+const skipQemuEnvVar = "TF_SKIP_QEMU_AGENT"
+
+const domWaitLeaseStillWaiting = "waiting-addresses"
+const domWaitLeaseDone = "all-addresses-obtained"
+
+var errDomainInvalidState = errors.New("invalid state for domain")
+
+func domainWaitForLeases(domain *libvirt.Domain, waitForLeases map[libvirtxml.DomainInterface]struct{}, timeout time.Duration) error {
+ waitFunc := func() (interface{}, string, error) {
+ state, err := domainGetState(*domain)
+ if err != nil {
+ return false, "", err
+ }
+
+ for _, fatalState := range []string{"crashed", "shutoff", "shutdown", "pmsuspended"} {
+ if state == fatalState {
+ return false, "", errDomainInvalidState
+ }
+ }
+
+ if state != "running" {
+ return false, domWaitLeaseStillWaiting, nil
+ }
+
+ // check we have IPs for all the interfaces we are waiting for
+ for iface := range waitForLeases {
+ found, ignore, err := domainIfaceHasAddress(*domain, iface)
+ if err != nil {
+ return false, "", err
+ }
+ if ignore {
+ log.Printf("[DEBUG] we don't care about the IP address for %+v", iface)
+ continue
+ }
+ if !found {
+ log.Printf("[DEBUG] IP address not found for iface=%+v: will try in a while", strings.ToUpper(iface.MAC.Address))
+ return false, domWaitLeaseStillWaiting, nil
+ }
+ }
+
+ log.Printf("[DEBUG] all the %d IP addresses obtained for the domain", len(waitForLeases))
+ return true, domWaitLeaseDone, nil
+ }
+
+ stateConf := &resource.StateChangeConf{
+ Pending: []string{domWaitLeaseStillWaiting},
+ Target: []string{domWaitLeaseDone},
+ Refresh: waitFunc,
+ Timeout: timeout,
+ MinTimeout: 10 * time.Second,
+ Delay: 5 * time.Second,
+ }
+
+ _, err := stateConf.WaitForState()
+ log.Print("[DEBUG] wait-for-leases was successful")
+ return err
+}
+
+func domainIfaceHasAddress(domain libvirt.Domain, iface libvirtxml.DomainInterface) (found bool, ignore bool, err error) {
+
+ mac := strings.ToUpper(iface.MAC.Address)
+ if mac == "" {
+ log.Printf("[DEBUG] Can't wait without a MAC address: ignoring interface %+v.\n", iface)
+ // we can't get the ip without a mac address
+ return false, true, nil
+ }
+
+ log.Printf("[DEBUG] waiting for network address for iface=%s\n", mac)
+ ifacesWithAddr, err := domainGetIfacesInfo(domain)
+ if err != nil {
+ return false, false, fmt.Errorf("Error retrieving interface addresses: %s", err)
+ }
+ log.Printf("[DEBUG] ifaces with addresses: %+v\n", ifacesWithAddr)
+
+ for _, ifaceWithAddr := range ifacesWithAddr {
+ if mac == strings.ToUpper(ifaceWithAddr.Hwaddr) {
+ log.Printf("[DEBUG] found IPs for MAC=%+v: %+v\n", mac, ifaceWithAddr.Addrs)
+ return true, false, nil
+ }
+ }
+
+ log.Printf("[DEBUG] %+v doesn't have IP address(es) yet...\n", mac)
+ return false, false, nil
+}
+
+func domainGetState(domain libvirt.Domain) (string, error) {
+ state, _, err := domain.GetState()
+ if err != nil {
+ return "", err
+ }
+
+ var stateStr string
+
+ switch state {
+ case libvirt.DOMAIN_NOSTATE:
+ stateStr = "nostate"
+ case libvirt.DOMAIN_RUNNING:
+ stateStr = "running"
+ case libvirt.DOMAIN_BLOCKED:
+ stateStr = "blocked"
+ case libvirt.DOMAIN_PAUSED:
+ stateStr = "paused"
+ case libvirt.DOMAIN_SHUTDOWN:
+ stateStr = "shutdown"
+ case libvirt.DOMAIN_CRASHED:
+ stateStr = "crashed"
+ case libvirt.DOMAIN_PMSUSPENDED:
+ stateStr = "pmsuspended"
+ case libvirt.DOMAIN_SHUTOFF:
+ stateStr = "shutoff"
+ default:
+ stateStr = fmt.Sprintf("unknown: %v", state)
+ }
+
+ return stateStr, nil
+}
+
+func domainIsRunning(domain libvirt.Domain) (bool, error) {
+ state, _, err := domain.GetState()
+ if err != nil {
+ return false, fmt.Errorf("Couldn't get state of domain: %s", err)
+ }
+
+ return state == libvirt.DOMAIN_RUNNING, nil
+}
+
+func domainGetIfacesInfo(domain libvirt.Domain) ([]libvirt.DomainInterface, error) {
+
+ _, found := os.LookupEnv(skipQemuEnvVar)
+ if found {
+ log.Printf("[DEBUG] %s defined in environment: skipping qemu-agent", skipQemuEnvVar)
+ } else {
+ // 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 := qemuAgentGetInterfacesInfo(&domain, true)
+ if len(interfaces) > 0 {
+ // the agent will always return all the interfaces, both the
+ // ones managed by libvirt and the ones attached to bridge interfaces
+ // or macvtap. Hence it has the highest priority
+ return interfaces, nil
+ }
+ }
+
+ // get all the interfaces attached to libvirt networks
+ log.Print("[DEBUG] no interfaces could be obtained with qemu-agent: falling back to the libvirt API")
+ interfaces, err := domain.ListAllInterfaceAddresses(libvirt.DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE)
+ if err != nil {
+ switch err.(type) {
+ default:
+ return interfaces, fmt.Errorf("Error retrieving interface addresses: %s", err)
+ case libvirt.Error:
+ virErr := err.(libvirt.Error)
+ if virErr.Code != libvirt.ERR_OPERATION_INVALID || virErr.Domain != libvirt.FROM_QEMU {
+ return interfaces, fmt.Errorf("Error retrieving interface addresses: %s", err)
+ }
+ }
+ }
+ log.Printf("[DEBUG] Interfaces info obtained with libvirt API:\n%s\n", spew.Sdump(interfaces))
+
+ return interfaces, nil
+}
diff --git a/libvirt/network_interface_def.go b/libvirt/network_interface_def.go
deleted file mode 100644
index 0af0cdf1..00000000
--- a/libvirt/network_interface_def.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package libvirt
-
-import "github.com/libvirt/libvirt-go-xml"
-
-// An interface definition, as returned/understood by libvirt
-// (see https://libvirt.org/formatdomain.html#elementsNICS)
-//
-// Something like:
-// <interface type='network'>
-// <source network='default'/>
-// </interface>
-//
-
-var waitForLeases map[libvirtxml.DomainInterface]bool
diff --git a/libvirt/qemu_agent.go b/libvirt/qemu_agent.go
index fd7cef39..7f3ca7a4 100644
--- a/libvirt/qemu_agent.go
+++ b/libvirt/qemu_agent.go
@@ -10,6 +10,9 @@ import (
libvirt "github.com/libvirt/libvirt-go"
)
+const qemuGetIfaceWait = "qemu-agent-wait"
+const qemuGetIfaceDone = "qemu-agent-done"
+
// QemuAgentInterfacesResponse type
type QemuAgentInterfacesResponse struct {
Interfaces []QemuAgentInterface `json:"return"`
@@ -29,19 +32,19 @@ type QemuAgentInterfaceIPAddress struct {
Prefix uint `json:"prefix"`
}
-func qemuAgentInterfacesRefreshFunc(domain LibVirtDomain, wait4ipv4 bool) resource.StateRefreshFunc {
+func qemuAgentInterfacesRefreshFunc(domain Domain, wait4ipv4 bool) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
var interfaces []libvirt.DomainInterface
- log.Printf("[DEBUG] sending command to qemu-agent in %s", domain)
+ log.Printf("[DEBUG] sending command to qemu-agent")
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
+ return interfaces, qemuGetIfaceWait, nil
}
log.Printf("[DEBUG] qemu-agent response: %s", result)
@@ -49,9 +52,9 @@ func qemuAgentInterfacesRefreshFunc(domain LibVirtDomain, wait4ipv4 bool) resour
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.Printf("[DEBUG] Original message: %+v", response)
log.Print("[DEBUG] Returning an empty list of interfaces")
- return interfaces, "fatal", nil
+ return interfaces, "", nil
}
log.Printf("[DEBUG] Parsed response %+v", response)
@@ -66,7 +69,7 @@ func qemuAgentInterfacesRefreshFunc(domain LibVirtDomain, wait4ipv4 bool) resour
Hwaddr: iface.Hwaddr}
ipv4Assigned := false
- for _, addr := range iface.IpAddresses {
+ for _, addr := range iface.IPAddresses {
if addr.Address == "" {
// ignore interfaces without an address (eg. waiting for dhcp lease)
continue
@@ -95,7 +98,7 @@ func qemuAgentInterfacesRefreshFunc(domain LibVirtDomain, wait4ipv4 bool) resour
}
log.Printf("[DEBUG] Interfaces obtained via qemu-agent: %+v", interfaces)
- return interfaces, "success", nil
+ return interfaces, qemuGetIfaceDone, nil
}
}
@@ -104,15 +107,15 @@ func qemuAgentInterfacesRefreshFunc(domain LibVirtDomain, wait4ipv4 bool) resour
// 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 {
+func qemuAgentGetInterfacesInfo(domain Domain, wait4ipv4 bool) []libvirt.DomainInterface {
qemuAgentQuery := &resource.StateChangeConf{
- Pending: []string{"failed"},
- Target: []string{"success"},
+ Pending: []string{qemuGetIfaceWait},
+ Target: []string{qemuGetIfaceDone},
Refresh: qemuAgentInterfacesRefreshFunc(domain, wait4ipv4),
MinTimeout: 4 * time.Second,
Delay: 4 * time.Second, // Wait this time before starting checks
- Timeout: 16 * time.Second,
+ Timeout: 30 * time.Second,
}
interfaces, err := qemuAgentQuery.WaitForState()
diff --git a/libvirt/qemu_agent_test.go b/libvirt/qemu_agent_test.go
index 03546054..b32b51dc 100644
--- a/libvirt/qemu_agent_test.go
+++ b/libvirt/qemu_agent_test.go
@@ -10,7 +10,7 @@ import (
func TestGetDomainInterfacesViaQemuAgentInvalidResponse(t *testing.T) {
domain := DomainMock{}
- interfaces := getDomainInterfacesViaQemuAgent(domain, false)
+ interfaces := qemuAgentGetInterfacesInfo(domain, false)
if len(interfaces) != 0 {
t.Errorf("wrong number of interfaces: %d instead of 0", len(interfaces))
@@ -29,7 +29,7 @@ func TestGetDomainInterfacesViaQemuAgentNoInterfaces(t *testing.T) {
QemuAgentCommandResponse: string(data),
}
- interfaces := getDomainInterfacesViaQemuAgent(domain, false)
+ interfaces := qemuAgentGetInterfacesInfo(domain, false)
if len(interfaces) != 0 {
t.Errorf("wrong number of interfaces: %d instead of 0", len(interfaces))
}
@@ -59,7 +59,7 @@ func TestGetDomainInterfacesViaQemuAgentIgnoreLoopbackDevice(t *testing.T) {
QemuAgentCommandResponse: string(data),
}
- interfaces := getDomainInterfacesViaQemuAgent(domain, false)
+ interfaces := qemuAgentGetInterfacesInfo(domain, false)
if len(interfaces) != 0 {
t.Errorf("wrong number of interfaces)")
@@ -90,7 +90,7 @@ func TestGetDomainInterfacesViaQemuAgentIgnoreDevicesWithoutAddress(t *testing.T
QemuAgentCommandResponse: string(data),
}
- interfaces := getDomainInterfacesViaQemuAgent(domain, false)
+ interfaces := qemuAgentGetInterfacesInfo(domain, false)
if len(interfaces) != 0 {
t.Errorf("wrong number of interfaces")
@@ -121,7 +121,7 @@ func TestGetDomainInterfacesViaQemuAgentUnknownIpAddressType(t *testing.T) {
QemuAgentCommandResponse: string(data),
}
- interfaces := getDomainInterfacesViaQemuAgent(domain, false)
+ interfaces := qemuAgentGetInterfacesInfo(domain, false)
if len(interfaces) != 0 {
t.Errorf("wrong number of interfaces: %d instead of 1", len(interfaces))
@@ -162,7 +162,7 @@ func TestGetDomainInterfacesViaQemuAgent(t *testing.T) {
QemuAgentCommandResponse: string(data),
}
- interfaces := getDomainInterfacesViaQemuAgent(domain, false)
+ interfaces := qemuAgentGetInterfacesInfo(domain, false)
if len(interfaces) != 1 {
t.Errorf("wrong number of interfaces: %d instead of 1", len(interfaces))
diff --git a/libvirt/resource_libvirt_domain.go b/libvirt/resource_libvirt_domain.go
index 25829f35..92af802a 100644
--- a/libvirt/resource_libvirt_domain.go
+++ b/libvirt/resource_libvirt_domain.go
@@ -15,7 +15,6 @@ import (
"time"
"github.com/davecgh/go-spew/spew"
- "github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
libvirt "github.com/libvirt/libvirt-go"
"github.com/libvirt/libvirt-go-xml"
@@ -525,7 +524,7 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
netIfacesCount := d.Get("network_interface.#").(int)
netIfaces := make([]libvirtxml.DomainInterface, 0, netIfacesCount)
partialNetIfaces := make(map[string]pendingMapping, netIfacesCount)
- waitForLeases = make(map[libvirtxml.DomainInterface]bool, netIfacesCount)
+ waitForLeases := make(map[libvirtxml.DomainInterface]struct{}, netIfacesCount)
for i := 0; i < netIfacesCount; i++ {
prefix := fmt.Sprintf("network_interface.%d", i)
@@ -549,6 +548,13 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
Address: mac,
}
+ // this is not passed to libvirt, but used by waitForAddress
+ if waitForLease, ok := d.GetOk(prefix + ".wait_for_lease"); ok {
+ if waitForLease.(bool) {
+ waitForLeases[netIface] = struct{}{}
+ }
+ }
+
// connect to the interface to the network... first, look for the network
if n, ok := d.GetOk(prefix + ".network_name"); ok {
// when using a "network_name" we do not try to do anything: we just
@@ -594,16 +600,14 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
}
}
} else {
- // no IPs provided so check whether we are waiting for a lease
- if waitForLeaseI, ok := d.GetOk(prefix + ".wait_for_lease"); ok {
- waitForLease := waitForLeaseI.(bool)
- if !waitForLease {
- return fmt.Errorf("Cannot map '%s': we are not waiting for lease and no IP has been provided", hostname)
- }
+ // no IPs provided: if the hostname has been provided, wait until we get an IP
+ if _, ok := waitForLeases[netIface]; ok {
+ return fmt.Errorf("Cannot map '%s': we are not waiting for DHCP lease and no IP has been provided", hostname)
}
- // we must wait until we have a valid lease and then read the IP we
- // have been assigned, so we can do the mapping
- log.Printf("[DEBUG] Will wait for an IP for hostname '%s'...", hostname)
+ // the resource specifies a hostname but not an IP, so we must wait until we
+ // have a valid lease and then read the IP we have been assigned, so we can
+ // do the mapping
+ log.Printf("[DEBUG] Do not have an IP for '%s' yet: will wait until DHCP provides one...", hostname)
partialNetIfaces[strings.ToUpper(mac)] = pendingMapping{
mac: strings.ToUpper(mac),
hostname: hostname,
@@ -640,11 +644,6 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
} else {
// no network has been specified: we are on our own
}
- // this is not passed to libvirt, but used by waitForAddress
- waitForLeases[netIface] = false
- if waitForLease, ok := d.GetOk(prefix + ".wait_for_lease"); ok {
- waitForLeases[netIface] = waitForLease.(bool)
- }
netIfaces = append(netIfaces, netIface)
}
@@ -699,28 +698,11 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
log.Printf("[INFO] Domain ID: %s", d.Id())
- domainMeta := DomainMeta{
- domain,
- make(chan libvirtxml.DomainInterface, len(netIfaces)),
- }
-
- // populate interface channels
- for _, iface := range netIfaces {
- domainMeta.ifaces <- iface
- }
-
- stateConf := &resource.StateChangeConf{
- Pending: []string{"blocked"},
- Target: []string{"running"},
- Refresh: resourceLibvirtDomainStateRefreshFunc(d, &domainMeta),
- Timeout: d.Timeout(schema.TimeoutCreate),
- MinTimeout: 10 * time.Second,
- Delay: 10 * time.Second,
- }
-
- _, err = stateConf.WaitForState()
- if err != nil {
- return err
+ if len(waitForLeases) > 0 {
+ err = domainWaitForLeases(domain, waitForLeases, d.Timeout(schema.TimeoutCreate))
+ if err != nil {
+ return err
+ }
}
err = resourceLibvirtDomainRead(d, meta)
@@ -768,7 +750,7 @@ func resourceLibvirtDomainUpdate(d *schema.ResourceData, meta interface{}) error
}
defer domain.Free()
- running, err := isDomainRunning(*domain)
+ running, err := domainIsRunning(*domain)
if err != nil {
return err
}
@@ -924,7 +906,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
// or it will show as changed
d.Set("emulator", domainDef.Devices.Emulator)
- running, err := isDomainRunning(*domain)
+ running, err := domainIsRunning(*domain)
if err != nil {
return err
}
@@ -993,7 +975,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
d.Set("filesystems", filesystems)
// look interfaces with addresses
- ifacesWithAddr, err := getDomainInterfaces(*domain)
+ ifacesWithAddr, err := domainGetIfacesInfo(*domain)
if err != nil {
return fmt.Errorf("Error retrieving interface addresses: %s", err)
}
@@ -1156,115 +1138,6 @@ func resourceLibvirtDomainDelete(d *schema.ResourceData, meta interface{}) error
return nil
}
-func resourceLibvirtDomainStateRefreshFunc(
- d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
- return func() (interface{}, string, error) {
- domain := meta.(*DomainMeta).domain
-
- state, err := getDomainState(*domain)
- if err != nil {
- return nil, "", err
- }
-
- if state == "running" {
- // domain and interface(s) are up, we're done
- if len(meta.(*DomainMeta).ifaces) == 0 {
- return meta, state, nil
- }
-
- // set state to "blocked" since we still have interfaces to check
- state = "blocked"
-
- iface := <-meta.(*DomainMeta).ifaces
- found, ignore, err := hasNetworkAddress(iface, *domain)
- if err != nil {
- return nil, "", err
- }
-
- if found {
- return meta, state, nil
- } else if !found && !ignore {
- // re-add the interface and deal with it later
- meta.(*DomainMeta).ifaces <- iface
- }
- }
-
- return meta, state, nil
- }
-}
-
-func hasNetworkAddress(iface libvirtxml.DomainInterface,
- domain libvirt.Domain) (found bool, ignore bool, err error) {
-
- if !waitForLeases[iface] {
- return false, true, nil
- }
-
- mac := strings.ToUpper(iface.MAC.Address)
- if mac == "" {
- log.Printf("[DEBUG] Can't wait without a mac address.\n")
- // we can't get the ip without a mac address
- return false, true, nil
- }
-
- log.Printf("[DEBUG] waiting for network address for interface with hwaddr: '%s'\n", iface.MAC.Address)
- ifacesWithAddr, err := getDomainInterfaces(domain)
- if err != nil {
- return false, false, fmt.Errorf("Error retrieving interface addresses: %s", err)
- }
- log.Printf("[DEBUG] ifaces with addresses: %+v\n", ifacesWithAddr)
-
- for _, ifaceWithAddr := range ifacesWithAddr {
- // found
- if mac == strings.ToUpper(ifaceWithAddr.Hwaddr) {
- return true, false, nil
- }
- }
-
- return false, false, nil
-}
-
-func getDomainState(domain libvirt.Domain) (string, error) {
- state, _, err := domain.GetState()
- if err != nil {
- return "", err
- }
-
- var stateStr string
-
- switch state {
- case libvirt.DOMAIN_NOSTATE:
- stateStr = "nostate"
- case libvirt.DOMAIN_RUNNING:
- stateStr = "running"
- case libvirt.DOMAIN_BLOCKED:
- stateStr = "blocked"
- case libvirt.DOMAIN_PAUSED:
- stateStr = "paused"
- case libvirt.DOMAIN_SHUTDOWN:
- stateStr = "shutdown"
- case libvirt.DOMAIN_CRASHED:
- stateStr = "crashed"
- case libvirt.DOMAIN_PMSUSPENDED:
- stateStr = "pmsuspended"
- case libvirt.DOMAIN_SHUTOFF:
- stateStr = "shutoff"
- default:
- stateStr = fmt.Sprintf("unknown: %v", state)
- }
-
- return stateStr, nil
-}
-
-func isDomainRunning(domain libvirt.Domain) (bool, error) {
- state, _, err := domain.GetState()
- if err != nil {
- return false, fmt.Errorf("Couldn't get state of domain: %s", err)
- }
-
- return state == libvirt.DOMAIN_RUNNING, nil
-}
-
func newDiskForCloudInit(virConn *libvirt.Connect, volumeKey string) (libvirtxml.DomainDisk, error) {
disk := libvirtxml.DomainDisk{
Type: "file",
@@ -1294,36 +1167,3 @@ func newDiskForCloudInit(virConn *libvirt.Connect, volumeKey string) (libvirtxml
return disk, nil
}
-
-func getDomainInterfaces(domain libvirt.Domain) ([]libvirt.DomainInterface, error) {
-
- // 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
- // ones managed by libvirt and the ones attached to bridge interfaces
- // or macvtap. Hence it has the highest priority
- return interfaces, nil
- }
-
- // 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) {
- default:
- return interfaces, fmt.Errorf("Error retrieving interface addresses: %s", err)
- case libvirt.Error:
- virErr := err.(libvirt.Error)
- if virErr.Code != libvirt.ERR_OPERATION_INVALID || virErr.Domain != libvirt.FROM_QEMU {
- return interfaces, fmt.Errorf("Error retrieving interface addresses: %s", err)
- }
- }
- }
- log.Printf("[DEBUG] Interfaces: %s", spew.Sdump(interfaces))
-
- return interfaces, nil
-}
diff --git a/travis/gofmtcheck.sh b/travis/run-gofmt
index d7d7aef6..d7d7aef6 100644..100755
--- a/travis/gofmtcheck.sh
+++ b/travis/run-gofmt
diff --git a/travis/run_acceptance_test.sh b/travis/run-tests-acceptance
index 5010505a..30d49207 100755
--- a/travis/run_acceptance_test.sh
+++ b/travis/run-tests-acceptance
@@ -5,4 +5,5 @@ unset http_proxy
export TERRAFORM_LIBVIRT_TEST_DOMAIN_TYPE=qemu
export LIBVIRT_DEFAULT_URI="qemu:///system"
export TF_ACC=true
+
go test -v -covermode=count -coverprofile=profile.cov -timeout=1200s ./libvirt
diff --git a/travis/run-tests-inside-guest b/travis/run-tests-inside-guest
index a860a4d7..32ff9773 100755
--- a/travis/run-tests-inside-guest
+++ b/travis/run-tests-inside-guest
@@ -1,19 +1,23 @@
#!/bin/bash
set -x
+base="/root/go/src/github.com/dmacvicar"
+
unset http_proxy
-export GOROOT=/usr/lib/go-1.9/
-export GOPATH=/root/go
+export GOROOT="/usr/lib/go-1.9/"
+export GOPATH="/root/go"
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
-mkdir -p /root/go/src/github.com/dmacvicar/
-cp -r /code/ /root/go/src/github.com/dmacvicar/terraform-provider-libvirt
-cd /root/go/src/github.com/dmacvicar/terraform-provider-libvirt
+mkdir -p $base
+cp -r /code/ $base/terraform-provider-libvirt
+cd $base/terraform-provider-libvirt
go build .
-export TERRAFORM_LIBVIRT_TEST_DOMAIN_TYPE=qemu
+export TERRAFORM_LIBVIRT_TEST_DOMAIN_TYPE="qemu"
export LIBVIRT_DEFAULT_URI="qemu:///system"
-export TF_ACC=true
+export TF_ACC="true"
+export TF_SKIP_QEMU_AGENT="true"
+
go test -v -covermode=count -coverprofile=profile.cov -timeout=1200s ./libvirt
diff --git a/travis/setup-host b/travis/setup-host
index cd9ce64c..6bb455cc 100755
--- a/travis/setup-host
+++ b/travis/setup-host
@@ -11,6 +11,7 @@ sudo sed -i 's/LXD_IPV4_NETWORK=".*"/LXD_IPV4_NETWORK="192.168.123.0\/24"/' /etc
sudo sed -i 's/LXD_IPV4_DHCP_RANGE=".*"/LXD_IPV4_DHCP_RANGE="192.168.123.2,192.168.123.12"/' /etc/default/lxd-bridge
sudo sed -i 's/LXD_IPV4_DHCP_MAX=".*"/LXD_IPV4_DHCP_MAX="10"/' /etc/default/lxd-bridge
+sudo service libvirtd restart
sudo service lxd restart
sudo lxc launch ubuntu:zesty libvirt -c security.privileged=true