diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e0c43ff4..29eabba01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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! diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 04f4706ad..1790cc960 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -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" diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/.drone.yml b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/.drone.yml new file mode 100644 index 000000000..da5ca0d48 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/.drone.yml @@ -0,0 +1,7 @@ +image: alexzorin/libvirt-go_test:1.2 +script: + - go test -v +notify: + email: + recipients: + - git@zor.io diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/.gitignore b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/.gitignore new file mode 100644 index 000000000..ce6b260e4 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/.gitignore @@ -0,0 +1,3 @@ +*.sublime-workspace +*.sublime-project +.vagrant \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/LICENSE b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/LICENSE new file mode 100644 index 000000000..202f5fcef --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/LICENSE @@ -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. \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/README.md b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/README.md new file mode 100644 index 000000000..f7638f5d9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/README.md @@ -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`. diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/cfuncs.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/cfuncs.go new file mode 100644 index 000000000..81ae51538 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/cfuncs.go @@ -0,0 +1,96 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include + +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" diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/constants.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/constants.go new file mode 100644 index 000000000..a9f2ceb20 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/constants.go @@ -0,0 +1,385 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +) diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/domain.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/domain.go new file mode 100644 index 000000000..99531b2f0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/domain.go @@ -0,0 +1,639 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/error.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/error.go new file mode 100644 index 000000000..810cd258e --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/error.go @@ -0,0 +1,504 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include + +#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) +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/events.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/events.go new file mode 100644 index 000000000..04f94f1f3 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/events.go @@ -0,0 +1,321 @@ +package libvirt + +import ( + "unsafe" +) + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +*/ +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) +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/interface.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/interface.go new file mode 100644 index 000000000..eeb9605f8 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/interface.go @@ -0,0 +1,87 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/libvirt.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/libvirt.go new file mode 100644 index 000000000..a60701065 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/libvirt.go @@ -0,0 +1,878 @@ +package libvirt + +import ( + "io/ioutil" + "reflect" + "unsafe" +) + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include + +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()) +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/network.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/network.go new file mode 100644 index 000000000..87b6b0afb --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/network.go @@ -0,0 +1,147 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/nodeinfo.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/nodeinfo.go new file mode 100644 index 000000000..fdcc3079a --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/nodeinfo.go @@ -0,0 +1,50 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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) +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/nwfilter.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/nwfilter.go new file mode 100644 index 000000000..b2d4f41fd --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/nwfilter.go @@ -0,0 +1,70 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/secret.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/secret.go new file mode 100644 index 000000000..b5f820d86 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/secret.go @@ -0,0 +1,78 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/snapshot.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/snapshot.go new file mode 100644 index 000000000..55955c4c4 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/snapshot.go @@ -0,0 +1,95 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/storage_pool.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/storage_pool.go new file mode 100644 index 000000000..8d3562c17 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/storage_pool.go @@ -0,0 +1,210 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/storage_volume.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/storage_volume.go new file mode 100644 index 000000000..26b446e8a --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/storage_volume.go @@ -0,0 +1,134 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/stream.go b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/stream.go new file mode 100644 index 000000000..e0b142b34 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/stream.go @@ -0,0 +1,79 @@ +package libvirt + +/* +#cgo LDFLAGS: -lvirt -ldl +#include +#include +#include +*/ +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 +} diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/vagrant/master/Vagrantfile b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/vagrant/master/Vagrantfile new file mode 100644 index 000000000..520b25093 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/vagrant/master/Vagrantfile @@ -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 diff --git a/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/vagrant/vagrant-provision-reboot-plugin.rb b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/vagrant/vagrant-provision-reboot-plugin.rb new file mode 100644 index 000000000..99d9920dd --- /dev/null +++ b/Godeps/_workspace/src/github.com/alexzorin/libvirt-go/vagrant/vagrant-provision-reboot-plugin.rb @@ -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 diff --git a/README.md b/README.md index 6eb7d31bf..3df3f1995 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/circle.yml b/circle.yml index 9c5a87b05..04666ede1 100644 --- a/circle.yml +++ b/circle.yml @@ -10,6 +10,8 @@ machine: - go version dependencies: + pre: + - sudo apt-get update; sudo apt-get install -y libvirt-dev override: - docker info diff --git a/plugins/all/all.go b/plugins/all/all.go index 37e7d27ea..b329f3dd1 100644 --- a/plugins/all/all.go +++ b/plugins/all/all.go @@ -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" diff --git a/plugins/libvirt/README.md b/plugins/libvirt/README.md new file mode 100644 index 000000000..7c1a2e24b --- /dev/null +++ b/plugins/libvirt/README.md @@ -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 diff --git a/plugins/libvirt/libvirt.go b/plugins/libvirt/libvirt.go new file mode 100644 index 000000000..d5d6a8d91 --- /dev/null +++ b/plugins/libvirt/libvirt.go @@ -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{} + }) +} diff --git a/plugins/libvirt/libvirt_test.go b/plugins/libvirt/libvirt_test.go new file mode 100644 index 000000000..4cc06d665 --- /dev/null +++ b/plugins/libvirt/libvirt_test.go @@ -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)) +}