This commit is contained in:
Philippe Hässig 2015-11-18 10:13:53 +00:00
commit ec000cbc06
29 changed files with 4246 additions and 0 deletions

View File

@ -21,6 +21,7 @@ changed to just run docker commands in the Makefile. See `make docker-run` and
same type.
### Features
- [#357](https://github.com/influxdb/telegraf/pull/357): Libvirt plugin. Thanks @neckhair!
- [#325](https://github.com/influxdb/telegraf/pull/325): NSQ output. Thanks @jrxFive!
- [#318](https://github.com/influxdb/telegraf/pull/318): Prometheus output. Thanks @oldmantaiter!
- [#338](https://github.com/influxdb/telegraf/pull/338): Restart Telegraf on package upgrade. Thanks @linsomniac!

5
Godeps/Godeps.json generated
View File

@ -22,6 +22,11 @@
"Comment": "v0.8.6-7-g9c060de",
"Rev": "9c060de643590dae45da9d7c26276463bfc46fa0"
},
{
"ImportPath": "github.com/alexzorin/libvirt-go",
"Comment": "v2.12.0",
"Rev": "66d8e5e3d8594066da97a9502693a47ab2a35469"
},
{
"ImportPath": "github.com/armon/go-metrics",
"Rev": "b2d95e5291cdbc26997d1301a5e467ecbb240e25"

View File

@ -0,0 +1,7 @@
image: alexzorin/libvirt-go_test:1.2
script:
- go test -v
notify:
email:
recipients:
- git@zor.io

View File

@ -0,0 +1,3 @@
*.sublime-workspace
*.sublime-project
.vagrant

View File

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2013 Alex Zorin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,49 @@
# libvirt-go
[![Build Status](http://ci.serversaurus.com/github.com/alexzorin/libvirt-go/status.svg?branch=master)](http://ci.serversaurus.com/github.com/alexzorin/libvirt-go)
Go bindings for libvirt.
Make sure to have `libvirt-dev` package (or the development files otherwise somewhere in your include path)
## Version Support
Currently, the only supported version of libvirt is **1.2.2**, tagged as `v2.x` releases `gopkg.in/alexzorin/libvirt-go.v2` [(docs)](http://gopkg.in/alexzorin/libvirt-go.v2).
The bindings will probably work with versions of libvirt that are higher than 1.2.2, depending on what is added in those releases. However, no features are currently being added that will cause the build or tests to break against 1.2.2.
### 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 7 | 1.2.4 from wheezy-backports |
| Debian 6 | 0.9.12 from squeeze-backports |
| Ubuntu 14.04 | 1.2.2 from trusty |
| 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).
## Documentation
* [api documentation for the bindings](http://godoc.org/github.com/alexzorin/libvirt-go)
* [api documentation for libvirt](http://libvirt.org/html/libvirt-libvirt.html)
## Contributing
Please fork and write tests.
Integration tests are available where functionality isn't provided by the test driver, see `integration_test.go`.
A `Vagrantfile` is included to run the integration tests:
* `cd ./vagrant/{branch}` (i.e `./vagrant/master`, where you will find a `Vagrantfile` for the `master` branch)
* `vagrant up` to provision the virtual machine
* `vagrant ssh` to login to the virtual machine
Once inside, `sudo su -`, `cd /libvirt-go` and `go test -tags integration`.

View File

@ -0,0 +1,96 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
void virErrorFuncDummy(void *userData, virErrorPtr error)
{
}
int domainEventLifecycleCallback_cgo(virConnectPtr c, virDomainPtr d,
int event, int detail, void *data)
{
return domainEventLifecycleCallback(c, d, event, detail, data);
}
int domainEventGenericCallback_cgo(virConnectPtr c, virDomainPtr d, void *data)
{
return domainEventGenericCallback(c, d, data);
}
int domainEventRTCChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
long long utcoffset, void *data)
{
return domainEventRTCChangeCallback(c, d, utcoffset, data);
}
int domainEventWatchdogCallback_cgo(virConnectPtr c, virDomainPtr d,
int action, void *data)
{
return domainEventWatchdogCallback(c, d, action, data);
}
int domainEventIOErrorCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *srcPath, const char *devAlias,
int action, void *data)
{
return domainEventIOErrorCallback(c, d, srcPath, devAlias, action, data);
}
int domainEventGraphicsCallback_cgo(virConnectPtr c, virDomainPtr d,
int phase, const virDomainEventGraphicsAddress *local,
const virDomainEventGraphicsAddress *remote,
const char *authScheme,
const virDomainEventGraphicsSubject *subject, void *data)
{
return domainEventGraphicsCallback(c, d, phase, local, remote, authScheme, subject, data);
}
int domainEventIOErrorReasonCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *srcPath, const char *devAlias,
int action, const char *reason, void *data)
{
return domainEventIOErrorReasonCallback(c, d, srcPath, devAlias, action, reason, data);
}
int domainEventBlockJobCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *disk, int type, int status, void *data)
{
return domainEventIOErrorReasonCallback(c, d, disk, type, status, data);
}
int domainEventDiskChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *oldSrcPath, const char *newSrcPath,
const char *devAlias, int reason, void *data)
{
return domainEventDiskChangeCallback(c, d, oldSrcPath, newSrcPath, devAlias, reason, data);
}
int domainEventTrayChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *devAlias, int reason, void *data)
{
return domainEventTrayChangeCallback(c, d, devAlias, reason, data);
}
int domainEventReasonCallback_cgo(virConnectPtr c, virDomainPtr d,
int reason, void *data)
{
return domainEventReasonCallback(c, d, reason, data);
}
int domainEventBalloonChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
unsigned long long actual, void *data)
{
return domainEventBalloonChangeCallback(c, d, actual, data);
}
int domainEventDeviceRemovedCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *devAlias, void *data)
{
return domainEventDeviceRemovedCallback(c, d, devAlias, data);
}
*/
import "C"

View File

