Add Reboot and Reset methods (#37)
This commit is contained in:
parent
208ef2aff1
commit
c09ce7b21d
@ -41,6 +41,7 @@ const (
|
|||||||
ProcConnectGetCapabilties = 7
|
ProcConnectGetCapabilties = 7
|
||||||
ProcDomainGetXMLDesc = 14
|
ProcDomainGetXMLDesc = 14
|
||||||
ProcDomainLookupByName = 23
|
ProcDomainLookupByName = 23
|
||||||
|
ProcDomainReboot = 27
|
||||||
ProcAuthList = 66
|
ProcAuthList = 66
|
||||||
ProcStoragePoolRefresh = 83
|
ProcStoragePoolRefresh = 83
|
||||||
ProcStoragePoolLookupByName = 84
|
ProcStoragePoolLookupByName = 84
|
||||||
@ -50,6 +51,7 @@ const (
|
|||||||
ProcDomainGetState = 212
|
ProcDomainGetState = 212
|
||||||
ProcDomainUndefineFlags = 231
|
ProcDomainUndefineFlags = 231
|
||||||
ProcDomainDestroyFlags = 234
|
ProcDomainDestroyFlags = 234
|
||||||
|
ProcDomainReset = 245
|
||||||
ProcDomainShutdownFlags = 258
|
ProcDomainShutdownFlags = 258
|
||||||
ProcConnectListAllDomains = 273
|
ProcConnectListAllDomains = 273
|
||||||
ProcConnectListAllStoragePools = 281
|
ProcConnectListAllStoragePools = 281
|
||||||
|
86
libvirt.go
86
libvirt.go
@ -299,6 +299,25 @@ const (
|
|||||||
DomainCreateFlagStartValidate
|
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
|
||||||
|
)
|
||||||
|
|
||||||
// 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) {
|
||||||
resp, err := l.request(constants.ProcConnectGetCapabilties, constants.ProgramRemote, nil)
|
resp, err := l.request(constants.ProcConnectGetCapabilties, constants.ProgramRemote, nil)
|
||||||
@ -1020,6 +1039,73 @@ func (l *Libvirt) Shutdown(dom string, flags ShutdownFlags) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
func (l *Libvirt) Reboot(dom string, flags RebootFlags) error {
|
||||||
|
d, err := l.lookup(dom)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := struct {
|
||||||
|
Domain Domain
|
||||||
|
Flags RebootFlags
|
||||||
|
}{
|
||||||
|
Domain: *d,
|
||||||
|
Flags: flags,
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := encode(&payload)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := l.request(constants.ProcDomainReboot, constants.ProgramRemote, &buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := <-resp
|
||||||
|
if r.Status != StatusOK {
|
||||||
|
return decodeError(r.Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset resets domain immediately without any guest OS shutdown
|
||||||
|
func (l *Libvirt) Reset(dom string) error {
|
||||||
|
d, err := l.lookup(dom)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := struct {
|
||||||
|
Domain Domain
|
||||||
|
Flags uint32
|
||||||
|
}{
|
||||||
|
Domain: *d,
|
||||||
|
Flags: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := encode(&payload)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := l.request(constants.ProcDomainReset, constants.ProgramRemote, &buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := <-resp
|
||||||
|
if r.Status != StatusOK {
|
||||||
|
return decodeError(r.Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// lookup returns a domain as seen by libvirt.
|
// lookup returns a domain as seen by libvirt.
|
||||||
func (l *Libvirt) lookup(name string) (*Domain, error) {
|
func (l *Libvirt) lookup(name string) (*Domain, error) {
|
||||||
payload := struct {
|
payload := struct {
|
||||||
|
@ -390,3 +390,22 @@ func TestShutdown(t *testing.T) {
|
|||||||
t.Fatalf("unexpected shutdown error: %v", err)
|
t.Fatalf("unexpected shutdown error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReboot(t *testing.T) {
|
||||||
|
conn := libvirttest.New()
|
||||||
|
l := New(conn)
|
||||||
|
|
||||||
|
var flags RebootFlags
|
||||||
|
if err := l.Reboot("test", flags); err != nil {
|
||||||
|
t.Fatalf("unexpected reboot error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReset(t *testing.T) {
|
||||||
|
conn := libvirttest.New()
|
||||||
|
l := New(conn)
|
||||||
|
|
||||||
|
if err := l.Reset("test"); err != nil {
|
||||||
|
t.Fatalf("unexpected reset error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -369,6 +369,16 @@ var testShutdownReply = []byte{
|
|||||||
0x00, 0x00, 0x00, 0x00, // status
|
0x00, 0x00, 0x00, 0x00, // status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var testRebootReply = []byte{
|
||||||
|
0x00, 0x00, 0x00, 0x1c, // length
|
||||||
|
0x20, 0x00, 0x80, 0x86, // program
|
||||||
|
0x00, 0x00, 0x00, 0x01, // version
|
||||||
|
0x00, 0x00, 0x00, 0xea, // procedure
|
||||||
|
0x00, 0x00, 0x00, 0x01, // type
|
||||||
|
0x00, 0x00, 0x00, 0x00, // serial
|
||||||
|
0x00, 0x00, 0x00, 0x00, // status
|
||||||
|
}
|
||||||
|
|
||||||
// MockLibvirt provides a mock libvirt server for testing.
|
// MockLibvirt provides a mock libvirt server for testing.
|
||||||
type MockLibvirt struct {
|
type MockLibvirt struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
@ -446,6 +456,10 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) {
|
|||||||
conn.Write(m.reply(testDestroyReply))
|
conn.Write(m.reply(testDestroyReply))
|
||||||
case constants.ProcDomainDefineXMLFlags:
|
case constants.ProcDomainDefineXMLFlags:
|
||||||
conn.Write(m.reply(testDefineXML))
|
conn.Write(m.reply(testDefineXML))
|
||||||
|
case constants.ProcDomainReboot:
|
||||||
|
conn.Write(m.reply(testRebootReply))
|
||||||
|
case constants.ProcDomainReset:
|
||||||
|
conn.Write(m.reply(testRebootReply))
|
||||||
case constants.ProcDomainCreateWithFlags:
|
case constants.ProcDomainCreateWithFlags:
|
||||||
conn.Write(m.reply(testCreateWithFlags))
|
conn.Write(m.reply(testCreateWithFlags))
|
||||||
case constants.ProcDomainShutdownFlags:
|
case constants.ProcDomainShutdownFlags:
|
||||||
|
Loading…
Reference in New Issue
Block a user