diff options
author | Duncan Mac-Vicar P <dmacvicar@suse.de> | 2016-05-17 00:26:52 +0200 |
---|---|---|
committer | Duncan Mac-Vicar P <dmacvicar@suse.de> | 2016-05-17 00:26:52 +0200 |
commit | 991d27783c90aec9e92bbf91e4d48e87f5897090 (patch) | |
tree | 29ee03ee7b2a91d63415abe0a17035b89fb9b23a | |
parent | 61227d660a95759bb80aa33dfe8fd1893b49d6f1 (diff) | |
download | terraform-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.go | 35 | ||||
-rw-r--r-- | libvirt/resource_libvirt_domain.go | 70 | ||||
-rw-r--r-- | libvirt/utils.go | 16 |
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 +} |