Skip to content

Commit

Permalink
qemu/qmp: Implement function to hot plug PCI devices
Browse files Browse the repository at this point in the history
ExecutePCIDeviceAdd is a function that can be used to hot plug
devices directly on pci(e).0 or pci(e) bridges. ExecutePCIDeviceAdd
is PCI specific because unlike ExecuteDeviceAdd, it includes an
extra parameter to specify the device address on its parent bus.

Signed-off-by: Julio Montes <julio.montes@intel.com>
  • Loading branch information
Julio Montes committed Oct 24, 2017
1 parent 83485dc commit 14316ce
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
16 changes: 16 additions & 0 deletions qmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,3 +675,19 @@ func (q *QMP) ExecuteDeviceDel(ctx context.Context, devID string) error {
}
return q.executeCommand(ctx, "device_del", args, filter)
}

// ExecutePCIDeviceAdd is the PCI version of ExecuteDeviceAdd. This function can be used
// to hot plug PCI devices on PCI(E) bridges, unlike ExecuteDeviceAdd this function receive the
// device address on its parent bus. bus is optional.
func (q *QMP) ExecutePCIDeviceAdd(ctx context.Context, blockdevID, devID, driver, addr, bus string) error {
args := map[string]interface{}{
"id": devID,
"driver": driver,
"drive": blockdevID,
"addr": addr,
}
if bus != "" {
args["bus"] = bus
}
return q.executeCommand(ctx, "device_add", args, nil)
}
25 changes: 25 additions & 0 deletions qmp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -785,3 +785,28 @@ func TestQMPLostLoop(t *testing.T) {
t.Error("Expected executeQMPCapabilities to fail")
}
}

// Checks that PCI devices are correctly added using device_add.
//
// We start a QMPLoop, send the device_add command and stop the loop.
//
// The device_add command should be correctly sent and the QMP loop should
// exit gracefully.
func TestQMPPCIDeviceAdd(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)
blockdevID := fmt.Sprintf("drive_%s", testutil.VolumeUUID)
devID := fmt.Sprintf("device_%s", testutil.VolumeUUID)
err := q.ExecutePCIDeviceAdd(context.Background(), blockdevID, devID,
"virtio-blk-pci", "0x1", "")
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
q.Shutdown()
<-disconnectedCh
}

0 comments on commit 14316ce

Please sign in to comment.