diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 9db50c1..bd71bda 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -26,12 +26,13 @@ const ( // libvirt procedure identifiers const ( - ProcConnectOpen = 1 - ProcConnectClose = 2 - ProcDomainLookupByName = 23 - ProcAuthList = 66 - ProcConnectGetLibVersion = 157 - ProcConnectListAllDomains = 273 + ProcConnectOpen = 1 + ProcConnectClose = 2 + ProcDomainLookupByName = 23 + ProcDomainMigrateSetMaxSpeed = 207 + ProcAuthList = 66 + ProcConnectGetLibVersion = 157 + ProcConnectListAllDomains = 273 ) // qemu procedure identifiers diff --git a/libvirt.go b/libvirt.go index 42d0d74..c00bf0b 100644 --- a/libvirt.go +++ b/libvirt.go @@ -204,6 +204,44 @@ func (l *Libvirt) Events(dom string) (<-chan DomainEvent, error) { return c, nil } +// MigrateSetMaxSpeed set the maximum migration bandwidth (in MiB/s) for a +// domain which is being migrated to another host. Specifying a negative value +// results in an essentially unlimited value being provided to the hypervisor. +func (l *Libvirt) MigrateSetMaxSpeed(dom string, speed int64) error { + d, err := l.lookup(dom) + if err != nil { + return err + } + + payload := struct { + Padding [4]byte + Domain Domain + Bandwidth int64 + Flags uint32 + }{ + Padding: [4]byte{0x0, 0x0, 0x1, 0x0}, + Domain: *d, + Bandwidth: speed, + } + + buf, err := encode(&payload) + if err != nil { + return err + } + + resp, err := l.request(constants.ProcDomainMigrateSetMaxSpeed, constants.ProgramRemote, &buf) + if err != nil { + return err + } + + r := <-resp + if r.Status != StatusOK { + return decodeError(r.Payload) + } + + return nil +} + // Run executes the given QAPI command against a domain's QEMU instance. // For a list of available QAPI commands, see: // http://git.qemu.org/?p=qemu.git;a=blob;f=qapi-schema.json;hb=HEAD diff --git a/libvirt_test.go b/libvirt_test.go index c665433..74ecb21 100644 --- a/libvirt_test.go +++ b/libvirt_test.go @@ -43,6 +43,15 @@ func TestDisconnect(t *testing.T) { } } +func TestMigrateSetMaxSpeed(t *testing.T) { + conn := libvirttest.New() + l := New(conn) + + if err := l.MigrateSetMaxSpeed("test", 100); err != nil { + t.Fatalf("unexpected error setting max speed for migrate: %v", err) + } +} + func TestDomains(t *testing.T) { conn := libvirttest.New() l := New(conn) diff --git a/libvirttest/libvirt.go b/libvirttest/libvirt.go index 2a3ccdd..4eee906 100644 --- a/libvirttest/libvirt.go +++ b/libvirttest/libvirt.go @@ -146,6 +146,16 @@ var testRunReplyFail = []byte{ 0x6e, 0x64, 0x22, 0x7d, 0x7d, 0x00, 0x00, 0x00, } +var testSetSpeedReply = []byte{ + 0x00, 0x00, 0x00, 0x1c, // length + 0x20, 0x00, 0x80, 0x86, // program + 0x00, 0x00, 0x00, 0x01, // version + 0x00, 0x00, 0x00, 0xcf, // procedure + 0x00, 0x00, 0x00, 0x01, // type + 0x00, 0x00, 0x00, 0x00, // serial + 0x00, 0x00, 0x00, 0x00, // status +} + var testDomainsReply = []byte{ 0x00, 0x00, 0x00, 0x6c, // length 0x20, 0x00, 0x80, 0x86, // program @@ -250,6 +260,8 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) { conn.Write(m.reply(testDomainResponse)) case constants.ProcConnectListAllDomains: conn.Write(m.reply(testDomainsReply)) + case constants.ProcDomainMigrateSetMaxSpeed: + conn.Write(m.reply(testSetSpeedReply)) } }