Generate the remaining consts. (#55)

* Generate the remaining consts.

There were a number of hand-written consts in go-libvirt, including flag
values for various libvirt functions. Remove these and generate them
instead, so that we now have a complete set, and the naming is
consistent. I used c-for-go to do this generation, but turned off any
cgo usage by the generated code - we don't want or need to introduce a
dependency on cgo just to get constants from C headers. All code is
still generated using 'go generate ./...', which now calls a wrapper
script for added robustness.

This change also returns to using Go types for flags for most libvirt
functions, instead of plain integers.
This commit is contained in:
Geoff Hickey 2018-01-03 15:19:28 -05:00 committed by GitHub
parent 1a220100bd
commit 59d541f193
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 2475 additions and 577 deletions

View File

@ -1,14 +1,14 @@
libvirt [![GoDoc](http://godoc.org/github.com/digitalocean/go-libvirt?status.svg)](http://godoc.org/github.com/digitalocean/go-libvirt) [![Build Status](https://travis-ci.org/digitalocean/go-libvirt.svg?branch=master)](https://travis-ci.org/digitalocean/go-libvirt) [![Report Card](https://goreportcard.com/badge/github.com/digitalocean/go-libvirt)](https://goreportcard.com/report/github.com/digitalocean/go-libvirt) libvirt [![GoDoc](http://godoc.org/github.com/digitalocean/go-libvirt?status.svg)](http://godoc.org/github.com/digitalocean/go-libvirt) [![Build Status](https://travis-ci.org/digitalocean/go-libvirt.svg?branch=master)](https://travis-ci.org/digitalocean/go-libvirt) [![Report Card](https://goreportcard.com/badge/github.com/digitalocean/go-libvirt)](https://goreportcard.com/report/github.com/digitalocean/go-libvirt)
==== ====
Package `libvirt` provides a pure Go interface for interacting with Libvirt. Package `go-libvirt` provides a pure Go interface for interacting with libvirt.
Rather than using Libvirt's C bindings, this package makes use of Rather than using Libvirt's C bindings, this package makes use of
Libvirt's RPC interface, as documented [here](https://libvirt.org/internals/rpc.html). libvirt's RPC interface, as documented [here](https://libvirt.org/internals/rpc.html).
Connections to the libvirt server may be local, or remote. RPC packets are encoded Connections to the libvirt server may be local, or remote. RPC packets are encoded
using the XDR standard as defined by [RFC 4506](https://tools.ietf.org/html/rfc4506.html). using the XDR standard as defined by [RFC 4506](https://tools.ietf.org/html/rfc4506.html).
Libvirt's RPC interface is quite extensive, and changes from one version to the next, so libvirt's RPC interface is quite extensive, and changes from one version to the next, so
this project uses a code generator to build the go bindings. The code generator should this project uses a code generator to build the go bindings. The code generator should
be run whenever you want to build go-libvirt for a new version of libvirt. To do this, be run whenever you want to build go-libvirt for a new version of libvirt. To do this,
you'll need to set an environment variable `LIBVIRT_SOURCE` to the directory containing you'll need to set an environment variable `LIBVIRT_SOURCE` to the directory containing
@ -18,8 +18,64 @@ and produces go bindings for all the remote procedures defined there.
[Pull requests are welcome](https://github.com/digitalocean/go-libvirt/blob/master/CONTRIBUTING.md)! [Pull requests are welcome](https://github.com/digitalocean/go-libvirt/blob/master/CONTRIBUTING.md)!
Feel free to join us in [`#go-qemu` on freenode](https://webchat.freenode.net/) How to Use This Library
if you'd like to discuss the project. -----------------------
Once you've vendored go-libvirt into your project, you'll probably want to call
some libvirt functions. There's some example code below showing how to connect
to libvirt and make one such call, but once you get past the introduction you'll
next want to call some other libvirt functions. How do you find them?
Start with the [libvirt API reference](https://libvirt.org/html/index.html).
Let's say you want to gracefully shutdown a VM, and after reading through the
libvirt docs you determine that virDomainShutdown() is the function you want to
call to do that. Where's that function in go-libvirt? We transform the names
slightly when building the go bindings. There's no need for a global prefix like
"vir" in Go, since all our functions are inside the package namespace, so we
drop it. That means the Go function for `virDomainShutdown()` is just `DomainShutdown()`,
and sure enough, you can find the Go function `DomainShutdown()` in libvirt.gen.go,
with parameters and return values equivalent to those documented in the API
reference.
Suppose you then decide you need more control over your shutdown, so you switch
over to `virDomainShutdownFlags()`. As its name suggests, this function takes a
flag parameter which has possible values specified in an enum called
`virDomainShutdownFlagValues`. Flag types like this are a little tricky for the
code generator, because the C functions just take an integer type - only the
libvirt documentation actually ties the flags to the enum types. In most cases
though we're able to generate a wrapper function with a distinct flag type,
making it easier for Go tooling to suggest possible flag values while you're
working. Checking the documentation for this function:
`godoc github.com/digitalocean/go-libvirt DomainShutdownFlags`
returns this:
`func (l *Libvirt) DomainShutdownFlags(Dom Domain, Flags DomainShutdownFlagValues) (err error)`
If you want to see the possible flag values, `godoc` can help again:
```
$ godoc github.com/digitalocean/go-libvirt DomainShutdownFlagValues
type DomainShutdownFlagValues int32
DomainShutdownFlagValues as declared in libvirt/libvirt-domain.h:1121
const (
DomainShutdownDefault DomainShutdownFlagValues = iota
DomainShutdownAcpiPowerBtn DomainShutdownFlagValues = 1
DomainShutdownGuestAgent DomainShutdownFlagValues = 2
DomainShutdownInitctl DomainShutdownFlagValues = 4
DomainShutdownSignal DomainShutdownFlagValues = 8
DomainShutdownParavirt DomainShutdownFlagValues = 16
)
DomainShutdownFlagValues enumeration from libvirt/libvirt-domain.h:1121
```
One other suggestion: most of the code in go-libvirt is now generated, but a few
hand-written routines still exist in libvirt.go, and wrap calls to the generated
code with slightly different parameters or return values. We suggest avoiding
these hand-written routines and calling the generated routines in libvirt.gen.go
instead. Over time these handwritten routines will be removed from go-libvirt.
Warning Warning
------- -------

1995
const.gen.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@ package lvgen
import ( import (
"fmt" "fmt"
"go/ast"
"io" "io"
"os" "os"
"strconv" "strconv"
@ -23,6 +24,8 @@ import (
"text/template" "text/template"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"golang.org/x/tools/go/loader"
) )
// If you're making changes to the generator, or troubleshooting the generated // If you're making changes to the generator, or troubleshooting the generated
@ -375,6 +378,8 @@ func fixAbbrevs(s string) string {
// defined in the protocol file. If one or both of these structs is not defined // defined in the protocol file. If one or both of these structs is not defined
// then either the args or return values are empty. // then either the args or return values are empty.
func procLink() { func procLink() {
flagTypes := mapFlagTypes()
for ix, proc := range Gen.Procs { for ix, proc := range Gen.Procs {
argsName := proc.Name + "Args" argsName := proc.Name + "Args"
retName := proc.Name + "Ret" retName := proc.Name + "Ret"
@ -383,6 +388,7 @@ func procLink() {
if hasArgs { if hasArgs {
argsStruct := Gen.Structs[argsIx] argsStruct := Gen.Structs[argsIx]
Gen.Procs[ix].ArgsStruct = argsStruct.Name Gen.Procs[ix].ArgsStruct = argsStruct.Name
changeFlagType(proc.Name, &argsStruct, flagTypes)
Gen.Procs[ix].Args = argsStruct.Members Gen.Procs[ix].Args = argsStruct.Members
} }
if hasRet { if hasRet {
@ -393,6 +399,138 @@ func procLink() {
} }
} }
// mapFlagTypes builds a map of the C types which appear to correspond to the
// various flags fields in libvirt calls. Determining whether a type actually
// corresponds to a set of flags is done by pattern matching the type name;
// libvirt isn't completely consistent about the names of flag types, but they
// all seem to have one of three suffixes, so that's what we look for here.
//
// This code uses the loader package to load the constants file generated by
// c-for-go, which runs against libvirt's C sources. This file is generated by
// 'go generate ./...' prior to the lvgen/ generator being run.
func mapFlagTypes() map[string]ast.Expr {
pconf := loader.Config{}
f, err := pconf.ParseFile("../../const.gen.go", nil)
if err != nil {
panic(fmt.Sprintln("failed to read constants file: ", err))
}
pconf.CreateFromFiles("const", f)
prog, err := pconf.Load()
if err != nil {
panic(fmt.Sprintln("failed to load package: ", err))
}
cpkg := prog.Package("const")
tmap := make(map[string]ast.Expr)
ast.Inspect(cpkg.Files[0], func(n ast.Node) bool {
switch t := n.(type) {
case *ast.TypeSpec:
// There isn't a single name pattern that covers all of the flag
// types, so we'll collect all the types that map to int32 here.
if fmt.Sprintf("%s", t.Type) == "int32" {
tmap[t.Name.String()] = t.Type
}
}
return true
})
return tmap
}
// Many libvirt calls use flags whose values come from a set of definitions
// whose name we can't predict. So this map exists to do the translation for us.
// The only way to remove this fragile map would be to use the comments from the
// .c files in libvirt, which contain doxygen-style parameter comments that
// specify the valid value types for flags.
var flagMap = map[string]string{
"ConnectOpen": "ConnectFlags",
"DomainAddIothread": "DomainModificationImpact",
"DomainCoreDumpWithFormat": "DomainCoreDumpFlags",
"DomainCreateXML": "DomainCreateFlags",
"DomainCreateWithFiles": "DomainCreateFlags",
"DomainCreateXMLWithFiles": "DomainCreateFlags",
"DomainDefineXMLFlags": "DomainDefineFlags",
"DomainDelIothread": "DomainModificationImpact",
"DomainDestroyFlags": "DomainDestroyFlagsValues",
"DomainGetCPUStats": "TypedParameterFlags",
"DomainGetEmulatorPinInfo": "DomainModificationImpact",
"DomainGetInterfaceParameters": "DomainModificationImpact",
"DomainGetIothreadInfo": "DomainModificationImpact",
"DomainGetMetadata": "DomainModificationImpact",
"DomainGetPerfEvents": "DomainModificationImpact",
"DomainGetXMLDesc": "DomainXMLFlags",
"DomainManagedSaveDefineXML": "DomainSaveRestoreFlags",
"DomainManagedSaveGetXMLDesc": "DomainXMLFlags",
"DomainMemoryPeek": "DomainMemoryFlags",
"DomainMigratePerform3Params": "DomainMigrateFlags",
"DomainOpenChannel": "DomainChannelFlags",
"DomainOpenGraphicsFd": "DomainOpenGraphicsFlags",
"DomainPinEmulator": "DomainModificationImpact",
"DomainPinIothread": "DomainModificationImpact",
"DomainSetLifecycleAction": "DomainModificationImpact",
"DomainSetMemoryStatsPeriod": "DomainMemoryModFlags",
"DomainSetMetadata": "DomainModificationImpact",
"DomainSetPerfEvents": "DomainModificationImpact",
"DomainSetVcpu": "DomainModificationImpact",
"DomainShutdownFlags": "DomainShutdownFlagValues",
"DomainUndefineFlags": "DomainUndefineFlagsValues",
"StoragePoolCreateXML": "StoragePoolCreateFlags",
"StoragePoolGetXMLDesc": "StorageXMLFlags",
"StorageVolCreateXML": "StorageVolCreateFlags",
"StorageVolCreateXMLFrom": "StorageVolCreateFlags",
}
// findFlagType attempts to find a real type for the flags passed to a given
// libvirt routine.
func findFlagType(procName string, flagTypes map[string]ast.Expr) (string, bool) {
flagName, ok := flagMap[procName]
if ok {
// Verify the mapped name exists
if _, ok = flagTypes[flagName]; ok == false {
// If one of the manual flag mappings is wrong, complain but
// continue. This happens with older versions of libvirt.
fmt.Printf("manual flag type %v for %v not found, continuing", flagName, procName)
return "", false
}
return flagName, true
}
// Not in the manual map, so do a search using the 3 patterns libvirt uses.
tnames := [...]string{procName + "Flags", procName + "FlagValues", procName + "FlagsValues"}
for _, n := range tnames {
if _, ok := flagTypes[n]; ok == true {
return n, true
}
}
return "", false
}
// changeFlagType looks up the go type for a libvirt call's flags field. In C
// these flags are all uint32, and you have to consult the documentation to
// determine what the valid set of flags is for a given libvirt call. For Go
// we're attempting to do better by specifying an actual type so that the
// possible values are easier to determine. This is a heuristic, however, based
// on naming patterns in the libvirt code. To do better we would need to look at
// the doxygen-style comments in the libvirt sources.
//
// Failing to find a flags type isn't a fatal error, it just means that we'll
// leave the flags with a type of uint32.
func changeFlagType(procName string, s *Structure, flagTypes map[string]ast.Expr) {
for ix, d := range s.Members {
if d.Name == "Flags" {
tname, found := findFlagType(procName, flagTypes)
if found {
s.Members[ix].Type = tname
} else {
// If you're adding procedures to to the manual map, you may
// want to uncomment this to see what flag types are not found.
// fmt.Println("flags type for", procName, "not found")
}
}
}
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Routines called by the parser's actions. // Routines called by the parser's actions.
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -592,7 +730,6 @@ func AddOptValue(identifier, itype string) {
atype := "[]" + itype atype := "[]" + itype
decl := NewDecl(identifier, atype) decl := NewDecl(identifier, atype)
newType := "Opt" + decl.Name newType := "Opt" + decl.Name
fmt.Printf("Adding mapping %v = %v\n", decl.Name, newType)
goEquivTypes[decl.Name] = newType goEquivTypes[decl.Name] = newType
decl.Name = newType decl.Name = newType
addDecl(decl) addDecl(decl)

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,10 @@
// For more information on the protocol, see https://libvirt.org/internals/l.html // For more information on the protocol, see https://libvirt.org/internals/l.html
package libvirt package libvirt
// We'll use c-for-go to extract the consts and typedefs from the libvirt
// sources so we don't have to duplicate them here.
//go:generate scripts/gen-consts.sh
import ( import (
"bufio" "bufio"
"bytes" "bytes"
@ -34,7 +38,7 @@ import (
// are unsupported by either QEMU or libvirt. // are unsupported by either QEMU or libvirt.
var ErrEventsNotSupported = errors.New("event monitor is not supported") var ErrEventsNotSupported = errors.New("event monitor is not supported")
// Libvirt implements LibVirt's remote procedure call protocol. // Libvirt implements libvirt's remote procedure call protocol.
type Libvirt struct { type Libvirt struct {
conn net.Conn conn net.Conn
r *bufio.Reader r *bufio.Reader
@ -72,371 +76,6 @@ type qemuError struct {
} `json:"error"` } `json:"error"`
} }
// DomainXMLFlags specifies options for dumping a domain's XML.
type DomainXMLFlags uint32
// DomainAffectFlags specifies options for whether an operation affects the
// running VM, or the persistent VM configuration on disk. See FlagDomain...
// consts for values.
type DomainAffectFlags uint32
// Consts used for flags
// virDomainModificationImpact and virTypedParameterFlags values. These are
// combined here because they are both used to set the same flags fields in the
// libvirt API.
const (
// FlagDomainAffectCurrent means affect the current domain state
FlagDomainAffectCurrent DomainAffectFlags = 0
// FlagDomainAffectLive means affect the running domain state
FlagDomainAffectLive = 1 << (iota - 1)
// FlagDomainAffectConfig means affect the persistent domain state.
FlagDomainAffectConfig
// FlagTypedParamStringOkay tells the server that this client understands
// TypedParamStrings.
FlagTypedParamStringOkay
)
const (
// DomainXMLFlagSecure dumps XML with sensitive information included.
DomainXMLFlagSecure DomainXMLFlags = 1 << iota
// DomainXMLFlagInactive dumps XML with inactive domain information.
DomainXMLFlagInactive
// DomainXMLFlagUpdateCPU dumps XML with guest CPU requirements according to the host CPU.
DomainXMLFlagUpdateCPU
// DomainXMLFlagMigratable dumps XML suitable for migration.
DomainXMLFlagMigratable
)
// scheduler parameters used as fields in TypedParam by the following functions:
// DomainGetSchedulerParameters
// DomainGetSchedulerParametersFlags
// DomainSetSchedulerParameters
// DomainSetSchedulerParametersFlags
const (
// DomainSchedulerCPUShares represents the propportional weight
// of the scheduler used on the host cpu, when using the posix
// scheduler. (ullong)
DomainSchedulerCPUShares = "cpu_shares"
// DomainSchedulerGlobalPeriod represents the enforcement period
// for a quota, in microseconds, for whole domain, when using the
// posix scheduler. (ullong)
DomainSchedulerGlobalPeriod = "global_period"
// DomainSchedulerGlobalQuota represents the maximum bandwidth to be
// used within a period for whole domain, when using the posix
// scheduler. (llong)
DomainSchedulerGlobalQuota = "global_quota"
// DomainSchedulerVCPUPeriod represents the enforcement period for a
// quota, in microseconds, for vcpus only, when using the posix
// scheduler. (ullong)
DomainSchedulerVCPUPeriod = "vcpu_period"
// DomainSchedulerVCPUQuota represents the maximum bandwidth to be
// used within a period for vcpus only, when using the posix
// scheduler. (llong)
DomainSchedulerVCPUQuota = "vcpu_quota"
// DomainSchedulerEmulatorPeriod represents the enforcement period
// for a quota in microseconds, when using the posix scheduler, for
// all emulator activity not tied to vcpus. (ullong)
DomainSchedulerEmulatorPeriod = "emulator_period"
// DomainSchedulerEmulatorQuota represents the maximum bandwidth to be
// used within a period for all emulator activity not tied to vcpus,
// when using the posix scheduler. (llong)
DomainSchedulerEmulatorQuota = "emulator_quota"
// DomainSchedulerIOThreadPeriod represents the enforcement period for
// a quota, in microseconds, for IOThreads only, when using the posix
// scheduler. (ullong)
DomainSchedulerIOThreadPeriod = "iothread_period"
// DomainSchedulerIOThreadQuota represents the maximum bandwidth to be
// used within a period for IOThreads only, when using the posix
// scheduler. (llong)
DomainSchedulerIOThreadQuota = "iothread_quota"
// DomainSchedulerWeight represents the relative weight, when using the
// credit scheduler. (uint)
DomainSchedulerWeight = "weight"
// DomainSchedulerCap represents the maximum scheduler cap, when using
// the credit scheduler. (uint)
DomainSchedulerCap = "cap"
// DomainSchedulerReservation represents the scheduler reservation
// value, when using the allocation scheduler. (llong)
DomainSchedulerReservation = "reservation"
// DomainSchedulerLimit represents the scheduler limit value, when using
// the allocation scheduler. (llong)
DomainSchedulerLimit = "limit"
// DomainSchedulerShares represents the scheduler shares value, when
// using the allocation scheduler. (int)
DomainSchedulerShares = "shares"
)
// MigrateFlags specifies options when performing a migration.
type MigrateFlags uint32
const (
// MigrateFlagLive performs a zero-downtime live migration.
MigrateFlagLive MigrateFlags = 1 << iota
// MigrateFlagPeerToPeer creates a direct source to destination control channel.
MigrateFlagPeerToPeer
// MigrateFlagTunneled tunnels migration data over the libvirtd connection.
MigrateFlagTunneled
// MigrateFlagPersistDestination will persist the VM on the destination host.
MigrateFlagPersistDestination
// MigrateFlagUndefineSource undefines the VM on the source host.
MigrateFlagUndefineSource
// MigrateFlagPaused will pause the remote side VM.
MigrateFlagPaused
// MigrateFlagNonSharedDisk migrate non-shared storage with full disk copy.
MigrateFlagNonSharedDisk
// MigrateFlagNonSharedIncremental migrate non-shared storage with incremental copy.
MigrateFlagNonSharedIncremental
// MigrateFlagChangeProtection prevents any changes to the domain configuration through the whole migration process.
MigrateFlagChangeProtection
// MigrateFlagUnsafe will force a migration even when it is considered unsafe.
MigrateFlagUnsafe
// MigrateFlagOffline is used to perform an offline migration.
MigrateFlagOffline
// MigrateFlagCompressed compresses data during migration.
MigrateFlagCompressed
// MigrateFlagAbortOnError will abort a migration on I/O errors encountered during migration.
MigrateFlagAbortOnError
// MigrateFlagAutoConverge forces convergence.
MigrateFlagAutoConverge
// MigrateFlagRDMAPinAll enables RDMA memory pinning.
MigrateFlagRDMAPinAll
)
// UndefineFlags specifies options available when undefining a domain.
type UndefineFlags uint32
const (
// UndefineFlagManagedSave removes all domain managed save data.
UndefineFlagManagedSave UndefineFlags = 1 << iota
// UndefineFlagSnapshotsMetadata removes all domain snapshot metadata.
UndefineFlagSnapshotsMetadata
// UndefineFlagNVRAM removes all domain NVRAM files.
UndefineFlagNVRAM
)
// DomainDefineXMLFlags specifies options available when defining a domain.
type DomainDefineXMLFlags uint32
const (
// DefineValidate validates the XML document against schema
DefineValidate DomainDefineXMLFlags = 1
)
// DestroyFlags specifies options available when destroying a domain.
type DestroyFlags uint32
const (
// DestroyFlagDefault default behavior, forcefully terminate the domain.
DestroyFlagDefault DestroyFlags = 1 << iota
// DestroyFlagGraceful only sends a SIGTERM no SIGKILL.
DestroyFlagGraceful
)
// ShutdownFlags specifies options available when shutting down a domain.
type ShutdownFlags uint32
const (
// ShutdownAcpiPowerBtn - send ACPI event
ShutdownAcpiPowerBtn ShutdownFlags = 1 << iota
// ShutdownGuestAgent - use guest agent
ShutdownGuestAgent
// ShutdownInitctl - use initctl
ShutdownInitctl
// ShutdownSignal - use signal
ShutdownSignal
// ShutdownParavirt - use paravirt guest control
ShutdownParavirt
)
// DomainState specifies state of the domain
type DomainState uint32
const (
// DomainStateNoState No state
DomainStateNoState DomainState = iota
// DomainStateRunning The domain is running
DomainStateRunning
// DomainStateBlocked The domain is blocked on resource
DomainStateBlocked
// DomainStatePaused The domain is paused by user
DomainStatePaused
// DomainStateShutdown The domain is being shut down
DomainStateShutdown
// DomainStateShutoff The domain is shut off
DomainStateShutoff
// DomainStateCrashed The domain is crashed
DomainStateCrashed
// DomainStatePMSuspended The domain is suspended by guest power management
DomainStatePMSuspended
// DomainStateLast This value will increase over time as new events are added to the libvirt
// API. It reflects the last state supported by this version of the libvirt API.
DomainStateLast
)
// SecretUsageType specifies the usage for a libvirt secret.
type SecretUsageType uint32
const (
// SecretUsageTypeNone specifies no usage.
SecretUsageTypeNone SecretUsageType = iota
// SecretUsageTypeVolume specifies a volume secret.
SecretUsageTypeVolume
// SecretUsageTypeCeph specifies secrets for ceph devices.
SecretUsageTypeCeph
// SecretUsageTypeISCSI specifies secrets for ISCSI devices.
SecretUsageTypeISCSI
)
// StoragePoolsFlags specifies storage pools to list.
type StoragePoolsFlags uint32
// These flags come in groups; if all bits from a group are 0,
// then that group is not used to filter results.
const (
StoragePoolsFlagInactive = 1 << iota
StoragePoolsFlagActive
StoragePoolsFlagPersistent
StoragePoolsFlagTransient
StoragePoolsFlagAutostart
StoragePoolsFlagNoAutostart
// pools by type
StoragePoolsFlagDir
StoragePoolsFlagFS
StoragePoolsFlagNETFS
StoragePoolsFlagLogical
StoragePoolsFlagDisk
StoragePoolsFlagISCSI
StoragePoolsFlagSCSI
StoragePoolsFlagMPATH
StoragePoolsFlagRBD
StoragePoolsFlagSheepdog
StoragePoolsFlagGluster
StoragePoolsFlagZFS
)
// DomainCreateFlags specify options for starting domains
type DomainCreateFlags uint32
const (
// DomainCreateFlagPaused creates paused domain.
DomainCreateFlagPaused = 1 << iota
// DomainCreateFlagAutoDestroy destoy domain after libvirt connection closed.
DomainCreateFlagAutoDestroy
// DomainCreateFlagBypassCache avoid file system cache pollution.
DomainCreateFlagBypassCache
// DomainCreateFlagStartForceBoot boot, discarding any managed save
DomainCreateFlagStartForceBoot
// DomainCreateFlagStartValidate validate the XML document against schema
DomainCreateFlagStartValidate
)
// RebootFlags specifies domain reboot methods
type RebootFlags uint32
const (
// RebootAcpiPowerBtn - send ACPI event
RebootAcpiPowerBtn RebootFlags = 1 << iota
// RebootGuestAgent - use guest agent
RebootGuestAgent
// RebootInitctl - use initctl
RebootInitctl
// RebootSignal - use signal
RebootSignal
// RebootParavirt - use paravirt guest control
RebootParavirt
)
// DomainMemoryStatTag specifies domain memory tags
type DomainMemoryStatTag uint32
const (
// DomainMemoryStatTagSwapIn - The total amount of data read from swap space (in kB).
DomainMemoryStatTagSwapIn DomainMemoryStatTag = iota
// DomainMemoryStatTagSwapOut - The total amount of memory written out to swap space (in kB).
DomainMemoryStatTagSwapOut
// DomainMemoryStatTagMajorFault - Page faults occur when a process makes a valid access to virtual memory
// that is not available. When servicing the page fault, if disk IO is
// required, it is considered a major fault.
// These are expressed as the number of faults that have occurred.
DomainMemoryStatTagMajorFault
// DomainMemoryStatTagMinorFault - If the page fault not require disk IO, it is a minor fault.
DomainMemoryStatTagMinorFault
// DomainMemoryStatTagUnused - The amount of memory left completely unused by the system (in kB).
DomainMemoryStatTagUnused
// DomainMemoryStatTagAvailable - The total amount of usable memory as seen by the domain (in kB).
DomainMemoryStatTagAvailable
// DomainMemoryStatTagActualBalloon - Current balloon value (in KB).
DomainMemoryStatTagActualBalloon
// DomainMemoryStatTagRss - Resident Set Size of the process running the domain (in KB).
DomainMemoryStatTagRss
// DomainMemoryStatTagUsable - How much the balloon can be inflated without pushing the guest system
// to swap, corresponds to 'Available' in /proc/meminfo
DomainMemoryStatTagUsable
// DomainMemoryStatTagLastUpdate - Timestamp of the last update of statistics, in seconds.
DomainMemoryStatTagLastUpdate
// DomainMemoryStatTagNr - The number of statistics supported by this version of the interface.
DomainMemoryStatTagNr
)
// Capabilities returns an XML document describing the host's capabilties. // Capabilities returns an XML document describing the host's capabilties.
func (l *Libvirt) Capabilities() ([]byte, error) { func (l *Libvirt) Capabilities() ([]byte, error) {
caps, err := l.ConnectGetCapabilities() caps, err := l.ConnectGetCapabilities()
@ -479,7 +118,7 @@ func (l *Libvirt) Domains() ([]Domain, error) {
func (l *Libvirt) DomainState(dom string) (DomainState, error) { func (l *Libvirt) DomainState(dom string) (DomainState, error) {
d, err := l.lookup(dom) d, err := l.lookup(dom)
if err != nil { if err != nil {
return DomainStateNoState, err return DomainNostate, err
} }
state, _, err := l.DomainGetState(d, 0) state, _, err := l.DomainGetState(d, 0)
@ -553,7 +192,7 @@ func (l *Libvirt) Events(dom string) (<-chan DomainEvent, error) {
// 'qemu+tcp://example.com/system'. The flags argument determines the // 'qemu+tcp://example.com/system'. The flags argument determines the
// type of migration and how it will be performed. For more information // type of migration and how it will be performed. For more information
// on available migration flags and their meaning, see MigrateFlag*. // on available migration flags and their meaning, see MigrateFlag*.
func (l *Libvirt) Migrate(dom string, dest string, flags MigrateFlags) error { func (l *Libvirt) Migrate(dom string, dest string, flags DomainMigrateFlags) error {
_, err := url.Parse(dest) _, err := url.Parse(dest)
if err != nil { if err != nil {
return err return err
@ -571,7 +210,7 @@ func (l *Libvirt) Migrate(dom string, dest string, flags MigrateFlags) error {
destURI := []string{dest} destURI := []string{dest}
remoteParams := []TypedParam{} remoteParams := []TypedParam{}
cookieIn := []byte{} cookieIn := []byte{}
_, err = l.DomainMigratePerform3Params(d, destURI, remoteParams, cookieIn, uint32(flags)) _, err = l.DomainMigratePerform3Params(d, destURI, remoteParams, cookieIn, flags)
return err return err
} }
@ -653,35 +292,35 @@ func (l *Libvirt) StoragePool(name string) (StoragePool, error) {
// StoragePools returns a list of defined storage pools. Pools are filtered by // StoragePools returns a list of defined storage pools. Pools are filtered by
// the provided flags. See StoragePools*. // the provided flags. See StoragePools*.
func (l *Libvirt) StoragePools(flags StoragePoolsFlags) ([]StoragePool, error) { func (l *Libvirt) StoragePools(flags ConnectListAllStoragePoolsFlags) ([]StoragePool, error) {
pools, _, err := l.ConnectListAllStoragePools(1, uint32(flags)) pools, _, err := l.ConnectListAllStoragePools(1, flags)
return pools, err return pools, err
} }
// Undefine undefines the domain specified by dom, e.g., 'prod-lb-01'. // Undefine undefines the domain specified by dom, e.g., 'prod-lb-01'.
// The flags argument allows additional options to be specified such as // The flags argument allows additional options to be specified such as
// cleaning up snapshot metadata. For more information on available // cleaning up snapshot metadata. For more information on available
// flags, see UndefineFlag*. // flags, see DomainUndefine*.
func (l *Libvirt) Undefine(dom string, flags UndefineFlags) error { func (l *Libvirt) Undefine(dom string, flags DomainUndefineFlagsValues) error {
d, err := l.lookup(dom) d, err := l.lookup(dom)
if err != nil { if err != nil {
return err return err
} }
return l.DomainUndefineFlags(d, uint32(flags)) return l.DomainUndefineFlags(d, flags)
} }
// Destroy destroys the domain specified by dom, e.g., 'prod-lb-01'. // Destroy destroys the domain specified by dom, e.g., 'prod-lb-01'.
// The flags argument allows additional options to be specified such as // The flags argument allows additional options to be specified such as
// allowing a graceful shutdown with SIGTERM than SIGKILL. // allowing a graceful shutdown with SIGTERM than SIGKILL.
// For more information on available flags, see DestroyFlag*. // For more information on available flags, see DomainDestroy*.
func (l *Libvirt) Destroy(dom string, flags DestroyFlags) error { func (l *Libvirt) Destroy(dom string, flags DomainDestroyFlagsValues) error {
d, err := l.lookup(dom) d, err := l.lookup(dom)
if err != nil { if err != nil {
return err return err
} }
return l.DomainDestroyFlags(d, uint32(flags)) return l.DomainDestroyFlags(d, flags)
} }
// XML returns a domain's raw XML definition, akin to `virsh dumpxml <domain>`. // XML returns a domain's raw XML definition, akin to `virsh dumpxml <domain>`.
@ -692,13 +331,13 @@ func (l *Libvirt) XML(dom string, flags DomainXMLFlags) ([]byte, error) {
return nil, err return nil, err
} }
xml, err := l.DomainGetXMLDesc(d, uint32(flags)) xml, err := l.DomainGetXMLDesc(d, flags)
return []byte(xml), err return []byte(xml), err
} }
// DefineXML defines a domain, but does not start it. // DefineXML defines a domain, but does not start it.
func (l *Libvirt) DefineXML(x []byte, flags DomainDefineXMLFlags) error { func (l *Libvirt) DefineXML(x []byte, flags DomainDefineFlags) error {
_, err := l.DomainDefineXMLFlags(string(x), uint32(flags)) _, err := l.DomainDefineXMLFlags(string(x), flags)
return err return err
} }
@ -724,24 +363,24 @@ func (l *Libvirt) Version() (string, error) {
// Shutdown shuts down a domain. Note that the guest OS may ignore the request. // Shutdown shuts down a domain. Note that the guest OS may ignore the request.
// If flags is set to 0 then the hypervisor will choose the method of shutdown it considers best. // If flags is set to 0 then the hypervisor will choose the method of shutdown it considers best.
func (l *Libvirt) Shutdown(dom string, flags ShutdownFlags) error { func (l *Libvirt) Shutdown(dom string, flags DomainShutdownFlagValues) error {
d, err := l.lookup(dom) d, err := l.lookup(dom)
if err != nil { if err != nil {
return err return err
} }
return l.DomainShutdownFlags(d, uint32(flags)) return l.DomainShutdownFlags(d, flags)
} }
// Reboot reboots the domain. Note that the guest OS may ignore the request. // Reboot reboots the domain. Note that the guest OS may ignore the request.
// If flags is set to zero, then the hypervisor will choose the method of shutdown it considers best. // If flags is set to zero, then the hypervisor will choose the method of shutdown it considers best.
func (l *Libvirt) Reboot(dom string, flags RebootFlags) error { func (l *Libvirt) Reboot(dom string, flags DomainRebootFlagValues) error {
d, err := l.lookup(dom) d, err := l.lookup(dom)
if err != nil { if err != nil {
return err return err
} }
return l.DomainReboot(d, uint32(flags)) return l.DomainReboot(d, flags)
} }
// Reset resets domain immediately without any guest OS shutdown // Reset resets domain immediately without any guest OS shutdown
@ -764,33 +403,6 @@ type BlockLimit struct {
Value uint64 Value uint64
} }
// BlockIOTune-able values. These tunables are different for different
// hypervisors; currently only the tunables for QEMU are defined here. These are
// not necessarily the only possible values; different libvirt versions may add
// or remove parameters from this list.
const (
QEMUBlockIOGroupName = "group_name"
QEMUBlockIOTotalBytesSec = "total_bytes_sec"
QEMUBlockIOReadBytesSec = "read_bytes_sec"
QEMUBlockIOWriteBytesSec = "write_bytes_sec"
QEMUBlockIOTotalIOPSSec = "total_iops_sec"
QEMUBlockIOReadIOPSSec = "read_iops_sec"
QEMUBlockIOWriteIOPSSec = "write_iops_sec"
QEMUBlockIOTotalBytesSecMax = "total_bytes_sec_max"
QEMUBlockIOReadBytesSecMax = "read_bytes_sec_max"
QEMUBlockIOWriteBytesSecMax = "write_bytes_sec_max"
QEMUBlockIOTotalIOPSSecMax = "total_iops_sec_max"
QEMUBlockIOReadIOPSSecMax = "read_iops_sec_max"
QEMUBlockIOWriteIOPSSecMax = "write_iops_sec_max"
QEMUBlockIOSizeIOPSSec = "size_iops_sec"
QEMUBlockIOTotalBytesSecMaxLength = "total_bytes_sec_max_length"
QEMUBlockIOReadBytesSecMaxLength = "read_bytes_sec_max_length"
QEMUBlockIOWriteBytesSecMaxLength = "write_bytes_sec_max_length"
QEMUBlockIOTotalIOPSSecMaxLength = "total_iops_sec_max_length"
QEMUBlockIOReadIOPSSecMaxLength = "read_iops_sec_max_length"
QEMUBlockIOWriteIOPSSecMaxLength = "write_iops_sec_max_length"
)
// SetBlockIOTune changes the per-device block I/O tunables within a guest. // SetBlockIOTune changes the per-device block I/O tunables within a guest.
// Parameters are the name of the VM, the name of the disk device to which the // Parameters are the name of the VM, the name of the disk device to which the
// limits should be applied, and 1 or more BlockLimit structs containing the // limits should be applied, and 1 or more BlockLimit structs containing the
@ -814,7 +426,7 @@ func (l *Libvirt) SetBlockIOTune(dom string, disk string, limits ...BlockLimit)
params[ix] = TypedParam{Field: limit.Name, Value: tpval} params[ix] = TypedParam{Field: limit.Name, Value: tpval}
} }
return l.DomainSetBlockIOTune(d, disk, params, FlagDomainAffectLive) return l.DomainSetBlockIOTune(d, disk, params, uint32(DomainAffectLive))
} }
// GetBlockIOTune returns a slice containing the current block I/O tunables for // GetBlockIOTune returns a slice containing the current block I/O tunables for
@ -825,7 +437,7 @@ func (l *Libvirt) GetBlockIOTune(dom string, disk string) ([]BlockLimit, error)
return nil, err return nil, err
} }
lims, _, err := l.DomainGetBlockIOTune(d, []string{disk}, 32, FlagTypedParamStringOkay) lims, _, err := l.DomainGetBlockIOTune(d, []string{disk}, 32, uint32(TypedParamStringOkay))
if err != nil { if err != nil {
return nil, err return nil, err
} }

59
libvirt.yml Normal file
View File

@ -0,0 +1,59 @@
# Configuration file for c-for-go, which go-libvirt uses to translate the const
# and type definitions from the C-language sources in the libvirt project into
# Go. This file is used by the c-for-go binary (github.com/xlab/c-for-go), which
# is called when 'go generate' is run. See libvirt.go for the command line used.
---
GENERATOR:
PackageName: libvirt
PackageLicense: |
Copyright 2017 The go-libvirt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Includes: []
PARSER:
# We can't use environment variables here, but we don't want to process the
# libvirt version installed in the system folders (if any). Instead we'll
# rely on our caller to link the libvirt source directory to lv_source/, and
# run on that code. This isn't ideal, but changes to c-for-go are needed to
# fix it.
IncludePaths: [./lv_source/include]
SourcesPaths:
- libvirt/libvirt.h
TRANSLATOR:
ConstRules:
defines: eval
Rules:
global:
- {action: accept, from: "^vir"}
post-global:
- {action: replace, from: "^vir"}
- {load: snakecase}
# Follow golint's capitalization conventions.
- {action: replace, from: "Api([A-Z]|$)", to: "API$1"}
- {action: replace, from: "Cpu([A-Z]|$)", to: "CPU$1"}
- {action: replace, from: "Dns([A-Z]|$)", to: "DNS$1"}
- {action: replace, from: "Eof([A-Z]|$)", to: "EOF$1"}
- {action: replace, from: "Id([A-Z]|$)", to: "ID$1"}
- {action: replace, from: "Ip([A-Z]|$)", to: "IP$1"}
- {action: replace, from: "Tls([A-Z]|$)", to: "TLS$1"}
- {action: replace, from: "Uuid([A-Z]|$)", to: "UUID$1"}
- {action: replace, from: "Uri([A-Z]|$)", to: "URI$1"}
- {action: replace, from: "Vcpu([A-Z]|$)", to: "VCPU$1"}
- {action: replace, from: "Xml([A-Z]|$)", to: "XML$1"}
const:
- {action: accept, from: "^VIR_"}
# Special case to prevent a collision with a type:
- {action: replace, from: "^VIR_DOMAIN_JOB_OPERATION", to: "VIR_DOMAIN_JOB_OPERATION_STR"}
- {transform: lower}

View File

@ -156,7 +156,7 @@ func TestStoragePoolsIntegration(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
pools, err := l.StoragePools(StoragePoolsFlagActive) pools, err := l.StoragePools(ConnectListStoragePoolsActive)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -182,7 +182,7 @@ func TestStoragePoolsAutostartIntegration(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
pools, err := l.StoragePools(StoragePoolsFlagAutostart) pools, err := l.StoragePools(ConnectListStoragePoolsAutostart)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@ -48,14 +48,14 @@ func TestMigrate(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
var flags MigrateFlags var flags DomainMigrateFlags
flags = MigrateFlagLive | flags = MigrateLive |
MigrateFlagPeerToPeer | MigratePeer2peer |
MigrateFlagPersistDestination | MigratePersistDest |
MigrateFlagChangeProtection | MigrateChangeProtection |
MigrateFlagAbortOnError | MigrateAbortOnError |
MigrateFlagAutoConverge | MigrateAutoConverge |
MigrateFlagNonSharedDisk MigrateNonSharedDisk
if err := l.Migrate("test", "qemu+tcp://foo/system", flags); err != nil { if err := l.Migrate("test", "qemu+tcp://foo/system", flags); err != nil {
t.Fatalf("unexpected live migration error: %v", err) t.Fatalf("unexpected live migration error: %v", err)
@ -66,14 +66,14 @@ func TestMigrateInvalidDest(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
var flags MigrateFlags var flags DomainMigrateFlags
flags = MigrateFlagLive | flags = MigrateLive |
MigrateFlagPeerToPeer | MigratePeer2peer |
MigrateFlagPersistDestination | MigratePersistDest |
MigrateFlagChangeProtection | MigrateChangeProtection |
MigrateFlagAbortOnError | MigrateAbortOnError |
MigrateFlagAutoConverge | MigrateAutoConverge |
MigrateFlagNonSharedDisk MigrateNonSharedDisk
dest := ":$'" dest := ":$'"
if err := l.Migrate("test", dest, flags); err == nil { if err := l.Migrate("test", dest, flags); err == nil {
@ -122,7 +122,7 @@ func TestDomainState(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
wantState := DomainState(DomainStateRunning) wantState := DomainState(DomainRunning)
gotState, err := l.DomainState("test") gotState, err := l.DomainState("test")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -325,7 +325,7 @@ func TestStoragePools(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
pools, err := l.StoragePools(StoragePoolsFlagActive) pools, err := l.StoragePools(ConnectListStoragePoolsTransient)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -371,7 +371,7 @@ func TestUndefine(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
var flags UndefineFlags var flags DomainUndefineFlagsValues
if err := l.Undefine("test", flags); err != nil { if err := l.Undefine("test", flags); err != nil {
t.Fatalf("unexpected undefine error: %v", err) t.Fatalf("unexpected undefine error: %v", err)
} }
@ -381,7 +381,7 @@ func TestDestroy(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
var flags DestroyFlags var flags DomainDestroyFlagsValues
if err := l.Destroy("test", flags); err != nil { if err := l.Destroy("test", flags); err != nil {
t.Fatalf("unexpected destroy error: %v", err) t.Fatalf("unexpected destroy error: %v", err)
} }
@ -406,7 +406,7 @@ func TestDefineXML(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
var flags DomainDefineXMLFlags var flags DomainDefineFlags
var buf []byte var buf []byte
if err := l.DefineXML(buf, flags); err != nil { if err := l.DefineXML(buf, flags); err != nil {
t.Fatalf("unexpected define error: %v", err) t.Fatalf("unexpected define error: %v", err)
@ -431,7 +431,7 @@ func TestShutdown(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
var flags ShutdownFlags var flags DomainShutdownFlagValues
if err := l.Shutdown("test", flags); err != nil { if err := l.Shutdown("test", flags); err != nil {
t.Fatalf("unexpected shutdown error: %v", err) t.Fatalf("unexpected shutdown error: %v", err)
} }
@ -441,7 +441,7 @@ func TestReboot(t *testing.T) {
conn := libvirttest.New() conn := libvirttest.New()
l := New(conn) l := New(conn)
var flags RebootFlags var flags DomainRebootFlagValues
if err := l.Reboot("test", flags); err != nil { if err := l.Reboot("test", flags); err != nil {
t.Fatalf("unexpected reboot error: %v", err) t.Fatalf("unexpected reboot error: %v", err)
} }

40
scripts/gen-consts.sh Executable file
View File

@ -0,0 +1,40 @@
#!/bin/bash
#
# This runs the first code generator used by go-libvirt: c-for-go. This script
# is run from the 'go generate ./...' command, and only needs to be run when
# changing to a different version of libvirt.
if [ -z "${LIBVIRT_SOURCE}" ]; then
echo "Set LIBVIRT_SOURCE to the root of the libvirt sources you want to use first."
exit 1
fi
# Make sure c-for-go is installed
if ! which c-for-go > /dev/null; then
echo "c-for-go not found. Attempting to install it..."
if ! go get github.com/xlab/c-for-go/...; then
echo "failed to install c-for-go. Please install it manually from https://github.com/xlab/c-for-go"
exit 1
fi
fi
# Make sure goyacc is installed (needed for the lvgen/ generator)
if ! which goyacc > /dev/null; then
echo "goyacc not found. Attempting to install it..."
if ! go get golang.org/x/tools/cmd/goyacc/...; then
echo "failed to install goyacc. Please install it manually from https://golang.org/x/tools/cmd/goyacc"
exit 1
fi
fi
# Temporarily symlink the libvirt sources to a subdirectory because c-for-go
# lacks a mechanism for us to pass it a search path for header files.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
LVDIR=lv_source
ln -sF ${LIBVIRT_SOURCE} ${LVDIR}
if ! c-for-go -nostamp -nocgo -ccincl libvirt.yml; then
echo "c-for-go failed"
exit 1
fi
mv libvirt/const.go ${DIR}/../const.gen.go
rm ${LVDIR}
rm -rf libvirt/

View File

@ -18,7 +18,6 @@ read -r -d '' EXPECTED <<EndOfLicense
// limitations under the License. // limitations under the License.
EndOfLicense EndOfLicense
# Scan each Go source file for license.
EXIT=0 EXIT=0
GOFILES=$(find . -name "*.go") GOFILES=$(find . -name "*.go")