diff --git a/AUTHORS b/AUTHORS index 1f0d4f6..fd8ef5d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,12 +4,13 @@ DigitalOcean, Inc Original Authors ---------------- -Ben LeMasurier -Matt Layher +Ben LeMasurier +Matt Layher Contributors ------------ -Justin Kim -Ricky Medina -Charlie Drage +Justin Kim +Ricky Medina +Charlie Drage Michael Koppmann +Simarpreet Singh diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 42d5183..13bd18b 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -43,6 +43,7 @@ const ( ProcConnectGetLibVersion = 157 ProcDomainMigrateSetMaxSpeed = 207 ProcDomainUndefineFlags = 231 + ProcDomainDestroyFlags = 234 ProcConnectListAllDomains = 273 ProcMigratePerformParams = 305 ) diff --git a/libvirt.go b/libvirt.go index 24cb5b9..c3833e7 100644 --- a/libvirt.go +++ b/libvirt.go @@ -142,6 +142,17 @@ const ( UndefineFlagNVRAM ) +// 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 +) + // Connect establishes communication with the libvirt server. // The underlying libvirt socket connection must be previously established. func (l *Libvirt) Connect() error { @@ -449,6 +460,42 @@ func (l *Libvirt) Undefine(dom string, flags UndefineFlags) error { return nil } +// Destroy destroys the domain specified by dom, e.g., 'prod-lb-01'. +// The flags argument allows additional options to be specified such as +// allowing a graceful shutdown with SIGTERM than SIGKILL. +// For more information on available flags, see DestroyFlag*. +func (l *Libvirt) Destroy(dom string, flags DestroyFlags) error { + d, err := l.lookup(dom) + if err != nil { + return err + } + + payload := struct { + Domain Domain + Flags DestroyFlags + }{ + Domain: *d, + Flags: flags, + } + + buf, err := encode(&payload) + if err != nil { + return err + } + + resp, err := l.request(constants.ProcDomainDestroyFlags, constants.ProgramRemote, &buf) + if err != nil { + return err + } + + r := <-resp + if r.Status != StatusOK { + return decodeError(r.Payload) + } + + return nil +} + // Version returns the version of the libvirt daemon. func (l *Libvirt) Version() (string, error) { resp, err := l.request(constants.ProcConnectGetLibVersion, constants.ProgramRemote, nil) diff --git a/libvirt_test.go b/libvirt_test.go index 78d9fb5..9cfc241 100644 --- a/libvirt_test.go +++ b/libvirt_test.go @@ -215,6 +215,16 @@ func TestUndefine(t *testing.T) { } } +func TestDestroy(t *testing.T) { + conn := libvirttest.New() + l := New(conn) + + var flags DestroyFlags + if err := l.Destroy("test", flags); err != nil { + t.Fatalf("unexpected destroy error: %v", err) + } +} + func TestVersion(t *testing.T) { conn := libvirttest.New() l := New(conn) diff --git a/libvirttest/libvirt.go b/libvirttest/libvirt.go index a886059..c22aa51 100644 --- a/libvirttest/libvirt.go +++ b/libvirttest/libvirt.go @@ -215,6 +215,16 @@ var testUndefineReply = []byte{ 0x00, 0x00, 0x00, 0x00, // status } +var testDestroyReply = []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 +} + var testVersionReply = []byte{ 0x00, 0x00, 0x00, 0x24, // length 0x20, 0x00, 0x80, 0x86, // program @@ -289,6 +299,8 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) { conn.Write(m.reply(testMigrateReply)) case constants.ProcDomainUndefineFlags: conn.Write(m.reply(testUndefineReply)) + case constants.ProcDomainDestroyFlags: + conn.Write(m.reply(testDestroyReply)) } }