resources: virt: convert to use github.com/libvirt/libvirt-go
Convert the code to use the new libvirt Go bindings. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
committed by
James Shubin
parent
ecc4aa09d3
commit
0b416e44f8
@@ -72,7 +72,7 @@ go get github.com/urfave/cli
|
|||||||
go get github.com/coreos/go-systemd/dbus
|
go get github.com/coreos/go-systemd/dbus
|
||||||
go get github.com/coreos/go-systemd/util
|
go get github.com/coreos/go-systemd/util
|
||||||
go get github.com/coreos/pkg/capnslog
|
go get github.com/coreos/pkg/capnslog
|
||||||
go get github.com/rgbkrk/libvirt-go
|
go get github.com/libvirt/libvirt-go
|
||||||
```
|
```
|
||||||
* stringer (optional for building), available as a package on some platforms, otherwise via `go get`
|
* stringer (optional for building), available as a package on some platforms, otherwise via `go get`
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ import (
|
|||||||
|
|
||||||
"github.com/purpleidea/mgmt/event"
|
"github.com/purpleidea/mgmt/event"
|
||||||
|
|
||||||
|
"github.com/libvirt/libvirt-go"
|
||||||
errwrap "github.com/pkg/errors"
|
errwrap "github.com/pkg/errors"
|
||||||
"github.com/rgbkrk/libvirt-go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -60,7 +60,7 @@ type VirtRes struct {
|
|||||||
URI string `yaml:"uri"` // connection uri, eg: qemu:///session
|
URI string `yaml:"uri"` // connection uri, eg: qemu:///session
|
||||||
State string `yaml:"state"` // running, paused, shutoff
|
State string `yaml:"state"` // running, paused, shutoff
|
||||||
Transient bool `yaml:"transient"` // defined (false) or undefined (true)
|
Transient bool `yaml:"transient"` // defined (false) or undefined (true)
|
||||||
CPUs uint16 `yaml:"cpus"`
|
CPUs uint `yaml:"cpus"`
|
||||||
Memory uint64 `yaml:"memory"` // in KBytes
|
Memory uint64 `yaml:"memory"` // in KBytes
|
||||||
OSInit string `yaml:"osinit"` // init used by lxc
|
OSInit string `yaml:"osinit"` // init used by lxc
|
||||||
Boot []string `yaml:"boot"` // boot order. values: fd, hd, cdrom, network
|
Boot []string `yaml:"boot"` // boot order. values: fd, hd, cdrom, network
|
||||||
@@ -70,13 +70,13 @@ type VirtRes struct {
|
|||||||
Filesystem []filesystemDevice `yaml:"filesystem"`
|
Filesystem []filesystemDevice `yaml:"filesystem"`
|
||||||
Auth *VirtAuth `yaml:"auth"`
|
Auth *VirtAuth `yaml:"auth"`
|
||||||
|
|
||||||
conn libvirt.VirConnection
|
conn *libvirt.Connect
|
||||||
absent bool // cached state
|
absent bool // cached state
|
||||||
uriScheme virtURISchemeType
|
uriScheme virtURISchemeType
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVirtRes is a constructor for this resource. It also calls Init() for you.
|
// NewVirtRes is a constructor for this resource. It also calls Init() for you.
|
||||||
func NewVirtRes(name string, uri, state string, transient bool, cpus uint16, memory uint64, osinit string) (*VirtRes, error) {
|
func NewVirtRes(name string, uri, state string, transient bool, cpus uint, memory uint64, osinit string) (*VirtRes, error) {
|
||||||
obj := &VirtRes{
|
obj := &VirtRes{
|
||||||
BaseRes: BaseRes{
|
BaseRes: BaseRes{
|
||||||
Name: name,
|
Name: name,
|
||||||
@@ -120,12 +120,31 @@ func (obj *VirtRes) Validate() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj *VirtRes) connect() (conn libvirt.VirConnection, err error) {
|
func (obj *VirtRes) connect() (conn *libvirt.Connect, err error) {
|
||||||
if obj.Auth != nil {
|
if obj.Auth != nil {
|
||||||
conn, err = libvirt.NewVirConnectionWithAuth(obj.URI, obj.Auth.Username, obj.Auth.Password)
|
callback := func(creds []*libvirt.ConnectCredential) {
|
||||||
|
// Populate credential structs with the
|
||||||
|
// prepared username/password values
|
||||||
|
for _, cred := range creds {
|
||||||
|
if cred.Type == libvirt.CRED_AUTHNAME {
|
||||||
|
cred.Result = obj.Auth.Username
|
||||||
|
cred.ResultLen = len(cred.Result)
|
||||||
|
} else if cred.Type == libvirt.CRED_PASSPHRASE {
|
||||||
|
cred.Result = obj.Auth.Password
|
||||||
|
cred.ResultLen = len(cred.Result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auth := &libvirt.ConnectAuth{
|
||||||
|
CredType: []libvirt.ConnectCredentialType{
|
||||||
|
libvirt.CRED_AUTHNAME, libvirt.CRED_PASSPHRASE,
|
||||||
|
},
|
||||||
|
Callback: callback,
|
||||||
|
}
|
||||||
|
conn, err = libvirt.NewConnectWithAuth(obj.URI, auth, 0)
|
||||||
}
|
}
|
||||||
if obj.Auth == nil || err != nil {
|
if obj.Auth == nil || err != nil {
|
||||||
conn, err = libvirt.NewVirConnection(obj.URI)
|
conn, err = libvirt.NewConnect(obj.URI)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -139,7 +158,7 @@ func (obj *VirtRes) Watch(processChan chan event.Event) error {
|
|||||||
return fmt.Errorf("Connection to libvirt failed with: %s", err)
|
return fmt.Errorf("Connection to libvirt failed with: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
eventChan := make(chan int) // TODO: do we need to buffer this?
|
eventChan := make(chan libvirt.DomainEventType) // TODO: do we need to buffer this?
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
exitChan := make(chan struct{})
|
exitChan := make(chan struct{})
|
||||||
defer close(exitChan)
|
defer close(exitChan)
|
||||||
@@ -167,25 +186,16 @@ func (obj *VirtRes) Watch(processChan chan event.Event) error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
callback := libvirt.DomainEventCallback(
|
callback := func(c *libvirt.Connect, d *libvirt.Domain, ev *libvirt.DomainEventLifecycle) {
|
||||||
func(c *libvirt.VirConnection, d *libvirt.VirDomain, eventDetails interface{}, f func()) int {
|
domName, _ := d.GetName()
|
||||||
if lifecycleEvent, ok := eventDetails.(libvirt.DomainLifecycleEvent); ok {
|
if domName == obj.GetName() {
|
||||||
domName, _ := d.GetName()
|
eventChan <- ev.Event
|
||||||
if domName == obj.GetName() {
|
}
|
||||||
eventChan <- lifecycleEvent.Event
|
}
|
||||||
}
|
callbackID, err := conn.DomainEventLifecycleRegister(nil, callback)
|
||||||
} else if obj.debug {
|
if err != nil {
|
||||||
log.Printf("%s[%s]: Event details isn't DomainLifecycleEvent", obj.Kind(), obj.GetName())
|
return err
|
||||||
}
|
}
|
||||||
return 0
|
|
||||||
},
|
|
||||||
)
|
|
||||||
callbackID := conn.DomainEventRegister(
|
|
||||||
libvirt.VirDomain{},
|
|
||||||
libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
|
|
||||||
&callback,
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
defer conn.DomainEventDeregister(callbackID)
|
defer conn.DomainEventDeregister(callbackID)
|
||||||
|
|
||||||
// notify engine that we're running
|
// notify engine that we're running
|
||||||
@@ -201,38 +211,38 @@ func (obj *VirtRes) Watch(processChan chan event.Event) error {
|
|||||||
case event := <-eventChan:
|
case event := <-eventChan:
|
||||||
// TODO: shouldn't we do these checks in CheckApply ?
|
// TODO: shouldn't we do these checks in CheckApply ?
|
||||||
switch event {
|
switch event {
|
||||||
case libvirt.VIR_DOMAIN_EVENT_DEFINED:
|
case libvirt.DOMAIN_EVENT_DEFINED:
|
||||||
if obj.Transient {
|
if obj.Transient {
|
||||||
obj.StateOK(false) // dirty
|
obj.StateOK(false) // dirty
|
||||||
send = true
|
send = true
|
||||||
}
|
}
|
||||||
case libvirt.VIR_DOMAIN_EVENT_UNDEFINED:
|
case libvirt.DOMAIN_EVENT_UNDEFINED:
|
||||||
if !obj.Transient {
|
if !obj.Transient {
|
||||||
obj.StateOK(false) // dirty
|
obj.StateOK(false) // dirty
|
||||||
send = true
|
send = true
|
||||||
}
|
}
|
||||||
case libvirt.VIR_DOMAIN_EVENT_STARTED:
|
case libvirt.DOMAIN_EVENT_STARTED:
|
||||||
fallthrough
|
fallthrough
|
||||||
case libvirt.VIR_DOMAIN_EVENT_RESUMED:
|
case libvirt.DOMAIN_EVENT_RESUMED:
|
||||||
if obj.State != "running" {
|
if obj.State != "running" {
|
||||||
obj.StateOK(false) // dirty
|
obj.StateOK(false) // dirty
|
||||||
send = true
|
send = true
|
||||||
}
|
}
|
||||||
case libvirt.VIR_DOMAIN_EVENT_SUSPENDED:
|
case libvirt.DOMAIN_EVENT_SUSPENDED:
|
||||||
if obj.State != "paused" {
|
if obj.State != "paused" {
|
||||||
obj.StateOK(false) // dirty
|
obj.StateOK(false) // dirty
|
||||||
send = true
|
send = true
|
||||||
}
|
}
|
||||||
case libvirt.VIR_DOMAIN_EVENT_STOPPED:
|
case libvirt.DOMAIN_EVENT_STOPPED:
|
||||||
fallthrough
|
fallthrough
|
||||||
case libvirt.VIR_DOMAIN_EVENT_SHUTDOWN:
|
case libvirt.DOMAIN_EVENT_SHUTDOWN:
|
||||||
if obj.State != "shutoff" {
|
if obj.State != "shutoff" {
|
||||||
obj.StateOK(false) // dirty
|
obj.StateOK(false) // dirty
|
||||||
send = true
|
send = true
|
||||||
}
|
}
|
||||||
case libvirt.VIR_DOMAIN_EVENT_PMSUSPENDED:
|
case libvirt.DOMAIN_EVENT_PMSUSPENDED:
|
||||||
fallthrough
|
fallthrough
|
||||||
case libvirt.VIR_DOMAIN_EVENT_CRASHED:
|
case libvirt.DOMAIN_EVENT_CRASHED:
|
||||||
obj.StateOK(false) // dirty
|
obj.StateOK(false) // dirty
|
||||||
send = true
|
send = true
|
||||||
}
|
}
|
||||||
@@ -281,7 +291,7 @@ func (obj *VirtRes) attrCheckApply(apply bool) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check memory
|
// check memory
|
||||||
if domInfo.GetMemory() != obj.Memory {
|
if domInfo.Memory != obj.Memory {
|
||||||
checkOK = false
|
checkOK = false
|
||||||
if !apply {
|
if !apply {
|
||||||
return false, nil
|
return false, nil
|
||||||
@@ -293,7 +303,7 @@ func (obj *VirtRes) attrCheckApply(apply bool) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check cpus
|
// check cpus
|
||||||
if domInfo.GetNrVirtCpu() != obj.CPUs {
|
if domInfo.NrVirtCpu != obj.CPUs {
|
||||||
checkOK = false
|
checkOK = false
|
||||||
if !apply {
|
if !apply {
|
||||||
return false, nil
|
return false, nil
|
||||||
@@ -309,21 +319,21 @@ func (obj *VirtRes) attrCheckApply(apply bool) (bool, error) {
|
|||||||
|
|
||||||
// domainCreate creates a transient or persistent domain in the correct state. It
|
// domainCreate creates a transient or persistent domain in the correct state. It
|
||||||
// doesn't check the state before hand, as it is a simple helper function.
|
// doesn't check the state before hand, as it is a simple helper function.
|
||||||
func (obj *VirtRes) domainCreate() (libvirt.VirDomain, bool, error) {
|
func (obj *VirtRes) domainCreate() (*libvirt.Domain, bool, error) {
|
||||||
|
|
||||||
if obj.Transient {
|
if obj.Transient {
|
||||||
var flag uint32
|
var flag libvirt.DomainCreateFlags
|
||||||
var state string
|
var state string
|
||||||
switch obj.State {
|
switch obj.State {
|
||||||
case "running":
|
case "running":
|
||||||
flag = libvirt.VIR_DOMAIN_NONE
|
flag = libvirt.DOMAIN_NONE
|
||||||
state = "started"
|
state = "started"
|
||||||
case "paused":
|
case "paused":
|
||||||
flag = libvirt.VIR_DOMAIN_START_PAUSED
|
flag = libvirt.DOMAIN_START_PAUSED
|
||||||
state = "paused"
|
state = "paused"
|
||||||
case "shutoff":
|
case "shutoff":
|
||||||
// a transient, shutoff machine, means machine is absent
|
// a transient, shutoff machine, means machine is absent
|
||||||
return libvirt.VirDomain{}, true, nil // returned dom is invalid
|
return nil, true, nil // returned dom is invalid
|
||||||
}
|
}
|
||||||
dom, err := obj.conn.DomainCreateXML(obj.getDomainXML(), flag)
|
dom, err := obj.conn.DomainCreateXML(obj.getDomainXML(), flag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -347,7 +357,7 @@ func (obj *VirtRes) domainCreate() (libvirt.VirDomain, bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if obj.State == "paused" {
|
if obj.State == "paused" {
|
||||||
if err := dom.CreateWithFlags(libvirt.VIR_DOMAIN_START_PAUSED); err != nil {
|
if err := dom.CreateWithFlags(libvirt.DOMAIN_START_PAUSED); err != nil {
|
||||||
return dom, false, err
|
return dom, false, err
|
||||||
}
|
}
|
||||||
log.Printf("%s[%s]: Domain created paused", obj.Kind(), obj.GetName())
|
log.Printf("%s[%s]: Domain created paused", obj.Kind(), obj.GetName())
|
||||||
@@ -370,7 +380,7 @@ func (obj *VirtRes) CheckApply(apply bool) (bool, error) {
|
|||||||
dom, err := obj.conn.LookupDomainByName(obj.GetName())
|
dom, err := obj.conn.LookupDomainByName(obj.GetName())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// pass
|
// pass
|
||||||
} else if virErr, ok := err.(libvirt.VirError); ok && virErr.Code == libvirt.VIR_ERR_NO_DOMAIN {
|
} else if virErr, ok := err.(libvirt.Error); ok && virErr.Code == libvirt.ERR_NO_DOMAIN {
|
||||||
// domain not found
|
// domain not found
|
||||||
if obj.absent {
|
if obj.absent {
|
||||||
return true, nil
|
return true, nil
|
||||||
@@ -421,7 +431,7 @@ func (obj *VirtRes) CheckApply(apply bool) (bool, error) {
|
|||||||
}
|
}
|
||||||
log.Printf("%s[%s]: Domain undefined", obj.Kind(), obj.GetName())
|
log.Printf("%s[%s]: Domain undefined", obj.Kind(), obj.GetName())
|
||||||
} else {
|
} else {
|
||||||
domXML, err := dom.GetXMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)
|
domXML, err := dom.GetXMLDesc(libvirt.DOMAIN_XML_INACTIVE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errwrap.Wrapf(err, "domain.GetXMLDesc failed")
|
return false, errwrap.Wrapf(err, "domain.GetXMLDesc failed")
|
||||||
}
|
}
|
||||||
@@ -434,13 +444,12 @@ func (obj *VirtRes) CheckApply(apply bool) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for valid state
|
// check for valid state
|
||||||
domState := domInfo.GetState()
|
|
||||||
switch obj.State {
|
switch obj.State {
|
||||||
case "running":
|
case "running":
|
||||||
if domState == libvirt.VIR_DOMAIN_RUNNING {
|
if domInfo.State == libvirt.DOMAIN_RUNNING {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if domState == libvirt.VIR_DOMAIN_BLOCKED {
|
if domInfo.State == libvirt.DOMAIN_BLOCKED {
|
||||||
// TODO: what should happen?
|
// TODO: what should happen?
|
||||||
return false, fmt.Errorf("Domain %s is blocked!", obj.GetName())
|
return false, fmt.Errorf("Domain %s is blocked!", obj.GetName())
|
||||||
}
|
}
|
||||||
@@ -462,7 +471,7 @@ func (obj *VirtRes) CheckApply(apply bool) (bool, error) {
|
|||||||
log.Printf("%s[%s]: Domain created", obj.Kind(), obj.GetName())
|
log.Printf("%s[%s]: Domain created", obj.Kind(), obj.GetName())
|
||||||
|
|
||||||
case "paused":
|
case "paused":
|
||||||
if domState == libvirt.VIR_DOMAIN_PAUSED {
|
if domInfo.State == libvirt.DOMAIN_PAUSED {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !apply {
|
if !apply {
|
||||||
@@ -476,14 +485,14 @@ func (obj *VirtRes) CheckApply(apply bool) (bool, error) {
|
|||||||
log.Printf("%s[%s]: Domain paused", obj.Kind(), obj.GetName())
|
log.Printf("%s[%s]: Domain paused", obj.Kind(), obj.GetName())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err := dom.CreateWithFlags(libvirt.VIR_DOMAIN_START_PAUSED); err != nil {
|
if err := dom.CreateWithFlags(libvirt.DOMAIN_START_PAUSED); err != nil {
|
||||||
return false, errwrap.Wrapf(err, "domain.CreateWithFlags failed")
|
return false, errwrap.Wrapf(err, "domain.CreateWithFlags failed")
|
||||||
}
|
}
|
||||||
checkOK = false
|
checkOK = false
|
||||||
log.Printf("%s[%s]: Domain created paused", obj.Kind(), obj.GetName())
|
log.Printf("%s[%s]: Domain created paused", obj.Kind(), obj.GetName())
|
||||||
|
|
||||||
case "shutoff":
|
case "shutoff":
|
||||||
if domState == libvirt.VIR_DOMAIN_SHUTOFF || domState == libvirt.VIR_DOMAIN_SHUTDOWN {
|
if domInfo.State == libvirt.DOMAIN_SHUTOFF || domInfo.State == libvirt.DOMAIN_SHUTDOWN {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !apply {
|
if !apply {
|
||||||
|
|||||||
Reference in New Issue
Block a user