summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Mac-Vicar P <dmacvicar@suse.de>2016-05-17 00:26:52 +0200
committerDuncan Mac-Vicar P <dmacvicar@suse.de>2016-05-17 00:26:52 +0200
commit991d27783c90aec9e92bbf91e4d48e87f5897090 (patch)
tree29ee03ee7b2a91d63415abe0a17035b89fb9b23a
parent61227d660a95759bb80aa33dfe8fd1893b49d6f1 (diff)
downloadterraform-provider-libvirt-991d27783c90aec9e92bbf91e4d48e87f5897090.tar
terraform-provider-libvirt-991d27783c90aec9e92bbf91e4d48e87f5897090.tar.gz
support for ip and connection information in libvirt.domain
-rw-r--r--libvirt/network_interface_def.go35
-rw-r--r--libvirt/resource_libvirt_domain.go70
-rw-r--r--libvirt/utils.go16
3 files changed, 117 insertions, 4 deletions
diff --git a/libvirt/network_interface_def.go b/libvirt/network_interface_def.go
index 4e401a6f..cf661954 100644
--- a/libvirt/network_interface_def.go
+++ b/libvirt/network_interface_def.go
@@ -9,8 +9,8 @@ type defNetworkInterface struct {
XMLName xml.Name `xml:"interface"`
Type string `xml:"type,attr"`
Mac struct {
- Address string `xml:"address,attr,omitempty"`
- } `xml:"mac,omitempty"`
+ Address string `xml:"address,attr"`
+ } `xml:"mac"`
Source struct {
Network string `xml:"network,attr"`
} `xml:"source"`
@@ -19,6 +19,26 @@ type defNetworkInterface struct {
} `xml:"model"`
}
+func networkAddressCommonSchema() map[string]*schema.Schema {
+ return map[string]*schema.Schema{
+ "type": &schema.Schema{
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ },
+ "address": &schema.Schema{
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ },
+ "prefix": &schema.Schema{
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ },
+ }
+}
+
func networkInterfaceCommonSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"network": &schema.Schema{
@@ -30,6 +50,17 @@ func networkInterfaceCommonSchema() map[string]*schema.Schema {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
+ DefaultFunc: func() (interface{}, error) {
+ return RandomMACAddress()
+ },
+ },
+ "address": &schema.Schema{
+ Type: schema.TypeList,
+ Optional: true,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: networkAddressCommonSchema(),
+ },
},
}
}
diff --git a/libvirt/resource_libvirt_domain.go b/libvirt/resource_libvirt_domain.go
index 095ebab7..f4b1982a 100644
--- a/libvirt/resource_libvirt_domain.go
+++ b/libvirt/resource_libvirt_domain.go
@@ -153,7 +153,7 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
virConn := meta.(*Client).libvirt
if virConn == nil {
- return fmt.Errorf("The libvirt connection was nil.")
+ return fmt.Errorf("The libvirt connection was nil.")
}
domain, err := virConn.LookupByUUIDString(d.Id())
@@ -203,16 +203,82 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
}
d.Set("disks", disks)
+ // look interfaces with addresses
+ start := time.Now()
+ var ifacesWithAddr []libvirt.VirDomainInterface
+ for {
+ ifacesWithAddr, err = domain.ListAllInterfaceAddresses(libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE)
+ if err != nil {
+ return fmt.Errorf("Error retrieving interface addresses: %s", err)
+ }
+
+ log.Printf("[DEBUG] %d interfaces defined. %d addresses available.", len(domainDef.Devices.NetworkInterfaces), len(ifacesWithAddr))
+
+ // wait for at least one address per interface
+ if len(ifacesWithAddr) >= len(domainDef.Devices.NetworkInterfaces) {
+ break
+ }
+
+ log.Printf("[DEBUG] waiting for addresses...")
+ time.Sleep(1 * time.Second)
+ if time.Since(start) > 5*time.Minute {
+ return fmt.Errorf("Timeout waiting for interface addresses")
+ }
+ }
+
netIfaces := make([]map[string]interface{}, 0)
for _, networkInterfaceDef := range domainDef.Devices.NetworkInterfaces {
+
+ if networkInterfaceDef.Type != "network" {
+ log.Printf("[DEBUG] ignoring interface of type '%s'", networkInterfaceDef.Type)
+ continue
+ }
+
netIface := map[string]interface{}{
"network": networkInterfaceDef.Source.Network,
"mac": networkInterfaceDef.Mac.Address,
}
+
+ netIfaceAddrs := make([]map[string]interface{}, 0)
+ // look for an ip address and try to match it with the mac address
+ // not sure if using the target device name is a better idea here
+ for _, ifaceWithAddr := range ifacesWithAddr {
+ log.Printf("[DEBUG] Trying with: '%s': '%s' against '%s'\n", ifaceWithAddr.Hwaddr, ifaceWithAddr.Addrs[0].Addr, networkInterfaceDef.Mac.Address)
+ if ifaceWithAddr.Hwaddr == networkInterfaceDef.Mac.Address {
+ for _, addr := range(ifaceWithAddr.Addrs) {
+ netIfaceAddr := map[string]interface{}{
+ "type": func() string {
+ switch addr.Type {
+ case libvirt.VIR_IP_ADDR_TYPE_IPV4:
+ return "ipv4"
+ case libvirt.VIR_IP_ADDR_TYPE_IPV6:
+ return "ipv6"
+ default:
+ return "other"
+ }
+ }(),
+ "address": addr.Addr,
+ "prefix": addr.Prefix,
+ }
+ netIfaceAddrs = append(netIfaceAddrs, netIfaceAddr)
+ }
+ } else {
+ log.Printf("[DEBUG] Unmatched address: '%s': '%s'\n", ifaceWithAddr.Hwaddr, networkInterfaceDef.Mac.Address)
+ }
+ }
+
+ log.Printf("[DEBUG] %d addresses for %s\n", len(netIfaceAddrs), networkInterfaceDef.Mac.Address)
+ netIface["address"] = netIfaceAddrs
netIfaces = append(netIfaces, netIface)
}
- d.Set("network_interfaces", netIfaces)
+ d.Set("network_interface", netIfaces)
+ if len(ifacesWithAddr) > 0 {
+ d.SetConnInfo(map[string]string{
+ "type": "ssh",
+ "host": ifacesWithAddr[0].Addrs[0].Addr,
+ })
+ }
return nil
}
diff --git a/libvirt/utils.go b/libvirt/utils.go
index 3dc8e17e..ee64d07b 100644
--- a/libvirt/utils.go
+++ b/libvirt/utils.go
@@ -1,6 +1,7 @@
package libvirt
import (
+ "crypto/rand"
"fmt"
"time"
)
@@ -35,3 +36,18 @@ func WaitForSuccess(errorMessage string, f func() error) error {
}
}
}
+
+func RandomMACAddress() (string, error) {
+ buf := make([]byte, 6)
+ _, err := rand.Read(buf)
+ if err != nil {
+ return "", err
+ }
+
+ // set local bit and unicast
+ buf[0] = (buf[0] | 2) & 0xfe
+ // Set the local bit
+ buf[0] |= 2
+
+ return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]), nil
+}