Commit 09296c8c authored by Daniel P. Berrange's avatar Daniel P. Berrange

Drop support for build tags as this is non-scalable

Currently the min required version of libvirt is 1.2.2
and opt-in for certains APIs in newer versions can be
done with go build tags. This is non-scalable going
forward as there are a huge number of releases adding
APIs to libvirt. This will result in people building
the libvirt go bindings having to specify 10, 20, 30
or more build tags to 'go build'. Even worse, these
build tags are a global namespace, so if libvirt uses
a tag '1.2.14', you have to hope there's no other
library that also uses such a build tag. The latter
problem could be avoided by adding a 'libvirt' prefix
to the build tags, but this makes it even more verbose.

Instead, the bindings master branch will always track
the latest libvirt master branch. Apps needing build
compatibility with older libvirt versions will have to
use a previous tag/branch of the bindings.
Signed-off-by: default avatarDaniel P. Berrange <berrange@redhat.com>
parent fa598c6d
......@@ -6,40 +6,19 @@ Make sure to have `libvirt-dev` package (or the development files otherwise some
## Version Support
The minimum supported version of libvirt is **1.2.2**. Due to the
The minimum required version of libvirt is **2.4.0**. Due to the
API/ABI compatibility promise of libvirt, more recent versions of
libvirt should work too.
Some features require a more recent version of libvirt. They are
disabled by default. If you want to enable them, build using one of
those additional tags (you need to use only the most recent one you
are interested in):
- **1.2.14**
For example:
go build -tags libvirt.1.2.14
### OS Compatibility Matrix
To quickly see what version of libvirt your OS can easily support (may be outdated). Obviously, nothing below 1.2.2 is usable with these bindings.
| OS Release | libvirt Version |
| ------------ | ------------------------------ |
| FC19 | 1.2.9 from libvirt.org/sources |
| Debian 8 | 1.2.9 from jessie |
| Debian 7 | 1.2.9 from wheezy-backports |
| Ubuntu 14.04 | 1.2.2 from trusty |
| Ubuntu 16.04 | 1.3.1 from xenial |
| RHEL 7 | 1.2.17 |
| RHEL 6 | 0.10.x |
| RHEL 5 | 0.8.x |
### 0.9.x Support
Previously there was support for libvirt 0.9.8 and below, however this is no longer being updated. These releases were tagged `v1.x` at `gopkg.in/alexzorin/libvirt-go.v1` [(docs)](http://gopkg.in/alexzorin/libvirt-go.v1).
The master branch of libvirt-go will always aim to support all
the APIs present in the master branch of the libvirt core library
API. At time of release, a tag will be created, so applications
that need build compatibility with an older version of libvirt
should checkout the tag corresponding to the version that they
require. This policy is appies from version 2.4.0 onwards. If
compatibility is required against a version of libvirt prior to
2.4.0, it will be necessary to create a branch and strip out
APIs.
## Documentation
......
......@@ -821,3 +821,58 @@ func (d *VirDomain) PinVcpuFlags(vcpu uint, cpuMap []uint32, flags uint, maxCPUs
return nil
}
type VirDomainIPAddress struct {
Type int
Addr string
Prefix uint
}
type VirDomainInterface struct {
Name string
Hwaddr string
Addrs []VirDomainIPAddress
}
func (d *VirDomain) ListAllInterfaceAddresses(src uint) ([]VirDomainInterface, error) {
var cList *C.virDomainInterfacePtr
numIfaces := int(C.virDomainInterfaceAddresses(d.ptr, (**C.virDomainInterfacePtr)(&cList), C.uint(src), 0))
if numIfaces == -1 {
return nil, GetLastError()
}
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cList)),
Len: int(numIfaces),
Cap: int(numIfaces),
}
ifaces := make([]VirDomainInterface, numIfaces)
ifaceSlice := *(*[]C.virDomainInterfacePtr)(unsafe.Pointer(&hdr))
for i := 0; i < numIfaces; i++ {
ifaces[i].Name = C.GoString(ifaceSlice[i].name)
ifaces[i].Hwaddr = C.GoString(ifaceSlice[i].hwaddr)
numAddr := int(ifaceSlice[i].naddrs)
addrHdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(&ifaceSlice[i].addrs)),
Len: int(numAddr),
Cap: int(numAddr),
}
ifaces[i].Addrs = make([]VirDomainIPAddress, numAddr)
addrSlice := *(*[]C.virDomainIPAddressPtr)(unsafe.Pointer(&addrHdr))
for k := 0; k < numAddr; k++ {
ifaces[i].Addrs[k] = VirDomainIPAddress{}
ifaces[i].Addrs[k].Type = int(addrSlice[k]._type)
ifaces[i].Addrs[k].Addr = C.GoString(addrSlice[k].addr)
ifaces[i].Addrs[k].Prefix = uint(addrSlice[k].prefix)
}
C.virDomainInterfaceFree(ifaceSlice[i])
}
C.free(unsafe.Pointer(cList))
return ifaces, nil
}
// +build libvirt.1.2.14
package libvirt
/*
#cgo LDFLAGS: -lvirt-qemu -lvirt
#include <libvirt/libvirt.h>
#include <libvirt/libvirt-qemu.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"reflect"
"unsafe"
)
type VirDomainIPAddress struct {
Type int
Addr string
Prefix uint
}
type VirDomainInterface struct {
Name string
Hwaddr string
Addrs []VirDomainIPAddress
}
func (d *VirDomain) ListAllInterfaceAddresses(src uint) ([]VirDomainInterface, error) {
var cList *C.virDomainInterfacePtr
numIfaces := int(C.virDomainInterfaceAddresses(d.ptr, (**C.virDomainInterfacePtr)(&cList), C.uint(src), 0))
if numIfaces == -1 {
return nil, GetLastError()
}
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cList)),
Len: int(numIfaces),
Cap: int(numIfaces),
}
ifaces := make([]VirDomainInterface, numIfaces)
ifaceSlice := *(*[]C.virDomainInterfacePtr)(unsafe.Pointer(&hdr))
for i := 0; i < numIfaces; i++ {
ifaces[i].Name = C.GoString(ifaceSlice[i].name)
ifaces[i].Hwaddr = C.GoString(ifaceSlice[i].hwaddr)
numAddr := int(ifaceSlice[i].naddrs)
addrHdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(&ifaceSlice[i].addrs)),
Len: int(numAddr),
Cap: int(numAddr),
}
ifaces[i].Addrs = make([]VirDomainIPAddress, numAddr)
addrSlice := *(*[]C.virDomainIPAddressPtr)(unsafe.Pointer(&addrHdr))
for k := 0; k < numAddr; k++ {
ifaces[i].Addrs[k] = VirDomainIPAddress{}
ifaces[i].Addrs[k].Type = int(addrSlice[k]._type)
ifaces[i].Addrs[k].Addr = C.GoString(addrSlice[k].addr)
ifaces[i].Addrs[k].Prefix = uint(addrSlice[k].prefix)
}
C.virDomainInterfaceFree(ifaceSlice[i])
}
C.free(unsafe.Pointer(cList))
return ifaces, nil
}
// +build libvirt.1.2.14
package libvirt
import (
"testing"
)
func TestDomainListAllInterfaceAddresses(t *testing.T) {
dom, conn := buildTestQEMUDomain()
defer func() {
dom.Free()
if res, _ := conn.CloseConnection(); res != 0 {
t.Errorf("CloseConnection() == %d, expected 0", res)
}
}()
if err := dom.Create(); err != nil {
t.Error(err)
return
}
defer dom.Destroy()
ifaces, err := dom.ListAllInterfaceAddresses(0)
if err != nil {
t.Fatal(err)
}
if len(ifaces) != 0 {
t.Fatal("should have 0 interfaces", len(ifaces))
}
}
......@@ -1311,3 +1311,26 @@ func TestStorageVolUploadDownload(t *testing.T) {
t.Fatal("Should have got one result, got", len(ms))
}
}*/
func TestDomainListAllInterfaceAddresses(t *testing.T) {
dom, conn := buildTestQEMUDomain()
defer func() {
dom.Free()
if res, _ := conn.CloseConnection(); res != 0 {
t.Errorf("CloseConnection() == %d, expected 0", res)
}
}()
if err := dom.Create(); err != nil {
t.Error(err)
return
}
defer dom.Destroy()
ifaces, err := dom.ListAllInterfaceAddresses(0)
if err != nil {
t.Fatal(err)
}
if len(ifaces) != 0 {
t.Fatal("should have 0 interfaces", len(ifaces))
}
}
......@@ -9,6 +9,8 @@ package libvirt
import "C"
import (
"reflect"
"time"
"unsafe"
)
......@@ -145,3 +147,55 @@ func (n *VirNetwork) Undefine() error {
}
return nil
}
func (n *VirNetwork) GetDHCPLeases() ([]VirNetworkDHCPLease, error) {
var cLeases *C.virNetworkDHCPLeasePtr
numLeases := C.virNetworkGetDHCPLeases(n.ptr, nil, (**C.virNetworkDHCPLeasePtr)(&cLeases), C.uint(0))
if numLeases == -1 {
return nil, GetLastError()
}
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cLeases)),
Len: int(numLeases),
Cap: int(numLeases),
}
var leases []VirNetworkDHCPLease
slice := *(*[]C.virNetworkDHCPLeasePtr)(unsafe.Pointer(&hdr))
for _, ptr := range slice {
leases = append(leases, VirNetworkDHCPLease{ptr})
}
C.free(unsafe.Pointer(cLeases))
return leases, nil
}
type VirNetworkDHCPLease struct {
ptr C.virNetworkDHCPLeasePtr
}
func (l *VirNetworkDHCPLease) GetIface() string {
return C.GoString(l.ptr.iface)
}
func (l *VirNetworkDHCPLease) GetExpiryTime() time.Time {
return time.Unix(int64(l.ptr.expirytime), 0)
}
func (l *VirNetworkDHCPLease) GetMACAddress() string {
return C.GoString(l.ptr.mac)
}
func (l *VirNetworkDHCPLease) GetIPAddress() string {
return C.GoString(l.ptr.ipaddr)
}
func (l *VirNetworkDHCPLease) GetIPPrefix() uint {
return uint(l.ptr.prefix)
}
func (l *VirNetworkDHCPLease) GetHostname() string {
return C.GoString(l.ptr.hostname)
}
func (l *VirNetworkDHCPLease) GetClientID() string {
return C.GoString(l.ptr.clientid)
}
// +build libvirt.1.2.14
package libvirt
/*
#cgo LDFLAGS: -lvirt
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"reflect"
"time"
"unsafe"
)
func (n *VirNetwork) GetDHCPLeases() ([]VirNetworkDHCPLease, error) {
var cLeases *C.virNetworkDHCPLeasePtr
numLeases := C.virNetworkGetDHCPLeases(n.ptr, nil, (**C.virNetworkDHCPLeasePtr)(&cLeases), C.uint(0))
if numLeases == -1 {
return nil, GetLastError()
}
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cLeases)),
Len: int(numLeases),
Cap: int(numLeases),
}
var leases []VirNetworkDHCPLease
slice := *(*[]C.virNetworkDHCPLeasePtr)(unsafe.Pointer(&hdr))
for _, ptr := range slice {
leases = append(leases, VirNetworkDHCPLease{ptr})
}
C.free(unsafe.Pointer(cLeases))
return leases, nil
}
type VirNetworkDHCPLease struct {
ptr C.virNetworkDHCPLeasePtr
}
func (l *VirNetworkDHCPLease) GetIface() string {
return C.GoString(l.ptr.iface)
}
func (l *VirNetworkDHCPLease) GetExpiryTime() time.Time {
return time.Unix(int64(l.ptr.expirytime), 0)
}
func (l *VirNetworkDHCPLease) GetMACAddress() string {
return C.GoString(l.ptr.mac)
}
func (l *VirNetworkDHCPLease) GetIPAddress() string {
return C.GoString(l.ptr.ipaddr)
}
func (l *VirNetworkDHCPLease) GetIPPrefix() uint {
return uint(l.ptr.prefix)
}
func (l *VirNetworkDHCPLease) GetHostname() string {
return C.GoString(l.ptr.hostname)
}
func (l *VirNetworkDHCPLease) GetClientID() string {
return C.GoString(l.ptr.clientid)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment