From ca46f21f3ffdbd23e8f4468a523d3c1cafa8d142 Mon Sep 17 00:00:00 2001 From: Julio Montes Date: Fri, 3 Aug 2018 08:01:05 -0500 Subject: [PATCH 1/2] qemu/qmp: implement function to hotplug character devices implement function to hotplug character devices using as backend unix sockets, binding a character device with a serial port allows the communnication between processes running in the guest with processes running in the host. Signed-off-by: Julio Montes --- qemu/qmp.go | 23 +++++++++++++++++++++++ qemu/qmp_test.go | 17 +++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/qemu/qmp.go b/qemu/qmp.go index 1e57aaa9e..fccc0f56a 100644 --- a/qemu/qmp.go +++ b/qemu/qmp.go @@ -963,3 +963,26 @@ func (q *QMP) ExecuteGetFD(ctx context.Context, fdname string, fd *os.File) erro _, err := q.executeCommandWithResponse(ctx, "getfd", args, oob, nil) return err } + +// ExecuteCharDevUnixSocketAdd adds a character device using as backend a unix socket, +// id is an identifier for the device, path specifies the local path of the unix socket, +// wait is to block waiting for a client to connect, server specifies that the socket is a listening socket. +func (q *QMP) ExecuteCharDevUnixSocketAdd(ctx context.Context, id, path string, wait, server bool) error { + args := map[string]interface{}{ + "id": id, + "backend": map[string]interface{}{ + "type": "socket", + "data": map[string]interface{}{ + "wait": wait, + "server": server, + "addr": map[string]interface{}{ + "type": "unix", + "data": map[string]interface{}{ + "path": path, + }, + }, + }, + }, + } + return q.executeCommand(ctx, "chardev-add", args, nil) +} diff --git a/qemu/qmp_test.go b/qemu/qmp_test.go index 0ffdf5bc3..2f60db1ab 100644 --- a/qemu/qmp_test.go +++ b/qemu/qmp_test.go @@ -1040,3 +1040,20 @@ func TestExecuteGetFdD(t *testing.T) { q.Shutdown() <-disconnectedCh } + +// Checks chardev-add unix socket +func TestExecuteCharDevUnixSocketAdd(t *testing.T) { + connectedCh := make(chan *QMPVersion) + disconnectedCh := make(chan struct{}) + buf := newQMPTestCommandBuffer(t) + buf.AddCommand("chardev-add", nil, "return", nil) + cfg := QMPConfig{Logger: qmpTestLogger{}} + q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh) + checkVersion(t, connectedCh) + err := q.ExecuteCharDevUnixSocketAdd(context.Background(), "foo", "foo.sock", false, true) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + q.Shutdown() + <-disconnectedCh +} From 80ed88edb120b5f70e748e5864c68e234a365d4a Mon Sep 17 00:00:00 2001 From: Julio Montes Date: Fri, 3 Aug 2018 08:10:44 -0500 Subject: [PATCH 2/2] qemu/qmp: implement function to hotplug serial ports Implement function to hotplug virtio serial ports, the serial ports are visible in the guest at the directory /dev/virtio-ports. Signed-off-by: Julio Montes --- qemu/qmp.go | 14 ++++++++++++++ qemu/qmp_test.go | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/qemu/qmp.go b/qemu/qmp.go index fccc0f56a..40e4781a6 100644 --- a/qemu/qmp.go +++ b/qemu/qmp.go @@ -986,3 +986,17 @@ func (q *QMP) ExecuteCharDevUnixSocketAdd(ctx context.Context, id, path string, } return q.executeCommand(ctx, "chardev-add", args, nil) } + +// ExecuteVirtSerialPortAdd adds a virtserialport. +// id is an identifier for the virtserialport, name is a name for the virtserialport and +// it will be visible in the VM, chardev is the character device id previously added. +func (q *QMP) ExecuteVirtSerialPortAdd(ctx context.Context, id, name, chardev string) error { + args := map[string]interface{}{ + "driver": VirtioSerialPort, + "id": id, + "name": name, + "chardev": chardev, + } + + return q.executeCommand(ctx, "device_add", args, nil) +} diff --git a/qemu/qmp_test.go b/qemu/qmp_test.go index 2f60db1ab..c6c4ed4f0 100644 --- a/qemu/qmp_test.go +++ b/qemu/qmp_test.go @@ -1057,3 +1057,20 @@ func TestExecuteCharDevUnixSocketAdd(t *testing.T) { q.Shutdown() <-disconnectedCh } + +// Checks virtio serial port hotplug +func TestExecuteVirtSerialPortAdd(t *testing.T) { + connectedCh := make(chan *QMPVersion) + disconnectedCh := make(chan struct{}) + buf := newQMPTestCommandBuffer(t) + buf.AddCommand("device_add", nil, "return", nil) + cfg := QMPConfig{Logger: qmpTestLogger{}} + q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh) + checkVersion(t, connectedCh) + err := q.ExecuteVirtSerialPortAdd(context.Background(), "foo", "foo.channel", "foo") + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + q.Shutdown() + <-disconnectedCh +}