Add Reboot and Reset methods (#37)

This commit is contained in:
Alexander Polakov 2017-05-04 19:30:22 +03:00 committed by Ben LeMasurier
parent 208ef2aff1
commit c09ce7b21d
4 changed files with 121 additions and 0 deletions

View File

@ -41,6 +41,7 @@ const (
ProcConnectGetCapabilties = 7
ProcDomainGetXMLDesc = 14
ProcDomainLookupByName = 23
ProcDomainReboot = 27
ProcAuthList = 66
ProcStoragePoolRefresh = 83
ProcStoragePoolLookupByName = 84
@ -50,6 +51,7 @@ const (
ProcDomainGetState = 212
ProcDomainUndefineFlags = 231
ProcDomainDestroyFlags = 234
ProcDomainReset = 245
ProcDomainShutdownFlags = 258
ProcConnectListAllDomains = 273
ProcConnectListAllStoragePools = 281

View File

@ -299,6 +299,25 @@ const (
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.
func (l *Libvirt) Capabilities() ([]byte, error) {
resp, err := l.request(constants.ProcConnectGetCapabilties, constants.ProgramRemote, nil)
@ -1020,6 +1039,73 @@ func (l *Libvirt) Shutdown(dom string, flags ShutdownFlags) error {
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.
func (l *Libvirt) lookup(name string) (*Domain, error) {
payload := struct {

View File

@ -390,3 +390,22 @@ func TestShutdown(t *testing.T) {
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)
}
}

View File

@ -369,6 +369,16 @@ var testShutdownReply = []byte{
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.
type MockLibvirt struct {
net.Conn
@ -446,6 +456,10 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) {
conn.Write(m.reply(testDestroyReply))
case constants.ProcDomainDefineXMLFlags:
conn.Write(m.reply(testDefineXML))
case constants.ProcDomainReboot:
conn.Write(m.reply(testRebootReply))
case constants.ProcDomainReset:
conn.Write(m.reply(testRebootReply))
case constants.ProcDomainCreateWithFlags:
conn.Write(m.reply(testCreateWithFlags))
case constants.ProcDomainShutdownFlags: