From c7cc7221d46e8fa7ee7d64c7eab64f5515980fc1 Mon Sep 17 00:00:00 2001 From: Alvaro Saurin Date: Thu, 19 Oct 2017 17:39:31 +0200 Subject: Simplify the wait_for_leases mechanism --- .travis.yml | 8 +- Makefile | 10 +- README.md | 2 +- libvirt/domain.go | 179 ++++++++++++++++++++++++++++++++ libvirt/network_interface_def.go | 14 --- libvirt/qemu_agent.go | 25 +++-- libvirt/qemu_agent_test.go | 12 +-- libvirt/resource_libvirt_domain.go | 206 +++++-------------------------------- travis/gofmtcheck.sh | 30 ------ travis/run-gofmt | 30 ++++++ travis/run-tests-acceptance | 9 ++ travis/run-tests-inside-guest | 18 ++-- travis/run_acceptance_test.sh | 8 -- travis/setup-host | 1 + 14 files changed, 284 insertions(+), 268 deletions(-) create mode 100644 libvirt/domain.go delete mode 100644 libvirt/network_interface_def.go delete mode 100644 travis/gofmtcheck.sh create mode 100755 travis/run-gofmt create mode 100755 travis/run-tests-acceptance delete mode 100755 travis/run_acceptance_test.sh 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: -// -// -// -// - -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/gofmtcheck.sh deleted file mode 100644 index d7d7aef6..00000000 --- a/travis/gofmtcheck.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -set -e -GOPKG="libvirt" - -lint_pkg () { - cd $1 - echo "*** checking pkg $1 with gofmt" - if [ -n "$(go fmt ./...)" ]; then - echo "Go code on pkg $1 is not formatted well, run 'go fmt on pkg $1'" - exit 1 - fi - echo " pkg $1 has no lint gofmt errors!" - cd .. -} - -lint_main () { - echo '*** running gofmt on main.go' - if [ -n "$(go fmt main.go)" ]; then - echo "Go code on main.go is not formatted, please run 'go fmt main.go'" - exit 1 - fi -} - -echo "==> Checking that code complies with gofmt requirements..." -lint_pkg $GOPKG -echo -lint_main -echo '==> go fmt OK !!! ***' -exit 0 diff --git a/travis/run-gofmt b/travis/run-gofmt new file mode 100755 index 00000000..d7d7aef6 --- /dev/null +++ b/travis/run-gofmt @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +set -e +GOPKG="libvirt" + +lint_pkg () { + cd $1 + echo "*** checking pkg $1 with gofmt" + if [ -n "$(go fmt ./...)" ]; then + echo "Go code on pkg $1 is not formatted well, run 'go fmt on pkg $1'" + exit 1 + fi + echo " pkg $1 has no lint gofmt errors!" + cd .. +} + +lint_main () { + echo '*** running gofmt on main.go' + if [ -n "$(go fmt main.go)" ]; then + echo "Go code on main.go is not formatted, please run 'go fmt main.go'" + exit 1 + fi +} + +echo "==> Checking that code complies with gofmt requirements..." +lint_pkg $GOPKG +echo +lint_main +echo '==> go fmt OK !!! ***' +exit 0 diff --git a/travis/run-tests-acceptance b/travis/run-tests-acceptance new file mode 100755 index 00000000..30d49207 --- /dev/null +++ b/travis/run-tests-acceptance @@ -0,0 +1,9 @@ +#!/bin/bash +set -x + +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/run_acceptance_test.sh b/travis/run_acceptance_test.sh deleted file mode 100755 index 5010505a..00000000 --- a/travis/run_acceptance_test.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -x - -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/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 -- cgit v1.2.3