Add Shutdown() method (#36)

* Add Shutdown() method
This commit is contained in:
Alexander Polakov 2017-05-04 18:39:45 +03:00 committed by Ben LeMasurier
parent d41d9eb855
commit 208ef2aff1
4 changed files with 76 additions and 0 deletions

View File

@ -50,6 +50,7 @@ const (
ProcDomainGetState = 212
ProcDomainUndefineFlags = 231
ProcDomainDestroyFlags = 234
ProcDomainShutdownFlags = 258
ProcConnectListAllDomains = 273
ProcConnectListAllStoragePools = 281
ProcConnectListAllSecrets = 287

View File

@ -191,6 +191,25 @@ const (
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
@ -967,6 +986,40 @@ func (l *Libvirt) Version() (string, error) {
return versionString, nil
}
// 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.
func (l *Libvirt) Shutdown(dom string, flags ShutdownFlags) error {
d, err := l.lookup(dom)
if err != nil {
return err
}
payload := struct {
Domain Domain
Flags ShutdownFlags
}{
Domain: *d,
Flags: flags,
}
buf, err := encode(&payload)
if err != nil {
return err
}
resp, err := l.request(constants.ProcDomainShutdownFlags, 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

@ -380,3 +380,13 @@ func TestDomainCreateWithFlags(t *testing.T) {
t.Fatalf("unexpected create error: %v", err)
}
}
func TestShutdown(t *testing.T) {
conn := libvirttest.New()
l := New(conn)
var flags ShutdownFlags
if err := l.Shutdown("test", flags); err != nil {
t.Fatalf("unexpected shutdown error: %v", err)
}
}

View File

@ -359,6 +359,16 @@ var testCreateWithFlags = []byte{
0xff, 0xff, 0xff, 0xff, // id
}
var testShutdownReply = []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
@ -438,6 +448,8 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) {
conn.Write(m.reply(testDefineXML))
case constants.ProcDomainCreateWithFlags:
conn.Write(m.reply(testCreateWithFlags))
case constants.ProcDomainShutdownFlags:
conn.Write(m.reply(testShutdownReply))
default:
fmt.Fprintln(os.Stderr, "unknown procedure", procedure)
}