diff --git a/AUTHORS b/AUTHORS index fd8ef5d..606522f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -14,3 +14,4 @@ Ricky Medina Charlie Drage Michael Koppmann Simarpreet Singh +Alexander Polyakov diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 21fdfab..9499451 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -45,6 +45,7 @@ const ( ProcStoragePoolRefresh = 83 ProcStoragePoolLookupByName = 84 ProcConnectGetLibVersion = 157 + ProcDomainCreateWithFlags = 196 ProcDomainMigrateSetMaxSpeed = 207 ProcDomainGetState = 212 ProcDomainUndefineFlags = 231 diff --git a/libvirt.go b/libvirt.go index 1c64840..d2609fa 100644 --- a/libvirt.go +++ b/libvirt.go @@ -260,6 +260,26 @@ const ( StoragePoolsFlagZFS ) +// DomainCreateFlags specify options for starting domains +type DomainCreateFlags uint32 + +const ( + // DomainCreateFlagPaused creates paused domain. + DomainCreateFlagPaused = 1 << iota + + // DomainCreateFlagAutoDestroy destoy domain after libvirt connection closed. + DomainCreateFlagAutoDestroy + + // DomainCreateFlagBypassCache avoid file system cache pollution. + DomainCreateFlagBypassCache + + // DomainCreateFlagStartForceBoot boot, discarding any managed save + DomainCreateFlagStartForceBoot + + // DomainCreateFlagStartValidate validate the XML document against schema + DomainCreateFlagStartValidate +) + // 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) @@ -343,6 +363,35 @@ func (l *Libvirt) Domains() ([]Domain, error) { return result.Domains, nil } +// DomainCreateWithFlags starts specified domain with flags +func (l *Libvirt) DomainCreateWithFlags(dom string, flags DomainCreateFlags) error { + d, err := l.lookup(dom) + if err != nil { + return err + } + req := struct { + Domain Domain + Flags DomainCreateFlags + } { + Domain: *d, + Flags: flags, + } + + buf, err := encode(&req) + if err != nil { + return err + } + resp, err := l.request(constants.ProcDomainCreateWithFlags, constants.ProgramRemote, &buf) + if err != nil { + return err + } + r := <-resp + if r.Status != StatusOK { + return decodeError(r.Payload) + } + return nil +} + // DomainState returns state of the domain managed by libvirt. func (l *Libvirt) DomainState(dom string) (DomainState, error) { d, err := l.lookup(dom) diff --git a/libvirt_test.go b/libvirt_test.go index 6ad9543..c9a9e56 100644 --- a/libvirt_test.go +++ b/libvirt_test.go @@ -370,3 +370,13 @@ func TestDefineXML(t *testing.T) { t.Fatalf("unexpected define error: %v", err) } } + +func TestDomainCreateWithFlags(t *testing.T) { + conn := libvirttest.New() + l := New(conn) + + var flags DomainCreateFlags + if err := l.DomainCreateWithFlags("test", flags); err != nil { + t.Fatalf("unexpected create error: %v", err) + } +} diff --git a/libvirttest/libvirt.go b/libvirttest/libvirt.go index 779cffe..a410949 100644 --- a/libvirttest/libvirt.go +++ b/libvirttest/libvirt.go @@ -21,6 +21,8 @@ import ( "sync/atomic" "github.com/digitalocean/go-libvirt/internal/constants" + "fmt" + "os" ) var testDomainResponse = []byte{ @@ -341,6 +343,22 @@ var testDefineXML = []byte{ 0xff, 0xff, 0xff, 0xff, // id } +var testCreateWithFlags = []byte{ + 0x00, 0x00, 0x00, 0x38, // length + 0x20, 0x00, 0x80, 0x86, // program + 0x00, 0x00, 0x00, 0x01, // version + 0x00, 0x00, 0x01, 0x5e, // procedure + 0x00, 0x00, 0x00, 0x01, // type + 0x00, 0x00, 0x00, 0x00, // serial + 0x00, 0x00, 0x00, 0x00, // status + 0x00, 0x00, 0x00, 0x04, // dom + 0x74, 0x65, 0x73, 0x74, // name + // uuid + 0xaf, 0xc2, 0xef, 0x71, 0x66, 0xe0, 0x45, 0xa7, + 0xa5, 0xec, 0xd8, 0xba, 0x1e, 0xa8, 0x17, 0x7d, + 0xff, 0xff, 0xff, 0xff, // id +} + // MockLibvirt provides a mock libvirt server for testing. type MockLibvirt struct { net.Conn @@ -418,6 +436,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.ProcDomainCreateWithFlags: + conn.Write(m.reply(testCreateWithFlags)) + default: + fmt.Fprintln(os.Stderr, "unknown procedure", procedure) } }