diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 22e2eea..e19b3b7 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -49,6 +49,7 @@ const ( ProcDomainDestroyFlags = 234 ProcConnectListAllDomains = 273 ProcMigratePerformParams = 305 + ProcDomainDefineXMLFlags = 350 ) // qemu procedure identifiers diff --git a/libvirt.go b/libvirt.go index 795e776..19996ef 100644 --- a/libvirt.go +++ b/libvirt.go @@ -159,6 +159,14 @@ const ( UndefineFlagNVRAM ) +// DomainDefineXMLFlags specifies options available when defining a domain. +type DomainDefineXMLFlags uint32 + +const ( + // DefineValidate validates the XML document against schema + DefineValidate DomainDefineXMLFlags = 1 +) + // DestroyFlags specifies options available when destroying a domain. type DestroyFlags uint32 @@ -641,6 +649,34 @@ func (l *Libvirt) XML(dom string, flags DomainXMLFlags) ([]byte, error) { return []byte(s), nil } +// DefineXML defines a domain, but does not start it. +func (l *Libvirt) DefineXML(x []byte, flags DomainDefineXMLFlags) error { + payload := struct { + Domain []byte + Flags DomainDefineXMLFlags + }{ + Domain: x, + Flags: flags, + } + + buf, err := encode(&payload) + if err != nil { + return err + } + + resp, err := l.request(constants.ProcDomainDefineXMLFlags, 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 871bbab..d734308 100644 --- a/libvirt_test.go +++ b/libvirt_test.go @@ -254,3 +254,14 @@ func TestVersion(t *testing.T) { t.Errorf("expected version %q, got %q", expected, version) } } + +func TestDefineXML(t *testing.T) { + conn := libvirttest.New() + l := New(conn) + + var flags DomainDefineXMLFlags + var buf []byte + if err := l.DefineXML(buf, flags); err != nil { + t.Fatalf("unexpected define error: %v", err) + } +} diff --git a/libvirttest/libvirt.go b/libvirttest/libvirt.go index 1528960..192a726 100644 --- a/libvirttest/libvirt.go +++ b/libvirttest/libvirt.go @@ -248,6 +248,22 @@ var testVersionReply = []byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x4d, 0xfc, // version (1003004) } +var testDefineXML = []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 @@ -315,6 +331,8 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) { conn.Write(m.reply(testUndefineReply)) case constants.ProcDomainDestroyFlags: conn.Write(m.reply(testDestroyReply)) + case constants.ProcDomainDefineXMLFlags: + conn.Write(m.reply(testDefineXML)) } }