mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-29 12:14:48 +00:00
qemu/qmp: implement getfd
`getfd` receives a file descriptor via SCM rights and assign it a name, this command is useful to send file descriptors from the host, and then hot plug devices that needs file descriptors like vhost-vsock-pci devices. Signed-off-by: Julio Montes <julio.montes@intel.com>
This commit is contained in:
parent
84b212f1b8
commit
03f1a1c3a8
28
qemu/qmp.go
28
qemu/qmp.go
@ -24,6 +24,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"context"
|
||||
@ -118,6 +120,7 @@ type qmpCommand struct {
|
||||
args map[string]interface{}
|
||||
filter *qmpEventFilter
|
||||
resultReceived bool
|
||||
oob []byte
|
||||
}
|
||||
|
||||
// QMP is a structure that contains the internal state used by startQMPLoop and
|
||||
@ -302,7 +305,12 @@ func (q *QMP) writeNextQMPCommand(cmdQueue *list.List) {
|
||||
}
|
||||
q.cfg.Logger.Infof("%s", string(encodedCmd))
|
||||
encodedCmd = append(encodedCmd, '\n')
|
||||
_, err = q.conn.Write(encodedCmd)
|
||||
if unixConn, ok := q.conn.(*net.UnixConn); ok && len(cmd.oob) > 0 {
|
||||
_, _, err = unixConn.WriteMsgUnix(encodedCmd, cmd.oob, nil)
|
||||
} else {
|
||||
_, err = q.conn.Write(encodedCmd)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
cmd.res <- qmpResult{
|
||||
err: fmt.Errorf("Unable to write command to qmp socket %v", err),
|
||||
@ -485,7 +493,7 @@ func startQMPLoop(conn io.ReadWriteCloser, cfg QMPConfig,
|
||||
}
|
||||
|
||||
func (q *QMP) executeCommandWithResponse(ctx context.Context, name string, args map[string]interface{},
|
||||
filter *qmpEventFilter) (interface{}, error) {
|
||||
oob []byte, filter *qmpEventFilter) (interface{}, error) {
|
||||
var err error
|
||||
var response interface{}
|
||||
resCh := make(chan qmpResult)
|
||||
@ -498,6 +506,7 @@ func (q *QMP) executeCommandWithResponse(ctx context.Context, name string, args
|
||||
name: name,
|
||||
args: args,
|
||||
filter: filter,
|
||||
oob: oob,
|
||||
}:
|
||||
}
|
||||
|
||||
@ -519,7 +528,7 @@ func (q *QMP) executeCommandWithResponse(ctx context.Context, name string, args
|
||||
func (q *QMP) executeCommand(ctx context.Context, name string, args map[string]interface{},
|
||||
filter *qmpEventFilter) error {
|
||||
|
||||
_, err := q.executeCommandWithResponse(ctx, name, args, filter)
|
||||
_, err := q.executeCommandWithResponse(ctx, name, args, nil, filter)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -809,7 +818,7 @@ func (q *QMP) ExecuteCPUDeviceAdd(ctx context.Context, driver, cpuID, socketID,
|
||||
|
||||
// ExecuteQueryHotpluggableCPUs returns a slice with the list of hotpluggable CPUs
|
||||
func (q *QMP) ExecuteQueryHotpluggableCPUs(ctx context.Context) ([]HotpluggableCPU, error) {
|
||||
response, err := q.executeCommandWithResponse(ctx, "query-hotpluggable-cpus", nil, nil)
|
||||
response, err := q.executeCommandWithResponse(ctx, "query-hotpluggable-cpus", nil, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -897,3 +906,14 @@ func (q *QMP) ExecutePCIVSockAdd(ctx context.Context, id, guestCID, vhostfd stri
|
||||
|
||||
return q.executeCommand(ctx, "device_add", args, nil)
|
||||
}
|
||||
|
||||
// ExecuteGetFD sends a file descriptor via SCM rights and assigns it a name
|
||||
func (q *QMP) ExecuteGetFD(ctx context.Context, fdname string, fd *os.File) error {
|
||||
oob := syscall.UnixRights(int(fd.Fd()))
|
||||
args := map[string]interface{}{
|
||||
"fdname": fdname,
|
||||
}
|
||||
|
||||
_, err := q.executeCommandWithResponse(ctx, "getfd", args, oob, nil)
|
||||
return err
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
@ -962,3 +963,20 @@ func TestExecutePCIVSockAdd(t *testing.T) {
|
||||
q.Shutdown()
|
||||
<-disconnectedCh
|
||||
}
|
||||
|
||||
// Checks getfd
|
||||
func TestExecuteGetFdD(t *testing.T) {
|
||||
connectedCh := make(chan *QMPVersion)
|
||||
disconnectedCh := make(chan struct{})
|
||||
buf := newQMPTestCommandBuffer(t)
|
||||
buf.AddCommand("getfd", nil, "return", nil)
|
||||
cfg := QMPConfig{Logger: qmpTestLogger{}}
|
||||
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
|
||||
checkVersion(t, connectedCh)
|
||||
err := q.ExecuteGetFD(context.Background(), "foo", os.NewFile(0, "foo"))
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error %v", err)
|
||||
}
|
||||
q.Shutdown()
|
||||
<-disconnectedCh
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user