@ -0,0 +1,385 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
// virDomainState
const (
VIR_DOMAIN_NOSTATE = C.VIR_DOMAIN_NOSTATE
VIR_DOMAIN_RUNNING = C.VIR_DOMAIN_RUNNING
VIR_DOMAIN_BLOCKED = C.VIR_DOMAIN_BLOCKED
VIR_DOMAIN_PAUSED = C.VIR_DOMAIN_PAUSED
VIR_DOMAIN_SHUTDOWN = C.VIR_DOMAIN_SHUTDOWN
VIR_DOMAIN_CRASHED = C.VIR_DOMAIN_CRASHED
VIR_DOMAIN_PMSUSPENDED = C.VIR_DOMAIN_PMSUSPENDED
VIR_DOMAIN_SHUTOFF = C.VIR_DOMAIN_SHUTOFF
)
//virConnectListAllDomainsFlags
const (
VIR_CONNECT_LIST_DOMAINS_ACTIVE = C.VIR_CONNECT_LIST_DOMAINS_ACTIVE
VIR_CONNECT_LIST_DOMAINS_INACTIVE = C.VIR_CONNECT_LIST_DOMAINS_INACTIVE
VIR_CONNECT_LIST_DOMAINS_PERSISTENT = C.VIR_CONNECT_LIST_DOMAINS_PERSISTENT
VIR_CONNECT_LIST_DOMAINS_TRANSIENT = C.VIR_CONNECT_LIST_DOMAINS_TRANSIENT
VIR_CONNECT_LIST_DOMAINS_RUNNING = C.VIR_CONNECT_LIST_DOMAINS_RUNNING
VIR_CONNECT_LIST_DOMAINS_PAUSED = C.VIR_CONNECT_LIST_DOMAINS_PAUSED
VIR_CONNECT_LIST_DOMAINS_SHUTOFF = C.VIR_CONNECT_LIST_DOMAINS_SHUTOFF
VIR_CONNECT_LIST_DOMAINS_OTHER = C.VIR_CONNECT_LIST_DOMAINS_OTHER
VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE = C.VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE
VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE = C.VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE
VIR_CONNECT_LIST_DOMAINS_AUTOSTART = C.VIR_CONNECT_LIST_DOMAINS_AUTOSTART
VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART = C.VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART
VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT = C.VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT
VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT = C.VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT
)
// virDomainMetadataType
const (
VIR_DOMAIN_METADATA_DESCRIPTION = C.VIR_DOMAIN_METADATA_DESCRIPTION
VIR_DOMAIN_METADATA_TITLE = C.VIR_DOMAIN_METADATA_TITLE
VIR_DOMAIN_METADATA_ELEMENT = C.VIR_DOMAIN_METADATA_ELEMENT
)
// virDomainVcpuFlags
const (
VIR_DOMAIN_VCPU_CONFIG = C.VIR_DOMAIN_VCPU_CONFIG
VIR_DOMAIN_VCPU_CURRENT = C.VIR_DOMAIN_VCPU_CURRENT
VIR_DOMAIN_VCPU_LIVE = C.VIR_DOMAIN_VCPU_LIVE
VIR_DOMAIN_VCPU_MAXIMUM = C.VIR_DOMAIN_VCPU_MAXIMUM
VIR_DOMAIN_VCPU_GUEST = C.VIR_DOMAIN_VCPU_GUEST
)
// virDomainMemoryModFlags
const (
VIR_DOMAIN_MEM_CONFIG = C.VIR_DOMAIN_AFFECT_CONFIG
VIR_DOMAIN_MEM_CURRENT = C.VIR_DOMAIN_AFFECT_CURRENT
VIR_DOMAIN_MEM_LIVE = C.VIR_DOMAIN_AFFECT_LIVE
VIR_DOMAIN_MEM_MAXIMUM = C.VIR_DOMAIN_MEM_MAXIMUM
)
// virStoragePoolState
const (
VIR_STORAGE_POOL_INACTIVE = C.VIR_STORAGE_POOL_INACTIVE // Not running
VIR_STORAGE_POOL_BUILDING = C.VIR_STORAGE_POOL_BUILDING // Initializing pool,not available
VIR_STORAGE_POOL_RUNNING = C.VIR_STORAGE_POOL_RUNNING // Running normally
VIR_STORAGE_POOL_DEGRADED = C.VIR_STORAGE_POOL_DEGRADED // Running degraded
VIR_STORAGE_POOL_INACCESSIBLE = C.VIR_STORAGE_POOL_INACCESSIBLE // Running,but not accessible
)
// virStoragePoolBuildFlags
const (
VIR_STORAGE_POOL_BUILD_NEW = C.VIR_STORAGE_POOL_BUILD_NEW // Regular build from scratch
VIR_STORAGE_POOL_BUILD_REPAIR = C.VIR_STORAGE_POOL_BUILD_REPAIR // Repair / reinitialize
VIR_STORAGE_POOL_BUILD_RESIZE = C.VIR_STORAGE_POOL_BUILD_RESIZE // Extend existing pool
VIR_STORAGE_POOL_BUILD_NO_OVERWRITE = C.VIR_STORAGE_POOL_BUILD_NO_OVERWRITE // Do not overwrite existing pool
VIR_STORAGE_POOL_BUILD_OVERWRITE = C.VIR_STORAGE_POOL_BUILD_OVERWRITE // Overwrite data
)
// virDomainDestroyFlags
const (
VIR_DOMAIN_DESTROY_DEFAULT = C.VIR_DOMAIN_DESTROY_DEFAULT
VIR_DOMAIN_DESTROY_GRACEFUL = C.VIR_DOMAIN_DESTROY_GRACEFUL
)
// virDomainShutdownFlags
const (
VIR_DOMAIN_SHUTDOWN_DEFAULT = C.VIR_DOMAIN_SHUTDOWN_DEFAULT
VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN = C.VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN
VIR_DOMAIN_SHUTDOWN_GUEST_AGENT = C.VIR_DOMAIN_SHUTDOWN_GUEST_AGENT
VIR_DOMAIN_SHUTDOWN_INITCTL = C.VIR_DOMAIN_SHUTDOWN_INITCTL
VIR_DOMAIN_SHUTDOWN_SIGNAL = C.VIR_DOMAIN_SHUTDOWN_SIGNAL
)
// virDomainAttachDeviceFlags
const (
VIR_DOMAIN_DEVICE_MODIFY_CONFIG = C.VIR_DOMAIN_AFFECT_CONFIG
VIR_DOMAIN_DEVICE_MODIFY_CURRENT = C.VIR_DOMAIN_AFFECT_CURRENT
VIR_DOMAIN_DEVICE_MODIFY_LIVE = C.VIR_DOMAIN_AFFECT_LIVE
VIR_DOMAIN_DEVICE_MODIFY_FORCE = C.VIR_DOMAIN_DEVICE_MODIFY_FORCE
)
// virStorageVolCreateFlags
const (
VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA = C.VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA
)
// virStorageVolDeleteFlags
const (
VIR_STORAGE_VOL_DELETE_NORMAL = C.VIR_STORAGE_VOL_DELETE_NORMAL // Delete metadata only (fast)
VIR_STORAGE_VOL_DELETE_ZEROED = C.VIR_STORAGE_VOL_DELETE_ZEROED // Clear all data to zeros (slow)
)
// virStorageVolResizeFlags
const (
VIR_STORAGE_VOL_RESIZE_ALLOCATE = C.VIR_STORAGE_VOL_RESIZE_ALLOCATE // force allocation of new size
VIR_STORAGE_VOL_RESIZE_DELTA = C.VIR_STORAGE_VOL_RESIZE_DELTA // size is relative to current
VIR_STORAGE_VOL_RESIZE_SHRINK = C.VIR_STORAGE_VOL_RESIZE_SHRINK // allow decrease in capacity
)
// virStorageVolType
const (
VIR_STORAGE_VOL_FILE = C.VIR_STORAGE_VOL_FILE // Regular file based volumes
VIR_STORAGE_VOL_BLOCK = C.VIR_STORAGE_VOL_BLOCK // Block based volumes
VIR_STORAGE_VOL_DIR = C.VIR_STORAGE_VOL_DIR // Directory-passthrough based volume
VIR_STORAGE_VOL_NETWORK = C.VIR_STORAGE_VOL_NETWORK //Network volumes like RBD (RADOS Block Device)
VIR_STORAGE_VOL_NETDIR = C.VIR_STORAGE_VOL_NETDIR // Network accessible directory that can contain other network volumes
)
// virStorageVolWipeAlgorithm
const (
VIR_STORAGE_VOL_WIPE_ALG_ZERO = C.VIR_STORAGE_VOL_WIPE_ALG_ZERO // 1-pass, all zeroes
VIR_STORAGE_VOL_WIPE_ALG_NNSA = C.VIR_STORAGE_VOL_WIPE_ALG_NNSA // 4-pass NNSA Policy Letter NAP-14.1-C (XVI-8)
VIR_STORAGE_VOL_WIPE_ALG_DOD = C.VIR_STORAGE_VOL_WIPE_ALG_DOD // 4-pass DoD 5220.22-M section 8-306 procedure
VIR_STORAGE_VOL_WIPE_ALG_BSI = C.VIR_STORAGE_VOL_WIPE_ALG_BSI // 9-pass method recommended by the German Center of Security in Information Technologies
VIR_STORAGE_VOL_WIPE_ALG_GUTMANN = C.VIR_STORAGE_VOL_WIPE_ALG_GUTMANN // The canonical 35-pass sequence
VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER = C.VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER // 7-pass method described by Bruce Schneier in "Applied Cryptography" (1996)
VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7 = C.VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7 // 7-pass random
VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33 = C.VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33 // 33-pass random
VIR_STORAGE_VOL_WIPE_ALG_RANDOM = C.VIR_STORAGE_VOL_WIPE_ALG_RANDOM // 1-pass random
)
// virSecretUsageType
const (
VIR_SECRET_USAGE_TYPE_NONE = C.VIR_SECRET_USAGE_TYPE_NONE
VIR_SECRET_USAGE_TYPE_VOLUME = C.VIR_SECRET_USAGE_TYPE_VOLUME
VIR_SECRET_USAGE_TYPE_CEPH = C.VIR_SECRET_USAGE_TYPE_CEPH
VIR_SECRET_USAGE_TYPE_ISCSI = C.VIR_SECRET_USAGE_TYPE_ISCSI
)
// virConnectListAllNetworksFlags
const (
VIR_CONNECT_LIST_NETWORKS_INACTIVE = C.VIR_CONNECT_LIST_NETWORKS_INACTIVE
VIR_CONNECT_LIST_NETWORKS_ACTIVE = C.VIR_CONNECT_LIST_NETWORKS_ACTIVE
VIR_CONNECT_LIST_NETWORKS_PERSISTENT = C.VIR_CONNECT_LIST_NETWORKS_PERSISTENT
VIR_CONNECT_LIST_NETWORKS_TRANSIENT = C.VIR_CONNECT_LIST_NETWORKS_TRANSIENT
VIR_CONNECT_LIST_NETWORKS_AUTOSTART = C.VIR_CONNECT_LIST_NETWORKS_AUTOSTART
VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART = C.VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART
)
// virConnectListAllStoragePoolsFlags
const (
VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE = C.VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE
VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE = C.VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE
VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT = C.VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT
VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT = C.VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT
VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART = C.VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART
VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART = C.VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART
VIR_CONNECT_LIST_STORAGE_POOLS_DIR = C.VIR_CONNECT_LIST_STORAGE_POOLS_DIR
VIR_CONNECT_LIST_STORAGE_POOLS_FS = C.VIR_CONNECT_LIST_STORAGE_POOLS_FS
VIR_CONNECT_LIST_STORAGE_POOLS_NETFS = C.VIR_CONNECT_LIST_STORAGE_POOLS_NETFS
VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL = C.VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL
VIR_CONNECT_LIST_STORAGE_POOLS_DISK = C.VIR_CONNECT_LIST_STORAGE_POOLS_DISK
VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI = C.VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI
VIR_CONNECT_LIST_STORAGE_POOLS_SCSI = C.VIR_CONNECT_LIST_STORAGE_POOLS_SCSI
VIR_CONNECT_LIST_STORAGE_POOLS_MPATH = C.VIR_CONNECT_LIST_STORAGE_POOLS_MPATH
VIR_CONNECT_LIST_STORAGE_POOLS_RBD = C.VIR_CONNECT_LIST_STORAGE_POOLS_RBD
VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG = C.VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG
VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER = C.VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER
)
// virStreamFlags
const (
VIR_STREAM_NONBLOCK = C.VIR_STREAM_NONBLOCK
)
// virKeycodeSet
const (
VIR_KEYCODE_SET_LINUX = C.VIR_KEYCODE_SET_LINUX
VIR_KEYCODE_SET_XT = C.VIR_KEYCODE_SET_XT
VIR_KEYCODE_SET_ATSET1 = C.VIR_KEYCODE_SET_ATSET1
VIR_KEYCODE_SET_ATSET2 = C.VIR_KEYCODE_SET_ATSET2
VIR_KEYCODE_SET_ATSET3 = C.VIR_KEYCODE_SET_ATSET3
VIR_KEYCODE_SET_OSX = C.VIR_KEYCODE_SET_OSX
VIR_KEYCODE_SET_XT_KBD = C.VIR_KEYCODE_SET_XT_KBD
VIR_KEYCODE_SET_USB = C.VIR_KEYCODE_SET_USB
VIR_KEYCODE_SET_WIN32 = C.VIR_KEYCODE_SET_WIN32
VIR_KEYCODE_SET_RFB = C.VIR_KEYCODE_SET_RFB
)
// virDomainCreateFlags
const (
VIR_DOMAIN_NONE = C.VIR_DOMAIN_NONE
VIR_DOMAIN_START_PAUSED = C.VIR_DOMAIN_START_PAUSED
VIR_DOMAIN_START_AUTODESTROY = C.VIR_DOMAIN_START_AUTODESTROY
VIR_DOMAIN_START_BYPASS_CACHE = C.VIR_DOMAIN_START_BYPASS_CACHE
VIR_DOMAIN_START_FORCE_BOOT = C.VIR_DOMAIN_START_FORCE_BOOT
)
const VIR_DOMAIN_MEMORY_PARAM_UNLIMITED = C.VIR_DOMAIN_MEMORY_PARAM_UNLIMITED
// virDomainEventID
const (
// event parameter in the callback is of type DomainLifecycleEvent
VIR_DOMAIN_EVENT_ID_LIFECYCLE = C.VIR_DOMAIN_EVENT_ID_LIFECYCLE
// event parameter in the callback is nil
VIR_DOMAIN_EVENT_ID_REBOOT = C.VIR_DOMAIN_EVENT_ID_REBOOT
// event parameter in the callback is of type DomainRTCChangeEvent
VIR_DOMAIN_EVENT_ID_RTC_CHANGE = C.VIR_DOMAIN_EVENT_ID_RTC_CHANGE
// event parameter in the callback is of type DomainWatchdogEvent
VIR_DOMAIN_EVENT_ID_WATCHDOG = C.VIR_DOMAIN_EVENT_ID_WATCHDOG
// event parameter in the callback is of type DomainIOErrorEvent
VIR_DOMAIN_EVENT_ID_IO_ERROR = C.VIR_DOMAIN_EVENT_ID_IO_ERROR
// event parameter in the callback is of type DomainGraphicsEvent
VIR_DOMAIN_EVENT_ID_GRAPHICS = C.VIR_DOMAIN_EVENT_ID_GRAPHICS
// virConnectDomainEventIOErrorReasonCallback
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON = C.VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
// event parameter in the callback is nil
VIR_DOMAIN_EVENT_ID_CONTROL_ERROR = C.VIR_DOMAIN_EVENT_ID_CONTROL_ERROR
// event parameter in the callback is of type DomainBlockJobEvent
VIR_DOMAIN_EVENT_ID_BLOCK_JOB = C.VIR_DOMAIN_EVENT_ID_BLOCK_JOB
// event parameter in the callback is of type DomainDiskChangeEvent
VIR_DOMAIN_EVENT_ID_DISK_CHANGE = C.VIR_DOMAIN_EVENT_ID_DISK_CHANGE
// event parameter in the callback is of type DomainTrayChangeEvent
VIR_DOMAIN_EVENT_ID_TRAY_CHANGE = C.VIR_DOMAIN_EVENT_ID_TRAY_CHANGE
// event parameter in the callback is of type DomainReasonEvent
VIR_DOMAIN_EVENT_ID_PMWAKEUP = C.VIR_DOMAIN_EVENT_ID_PMWAKEUP
// event parameter in the callback is of type DomainReasonEvent
VIR_DOMAIN_EVENT_ID_PMSUSPEND = C.VIR_DOMAIN_EVENT_ID_PMSUSPEND
// event parameter in the callback is of type DomainBalloonChangeEvent
VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE = C.VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE
// event parameter in the callback is of type DomainReasonEvent
VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK = C.VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK
// event parameter in the callback is of type DomainDeviceRemovedEvent
VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED = C.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED
// TODO Post 1.2.4, enable later
// event parameter in the callback is of type DomainBlockJobEvent
// VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2 = C.VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2
)
// virDomainEventType
const (
VIR_DOMAIN_EVENT_DEFINED = C.VIR_DOMAIN_EVENT_DEFINED
VIR_DOMAIN_EVENT_UNDEFINED = C.VIR_DOMAIN_EVENT_UNDEFINED
VIR_DOMAIN_EVENT_STARTED = C.VIR_DOMAIN_EVENT_STARTED
VIR_DOMAIN_EVENT_SUSPENDED = C.VIR_DOMAIN_EVENT_SUSPENDED
VIR_DOMAIN_EVENT_RESUMED = C.VIR_DOMAIN_EVENT_RESUMED
VIR_DOMAIN_EVENT_STOPPED = C.VIR_DOMAIN_EVENT_STOPPED
VIR_DOMAIN_EVENT_SHUTDOWN = C.VIR_DOMAIN_EVENT_SHUTDOWN
VIR_DOMAIN_EVENT_PMSUSPENDED = C.VIR_DOMAIN_EVENT_PMSUSPENDED
VIR_DOMAIN_EVENT_CRASHED = C.VIR_DOMAIN_EVENT_CRASHED
)
// virDomainEventWatchdogAction:
// The action that is to be taken due to the watchdog device firing
const (
// No action, watchdog ignored
VIR_DOMAIN_EVENT_WATCHDOG_NONE = C.VIR_DOMAIN_EVENT_WATCHDOG_NONE
// Guest CPUs are paused
VIR_DOMAIN_EVENT_WATCHDOG_PAUSE = C.VIR_DOMAIN_EVENT_WATCHDOG_PAUSE
// Guest CPUs are reset
VIR_DOMAIN_EVENT_WATCHDOG_RESET = C.VIR_DOMAIN_EVENT_WATCHDOG_RESET
// Guest is forcibly powered off
VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF = C.VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF
// Guest is requested to gracefully shutdown
VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN = C.VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN
// No action, a debug message logged
VIR_DOMAIN_EVENT_WATCHDOG_DEBUG = C.VIR_DOMAIN_EVENT_WATCHDOG_DEBUG
)
// virDomainEventIOErrorAction
// The action that is to be taken due to an IO error occurring
const (
// No action, IO error ignored
VIR_DOMAIN_EVENT_IO_ERROR_NONE = C.VIR_DOMAIN_EVENT_IO_ERROR_NONE
// Guest CPUs are paused
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE = C.VIR_DOMAIN_EVENT_IO_ERROR_PAUSE
// IO error reported to guest OS
VIR_DOMAIN_EVENT_IO_ERROR_REPORT = C.VIR_DOMAIN_EVENT_IO_ERROR_REPORT
)
// virDomainEventGraphicsPhase
// The phase of the graphics client connection
const (
// Initial socket connection established
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = C.VIR_DOMAIN_EVENT_GRAPHICS_CONNECT
// Authentication & setup completed
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE = C.VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE
// Final socket disconnection
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT = C.VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT
)
// virDomainEventGraphicsAddressType
const (
// IPv4 address
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4 = C.VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4
// IPv6 address
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6 = C.VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6
// UNIX socket path
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_UNIX = C.VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_UNIX
)
// virDomainBlockJobType
const (
// Placeholder
VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN = C.VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN
// Block Pull (virDomainBlockPull, or virDomainBlockRebase without
// flags), job ends on completion
VIR_DOMAIN_BLOCK_JOB_TYPE_PULL = C.VIR_DOMAIN_BLOCK_JOB_TYPE_PULL
// Block Copy (virDomainBlockCopy, or virDomainBlockRebase with
// flags), job exists as long as mirroring is active
VIR_DOMAIN_BLOCK_JOB_TYPE_COPY = C.VIR_DOMAIN_BLOCK_JOB_TYPE_COPY
// Block Commit (virDomainBlockCommit without flags), job ends on
// completion
VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT = C.VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT
// TODO Post 1.2.4, enable later
// Active Block Commit (virDomainBlockCommit with flags), job
// exists as long as sync is active
// VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT = C.VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT
)
// virConnectDomainEventBlockJobStatus
const (
VIR_DOMAIN_BLOCK_JOB_COMPLETED = C.VIR_DOMAIN_BLOCK_JOB_COMPLETED
VIR_DOMAIN_BLOCK_JOB_FAILED = C.VIR_DOMAIN_BLOCK_JOB_FAILED
VIR_DOMAIN_BLOCK_JOB_CANCELED = C.VIR_DOMAIN_BLOCK_JOB_CANCELED
VIR_DOMAIN_BLOCK_JOB_READY = C.VIR_DOMAIN_BLOCK_JOB_READY
)
// virConnectDomainEventDiskChangeReason
const (
// OldSrcPath is set
VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START = C.VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START
VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START = C.VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START
)
// virConnectDomainEventTrayChangeReason
const (
VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN = C.VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN
VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE = C.VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE
)

View File

@ -0,0 +1,639 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"reflect"
"strings"
"unsafe"
)
type VirDomain struct {
ptr C.virDomainPtr
}
type VirDomainBlockInfo struct {
ptr C.virDomainBlockInfo
}
type VirDomainInfo struct {
ptr C.virDomainInfo
}
type VirTypedParameter struct {
Name string
Value interface{}
}
type VirDomainMemoryStat struct {
Tag int32
Val uint64
}
type VirVcpuInfo struct {
Number uint32
State int32
CpuTime uint64
Cpu int32
}
type VirTypedParameters []VirTypedParameter
func (dest *VirTypedParameters) loadFromCPtr(params C.virTypedParameterPtr, nParams int) {
// reset slice
*dest = VirTypedParameters{}
// transform that C array to a go slice
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(params)),
Len: int(nParams),
Cap: int(nParams),
}
rawParams := *(*[]C.struct__virTypedParameter)(unsafe.Pointer(&hdr))
// there is probably a more elegant way to deal with that union
for _, rawParam := range rawParams {
name := C.GoStringN(&rawParam.field[0], C.VIR_TYPED_PARAM_FIELD_LENGTH)
if nbIdx := strings.Index(name, "\x00"); nbIdx != -1 {
name = name[:nbIdx]
}
switch rawParam._type {
case C.VIR_TYPED_PARAM_INT:
*dest = append(*dest, VirTypedParameter{name, int(*(*C.int)(unsafe.Pointer(&rawParam.value[0])))})
case C.VIR_TYPED_PARAM_UINT:
*dest = append(*dest, VirTypedParameter{name, uint32(*(*C.uint)(unsafe.Pointer(&rawParam.value[0])))})
case C.VIR_TYPED_PARAM_LLONG:
*dest = append(*dest, VirTypedParameter{name, int64(*(*C.longlong)(unsafe.Pointer(&rawParam.value[0])))})
case C.VIR_TYPED_PARAM_ULLONG:
*dest = append(*dest, VirTypedParameter{name, uint64(*(*C.ulonglong)(unsafe.Pointer(&rawParam.value[0])))})
case C.VIR_TYPED_PARAM_DOUBLE:
*dest = append(*dest, VirTypedParameter{name, float64(*(*C.double)(unsafe.Pointer(&rawParam.value[0])))})
case C.VIR_TYPED_PARAM_BOOLEAN:
if int(*(*C.char)(unsafe.Pointer(&rawParam.value[0]))) == 1 {
*dest = append(*dest, VirTypedParameter{name, true})
} else {
*dest = append(*dest, VirTypedParameter{name, false})
}
case C.VIR_TYPED_PARAM_STRING:
*dest = append(*dest, VirTypedParameter{name, C.GoString((*C.char)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&rawParam.value[0])))))})
}
}
}
func (d *VirDomain) Free() error {
if result := C.virDomainFree(d.ptr); result != 0 {
return GetLastError()
}
return nil
}
func (d *VirDomain) Create() error {
result := C.virDomainCreate(d.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) Destroy() error {
result := C.virDomainDestroy(d.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) Shutdown() error {
result := C.virDomainShutdown(d.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) Reboot(flags uint) error {
result := C.virDomainReboot(d.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) IsActive() (bool, error) {
result := C.virDomainIsActive(d.ptr)
if result == -1 {
return false, GetLastError()
}
if result == 1 {
return true, nil
}
return false, nil
}
func (d *VirDomain) SetAutostart(autostart bool) error {
var cAutostart C.int
switch autostart {
case true:
cAutostart = 1
default:
cAutostart = 0
}
result := C.virDomainSetAutostart(d.ptr, cAutostart)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) GetAutostart() (bool, error) {
var out C.int
result := C.virDomainGetAutostart(d.ptr, (*C.int)(unsafe.Pointer(&out)))
if result == -1 {
return false, GetLastError()
}
switch out {
case 1:
return true, nil
default:
return false, nil
}
}
func (d *VirDomain) GetBlockInfo(disk string, flag uint) (VirDomainBlockInfo, error) {
bi := VirDomainBlockInfo{}
var ptr C.virDomainBlockInfo
cDisk := C.CString(disk)
defer C.free(unsafe.Pointer(cDisk))
result := C.virDomainGetBlockInfo(d.ptr, cDisk, (*C.virDomainBlockInfo)(unsafe.Pointer(&ptr)), C.uint(flag))
if result == -1 {
return bi, GetLastError()
}
bi.ptr = ptr
return bi, nil
}
func (b *VirDomainBlockInfo) Allocation() uint64 {
return uint64(b.ptr.allocation)
}
func (b *VirDomainBlockInfo) Capacity() uint64 {
return uint64(b.ptr.capacity)
}
func (b *VirDomainBlockInfo) Physical() uint64 {
return uint64(b.ptr.physical)
}
func (d *VirDomain) GetName() (string, error) {
name := C.virDomainGetName(d.ptr)
if name == nil {
return "", GetLastError()
}
return C.GoString(name), nil
}
func (d *VirDomain) GetState() ([]int, error) {
var cState C.int
var cReason C.int
result := C.virDomainGetState(d.ptr,
(*C.int)(unsafe.Pointer(&cState)),
(*C.int)(unsafe.Pointer(&cReason)),
0)
if int(result) == -1 {
return []int{}, GetLastError()
}
return []int{int(cState), int(cReason)}, nil
}
func (d *VirDomain) GetID() (uint, error) {
id := uint(C.virDomainGetID(d.ptr))
if id == ^uint(0) {
return id, GetLastError()
}
return id, nil
}
func (d *VirDomain) GetUUID() ([]byte, error) {
var cUuid [C.VIR_UUID_BUFLEN](byte)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virDomainGetUUID(d.ptr, (*C.uchar)(cuidPtr))
if result != 0 {
return []byte{}, GetLastError()
}
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
}
func (d *VirDomain) GetUUIDString() (string, error) {
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virDomainGetUUIDString(d.ptr, (*C.char)(cuidPtr))
if result != 0 {
return "", GetLastError()
}
return C.GoString((*C.char)(cuidPtr)), nil
}
func (d *VirDomain) GetInfo() (VirDomainInfo, error) {
di := VirDomainInfo{}
var ptr C.virDomainInfo
result := C.virDomainGetInfo(d.ptr, (*C.virDomainInfo)(unsafe.Pointer(&ptr)))
if result == -1 {
return di, GetLastError()
}
di.ptr = ptr
return di, nil
}
func (d *VirDomain) GetXMLDesc(flags uint32) (string, error) {
result := C.virDomainGetXMLDesc(d.ptr, C.uint(flags))
if result == nil {
return "", GetLastError()
}
xml := C.GoString(result)
C.free(unsafe.Pointer(result))
return xml, nil
}
func (i *VirDomainInfo) GetState() uint8 {
return uint8(i.ptr.state)
}
func (i *VirDomainInfo) GetMaxMem() uint64 {
return uint64(i.ptr.maxMem)
}
func (i *VirDomainInfo) GetMemory() uint64 {
return uint64(i.ptr.memory)
}
func (i *VirDomainInfo) GetNrVirtCpu() uint16 {
return uint16(i.ptr.nrVirtCpu)
}
func (i *VirDomainInfo) GetCpuTime() uint64 {
return uint64(i.ptr.cpuTime)
}
func (d *VirDomain) GetCPUStats(params *VirTypedParameters, nParams int, startCpu int, nCpus uint32, flags uint32) (int, error) {
var cParams C.virTypedParameterPtr
var cParamsLen int
cParamsLen = int(nCpus) * nParams
if params != nil && cParamsLen > 0 {
cParams = (C.virTypedParameterPtr)(C.calloc(C.size_t(cParamsLen), C.size_t(unsafe.Sizeof(C.struct__virTypedParameter{}))))
defer C.virTypedParamsFree(cParams, C.int(cParamsLen))
} else {
cParamsLen = 0
cParams = nil
}
result := int(C.virDomainGetCPUStats(d.ptr, (C.virTypedParameterPtr)(cParams), C.uint(nParams), C.int(startCpu), C.uint(nCpus), C.uint(flags)))
if result == -1 {
return result, GetLastError()
}
if cParamsLen > 0 {
params.loadFromCPtr(cParams, cParamsLen)
}
return result, nil
}
// Warning: No test written for this function
func (d *VirDomain) GetInterfaceParameters(device string, params *VirTypedParameters, nParams *int, flags uint32) (int, error) {
var cParams C.virTypedParameterPtr
if params != nil && *nParams > 0 {
cParams = (C.virTypedParameterPtr)(C.calloc(C.size_t(*nParams), C.size_t(unsafe.Sizeof(C.struct__virTypedParameter{}))))
defer C.virTypedParamsFree(cParams, C.int(*nParams))
} else {
cParams = nil
}
result := int(C.virDomainGetInterfaceParameters(d.ptr, C.CString(device), (C.virTypedParameterPtr)(cParams), (*C.int)(unsafe.Pointer(nParams)), C.uint(flags)))
if result == -1 {
return result, GetLastError()
}
if params != nil && *nParams > 0 {
params.loadFromCPtr(cParams, *nParams)
}
return result, nil
}
func (d *VirDomain) GetMetadata(tipus int, uri string, flags uint32) (string, error) {
var cUri *C.char
if uri != "" {
cUri = C.CString(uri)
defer C.free(unsafe.Pointer(cUri))
}
result := C.virDomainGetMetadata(d.ptr, C.int(tipus), cUri, C.uint(flags))
if result == nil {
return "", GetLastError()
}
defer C.free(unsafe.Pointer(result))
return C.GoString(result), nil
}
func (d *VirDomain) SetMetadata(metaDataType int, metaDataCont, uriKey, uri string, flags uint32) error {
var cMetaDataCont *C.char
var cUriKey *C.char
var cUri *C.char
cMetaDataCont = C.CString(metaDataCont)
defer C.free(unsafe.Pointer(cMetaDataCont))
if metaDataType == VIR_DOMAIN_METADATA_ELEMENT {
cUriKey = C.CString(uriKey)
defer C.free(unsafe.Pointer(cUriKey))
cUri = C.CString(uri)
defer C.free(unsafe.Pointer(cUri))
}
result := C.virDomainSetMetadata(d.ptr, C.int(metaDataType), cMetaDataCont, cUriKey, cUri, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) Undefine() error {
result := C.virDomainUndefine(d.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) SetMaxMemory(memory uint) error {
result := C.virDomainSetMaxMemory(d.ptr, C.ulong(memory))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) SetMemory(memory uint64) error {
result := C.virDomainSetMemory(d.ptr, C.ulong(memory))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) SetMemoryFlags(memory uint64, flags uint32) error {
result := C.virDomainSetMemoryFlags(d.ptr, C.ulong(memory), C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) SetMemoryStatsPeriod(period int, flags uint) error {
result := C.virDomainSetMemoryStatsPeriod(d.ptr, C.int(period), C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) SetVcpus(vcpu uint) error {
result := C.virDomainSetVcpus(d.ptr, C.uint(vcpu))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) SetVcpusFlags(vcpu uint, flags uint) error {
result := C.virDomainSetVcpusFlags(d.ptr, C.uint(vcpu), C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) Suspend() error {
result := C.virDomainSuspend(d.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) Resume() error {
result := C.virDomainResume(d.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) AbortJob() error {
result := C.virDomainAbortJob(d.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) DestroyFlags(flags uint) error {
result := C.virDomainDestroyFlags(d.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) ShutdownFlags(flags uint) error {
result := C.virDomainShutdownFlags(d.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) AttachDevice(xml string) error {
cXml := C.CString(xml)
defer C.free(unsafe.Pointer(cXml))
result := C.virDomainAttachDevice(d.ptr, cXml)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) AttachDeviceFlags(xml string, flags uint) error {
cXml := C.CString(xml)
defer C.free(unsafe.Pointer(cXml))
result := C.virDomainAttachDeviceFlags(d.ptr, cXml, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) DetachDevice(xml string) error {
cXml := C.CString(xml)
defer C.free(unsafe.Pointer(cXml))
result := C.virDomainDetachDevice(d.ptr, cXml)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) DetachDeviceFlags(xml string, flags uint) error {
cXml := C.CString(xml)
defer C.free(unsafe.Pointer(cXml))
result := C.virDomainDetachDeviceFlags(d.ptr, cXml, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) Screenshot(stream *VirStream, screen, flags uint) (string, error) {
cType := C.virDomainScreenshot(d.ptr, stream.ptr, C.uint(screen), C.uint(flags))
if cType == nil {
return "", GetLastError()
}
defer C.free(unsafe.Pointer(cType))
mimeType := C.GoString(cType)
return mimeType, nil
}
func (d *VirDomain) SendKey(codeset, holdtime uint, keycodes []uint, flags uint) error {
result := C.virDomainSendKey(d.ptr, C.uint(codeset), C.uint(holdtime), (*C.uint)(unsafe.Pointer(&keycodes[0])), C.int(len(keycodes)), C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) BlockStatsFlags(disk string, params *VirTypedParameters, nParams int, flags uint32) (int, error) {
var cParams C.virTypedParameterPtr
cDisk := C.CString(disk)
defer C.free(unsafe.Pointer(cDisk))
cParamsLen := C.int(nParams)
if params != nil && nParams > 0 {
cParams = (C.virTypedParameterPtr)(C.calloc(C.size_t(nParams), C.size_t(unsafe.Sizeof(C.struct__virTypedParameter{}))))
defer C.virTypedParamsFree(cParams, cParamsLen)
} else {
cParams = nil
}
result := int(C.virDomainBlockStatsFlags(d.ptr, cDisk, (C.virTypedParameterPtr)(cParams), &cParamsLen, C.uint(flags)))
if result == -1 {
return result, GetLastError()
}
if cParamsLen > 0 && params != nil {
params.loadFromCPtr(cParams, nParams)
}
return int(cParamsLen), nil
}
type VirDomainInterfaceStats struct {
RxBytes int64
RxPackets int64
RxErrs int64
RxDrop int64
TxBytes int64
TxPackets int64
TxErrs int64
TxDrop int64
}
func (d *VirDomain) InterfaceStats(path string) (VirDomainInterfaceStats, error) {
cPath := C.CString(path)
defer C.free(unsafe.Pointer(cPath))
size := C.size_t(unsafe.Sizeof(C.struct__virDomainInterfaceStats{}))
cStats := (C.virDomainInterfaceStatsPtr)(C.malloc(size))
defer C.free(unsafe.Pointer(cStats))
result := C.virDomainInterfaceStats(d.ptr, cPath, (C.virDomainInterfaceStatsPtr)(cStats), size)
if result != 0 {
return VirDomainInterfaceStats{}, GetLastError()
}
return VirDomainInterfaceStats{
RxBytes: int64(cStats.rx_bytes),
RxPackets: int64(cStats.rx_packets),
RxErrs: int64(cStats.rx_errs),
RxDrop: int64(cStats.rx_drop),
TxBytes: int64(cStats.tx_bytes),
TxPackets: int64(cStats.tx_packets),
TxErrs: int64(cStats.tx_errs),
TxDrop: int64(cStats.tx_drop),
}, nil
}
func (d *VirDomain) MemoryStats(nrStats uint32, flags uint32) ([]VirDomainMemoryStat, error) {
ptr := make([]C.virDomainMemoryStatStruct, nrStats)
result := C.virDomainMemoryStats(
d.ptr, (C.virDomainMemoryStatPtr)(unsafe.Pointer(&ptr[0])),
C.uint(nrStats), C.uint(flags))
if result == -1 {
return []VirDomainMemoryStat{}, GetLastError()
}
out := make([]VirDomainMemoryStat, result)
for i := 0; i < int(result); i++ {
out = append(out, VirDomainMemoryStat{
Tag: int32(ptr[i].tag),
Val: uint64(ptr[i].val),
})
}
return out, nil
}
func (d *VirDomain) GetVcpus(maxInfo int32) ([]VirVcpuInfo, error) {
ptr := make([]C.virVcpuInfo, maxInfo)
result := C.virDomainGetVcpus(
d.ptr, (C.virVcpuInfoPtr)(unsafe.Pointer(&ptr[0])),
C.int(maxInfo), nil, C.int(0))
if result == -1 {
return []VirVcpuInfo{}, GetLastError()
}
out := make([]VirVcpuInfo, 0)
for i := 0; i < int(result); i++ {
out = append(out, VirVcpuInfo{
Number: uint32(ptr[i].number),
State: int32(ptr[i].state),
CpuTime: uint64(ptr[i].cpuTime),
Cpu: int32(ptr[i].cpu),
})
}
return out, nil
}
func (d *VirDomain) GetVcpusFlags(flags uint32) (int32, error) {
result := C.virDomainGetVcpusFlags(d.ptr, C.uint(flags))
if result == -1 {
return 0, GetLastError()
}
return int32(result), nil
}

View File

@ -0,0 +1,504 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
#ifndef VIR_FROM_BHYVE
#define VIR_FROM_BHYVE 57
#endif
#ifndef VIR_FROM_CRYPTO
#define VIR_FROM_CRYPTO 58
#endif
#ifndef VIR_FROM_FIREWALL
#define VIR_FROM_FIREWALL 59
#endif
*/
import "C"
import "fmt"
// virErrorLevel
const (
VIR_ERR_NONE = C.VIR_ERR_NONE
VIR_ERR_WARNING = C.VIR_ERR_WARNING
VIR_ERR_ERROR = C.VIR_ERR_ERROR
)
// virErrorNumber
const (
VIR_ERR_OK = C.VIR_ERR_OK
// internal error
VIR_ERR_INTERNAL_ERROR = C.VIR_ERR_INTERNAL_ERROR
// memory allocation failure
VIR_ERR_NO_MEMORY = C.VIR_ERR_NO_MEMORY
// no support for this function
VIR_ERR_NO_SUPPORT = C.VIR_ERR_NO_SUPPORT
// could not resolve hostname
VIR_ERR_UNKNOWN_HOST = C.VIR_ERR_UNKNOWN_HOST
// can't connect to hypervisor
VIR_ERR_NO_CONNECT = C.VIR_ERR_NO_CONNECT
// invalid connection object
VIR_ERR_INVALID_CONN = C.VIR_ERR_INVALID_CONN
// invalid domain object
VIR_ERR_INVALID_DOMAIN = C.VIR_ERR_INVALID_DOMAIN
// invalid function argument
VIR_ERR_INVALID_ARG = C.VIR_ERR_INVALID_ARG
// a command to hypervisor failed
VIR_ERR_OPERATION_FAILED = C.VIR_ERR_OPERATION_FAILED
// a HTTP GET command to failed
VIR_ERR_GET_FAILED = C.VIR_ERR_GET_FAILED
// a HTTP POST command to failed
VIR_ERR_POST_FAILED = C.VIR_ERR_POST_FAILED
// unexpected HTTP error code
VIR_ERR_HTTP_ERROR = C.VIR_ERR_HTTP_ERROR
// failure to serialize an S-Expr
VIR_ERR_SEXPR_SERIAL = C.VIR_ERR_SEXPR_SERIAL
// could not open Xen hypervisor control
VIR_ERR_NO_XEN = C.VIR_ERR_NO_XEN
// failure doing an hypervisor call
VIR_ERR_XEN_CALL = C.VIR_ERR_XEN_CALL
// unknown OS type
VIR_ERR_OS_TYPE = C.VIR_ERR_OS_TYPE
// missing kernel information
VIR_ERR_NO_KERNEL = C.VIR_ERR_NO_KERNEL
// missing root device information
VIR_ERR_NO_ROOT = C.VIR_ERR_NO_ROOT
// missing source device information
VIR_ERR_NO_SOURCE = C.VIR_ERR_NO_SOURCE
// missing target device information
VIR_ERR_NO_TARGET = C.VIR_ERR_NO_TARGET
// missing domain name information
VIR_ERR_NO_NAME = C.VIR_ERR_NO_NAME
// missing domain OS information
VIR_ERR_NO_OS = C.VIR_ERR_NO_OS
// missing domain devices information
VIR_ERR_NO_DEVICE = C.VIR_ERR_NO_DEVICE
// could not open Xen Store control
VIR_ERR_NO_XENSTORE = C.VIR_ERR_NO_XENSTORE
// too many drivers registered
VIR_ERR_DRIVER_FULL = C.VIR_ERR_DRIVER_FULL
// not supported by the drivers (DEPRECATED)
VIR_ERR_CALL_FAILED = C.VIR_ERR_CALL_FAILED
// an XML description is not well formed or broken
VIR_ERR_XML_ERROR = C.VIR_ERR_XML_ERROR
// the domain already exist
VIR_ERR_DOM_EXIST = C.VIR_ERR_DOM_EXIST
// operation forbidden on read-only connections
VIR_ERR_OPERATION_DENIED = C.VIR_ERR_OPERATION_DENIED
// failed to open a conf file
VIR_ERR_OPEN_FAILED = C.VIR_ERR_OPEN_FAILED
// failed to read a conf file
VIR_ERR_READ_FAILED = C.VIR_ERR_READ_FAILED
// failed to parse a conf file
VIR_ERR_PARSE_FAILED = C.VIR_ERR_PARSE_FAILED
// failed to parse the syntax of a conf file
VIR_ERR_CONF_SYNTAX = C.VIR_ERR_CONF_SYNTAX
// failed to write a conf file
VIR_ERR_WRITE_FAILED = C.VIR_ERR_WRITE_FAILED
// detail of an XML error
VIR_ERR_XML_DETAIL = C.VIR_ERR_XML_DETAIL
// invalid network object
VIR_ERR_INVALID_NETWORK = C.VIR_ERR_INVALID_NETWORK
// the network already exist
VIR_ERR_NETWORK_EXIST = C.VIR_ERR_NETWORK_EXIST
// general system call failure
VIR_ERR_SYSTEM_ERROR = C.VIR_ERR_SYSTEM_ERROR
// some sort of RPC error
VIR_ERR_RPC = C.VIR_ERR_RPC
// error from a GNUTLS call
VIR_ERR_GNUTLS_ERROR = C.VIR_ERR_GNUTLS_ERROR
// failed to start network
VIR_WAR_NO_NETWORK = C.VIR_WAR_NO_NETWORK
// domain not found or unexpectedly disappeared
VIR_ERR_NO_DOMAIN = C.VIR_ERR_NO_DOMAIN
// network not found
VIR_ERR_NO_NETWORK = C.VIR_ERR_NO_NETWORK
// invalid MAC address
VIR_ERR_INVALID_MAC = C.VIR_ERR_INVALID_MAC
// authentication failed
VIR_ERR_AUTH_FAILED = C.VIR_ERR_AUTH_FAILED
// invalid storage pool object
VIR_ERR_INVALID_STORAGE_POOL = C.VIR_ERR_INVALID_STORAGE_POOL
// invalid storage vol object
VIR_ERR_INVALID_STORAGE_VOL = C.VIR_ERR_INVALID_STORAGE_VOL
// failed to start storage
VIR_WAR_NO_STORAGE = C.VIR_WAR_NO_STORAGE
// storage pool not found
VIR_ERR_NO_STORAGE_POOL = C.VIR_ERR_NO_STORAGE_POOL
// storage volume not found
VIR_ERR_NO_STORAGE_VOL = C.VIR_ERR_NO_STORAGE_VOL
// failed to start node driver
VIR_WAR_NO_NODE = C.VIR_WAR_NO_NODE
// invalid node device object
VIR_ERR_INVALID_NODE_DEVICE = C.VIR_ERR_INVALID_NODE_DEVICE
// node device not found
VIR_ERR_NO_NODE_DEVICE = C.VIR_ERR_NO_NODE_DEVICE
// security model not found
VIR_ERR_NO_SECURITY_MODEL = C.VIR_ERR_NO_SECURITY_MODEL
// operation is not applicable at this time
VIR_ERR_OPERATION_INVALID = C.VIR_ERR_OPERATION_INVALID
// failed to start interface driver
VIR_WAR_NO_INTERFACE = C.VIR_WAR_NO_INTERFACE
// interface driver not running
VIR_ERR_NO_INTERFACE = C.VIR_ERR_NO_INTERFACE
// invalid interface object
VIR_ERR_INVALID_INTERFACE = C.VIR_ERR_INVALID_INTERFACE
// more than one matching interface found
VIR_ERR_MULTIPLE_INTERFACES = C.VIR_ERR_MULTIPLE_INTERFACES
// failed to start nwfilter driver
VIR_WAR_NO_NWFILTER = C.VIR_WAR_NO_NWFILTER
// invalid nwfilter object
VIR_ERR_INVALID_NWFILTER = C.VIR_ERR_INVALID_NWFILTER
// nw filter pool not found
VIR_ERR_NO_NWFILTER = C.VIR_ERR_NO_NWFILTER
// nw filter pool not found
VIR_ERR_BUILD_FIREWALL = C.VIR_ERR_BUILD_FIREWALL
// failed to start secret storage
VIR_WAR_NO_SECRET = C.VIR_WAR_NO_SECRET
// invalid secret
VIR_ERR_INVALID_SECRET = C.VIR_ERR_INVALID_SECRET
// secret not found
VIR_ERR_NO_SECRET = C.VIR_ERR_NO_SECRET
// unsupported configuration construct
VIR_ERR_CONFIG_UNSUPPORTED = C.VIR_ERR_CONFIG_UNSUPPORTED
// timeout occurred during operation
VIR_ERR_OPERATION_TIMEOUT = C.VIR_ERR_OPERATION_TIMEOUT
// a migration worked, but making the VM persist on the dest host failed
VIR_ERR_MIGRATE_PERSIST_FAILED = C.VIR_ERR_MIGRATE_PERSIST_FAILED
// a synchronous hook script failed
VIR_ERR_HOOK_SCRIPT_FAILED = C.VIR_ERR_HOOK_SCRIPT_FAILED
// invalid domain snapshot
VIR_ERR_INVALID_DOMAIN_SNAPSHOT = C.VIR_ERR_INVALID_DOMAIN_SNAPSHOT
// domain snapshot not found
VIR_ERR_NO_DOMAIN_SNAPSHOT = C.VIR_ERR_NO_DOMAIN_SNAPSHOT
// stream pointer not valid
VIR_ERR_INVALID_STREAM = C.VIR_ERR_INVALID_STREAM
// valid API use but unsupported by the given driver
VIR_ERR_ARGUMENT_UNSUPPORTED = C.VIR_ERR_ARGUMENT_UNSUPPORTED
// storage pool probe failed
VIR_ERR_STORAGE_PROBE_FAILED = C.VIR_ERR_STORAGE_PROBE_FAILED
// storage pool already built
VIR_ERR_STORAGE_POOL_BUILT = C.VIR_ERR_STORAGE_POOL_BUILT
// force was not requested for a risky domain snapshot revert
VIR_ERR_SNAPSHOT_REVERT_RISKY = C.VIR_ERR_SNAPSHOT_REVERT_RISKY
// operation on a domain was canceled/aborted by user
VIR_ERR_OPERATION_ABORTED = C.VIR_ERR_OPERATION_ABORTED
// authentication cancelled
VIR_ERR_AUTH_CANCELLED = C.VIR_ERR_AUTH_CANCELLED
// The metadata is not present
VIR_ERR_NO_DOMAIN_METADATA = C.VIR_ERR_NO_DOMAIN_METADATA
// Migration is not safe
VIR_ERR_MIGRATE_UNSAFE = C.VIR_ERR_MIGRATE_UNSAFE
// integer overflow
VIR_ERR_OVERFLOW = C.VIR_ERR_OVERFLOW
// action prevented by block copy job
VIR_ERR_BLOCK_COPY_ACTIVE = C.VIR_ERR_BLOCK_COPY_ACTIVE
// The requested operation is not supported
VIR_ERR_OPERATION_UNSUPPORTED = C.VIR_ERR_OPERATION_UNSUPPORTED
// error in ssh transport driver
VIR_ERR_SSH = C.VIR_ERR_SSH
// guest agent is unresponsive, not running or not usable
VIR_ERR_AGENT_UNRESPONSIVE = C.VIR_ERR_AGENT_UNRESPONSIVE
// resource is already in use
VIR_ERR_RESOURCE_BUSY = C.VIR_ERR_RESOURCE_BUSY
// operation on the object/resource was denied
VIR_ERR_ACCESS_DENIED = C.VIR_ERR_ACCESS_DENIED
// error from a dbus service
VIR_ERR_DBUS_SERVICE = C.VIR_ERR_DBUS_SERVICE
// the storage vol already exists
VIR_ERR_STORAGE_VOL_EXIST = C.VIR_ERR_STORAGE_VOL_EXIST
// given CPU is incompatible with host CPU
// added in libvirt 1.2.6
// VIR_ERR_CPU_INCOMPATIBLE = C.VIR_ERR_CPU_INCOMPATIBLE
)
// virErrorDomain
const (
VIR_FROM_NONE = C.VIR_FROM_NONE
// Error at Xen hypervisor layer
VIR_FROM_XEN = C.VIR_FROM_XEN
// Error at connection with xend daemon
VIR_FROM_XEND = C.VIR_FROM_XEND
// Error at connection with xen store
VIR_FROM_XENSTORE = C.VIR_FROM_XENSTORE
// Error in the S-Expression code
VIR_FROM_SEXPR = C.VIR_FROM_SEXPR
// Error in the XML code
VIR_FROM_XML = C.VIR_FROM_XML
// Error when operating on a domain
VIR_FROM_DOM = C.VIR_FROM_DOM
// Error in the XML-RPC code
VIR_FROM_RPC = C.VIR_FROM_RPC
// Error in the proxy code; unused since 0.8.6
VIR_FROM_PROXY = C.VIR_FROM_PROXY
// Error in the configuration file handling
VIR_FROM_CONF = C.VIR_FROM_CONF
// Error at the QEMU daemon
VIR_FROM_QEMU = C.VIR_FROM_QEMU
// Error when operating on a network
VIR_FROM_NET = C.VIR_FROM_NET
// Error from test driver
VIR_FROM_TEST = C.VIR_FROM_TEST
// Error from remote driver
VIR_FROM_REMOTE = C.VIR_FROM_REMOTE
// Error from OpenVZ driver
VIR_FROM_OPENVZ = C.VIR_FROM_OPENVZ
// Error at Xen XM layer
VIR_FROM_XENXM = C.VIR_FROM_XENXM
// Error in the Linux Stats code
VIR_FROM_STATS_LINUX = C.VIR_FROM_STATS_LINUX
// Error from Linux Container driver
VIR_FROM_LXC = C.VIR_FROM_LXC
// Error from storage driver
VIR_FROM_STORAGE = C.VIR_FROM_STORAGE
// Error from network config
VIR_FROM_NETWORK = C.VIR_FROM_NETWORK
// Error from domain config
VIR_FROM_DOMAIN = C.VIR_FROM_DOMAIN
// Error at the UML driver
VIR_FROM_UML = C.VIR_FROM_UML
// Error from node device monitor
VIR_FROM_NODEDEV = C.VIR_FROM_NODEDEV
// Error from xen inotify layer
VIR_FROM_XEN_INOTIFY = C.VIR_FROM_XEN_INOTIFY
// Error from security framework
VIR_FROM_SECURITY = C.VIR_FROM_SECURITY
// Error from VirtualBox driver
VIR_FROM_VBOX = C.VIR_FROM_VBOX
// Error when operating on an interface
VIR_FROM_INTERFACE = C.VIR_FROM_INTERFACE
// The OpenNebula driver no longer exists. Retained for ABI/API compat only
VIR_FROM_ONE = C.VIR_FROM_ONE
// Error from ESX driver
VIR_FROM_ESX = C.VIR_FROM_ESX
// Error from IBM power hypervisor
VIR_FROM_PHYP = C.VIR_FROM_PHYP
// Error from secret storage
VIR_FROM_SECRET = C.VIR_FROM_SECRET
// Error from CPU driver
VIR_FROM_CPU = C.VIR_FROM_CPU
// Error from XenAPI
VIR_FROM_XENAPI = C.VIR_FROM_XENAPI
// Error from network filter driver
VIR_FROM_NWFILTER = C.VIR_FROM_NWFILTER
// Error from Synchronous hooks
VIR_FROM_HOOK = C.VIR_FROM_HOOK
// Error from domain snapshot
VIR_FROM_DOMAIN_SNAPSHOT = C.VIR_FROM_DOMAIN_SNAPSHOT
// Error from auditing subsystem
VIR_FROM_AUDIT = C.VIR_FROM_AUDIT
// Error from sysinfo/SMBIOS
VIR_FROM_SYSINFO = C.VIR_FROM_SYSINFO
// Error from I/O streams
VIR_FROM_STREAMS = C.VIR_FROM_STREAMS
// Error from VMware driver
VIR_FROM_VMWARE = C.VIR_FROM_VMWARE
// Error from event loop impl
VIR_FROM_EVENT = C.VIR_FROM_EVENT
// Error from libxenlight driver
VIR_FROM_LIBXL = C.VIR_FROM_LIBXL
// Error from lock manager
VIR_FROM_LOCKING = C.VIR_FROM_LOCKING
// Error from Hyper-V driver
VIR_FROM_HYPERV = C.VIR_FROM_HYPERV
// Error from capabilities
VIR_FROM_CAPABILITIES = C.VIR_FROM_CAPABILITIES
// Error from URI handling
VIR_FROM_URI = C.VIR_FROM_URI
// Error from auth handling
VIR_FROM_AUTH = C.VIR_FROM_AUTH
// Error from DBus
VIR_FROM_DBUS = C.VIR_FROM_DBUS
// Error from Parallels
VIR_FROM_PARALLELS = C.VIR_FROM_PARALLELS
// Error from Device
VIR_FROM_DEVICE = C.VIR_FROM_DEVICE
// Error from libssh2 connection transport
VIR_FROM_SSH = C.VIR_FROM_SSH
// Error from lockspace
VIR_FROM_LOCKSPACE = C.VIR_FROM_LOCKSPACE
// Error from initctl device communication
VIR_FROM_INITCTL = C.VIR_FROM_INITCTL
// Error from identity code
VIR_FROM_IDENTITY = C.VIR_FROM_IDENTITY
// Error from cgroups
VIR_FROM_CGROUP = C.VIR_FROM_CGROUP
// Error from access control manager
VIR_FROM_ACCESS = C.VIR_FROM_ACCESS
// Error from systemd code
VIR_FROM_SYSTEMD = C.VIR_FROM_SYSTEMD
// Error from bhyve driver
VIR_FROM_BHYVE = C.VIR_FROM_BHYVE
// Error from crypto code
VIR_FROM_CRYPTO = C.VIR_FROM_CRYPTO
// Error from firewall
VIR_FROM_FIREWALL = C.VIR_FROM_FIREWALL
)
type VirError struct {
Code int
Domain int
Message string
Level int
}
func (err VirError) Error() string {
return fmt.Sprintf("[Code-%d] [Domain-%d] %s",
err.Code, err.Domain, err.Message)
}

View File

@ -0,0 +1,321 @@
package libvirt
import (
"unsafe"
)
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
*/
import "C"
type DomainLifecycleEvent struct {
Event int
Detail int
}
type DomainRTCChangeEvent struct {
Utcoffset int64
}
type DomainWatchdogEvent struct {
Action int
}
type DomainIOErrorEvent struct {
SrcPath string
DevAlias string
Action int
}
type DomainEventGraphicsAddress struct {
Family int
Node string
Service string
}
type DomainEventGraphicsSubjectIdentity struct {
Type string
Name string
}
type DomainGraphicsEvent struct {
Phase int
Local DomainEventGraphicsAddress
Remote DomainEventGraphicsAddress
AuthScheme string
Subject []DomainEventGraphicsSubjectIdentity
}
type DomainIOErrorReasonEvent struct {
DomainIOErrorEvent
Reason string
}
type DomainBlockJobEvent struct {
Disk string
Type int
Status int
}
type DomainDiskChangeEvent struct {
OldSrcPath string
NewSrcPath string
DevAlias string
Reason int
}
type DomainTrayChangeEvent struct {
DevAlias string
Reason int
}
type DomainReasonEvent struct {
Reason int
}
type DomainBalloonChangeEvent struct {
Actual uint64
}
type DomainDeviceRemovedEvent struct {
DevAlias string
}
//export domainEventLifecycleCallback
func domainEventLifecycleCallback(c C.virConnectPtr, d C.virDomainPtr,
event int, detail int,
opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainLifecycleEvent{
Event: event,
Detail: detail,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventGenericCallback
func domainEventGenericCallback(c C.virConnectPtr, d C.virDomainPtr,
opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
return (*context.cb)(&connection, &domain, nil, context.f)
}
//export domainEventRTCChangeCallback
func domainEventRTCChangeCallback(c C.virConnectPtr, d C.virDomainPtr,
utcoffset int64, opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainRTCChangeEvent{
Utcoffset: utcoffset,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventWatchdogCallback
func domainEventWatchdogCallback(c C.virConnectPtr, d C.virDomainPtr,
action int, opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainWatchdogEvent{
Action: action,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventIOErrorCallback
func domainEventIOErrorCallback(c C.virConnectPtr, d C.virDomainPtr,
srcPath string, devAlias string, action int, opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainIOErrorEvent{
SrcPath: srcPath,
DevAlias: devAlias,
Action: action,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventGraphicsCallback
func domainEventGraphicsCallback(c C.virConnectPtr, d C.virDomainPtr,
phase int,
local C.virDomainEventGraphicsAddressPtr,
remote C.virDomainEventGraphicsAddressPtr,
authScheme string,
subject C.virDomainEventGraphicsSubjectPtr,
opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
subjectGo := make([]DomainEventGraphicsSubjectIdentity, subject.nidentity)
nidentities := int(subject.nidentity)
identities := (*[1 << 30]C.virDomainEventGraphicsSubjectIdentity)(unsafe.Pointer(&subject.identities))[:nidentities:nidentities]
for _, identity := range identities {
subjectGo = append(subjectGo,
DomainEventGraphicsSubjectIdentity{
Type: C.GoString(identity._type),
Name: C.GoString(identity.name),
},
)
}
eventDetails := DomainGraphicsEvent{
Phase: phase,
Local: DomainEventGraphicsAddress{
Family: int(local.family),
Node: C.GoString(local.node),
Service: C.GoString(local.service),
},
Remote: DomainEventGraphicsAddress{
Family: int(remote.family),
Node: C.GoString(remote.node),
Service: C.GoString(remote.service),
},
AuthScheme: authScheme,
Subject: subjectGo,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventIOErrorReasonCallback
func domainEventIOErrorReasonCallback(c C.virConnectPtr, d C.virDomainPtr,
srcPath string, devAlias string, action int, reason string,
opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainIOErrorReasonEvent{
DomainIOErrorEvent: DomainIOErrorEvent{
SrcPath: srcPath,
DevAlias: devAlias,
Action: action,
},
Reason: reason,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventBlockJobCallback
func domainEventBlockJobCallback(c C.virConnectPtr, d C.virDomainPtr,
disk string, _type int, status int, opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainBlockJobEvent{
Disk: disk,
Type: _type,
Status: status,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventDiskChangeCallback
func domainEventDiskChangeCallback(c C.virConnectPtr, d C.virDomainPtr,
oldSrcPath string, newSrcPath string, devAlias string,
reason int, opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainDiskChangeEvent{
OldSrcPath: oldSrcPath,
NewSrcPath: newSrcPath,
DevAlias: devAlias,
Reason: reason,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventTrayChangeCallback
func domainEventTrayChangeCallback(c C.virConnectPtr, d C.virDomainPtr,
devAlias string, reason int, opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainTrayChangeEvent{
DevAlias: devAlias,
Reason: reason,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventReasonCallback
func domainEventReasonCallback(c C.virConnectPtr, d C.virDomainPtr,
reason int, opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainReasonEvent{
Reason: reason,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventBalloonChangeCallback
func domainEventBalloonChangeCallback(c C.virConnectPtr, d C.virDomainPtr,
actual uint64, opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainBalloonChangeEvent{
Actual: actual,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}
//export domainEventDeviceRemovedCallback
func domainEventDeviceRemovedCallback(c C.virConnectPtr, d C.virDomainPtr,
devAlias string, opaque unsafe.Pointer) int {
context := *(*domainCallbackContext)(opaque)
domain := VirDomain{ptr: d}
connection := VirConnection{ptr: c}
eventDetails := DomainDeviceRemovedEvent{
DevAlias: devAlias,
}
return (*context.cb)(&connection, &domain, eventDetails, context.f)
}

View File

@ -0,0 +1,87 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"unsafe"
)
type VirInterface struct {
ptr C.virInterfacePtr
}
func (n *VirInterface) Create(flags uint32) error {
result := C.virInterfaceCreate(n.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (n *VirInterface) Destroy(flags uint32) error {
result := C.virInterfaceDestroy(n.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (n *VirInterface) IsActive() (bool, error) {
result := C.virInterfaceIsActive(n.ptr)
if result == -1 {
return false, GetLastError()
}
if result == 1 {
return true, nil
}
return false, nil
}
func (n *VirInterface) GetMACString() (string, error) {
result := C.virInterfaceGetMACString(n.ptr)
if result == nil {
return "", GetLastError()
}
mac := C.GoString(result)
return mac, nil
}
func (n *VirInterface) GetName() (string, error) {
result := C.virInterfaceGetName(n.ptr)
if result == nil {
return "", GetLastError()
}
name := C.GoString(result)
return name, nil
}
func (n *VirInterface) GetXMLDesc(flags uint32) (string, error) {
result := C.virInterfaceGetXMLDesc(n.ptr, C.uint(flags))
if result == nil {
return "", GetLastError()
}
xml := C.GoString(result)
C.free(unsafe.Pointer(result))
return xml, nil
}
func (n *VirInterface) Undefine() error {
result := C.virInterfaceUndefine(n.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (n *VirInterface) Free() error {
if result := C.virInterfaceFree(n.ptr); result != 0 {
return GetLastError()
}
return nil
}

View File

@ -0,0 +1,878 @@
package libvirt
import (
"io/ioutil"
"reflect"
"unsafe"
)
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
void virErrorFuncDummy(void *userData, virErrorPtr error);
int domainEventLifecycleCallback_cgo(virConnectPtr c, virDomainPtr d,
int event, int detail, void* data);
int domainEventGenericCallback_cgo(virConnectPtr c, virDomainPtr d, void* data);
int domainEventRTCChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
long long utcoffset, void* data);
int domainEventWatchdogCallback_cgo(virConnectPtr c, virDomainPtr d,
int action, void* data);
int domainEventIOErrorCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *srcPath, const char *devAlias,
int action, void* data);
int domainEventGraphicsCallback_cgo(virConnectPtr c, virDomainPtr d,
int phase, const virDomainEventGraphicsAddress *local,
const virDomainEventGraphicsAddress *remote,
const char *authScheme,
const virDomainEventGraphicsSubject *subject, void* data);
int domainEventIOErrorReasonCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *srcPath, const char *devAlias,
int action, const char *reason, void* data);
int domainEventBlockJobCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *disk, int type, int status, void* data);
int domainEventDiskChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *oldSrcPath, const char *newSrcPath,
const char *devAlias, int reason, void* data);
int domainEventTrayChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *devAlias, int reason, void* data);
int domainEventReasonCallback_cgo(virConnectPtr c, virDomainPtr d,
int reason, void* data);
int domainEventBalloonChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
unsigned long long actual, void* data);
int domainEventDeviceRemovedCallback_cgo(virConnectPtr c, virDomainPtr d,
const char *devAlias, void* data);
*/
import "C"
func init() {
// libvirt won't print to stderr
C.virSetErrorFunc(nil, C.virErrorFunc(unsafe.Pointer(C.virErrorFuncDummy)))
}
type VirConnection struct {
ptr C.virConnectPtr
}
func NewVirConnection(uri string) (VirConnection, error) {
var cUri *C.char
if uri != "" {
cUri = C.CString(uri)
defer C.free(unsafe.Pointer(cUri))
}
ptr := C.virConnectOpen(cUri)
if ptr == nil {
return VirConnection{}, GetLastError()
}
obj := VirConnection{ptr: ptr}
return obj, nil
}
func NewVirConnectionReadOnly(uri string) (VirConnection, error) {
var cUri *C.char
if uri != "" {
cUri = C.CString(uri)
defer C.free(unsafe.Pointer(cUri))
}
ptr := C.virConnectOpenReadOnly(cUri)
if ptr == nil {
return VirConnection{}, GetLastError()
}
obj := VirConnection{ptr: ptr}
return obj, nil
}
func GetLastError() VirError {
var virErr VirError
err := C.virGetLastError()
virErr.Code = int(err.code)
virErr.Domain = int(err.domain)
virErr.Message = C.GoString(err.message)
virErr.Level = int(err.level)
C.virResetError(err)
return virErr
}
func (c *VirConnection) CloseConnection() (int, error) {
result := int(C.virConnectClose(c.ptr))
if result == -1 {
return result, GetLastError()
}
return result, nil
}
func (c *VirConnection) UnrefAndCloseConnection() error {
closeRes := 1
var err error
for closeRes > 0 {
closeRes, err = c.CloseConnection()
if err != nil {
return err
}
}
return nil
}
func (c *VirConnection) GetCapabilities() (string, error) {
str := C.virConnectGetCapabilities(c.ptr)
if str == nil {
return "", GetLastError()
}
capabilities := C.GoString(str)
C.free(unsafe.Pointer(str))
return capabilities, nil
}
func (c *VirConnection) GetNodeInfo() (VirNodeInfo, error) {
ni := VirNodeInfo{}
var ptr C.virNodeInfo
result := C.virNodeGetInfo(c.ptr, (*C.virNodeInfo)(unsafe.Pointer(&ptr)))
if result == -1 {
return ni, GetLastError()
}
ni.ptr = ptr
return ni, nil
}
func (c *VirConnection) GetHostname() (string, error) {
str := C.virConnectGetHostname(c.ptr)
if str == nil {
return "", GetLastError()
}
hostname := C.GoString(str)
C.free(unsafe.Pointer(str))
return hostname, nil
}
func (c *VirConnection) GetLibVersion() (uint32, error) {
var version C.ulong
if err := C.virConnectGetLibVersion(c.ptr, &version); err < 0 {
return 0, GetLastError()
}
return uint32(version), nil
}
func (c *VirConnection) GetType() (string, error) {
str := C.virConnectGetType(c.ptr)
if str == nil {
return "", GetLastError()
}
hypDriver := C.GoString(str)
return hypDriver, nil
}
func (c *VirConnection) IsAlive() (bool, error) {
result := C.virConnectIsAlive(c.ptr)
if result == -1 {
return false, GetLastError()
}
if result == 1 {
return true, nil
}
return false, nil
}
func (c *VirConnection) IsEncrypted() (bool, error) {
result := C.virConnectIsEncrypted(c.ptr)
if result == -1 {
return false, GetLastError()
}
if result == 1 {
return true, nil
}
return false, nil
}
func (c *VirConnection) IsSecure() (bool, error) {
result := C.virConnectIsSecure(c.ptr)
if result == -1 {
return false, GetLastError()
}
if result == 1 {
return true, nil
}
return false, nil
}
func (c *VirConnection) ListDefinedDomains() ([]string, error) {
var names [1024](*C.char)
namesPtr := unsafe.Pointer(&names)
numDomains := C.virConnectListDefinedDomains(
c.ptr,
(**C.char)(namesPtr),
1024)
if numDomains == -1 {
return nil, GetLastError()
}
goNames := make([]string, numDomains)
for k := 0; k < int(numDomains); k++ {
goNames[k] = C.GoString(names[k])
C.free(unsafe.Pointer(names[k]))
}
return goNames, nil
}
func (c *VirConnection) ListDomains() ([]uint32, error) {
var cDomainsIds [512](uint32)
cDomainsPointer := unsafe.Pointer(&cDomainsIds)
numDomains := C.virConnectListDomains(c.ptr, (*C.int)(cDomainsPointer), 512)
if numDomains == -1 {
return nil, GetLastError()
}
return cDomainsIds[:numDomains], nil
}
func (c *VirConnection) ListInterfaces() ([]string, error) {
const maxIfaces = 1024
var names [maxIfaces](*C.char)
namesPtr := unsafe.Pointer(&names)
numIfaces := C.virConnectListInterfaces(
c.ptr,
(**C.char)(namesPtr),
maxIfaces)
if numIfaces == -1 {
return nil, GetLastError()
}
goNames := make([]string, numIfaces)
for k := 0; k < int(numIfaces); k++ {
goNames[k] = C.GoString(names[k])
C.free(unsafe.Pointer(names[k]))
}
return goNames, nil
}
func (c *VirConnection) ListNetworks() ([]string, error) {
const maxNets = 1024
var names [maxNets](*C.char)
namesPtr := unsafe.Pointer(&names)
numNetworks := C.virConnectListNetworks(
c.ptr,
(**C.char)(namesPtr),
maxNets)
if numNetworks == -1 {
return nil, GetLastError()
}
goNames := make([]string, numNetworks)
for k := 0; k < int(numNetworks); k++ {
goNames[k] = C.GoString(names[k])
C.free(unsafe.Pointer(names[k]))
}
return goNames, nil
}
func (c *VirConnection) ListStoragePools() ([]string, error) {
const maxPools = 1024
var names [maxPools](*C.char)
namesPtr := unsafe.Pointer(&names)
numStoragePools := C.virConnectListStoragePools(
c.ptr,
(**C.char)(namesPtr),
maxPools)
if numStoragePools == -1 {
return nil, GetLastError()
}
goNames := make([]string, numStoragePools)
for k := 0; k < int(numStoragePools); k++ {
goNames[k] = C.GoString(names[k])
C.free(unsafe.Pointer(names[k]))
}
return goNames, nil
}
func (c *VirConnection) LookupDomainById(id uint32) (VirDomain, error) {
ptr := C.virDomainLookupByID(c.ptr, C.int(id))
if ptr == nil {
return VirDomain{}, GetLastError()
}
return VirDomain{ptr: ptr}, nil
}
func (c *VirConnection) LookupDomainByName(id string) (VirDomain, error) {
cName := C.CString(id)
defer C.free(unsafe.Pointer(cName))
ptr := C.virDomainLookupByName(c.ptr, cName)
if ptr == nil {
return VirDomain{}, GetLastError()
}
return VirDomain{ptr: ptr}, nil
}
func (c *VirConnection) DomainCreateXMLFromFile(xmlFile string, flags uint32) (VirDomain, error) {
xmlConfig, err := ioutil.ReadFile(xmlFile)
if err != nil {
return VirDomain{}, err
}
return c.DomainCreateXML(string(xmlConfig), flags)
}
func (c *VirConnection) DomainCreateXML(xmlConfig string, flags uint32) (VirDomain, error) {
cXml := C.CString(string(xmlConfig))
defer C.free(unsafe.Pointer(cXml))
ptr := C.virDomainCreateXML(c.ptr, cXml, C.uint(flags))
if ptr == nil {
return VirDomain{}, GetLastError()
}
return VirDomain{ptr: ptr}, nil
}
func (c *VirConnection) DomainDefineXMLFromFile(xmlFile string) (VirDomain, error) {
xmlConfig, err := ioutil.ReadFile(xmlFile)
if err != nil {
return VirDomain{}, err
}
return c.DomainDefineXML(string(xmlConfig))
}
func (c *VirConnection) DomainDefineXML(xmlConfig string) (VirDomain, error) {
cXml := C.CString(string(xmlConfig))
defer C.free(unsafe.Pointer(cXml))
ptr := C.virDomainDefineXML(c.ptr, cXml)
if ptr == nil {
return VirDomain{}, GetLastError()
}
return VirDomain{ptr: ptr}, nil
}
func (c *VirConnection) ListDefinedInterfaces() ([]string, error) {
const maxIfaces = 1024
var names [maxIfaces](*C.char)
namesPtr := unsafe.Pointer(&names)
numIfaces := C.virConnectListDefinedInterfaces(
c.ptr,
(**C.char)(namesPtr),
maxIfaces)
if numIfaces == -1 {
return nil, GetLastError()
}
goNames := make([]string, numIfaces)
for k := 0; k < int(numIfaces); k++ {
goNames[k] = C.GoString(names[k])
C.free(unsafe.Pointer(names[k]))
}
return goNames, nil
}
func (c *VirConnection) ListDefinedNetworks() ([]string, error) {
const maxNets = 1024
var names [maxNets](*C.char)
namesPtr := unsafe.Pointer(&names)
numNetworks := C.virConnectListDefinedNetworks(
c.ptr,
(**C.char)(namesPtr),
maxNets)
if numNetworks == -1 {
return nil, GetLastError()
}
goNames := make([]string, numNetworks)
for k := 0; k < int(numNetworks); k++ {
goNames[k] = C.GoString(names[k])
C.free(unsafe.Pointer(names[k]))
}
return goNames, nil
}
func (c *VirConnection) ListDefinedStoragePools() ([]string, error) {
const maxPools = 1024
var names [maxPools](*C.char)
namesPtr := unsafe.Pointer(&names)
numStoragePools := C.virConnectListDefinedStoragePools(
c.ptr,
(**C.char)(namesPtr),
maxPools)
if numStoragePools == -1 {
return nil, GetLastError()
}
goNames := make([]string, numStoragePools)
for k := 0; k < int(numStoragePools); k++ {
goNames[k] = C.GoString(names[k])
C.free(unsafe.Pointer(names[k]))
}
return goNames, nil
}
func (c *VirConnection) NumOfDefinedInterfaces() (int, error) {
result := int(C.virConnectNumOfDefinedInterfaces(c.ptr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (c *VirConnection) NumOfDefinedNetworks() (int, error) {
result := int(C.virConnectNumOfDefinedNetworks(c.ptr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (c *VirConnection) NumOfDefinedStoragePools() (int, error) {
result := int(C.virConnectNumOfDefinedStoragePools(c.ptr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (c *VirConnection) NumOfDomains() (int, error) {
result := int(C.virConnectNumOfDomains(c.ptr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (c *VirConnection) NumOfInterfaces() (int, error) {
result := int(C.virConnectNumOfInterfaces(c.ptr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (c *VirConnection) NumOfNetworks() (int, error) {
result := int(C.virConnectNumOfNetworks(c.ptr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (c *VirConnection) NumOfNWFilters() (int, error) {
result := int(C.virConnectNumOfNWFilters(c.ptr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (c *VirConnection) NumOfSecrets() (int, error) {
result := int(C.virConnectNumOfSecrets(c.ptr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (c *VirConnection) NetworkDefineXMLFromFile(xmlFile string) (VirNetwork, error) {
xmlConfig, err := ioutil.ReadFile(xmlFile)
if err != nil {
return VirNetwork{}, err
}
return c.NetworkDefineXML(string(xmlConfig))
}
func (c *VirConnection) NetworkDefineXML(xmlConfig string) (VirNetwork, error) {
cXml := C.CString(string(xmlConfig))
defer C.free(unsafe.Pointer(cXml))
ptr := C.virNetworkDefineXML(c.ptr, cXml)
if ptr == nil {
return VirNetwork{}, GetLastError()
}
return VirNetwork{ptr: ptr}, nil
}
func (c *VirConnection) LookupNetworkByName(name string) (VirNetwork, error) {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
ptr := C.virNetworkLookupByName(c.ptr, cName)
if ptr == nil {
return VirNetwork{}, GetLastError()
}
return VirNetwork{ptr: ptr}, nil
}
func (c *VirConnection) GetSysinfo(flags uint) (string, error) {
cStr := C.virConnectGetSysinfo(c.ptr, C.uint(flags))
if cStr == nil {
return "", GetLastError()
}
info := C.GoString(cStr)
C.free(unsafe.Pointer(cStr))
return info, nil
}
func (c *VirConnection) GetURI() (string, error) {
cStr := C.virConnectGetURI(c.ptr)
if cStr == nil {
return "", GetLastError()
}
uri := C.GoString(cStr)
C.free(unsafe.Pointer(cStr))
return uri, nil
}
func (c *VirConnection) GetMaxVcpus(typeAttr string) (int, error) {
var cTypeAttr *C.char
if typeAttr != "" {
cTypeAttr = C.CString(typeAttr)
defer C.free(unsafe.Pointer(cTypeAttr))
}
result := int(C.virConnectGetMaxVcpus(c.ptr, cTypeAttr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (c *VirConnection) InterfaceDefineXMLFromFile(xmlFile string) (VirInterface, error) {
xmlConfig, err := ioutil.ReadFile(xmlFile)
if err != nil {
return VirInterface{}, err
}
return c.InterfaceDefineXML(string(xmlConfig), 0)
}
func (c *VirConnection) InterfaceDefineXML(xmlConfig string, flags uint32) (VirInterface, error) {
cXml := C.CString(string(xmlConfig))
defer C.free(unsafe.Pointer(cXml))
ptr := C.virInterfaceDefineXML(c.ptr, cXml, C.uint(flags))
if ptr == nil {
return VirInterface{}, GetLastError()
}
return VirInterface{ptr: ptr}, nil
}
func (c *VirConnection) LookupInterfaceByName(name string) (VirInterface, error) {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
ptr := C.virInterfaceLookupByName(c.ptr, cName)
if ptr == nil {
return VirInterface{}, GetLastError()
}
return VirInterface{ptr: ptr}, nil
}
func (c *VirConnection) LookupInterfaceByMACString(mac string) (VirInterface, error) {
cName := C.CString(mac)
defer C.free(unsafe.Pointer(cName))
ptr := C.virInterfaceLookupByMACString(c.ptr, cName)
if ptr == nil {
return VirInterface{}, GetLastError()
}
return VirInterface{ptr: ptr}, nil
}
func (c *VirConnection) StoragePoolDefineXMLFromFile(xmlFile string) (VirStoragePool, error) {
xmlConfig, err := ioutil.ReadFile(xmlFile)
if err != nil {
return VirStoragePool{}, err
}
return c.StoragePoolDefineXML(string(xmlConfig), 0)
}
func (c *VirConnection) StoragePoolDefineXML(xmlConfig string, flags uint32) (VirStoragePool, error) {
cXml := C.CString(string(xmlConfig))
defer C.free(unsafe.Pointer(cXml))
ptr := C.virStoragePoolDefineXML(c.ptr, cXml, C.uint(flags))
if ptr == nil {
return VirStoragePool{}, GetLastError()
}
return VirStoragePool{ptr: ptr}, nil
}
func (c *VirConnection) LookupStoragePoolByName(name string) (VirStoragePool, error) {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
ptr := C.virStoragePoolLookupByName(c.ptr, cName)
if ptr == nil {
return VirStoragePool{}, GetLastError()
}
return VirStoragePool{ptr: ptr}, nil
}
func (c *VirConnection) LookupStoragePoolByUUIDString(uuid string) (VirStoragePool, error) {
cUuid := C.CString(uuid)
defer C.free(unsafe.Pointer(cUuid))
ptr := C.virStoragePoolLookupByUUIDString(c.ptr, cUuid)
if ptr == nil {
return VirStoragePool{}, GetLastError()
}
return VirStoragePool{ptr: ptr}, nil
}
func (c *VirConnection) NWFilterDefineXMLFromFile(xmlFile string) (VirNWFilter, error) {
xmlConfig, err := ioutil.ReadFile(xmlFile)
if err != nil {
return VirNWFilter{}, err
}
return c.NWFilterDefineXML(string(xmlConfig))
}
func (c *VirConnection) NWFilterDefineXML(xmlConfig string) (VirNWFilter, error) {
cXml := C.CString(string(xmlConfig))
defer C.free(unsafe.Pointer(cXml))
ptr := C.virNWFilterDefineXML(c.ptr, cXml)
if ptr == nil {
return VirNWFilter{}, GetLastError()
}
return VirNWFilter{ptr: ptr}, nil
}
func (c *VirConnection) LookupNWFilterByName(name string) (VirNWFilter, error) {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
ptr := C.virNWFilterLookupByName(c.ptr, cName)
if ptr == nil {
return VirNWFilter{}, GetLastError()
}
return VirNWFilter{ptr: ptr}, nil
}
func (c *VirConnection) LookupNWFilterByUUIDString(uuid string) (VirNWFilter, error) {
cUuid := C.CString(uuid)
defer C.free(unsafe.Pointer(cUuid))
ptr := C.virNWFilterLookupByUUIDString(c.ptr, cUuid)
if ptr == nil {
return VirNWFilter{}, GetLastError()
}
return VirNWFilter{ptr: ptr}, nil
}
func (c *VirConnection) LookupStorageVolByKey(key string) (VirStorageVol, error) {
cKey := C.CString(key)
defer C.free(unsafe.Pointer(cKey))
ptr := C.virStorageVolLookupByKey(c.ptr, cKey)
if ptr == nil {
return VirStorageVol{}, GetLastError()
}
return VirStorageVol{ptr: ptr}, nil
}
func (c *VirConnection) LookupStorageVolByPath(path string) (VirStorageVol, error) {
cPath := C.CString(path)
defer C.free(unsafe.Pointer(cPath))
ptr := C.virStorageVolLookupByPath(c.ptr, cPath)
if ptr == nil {
return VirStorageVol{}, GetLastError()
}
return VirStorageVol{ptr: ptr}, nil
}
func (c *VirConnection) SecretDefineXMLFromFile(xmlFile string) (VirSecret, error) {
xmlConfig, err := ioutil.ReadFile(xmlFile)
if err != nil {
return VirSecret{}, err
}
return c.SecretDefineXML(string(xmlConfig), 0)
}
func (c *VirConnection) SecretDefineXML(xmlConfig string, flags uint32) (VirSecret, error) {
cXml := C.CString(string(xmlConfig))
defer C.free(unsafe.Pointer(cXml))
ptr := C.virSecretDefineXML(c.ptr, cXml, C.uint(flags))
if ptr == nil {
return VirSecret{}, GetLastError()
}
return VirSecret{ptr: ptr}, nil
}
func (c *VirConnection) LookupSecretByUUIDString(uuid string) (VirSecret, error) {
cUuid := C.CString(uuid)
defer C.free(unsafe.Pointer(cUuid))
ptr := C.virSecretLookupByUUIDString(c.ptr, cUuid)
if ptr == nil {
return VirSecret{}, GetLastError()
}
return VirSecret{ptr: ptr}, nil
}
func (c *VirConnection) LookupSecretByUsage(usageType int, usageID string) (VirSecret, error) {
cUsageID := C.CString(usageID)
defer C.free(unsafe.Pointer(cUsageID))
ptr := C.virSecretLookupByUsage(c.ptr, C.int(usageType), cUsageID)
if ptr == nil {
return VirSecret{}, GetLastError()
}
return VirSecret{ptr: ptr}, nil
}
func (c *VirConnection) ListAllInterfaces(flags uint32) ([]VirInterface, error) {
var cList *C.virInterfacePtr
numIfaces := C.virConnectListAllInterfaces(c.ptr, (**C.virInterfacePtr)(&cList), C.uint(flags))
if numIfaces == -1 {
return nil, GetLastError()
}
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cList)),
Len: int(numIfaces),
Cap: int(numIfaces),
}
var ifaces []VirInterface
slice := *(*[]C.virInterfacePtr)(unsafe.Pointer(&hdr))
for _, ptr := range slice {
ifaces = append(ifaces, VirInterface{ptr})
}
C.free(unsafe.Pointer(cList))
return ifaces, nil
}
func (c *VirConnection) ListAllNetworks(flags uint32) ([]VirNetwork, error) {
var cList *C.virNetworkPtr
numNets := C.virConnectListAllNetworks(c.ptr, (**C.virNetworkPtr)(&cList), C.uint(flags))
if numNets == -1 {
return nil, GetLastError()
}
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cList)),
Len: int(numNets),
Cap: int(numNets),
}
var nets []VirNetwork
slice := *(*[]C.virNetworkPtr)(unsafe.Pointer(&hdr))
for _, ptr := range slice {
nets = append(nets, VirNetwork{ptr})
}
C.free(unsafe.Pointer(cList))
return nets, nil
}
func (c *VirConnection) ListAllDomains(flags uint32) ([]VirDomain, error) {
var cList *C.virDomainPtr
numDomains := C.virConnectListAllDomains(c.ptr, (**C.virDomainPtr)(&cList), C.uint(flags))
if numDomains == -1 {
return nil, GetLastError()
}
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cList)),
Len: int(numDomains),
Cap: int(numDomains),
}
var domains []VirDomain
slice := *(*[]C.virDomainPtr)(unsafe.Pointer(&hdr))
for _, ptr := range slice {
domains = append(domains, VirDomain{ptr})
}
C.free(unsafe.Pointer(cList))
return domains, nil
}
func (c *VirConnection) ListAllNWFilters(flags uint32) ([]VirNWFilter, error) {
var cList *C.virNWFilterPtr
numNWFilters := C.virConnectListAllNWFilters(c.ptr, (**C.virNWFilterPtr)(&cList), C.uint(flags))
if numNWFilters == -1 {
return nil, GetLastError()
}
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cList)),
Len: int(numNWFilters),
Cap: int(numNWFilters),
}
var filters []VirNWFilter
slice := *(*[]C.virNWFilterPtr)(unsafe.Pointer(&hdr))
for _, ptr := range slice {
filters = append(filters, VirNWFilter{ptr})
}
C.free(unsafe.Pointer(cList))
return filters, nil
}
func (c *VirConnection) ListAllStoragePools(flags uint32) ([]VirStoragePool, error) {
var cList *C.virStoragePoolPtr
numPools := C.virConnectListAllStoragePools(c.ptr, (**C.virStoragePoolPtr)(&cList), C.uint(flags))
if numPools == -1 {
return nil, GetLastError()
}
hdr := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cList)),
Len: int(numPools),
Cap: int(numPools),
}
var pools []VirStoragePool
slice := *(*[]C.virStoragePoolPtr)(unsafe.Pointer(&hdr))
for _, ptr := range slice {
pools = append(pools, VirStoragePool{ptr})
}
C.free(unsafe.Pointer(cList))
return pools, nil
}
type DomainEventCallback func(c *VirConnection, d *VirDomain,
event interface{}, f func()) int
type domainCallbackContext struct {
cb *DomainEventCallback
f func()
}
func (c *VirConnection) DomainEventRegister(dom VirDomain,
eventId int,
callback *DomainEventCallback,
opaque func()) int {
var callbackPtr unsafe.Pointer
context := domainCallbackContext{
cb: callback,
f: opaque,
}
switch eventId {
case VIR_DOMAIN_EVENT_ID_LIFECYCLE:
callbackPtr = unsafe.Pointer(C.domainEventLifecycleCallback_cgo)
case VIR_DOMAIN_EVENT_ID_REBOOT:
case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR:
callbackPtr = unsafe.Pointer(C.domainEventGenericCallback_cgo)
case VIR_DOMAIN_EVENT_ID_RTC_CHANGE:
callbackPtr = unsafe.Pointer(C.domainEventRTCChangeCallback_cgo)
case VIR_DOMAIN_EVENT_ID_WATCHDOG:
callbackPtr = unsafe.Pointer(C.domainEventWatchdogCallback_cgo)
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
callbackPtr = unsafe.Pointer(C.domainEventIOErrorCallback_cgo)
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
callbackPtr = unsafe.Pointer(C.domainEventGraphicsCallback_cgo)
case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
callbackPtr = unsafe.Pointer(C.domainEventIOErrorReasonCallback_cgo)
case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
// TODO Post 1.2.4, uncomment later
// case VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2:
callbackPtr = unsafe.Pointer(C.domainEventBlockJobCallback_cgo)
case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
callbackPtr = unsafe.Pointer(C.domainEventDiskChangeCallback_cgo)
case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE:
callbackPtr = unsafe.Pointer(C.domainEventTrayChangeCallback_cgo)
case VIR_DOMAIN_EVENT_ID_PMWAKEUP:
case VIR_DOMAIN_EVENT_ID_PMSUSPEND:
case VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK:
callbackPtr = unsafe.Pointer(C.domainEventReasonCallback_cgo)
case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE:
callbackPtr = unsafe.Pointer(C.domainEventBalloonChangeCallback_cgo)
case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED:
callbackPtr = unsafe.Pointer(C.domainEventDeviceRemovedCallback_cgo)
default:
}
ret := C.virConnectDomainEventRegisterAny(c.ptr, dom.ptr, C.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
C.virConnectDomainEventGenericCallback(callbackPtr),
unsafe.Pointer(&context),
nil)
return int(ret)
}
func (c *VirConnection) DomainEventDeregister(callbackId int) int {
// Deregister the callback
return int(C.virConnectDomainEventDeregisterAny(c.ptr, C.int(callbackId)))
}
func EventRegisterDefaultImpl() int {
return int(C.virEventRegisterDefaultImpl())
}
func EventRunDefaultImpl() int {
return int(C.virEventRunDefaultImpl())
}

View File

@ -0,0 +1,147 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"unsafe"
)
type VirNetwork struct {
ptr C.virNetworkPtr
}
func (n *VirNetwork) Free() error {
if result := C.virNetworkFree(n.ptr); result != 0 {
return GetLastError()
}
return nil
}
func (n *VirNetwork) Create() error {
result := C.virNetworkCreate(n.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (n *VirNetwork) Destroy() error {
result := C.virNetworkDestroy(n.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (n *VirNetwork) IsActive() (bool, error) {
result := C.virNetworkIsActive(n.ptr)
if result == -1 {
return false, GetLastError()
}
if result == 1 {
return true, nil
}
return false, nil
}
func (n *VirNetwork) IsPersistent() (bool, error) {
result := C.virNetworkIsPersistent(n.ptr)
if result == -1 {
return false, GetLastError()
}
if result == 1 {
return true, nil
}
return false, nil
}
func (n *VirNetwork) GetAutostart() (bool, error) {
var out C.int
result := C.virNetworkGetAutostart(n.ptr, (*C.int)(unsafe.Pointer(&out)))
if result == -1 {
return false, GetLastError()
}
switch out {
case 1:
return true, nil
default:
return false, nil
}
}
func (n *VirNetwork) SetAutostart(autostart bool) error {
var cAutostart C.int
switch autostart {
case true:
cAutostart = 1
default:
cAutostart = 0
}
result := C.virNetworkSetAutostart(n.ptr, cAutostart)
if result == -1 {
return GetLastError()
}
return nil
}
func (n *VirNetwork) GetName() (string, error) {
name := C.virNetworkGetName(n.ptr)
if name == nil {
return "", GetLastError()
}
return C.GoString(name), nil
}
func (n *VirNetwork) GetUUID() ([]byte, error) {
var cUuid [C.VIR_UUID_BUFLEN](byte)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virNetworkGetUUID(n.ptr, (*C.uchar)(cuidPtr))
if result != 0 {
return []byte{}, GetLastError()
}
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
}
func (n *VirNetwork) GetUUIDString() (string, error) {
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virNetworkGetUUIDString(n.ptr, (*C.char)(cuidPtr))
if result != 0 {
return "", GetLastError()
}
return C.GoString((*C.char)(cuidPtr)), nil
}
func (n *VirNetwork) GetBridgeName() (string, error) {
result := C.virNetworkGetBridgeName(n.ptr)
if result == nil {
return "", GetLastError()
}
bridge := C.GoString(result)
C.free(unsafe.Pointer(result))
return bridge, nil
}
func (n *VirNetwork) GetXMLDesc(flags uint32) (string, error) {
result := C.virNetworkGetXMLDesc(n.ptr, C.uint(flags))
if result == nil {
return "", GetLastError()
}
xml := C.GoString(result)
C.free(unsafe.Pointer(result))
return xml, nil
}
func (n *VirNetwork) Undefine() error {
result := C.virNetworkUndefine(n.ptr)
if result == -1 {
return GetLastError()
}
return nil
}

View File

@ -0,0 +1,50 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"unsafe"
)
type VirNodeInfo struct {
ptr C.virNodeInfo
}
func (ni *VirNodeInfo) GetModel() string {
model := C.GoString((*C.char)(unsafe.Pointer(&ni.ptr.model)))
return model
}
func (ni *VirNodeInfo) GetMemoryKB() uint64 {
return uint64(ni.ptr.memory)
}
func (ni *VirNodeInfo) GetCPUs() uint32 {
return uint32(ni.ptr.cpus)
}
func (ni *VirNodeInfo) GetMhz() uint32 {
return uint32(ni.ptr.mhz)
}
func (ni *VirNodeInfo) GetNodes() uint32 {
return uint32(ni.ptr.nodes)
}
func (ni *VirNodeInfo) GetSockets() uint32 {
return uint32(ni.ptr.sockets)
}
func (ni *VirNodeInfo) GetCores() uint32 {
return uint32(ni.ptr.cores)
}
func (ni *VirNodeInfo) GetThreads() uint32 {
return uint32(ni.ptr.threads)
}

View File

@ -0,0 +1,70 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"unsafe"
)
type VirNWFilter struct {
ptr C.virNWFilterPtr
}
func (f *VirNWFilter) Free() error {
if result := C.virNWFilterFree(f.ptr); result != 0 {
return GetLastError()
}
return nil
}
func (f *VirNWFilter) GetName() (string, error) {
name := C.virNWFilterGetName(f.ptr)
if name == nil {
return "", GetLastError()
}
return C.GoString(name), nil
}
func (f *VirNWFilter) Undefine() error {
result := C.virNWFilterUndefine(f.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (f *VirNWFilter) GetUUID() ([]byte, error) {
var cUuid [C.VIR_UUID_BUFLEN](byte)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virNWFilterGetUUID(f.ptr, (*C.uchar)(cuidPtr))
if result != 0 {
return []byte{}, GetLastError()
}
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
}
func (f *VirNWFilter) GetUUIDString() (string, error) {
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virNWFilterGetUUIDString(f.ptr, (*C.char)(cuidPtr))
if result != 0 {
return "", GetLastError()
}
return C.GoString((*C.char)(cuidPtr)), nil
}
func (f *VirNWFilter) GetXMLDesc(flags uint32) (string, error) {
result := C.virNWFilterGetXMLDesc(f.ptr, C.uint(flags))
if result == nil {
return "", GetLastError()
}
xml := C.GoString(result)
C.free(unsafe.Pointer(result))
return xml, nil
}

View File

@ -0,0 +1,78 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"unsafe"
)
type VirSecret struct {
ptr C.virSecretPtr
}
func (s *VirSecret) Free() error {
if result := C.virSecretFree(s.ptr); result != 0 {
return GetLastError()
}
return nil
}
func (s *VirSecret) Undefine() error {
result := C.virSecretUndefine(s.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (s *VirSecret) GetUUID() ([]byte, error) {
var cUuid [C.VIR_UUID_BUFLEN](byte)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virSecretGetUUID(s.ptr, (*C.uchar)(cuidPtr))
if result != 0 {
return []byte{}, GetLastError()
}
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
}
func (s *VirSecret) GetUUIDString() (string, error) {
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virSecretGetUUIDString(s.ptr, (*C.char)(cuidPtr))
if result != 0 {
return "", GetLastError()
}
return C.GoString((*C.char)(cuidPtr)), nil
}
func (s *VirSecret) GetUsageID() (string, error) {
result := C.virSecretGetUsageID(s.ptr)
if result == nil {
return "", GetLastError()
}
return C.GoString(result), nil
}
func (s *VirSecret) GetUsageType() (int, error) {
result := int(C.virSecretGetUsageType(s.ptr))
if result == -1 {
return 0, GetLastError()
}
return result, nil
}
func (s *VirSecret) GetXMLDesc(flags uint32) (string, error) {
result := C.virSecretGetXMLDesc(s.ptr, C.uint(flags))
if result == nil {
return "", GetLastError()
}
xml := C.GoString(result)
C.free(unsafe.Pointer(result))
return xml, nil
}

View File

@ -0,0 +1,95 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"unsafe"
)
type VirDomainSnapshot struct {
ptr C.virDomainSnapshotPtr
}
func (s *VirDomainSnapshot) Free() error {
if result := C.virDomainSnapshotFree(s.ptr); result != 0 {
return GetLastError()
}
return nil
}
func (s *VirDomainSnapshot) Delete(flags uint32) error {
result := C.virDomainSnapshotDelete(s.ptr, C.uint(flags))
if result != 0 {
return GetLastError()
}
return nil
}
func (s *VirDomainSnapshot) RevertToSnapshot(flags uint32) error {
result := C.virDomainRevertToSnapshot(s.ptr, C.uint(flags))
if result != 0 {
return GetLastError()
}
return nil
}
func (d *VirDomain) CreateSnapshotXML(xml string, flags uint32) (VirDomainSnapshot, error) {
cXml := C.CString(xml)
defer C.free(unsafe.Pointer(cXml))
result := C.virDomainSnapshotCreateXML(d.ptr, cXml, C.uint(flags))
if result == nil {
return VirDomainSnapshot{}, GetLastError()
}
return VirDomainSnapshot{ptr: result}, nil
}
func (d *VirDomain) Save(destFile string) error {
cPath := C.CString(destFile)
defer C.free(unsafe.Pointer(cPath))
result := C.virDomainSave(d.ptr, cPath)
if result == -1 {
return GetLastError()
}
return nil
}
func (d *VirDomain) SaveFlags(destFile string, destXml string, flags uint32) error {
cDestFile := C.CString(destFile)
cDestXml := C.CString(destXml)
defer C.free(unsafe.Pointer(cDestXml))
defer C.free(unsafe.Pointer(cDestFile))
result := C.virDomainSaveFlags(d.ptr, cDestFile, cDestXml, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (conn VirConnection) Restore(srcFile string) error {
cPath := C.CString(srcFile)
defer C.free(unsafe.Pointer(cPath))
if result := C.virDomainRestore(conn.ptr, cPath); result == -1 {
return GetLastError()
}
return nil
}
func (conn VirConnection) RestoreFlags(srcFile, xmlConf string, flags uint32) error {
cPath := C.CString(srcFile)
defer C.free(unsafe.Pointer(cPath))
var cXmlConf *C.char
if xmlConf != "" {
cXmlConf = C.CString(xmlConf)
defer C.free(unsafe.Pointer(cXmlConf))
}
if result := C.virDomainRestoreFlags(conn.ptr, cPath, cXmlConf, C.uint(flags)); result == -1 {
return GetLastError()
}
return nil
}

View File

@ -0,0 +1,210 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"io/ioutil"
"unsafe"
)
type VirStoragePool struct {
ptr C.virStoragePoolPtr
}
type VirStoragePoolInfo struct {
ptr C.virStoragePoolInfo
}
func (p *VirStoragePool) Build(flags uint32) error {
result := C.virStoragePoolBuild(p.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (p *VirStoragePool) Create(flags uint32) error {
result := C.virStoragePoolCreate(p.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (p *VirStoragePool) Delete(flags uint32) error {
result := C.virStoragePoolDelete(p.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (p *VirStoragePool) Destroy() error {
result := C.virStoragePoolDestroy(p.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (p *VirStoragePool) Free() error {
if result := C.virStoragePoolFree(p.ptr); result != 0 {
return GetLastError()
}
return nil
}
func (p *VirStoragePool) GetAutostart() (bool, error) {
var out C.int
result := C.virStoragePoolGetAutostart(p.ptr, (*C.int)(unsafe.Pointer(&out)))
if result == -1 {
return false, GetLastError()
}
switch out {
case 1:
return true, nil
default:
return false, nil
}
}
func (p *VirStoragePool) GetInfo() (VirStoragePoolInfo, error) {
pi := VirStoragePoolInfo{}
var ptr C.virStoragePoolInfo
result := C.virStoragePoolGetInfo(p.ptr, (*C.virStoragePoolInfo)(unsafe.Pointer(&ptr)))
if result == -1 {
return pi, GetLastError()
}
pi.ptr = ptr
return pi, nil
}
func (p *VirStoragePool) GetName() (string, error) {
name := C.virStoragePoolGetName(p.ptr)
if name == nil {
return "", GetLastError()
}
return C.GoString(name), nil
}
func (p *VirStoragePool) GetUUID() ([]byte, error) {
var cUuid [C.VIR_UUID_BUFLEN](byte)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virStoragePoolGetUUID(p.ptr, (*C.uchar)(cuidPtr))
if result != 0 {
return []byte{}, GetLastError()
}
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
}
func (p *VirStoragePool) GetUUIDString() (string, error) {
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
cuidPtr := unsafe.Pointer(&cUuid)
result := C.virStoragePoolGetUUIDString(p.ptr, (*C.char)(cuidPtr))
if result != 0 {
return "", GetLastError()
}
return C.GoString((*C.char)(cuidPtr)), nil
}
func (p *VirStoragePool) GetXMLDesc(flags uint32) (string, error) {
result := C.virStoragePoolGetXMLDesc(p.ptr, C.uint(flags))
if result == nil {
return "", GetLastError()
}
xml := C.GoString(result)
C.free(unsafe.Pointer(result))
return xml, nil
}
func (p *VirStoragePool) IsActive() (bool, error) {
result := C.virStoragePoolIsActive(p.ptr)
if result == -1 {
return false, GetLastError()
}
if result == 1 {
return true, nil
}
return false, nil
}
func (p *VirStoragePool) SetAutostart(autostart bool) error {
var cAutostart C.int
switch autostart {
case true:
cAutostart = 1
default:
cAutostart = 0
}
result := C.virStoragePoolSetAutostart(p.ptr, cAutostart)
if result == -1 {
return GetLastError()
}
return nil
}
func (p *VirStoragePool) Refresh(flags uint32) error {
result := C.virStoragePoolRefresh(p.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (p *VirStoragePool) Undefine() error {
result := C.virStoragePoolUndefine(p.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (i *VirStoragePoolInfo) GetState() uint8 {
return uint8(i.ptr.state)
}
func (i *VirStoragePoolInfo) GetCapacityInBytes() uint64 {
return uint64(i.ptr.capacity)
}
func (i *VirStoragePoolInfo) GetAllocationInBytes() uint64 {
return uint64(i.ptr.allocation)
}
func (i *VirStoragePoolInfo) GetAvailableInBytes() uint64 {
return uint64(i.ptr.available)
}
func (p *VirStoragePool) StorageVolCreateXMLFromFile(xmlFile string, flags uint32) (VirStorageVol, error) {
xmlConfig, err := ioutil.ReadFile(xmlFile)
if err != nil {
return VirStorageVol{}, err
}
return p.StorageVolCreateXML(string(xmlConfig), flags)
}
func (p *VirStoragePool) StorageVolCreateXML(xmlConfig string, flags uint32) (VirStorageVol, error) {
cXml := C.CString(string(xmlConfig))
defer C.free(unsafe.Pointer(cXml))
ptr := C.virStorageVolCreateXML(p.ptr, cXml, C.uint(flags))
if ptr == nil {
return VirStorageVol{}, GetLastError()
}
return VirStorageVol{ptr: ptr}, nil
}
func (p *VirStoragePool) LookupStorageVolByName(name string) (VirStorageVol, error) {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
ptr := C.virStorageVolLookupByName(p.ptr, cName)
if ptr == nil {
return VirStorageVol{}, GetLastError()
}
return VirStorageVol{ptr: ptr}, nil
}

View File

@ -0,0 +1,134 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"unsafe"
)
type VirStorageVol struct {
ptr C.virStorageVolPtr
}
type VirStorageVolInfo struct {
ptr C.virStorageVolInfo
}
func (v *VirStorageVol) Delete(flags uint32) error {
result := C.virStorageVolDelete(v.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (v *VirStorageVol) Free() error {
if result := C.virStorageVolFree(v.ptr); result != 0 {
return GetLastError()
}
return nil
}
func (v *VirStorageVol) GetInfo() (VirStorageVolInfo, error) {
vi := VirStorageVolInfo{}
var ptr C.virStorageVolInfo
result := C.virStorageVolGetInfo(v.ptr, (*C.virStorageVolInfo)(unsafe.Pointer(&ptr)))
if result == -1 {
return vi, GetLastError()
}
vi.ptr = ptr
return vi, nil
}
func (i *VirStorageVolInfo) GetType() int {
return int(i.ptr._type)
}
func (i *VirStorageVolInfo) GetCapacityInBytes() uint64 {
return uint64(i.ptr.capacity)
}
func (i *VirStorageVolInfo) GetAllocationInBytes() uint64 {
return uint64(i.ptr.allocation)
}
func (v *VirStorageVol) GetKey() (string, error) {
key := C.virStorageVolGetKey(v.ptr)
if key == nil {
return "", GetLastError()
}
return C.GoString(key), nil
}
func (v *VirStorageVol) GetName() (string, error) {
name := C.virStorageVolGetName(v.ptr)
if name == nil {
return "", GetLastError()
}
return C.GoString(name), nil
}
func (v *VirStorageVol) GetPath() (string, error) {
result := C.virStorageVolGetPath(v.ptr)
if result == nil {
return "", GetLastError()
}
path := C.GoString(result)
C.free(unsafe.Pointer(result))
return path, nil
}
func (v *VirStorageVol) GetXMLDesc(flags uint32) (string, error) {
result := C.virStorageVolGetXMLDesc(v.ptr, C.uint(flags))
if result == nil {
return "", GetLastError()
}
xml := C.GoString(result)
C.free(unsafe.Pointer(result))
return xml, nil
}
func (v *VirStorageVol) Resize(capacity uint64, flags uint32) error {
result := C.virStorageVolResize(v.ptr, C.ulonglong(capacity), C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (v *VirStorageVol) Wipe(flags uint32) error {
result := C.virStorageVolWipe(v.ptr, C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (v *VirStorageVol) WipePattern(algorithm uint32, flags uint32) error {
result := C.virStorageVolWipePattern(v.ptr, C.uint(algorithm), C.uint(flags))
if result == -1 {
return GetLastError()
}
return nil
}
func (v *VirStorageVol) Upload(stream *VirStream, offset, length uint64, flags uint32) error {
if C.virStorageVolUpload(v.ptr, stream.ptr, C.ulonglong(offset),
C.ulonglong(length), C.uint(flags)) == -1 {
return GetLastError()
}
return nil
}
func (v *VirStorageVol) Download(stream *VirStream, offset, length uint64, flags uint32) error {
if C.virStorageVolDownload(v.ptr, stream.ptr, C.ulonglong(offset),
C.ulonglong(length), C.uint(flags)) == -1 {
return GetLastError()
}
return nil
}

View File

@ -0,0 +1,79 @@
package libvirt
/*
#cgo LDFLAGS: -lvirt -ldl
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
*/
import "C"
import (
"io"
"unsafe"
)
type VirStream struct {
ptr C.virStreamPtr
}
func NewVirStream(c *VirConnection, flags uint) (*VirStream, error) {
virStream := C.virStreamNew(c.ptr, C.uint(flags))
if virStream == nil {
return nil, GetLastError()
}
return &VirStream{
ptr: virStream,
}, nil
}
func (v *VirStream) Abort() error {
result := C.virStreamAbort(v.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (v *VirStream) Close() error {
result := C.virStreamFinish(v.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (v *VirStream) Free() error {
result := C.virStreamFree(v.ptr)
if result == -1 {
return GetLastError()
}
return nil
}
func (v *VirStream) Read(p []byte) (int, error) {
n := C.virStreamRecv(v.ptr, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(len(p)))
if n < 0 {
return 0, GetLastError()
}
if n == 0 {
return 0, io.EOF
}
return int(n), nil
}
func (v *VirStream) Write(p []byte) (int, error) {
n := C.virStreamSend(v.ptr, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(len(p)))
if n < 0 {
return 0, GetLastError()
}
if n == 0 {
return 0, io.EOF
}
return int(n), nil
}

View File

@ -0,0 +1,83 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
#######################################################################################################
#
# If you get problems about guest additions versions, please get this plugin to fix it up:
#
# vagrant plugin install vagrant-vbguest
#
#######################################################################################################
require '../vagrant-provision-reboot-plugin'
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "chef/fedora-19"
config.vm.provision "shell", privileged: true, inline: <<-EOF
set -e
echo "Installing LXC + libvirt dependencies"
yum -y install cyrus-sasl-devel device-mapper-devel gnutls-devel \
libxml2-devel cyrus-sasl-md5 gnutls-utils nc numactl numactl-libs libwsman1 \
libwsman-devel avahi-devel e2fsprogs-devel libcap-ng-devel libnl-devel \
libpciaccess-devel libselinux-devel libssh2-devel libudev-devel netcf-devel \
numactl-devel parted-devel python-devel readline-devel xen-devel xhtml1-dtds \
xmlrpc-c-devel yajl-devel pm-utils dmidecode libcgroup numad iptables-ipv6 \
radvd lzop glusterfs-client iscsi-initiator-utils sheepdog fuse-libs \
glusterfs-api librados2 librbd1 qemu-img lxc
echo "Download libvirt 1.2.2 RPMs"
mkdir -p /tmp/rpms && cd /tmp/rpms
wget -N http://libvirt.org/sources/libvirt-client-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-config-network-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-config-nwfilter-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-interface-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-libxl-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-lxc-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-network-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-nodedev-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-nwfilter-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-qemu-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-secret-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-storage-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-uml-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-vbox-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-driver-xen-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-daemon-lxc-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-devel-1.2.2-1.fc19.x86_64.rpm \
http://libvirt.org/sources/libvirt-docs-1.2.2-1.fc19.x86_64.rpm
echo "Installing libvirt RPMs"
cd /tmp/rpms
# sigh, bad rpm
rpm -ivh *.rpm || true
GOVERSION="1.3.3"
GOTARBALL="go${GOVERSION}.linux-amd64.tar.gz"
export GOROOT=/usr/local/go
export GOPATH=/opt/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
echo "Installing Go $GOVERSION"
if [ ! $(which go) ]; then
echo " Downloading $GOTARBALL"
wget --quiet --directory-prefix=/tmp https://storage.googleapis.com/golang/$GOTARBALL
echo " Extracting $GOTARBALL to $GOROOT"
tar -C /usr/local -xzf /tmp/$GOTARBALL
echo " Configuring GOPATH"
mkdir -p $GOPATH/src $GOPATH/bin $GOPATH/pkg
chown -R vagrant $GOPATH
echo " Configuring env vars"
echo "export PATH=\$PATH:$GOROOT/bin:$GOPATH/bin" | tee /etc/profile.d/golang.sh > /dev/null
echo "export GOROOT=$GOROOT" | tee --append /etc/profile.d/golang.sh > /dev/null
echo "export GOPATH=$GOPATH" | tee --append /etc/profile.d/golang.sh > /dev/null
fi
systemctl enable lxc
systemctl enable libvirtd
EOF
config.vm.provision :unix_reboot
config.vm.synced_folder "../..", "/libvirt-go"
end

View File

@ -0,0 +1,176 @@
# A quick hack to allow rebooting of a Vagrant VM during provisioning.
#
# This is tested with Vagrant 1.4.3. It may work with slightly earlier versions,
# but definitely won't work with much earlier versions. The code is fragile with
# respect to internal changes in Vagrant.
#
# Adapted from: https://gist.github.com/ukabu/6780121
#
# This file should be placed into the same folder as your Vagrantfile. Then in
# your Vagrantfile, you'll want to do something like the following:
#
# ----------------------------------------------------------------------------
#
# require './vagrant-provision-reboot-plugin'
#
# Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
#
# # Run your pre-reboot provisioning block.
# #config.vm.provision :chef_solo do |chef|
# # ...
# #end
#
# # Run a reboot of a *NIX guest.
# config.vm.provision :unix_reboot
# # Run a reboot of a Windows guest, assuming that you are set up with the
# # relevant plugins and configurations to manage a Windows guest in Vagrant.
# #config.vm.provision :windows_reboot
#
# # Run your post-reboot provisioning block.
# #config.vm.provision :chef_solo do |chef|
# # ...
# #end
#
# ----------------------------------------------------------------------------
#
# The provisioner takes care of remounting the synced folders.
#
# This will work for the VirtualBox provider. For other providers, a
# 'remount_synched_folders' action must be added to the provider implementation.
require 'vagrant'
# Monkey-patch the VirtualBox provider to be able to remap synced folders after
# reboot.
#
# This involves pulling out some code fragments from the existing SyncedFolders
# class - which is unpleasant, but there are no usefully exposed methods such
# that we can run only what we need to.
module VagrantPlugins
module ProviderVirtualBox
module Action
class RemountSyncedFolders < SyncedFolders
def initialize(app, env)
super(app, env)
end
def call(env)
@env = env
@app.call(env)
# Copied out of /lib/vagrant/action/builtin/synced_folders.rb in
# Vagrant 1.4.3. This is going to be fragile with respect to future
# changes, but that's just the way the cookie crumbles.
#
# We can't just run the whole SyncedFolders.call() method because
# it undertakes a lot more setup and will error out if invoked twice
# during "vagrant up" or "vagrant provision".
folders = synced_folders(env[:machine])
folders.each do |impl_name, fs|
plugins[impl_name.to_sym][0].new.enable(env[:machine], fs, impl_opts(impl_name, env))
end
end
end
def self.action_remount_synced_folders
Vagrant::Action::Builder.new.tap do |b|
b.use RemountSyncedFolders
end
end
end
end
end
# Define the plugin.
class RebootPlugin < Vagrant.plugin('2')
name 'Reboot Plugin'
# This plugin provides a provisioner called unix_reboot.
provisioner 'unix_reboot' do
# Create a provisioner.
class RebootProvisioner < Vagrant.plugin('2', :provisioner)
# Initialization, define internal state. Nothing needed.
def initialize(machine, config)
super(machine, config)
end
# Configuration changes to be done. Nothing needed here either.
def configure(root_config)
super(root_config)
end
# Run the provisioning.
def provision
command = 'shutdown -r now'
@machine.ui.info("Issuing command: #{command}")
@machine.communicate.sudo(command) do |type, data|
if type == :stderr
@machine.ui.error(data);
end
end
begin
sleep 5
end until @machine.communicate.ready?
# Now the machine is up again, perform the necessary tasks.
@machine.ui.info("Launching remount_synced_folders action...")
@machine.action('remount_synced_folders')
end
# Nothing needs to be done on cleanup.
def cleanup
super
end
end
RebootProvisioner
end
# This plugin provides a provisioner called windows_reboot.
provisioner 'windows_reboot' do
# Create a provisioner.
class RebootProvisioner < Vagrant.plugin('2', :provisioner)
# Initialization, define internal state. Nothing needed.
def initialize(machine, config)
super(machine, config)
end
# Configuration changes to be done. Nothing needed here either.
def configure(root_config)
super(root_config)
end
# Run the provisioning.
def provision
command = 'shutdown -t 0 -r -f'
@machine.ui.info("Issuing command: #{command}")
@machine.communicate.execute(command) do
if type == :stderr
@machine.ui.error(data);
end
end
begin
sleep 5
end until @machine.communicate.ready?
# Now the machine is up again, perform the necessary tasks.
@machine.ui.info("Launching remount_synced_folders action...")
@machine.action('remount_synced_folders')
end
# Nothing needs to be done on cleanup.
def cleanup
super
end
end
RebootProvisioner
end
end

View File

@ -166,6 +166,7 @@ Telegraf currently has support for collecting metrics from:
* jolokia (remote JMX with JSON over HTTP)
* kafka_consumer
* leofs
* libvirt
* lustre2
* memcached
* mongodb

View File

@ -10,6 +10,8 @@ machine:
- go version
dependencies:
pre:
- sudo apt-get update; sudo apt-get install -y libvirt-dev
override:
- docker info

View File

@ -12,6 +12,7 @@ import (
_ "github.com/influxdb/telegraf/plugins/jolokia"
_ "github.com/influxdb/telegraf/plugins/kafka_consumer"
_ "github.com/influxdb/telegraf/plugins/leofs"
_ "github.com/influxdb/telegraf/plugins/libvirt"
_ "github.com/influxdb/telegraf/plugins/lustre2"
_ "github.com/influxdb/telegraf/plugins/memcached"
_ "github.com/influxdb/telegraf/plugins/mongodb"

32
plugins/libvirt/README.md Normal file
View File

@ -0,0 +1,32 @@
# Telegraf Plugin: libvirt
#### Description
The libvirt plugin collects libvirt statistics.
To test this plugin set the following configuration:
```toml
[libvirt]
uri = "test:///default"
```
This mocks a libvirt deamon with one running domain. The URI for a connection to a local qemu would be
`qemu:///system`.
## Resources
* http://wiki.libvirt.org/page/UbuntuKVMWalkthrough
* http://godoc.org/github.com/alexzorin/libvirt-go
## Measurements:
Meta:
- units: int64
- tags: `domain=vader`
Measurements names:
- libvirt_cpu_time
- libvirt_max_mem
- libvirt_memory
- libvirt_nr_virt_cpu

View File

@ -0,0 +1,69 @@
package libvirt
import (
lv "github.com/alexzorin/libvirt-go"
"github.com/influxdb/telegraf/plugins"
)
const sampleConfig = `
# specify a libvirt connection uri
uri = "qemu:///system"
`
type Libvirt struct {
Uri string
}
func (l *Libvirt) SampleConfig() string {
return sampleConfig
}
func (l *Libvirt) Description() string {
return "Read domain infos from a libvirt deamon"
}
func (l *Libvirt) Gather(acc plugins.Accumulator) error {
connection, err := lv.NewVirConnectionReadOnly(l.Uri)
if err != nil {
return err
}
defer connection.CloseConnection()
domains, err := connection.ListDomains()
if err != nil {
return err
}
for _, domainId := range domains {
domain, err := connection.LookupDomainById(domainId)
if err != nil {
return err
}
domainName, _ := domain.GetName()
tags := map[string]string{"domain": domainName}
l.gatherDomain(acc, domain, tags)
}
return nil
}
func (m *Libvirt) gatherDomain(acc plugins.Accumulator, domain lv.VirDomain, tags map[string]string) error {
domainInfo, err := domain.GetInfo()
if err != nil {
return err
}
acc.Add("cpu_time", domainInfo.GetCpuTime(), tags)
acc.Add("max_mem", domainInfo.GetMaxMem(), tags)
acc.Add("memory", domainInfo.GetMemory(), tags)
acc.Add("nr_virt_cpu", domainInfo.GetNrVirtCpu(), tags)
return nil
}
func init() {
plugins.Add("libvirt", func() plugins.Plugin {
return &Libvirt{}
})
}

View File

@ -0,0 +1,23 @@
package libvirt
import (
"testing"
"github.com/influxdb/telegraf/testutil"
"github.com/stretchr/testify/assert"
)
func TestLibvirt(t *testing.T) {
var acc testutil.Accumulator
l := &Libvirt{Uri: "test:///default"}
l.Gather(&acc)
assert.True(t, acc.HasUIntValue("cpu_time"))
assert.True(t, acc.HasUIntValue("memory"))
assert.True(t, acc.HasUIntValue("max_mem"))
expectedTags := map[string]string{"domain": "test"}
expectedNumberOfCpus := uint16(2)
assert.NoError(t, acc.ValidateTaggedValue("nr_virt_cpu", expectedNumberOfCpus, expectedTags))
}