Merge pull request #267 from amshinde/pass-pci-addr

Determine and pass PCI addresses for block devices
This commit is contained in:
Eric Ernst 2018-05-03 16:20:47 -07:00 committed by GitHub
commit 992c895eaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 53 additions and 32 deletions

View File

@ -212,6 +212,17 @@ func (c *Container) setStateHotpluggedDrive(hotplugged bool) error {
return nil return nil
} }
func (c *Container) setContainerRootfsPCIAddr(addr string) error {
c.state.RootfsPCIAddr = addr
err := c.sandbox.storage.storeContainerResource(c.sandbox.id, c.id, stateFileType, c.state)
if err != nil {
return err
}
return nil
}
// GetAnnotations returns container's annotations // GetAnnotations returns container's annotations
func (c *Container) GetAnnotations() map[string]string { func (c *Container) GetAnnotations() map[string]string {
return c.config.Annotations return c.config.Annotations
@ -788,9 +799,14 @@ func (c *Container) hotplugDrive() error {
Index: driveIndex, Index: driveIndex,
} }
if err := c.sandbox.hypervisor.hotplugAddDevice(drive, blockDev); err != nil { if err := c.sandbox.hypervisor.hotplugAddDevice(&drive, blockDev); err != nil {
return err return err
} }
if drive.PCIAddr != "" {
c.setContainerRootfsPCIAddr(drive.PCIAddr)
}
c.setStateHotpluggedDrive(true) c.setStateHotpluggedDrive(true)
if err := c.setStateBlockIndex(driveIndex); err != nil { if err := c.setStateBlockIndex(driveIndex); err != nil {
@ -813,7 +829,7 @@ func (c *Container) removeDrive() (err error) {
c.Logger().Info("unplugging block device") c.Logger().Info("unplugging block device")
devID := makeNameID("drive", c.id) devID := makeNameID("drive", c.id)
drive := Drive{ drive := &Drive{
ID: devID, ID: devID,
} }

View File

@ -334,6 +334,9 @@ type BlockDevice struct {
// Path at which the device appears inside the VM, outside of the container mount namespace // Path at which the device appears inside the VM, outside of the container mount namespace
VirtPath string VirtPath string
// PCI Slot of the block device
PCIAddr string
} }
func newBlockDevice(devInfo DeviceInfo) *BlockDevice { func newBlockDevice(devInfo DeviceInfo) *BlockDevice {
@ -380,7 +383,7 @@ func (device *BlockDevice) attach(h hypervisor, c *Container) (err error) {
deviceLogger().WithField("device", device.DeviceInfo.HostPath).Info("Attaching block device") deviceLogger().WithField("device", device.DeviceInfo.HostPath).Info("Attaching block device")
if err = h.hotplugAddDevice(drive, blockDev); err != nil { if err = h.hotplugAddDevice(&drive, blockDev); err != nil {
return err return err
} }
@ -388,6 +391,7 @@ func (device *BlockDevice) attach(h hypervisor, c *Container) (err error) {
if c.sandbox.config.HypervisorConfig.BlockDeviceDriver == VirtioBlock { if c.sandbox.config.HypervisorConfig.BlockDeviceDriver == VirtioBlock {
device.VirtPath = filepath.Join("/dev", driveName) device.VirtPath = filepath.Join("/dev", driveName)
device.PCIAddr = drive.PCIAddr
} else { } else {
scsiAddr, err := getSCSIAddress(index) scsiAddr, err := getSCSIAddress(index)
if err != nil { if err != nil {
@ -404,7 +408,7 @@ func (device BlockDevice) detach(h hypervisor) error {
if device.DeviceInfo.Hotplugged { if device.DeviceInfo.Hotplugged {
deviceLogger().WithField("device", device.DeviceInfo.HostPath).Info("Unplugging block device") deviceLogger().WithField("device", device.DeviceInfo.HostPath).Info("Unplugging block device")
drive := Drive{ drive := &Drive{
ID: makeNameID("drive", device.DeviceInfo.ID), ID: makeNameID("drive", device.DeviceInfo.ID),
} }

View File

@ -40,7 +40,6 @@ var (
kataGuestSharedDir = "/run/kata-containers/shared/containers/" kataGuestSharedDir = "/run/kata-containers/shared/containers/"
mountGuest9pTag = "kataShared" mountGuest9pTag = "kataShared"
type9pFs = "9p" type9pFs = "9p"
devPath = "/dev"
vsockSocketScheme = "vsock" vsockSocketScheme = "vsock"
kata9pDevType = "9p" kata9pDevType = "9p"
kataBlkDevType = "blk" kataBlkDevType = "blk"
@ -629,7 +628,7 @@ func (k *kataAgent) appendDevices(deviceList []*grpc.Device, devices []Device) [
if d.SCSIAddr == "" { if d.SCSIAddr == "" {
kataDevice.Type = kataBlkDevType kataDevice.Type = kataBlkDevType
kataDevice.VmPath = d.VirtPath kataDevice.Id = d.PCIAddr
} else { } else {
kataDevice.Type = kataSCSIDevType kataDevice.Type = kataSCSIDevType
kataDevice.Id = d.SCSIAddr kataDevice.Id = d.SCSIAddr
@ -692,15 +691,8 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
// If virtio-scsi driver, the agent will be able to find the // If virtio-scsi driver, the agent will be able to find the
// device based on the provided address. // device based on the provided address.
if sandbox.config.HypervisorConfig.BlockDeviceDriver == VirtioBlock { if sandbox.config.HypervisorConfig.BlockDeviceDriver == VirtioBlock {
// driveName is the predicted virtio-block guest name (the vd* in /dev/vd*).
driveName, err := getVirtDriveName(c.state.BlockIndex)
if err != nil {
return nil, err
}
virtPath := filepath.Join(devPath, driveName)
rootfs.Driver = kataBlkDevType rootfs.Driver = kataBlkDevType
rootfs.Source = virtPath rootfs.Source = c.state.RootfsPCIAddr
} else { } else {
scsiAddr, err := getSCSIAddress(c.state.BlockIndex) scsiAddr, err := getSCSIAddress(c.state.BlockIndex)
if err != nil { if err != nil {

View File

@ -25,8 +25,8 @@ import (
var ( var (
testKataProxyURLTempl = "unix://%s/kata-proxy-test.sock" testKataProxyURLTempl = "unix://%s/kata-proxy-test.sock"
testBlockDeviceVirtPath = "testBlockDeviceVirtPath"
testBlockDeviceCtrPath = "testBlockDeviceCtrPath" testBlockDeviceCtrPath = "testBlockDeviceCtrPath"
testPCIAddr = "04/02"
) )
func proxyHandlerDiscard(c net.Conn) { func proxyHandlerDiscard(c net.Conn) {
@ -366,16 +366,16 @@ func TestAppendDevices(t *testing.T) {
expected := []*pb.Device{ expected := []*pb.Device{
{ {
Type: kataBlkDevType, Type: kataBlkDevType,
VmPath: testBlockDeviceVirtPath,
ContainerPath: testBlockDeviceCtrPath, ContainerPath: testBlockDeviceCtrPath,
Id: testPCIAddr,
}, },
} }
ctrDevices := []Device{ ctrDevices := []Device{
&BlockDevice{ &BlockDevice{
VirtPath: testBlockDeviceVirtPath,
DeviceInfo: DeviceInfo{ DeviceInfo: DeviceInfo{
ContainerPath: testBlockDeviceCtrPath, ContainerPath: testBlockDeviceCtrPath,
}, },
PCIAddr: testPCIAddr,
}, },
} }

View File

@ -565,7 +565,7 @@ func (q *qemu) qmpSetup() (*govmmQemu.QMP, error) {
return qmp, nil return qmp, nil
} }
func (q *qemu) addDeviceToBridge(ID string) (string, string, error) { func (q *qemu) addDeviceToBridge(ID string) (string, Bridge, error) {
var err error var err error
var addr uint32 var addr uint32
@ -573,11 +573,11 @@ func (q *qemu) addDeviceToBridge(ID string) (string, string, error) {
for _, b := range q.state.Bridges { for _, b := range q.state.Bridges {
addr, err = b.addDevice(ID) addr, err = b.addDevice(ID)
if err == nil { if err == nil {
return fmt.Sprintf("0x%x", addr), b.ID, nil return fmt.Sprintf("%02x", addr), b, nil
} }
} }
return "", "", err return "", Bridge{}, err
} }
func (q *qemu) removeDeviceFromBridge(ID string) error { func (q *qemu) removeDeviceFromBridge(ID string) error {
@ -593,7 +593,7 @@ func (q *qemu) removeDeviceFromBridge(ID string) error {
return err return err
} }
func (q *qemu) hotplugBlockDevice(drive Drive, op operation) error { func (q *qemu) hotplugBlockDevice(drive *Drive, op operation) error {
defer func(qemu *qemu) { defer func(qemu *qemu) {
if q.qmpMonitorCh.qmp != nil { if q.qmpMonitorCh.qmp != nil {
q.qmpMonitorCh.qmp.Shutdown() q.qmpMonitorCh.qmp.Shutdown()
@ -616,12 +616,15 @@ func (q *qemu) hotplugBlockDevice(drive Drive, op operation) error {
if q.config.BlockDeviceDriver == VirtioBlock { if q.config.BlockDeviceDriver == VirtioBlock {
driver := "virtio-blk-pci" driver := "virtio-blk-pci"
addr, bus, err := q.addDeviceToBridge(drive.ID) addr, bridge, err := q.addDeviceToBridge(drive.ID)
if err != nil { if err != nil {
return err return err
} }
if err = q.qmpMonitorCh.qmp.ExecutePCIDeviceAdd(q.qmpMonitorCh.ctx, drive.ID, devID, driver, addr, bus); err != nil { // PCI address is in the format bridge-addr/device-addr eg. "03/02"
drive.PCIAddr = fmt.Sprintf("%02x", bridge.Addr) + "/" + addr
if err = q.qmpMonitorCh.qmp.ExecutePCIDeviceAdd(q.qmpMonitorCh.ctx, drive.ID, devID, driver, addr, bridge.ID); err != nil {
return err return err
} }
} else { } else {
@ -676,12 +679,12 @@ func (q *qemu) hotplugVFIODevice(device VFIODevice, op operation) error {
devID := "vfio-" + device.DeviceInfo.ID devID := "vfio-" + device.DeviceInfo.ID
if op == addDevice { if op == addDevice {
addr, bus, err := q.addDeviceToBridge(devID) addr, bridge, err := q.addDeviceToBridge(devID)
if err != nil { if err != nil {
return err return err
} }
if err := q.qmpMonitorCh.qmp.ExecutePCIVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, addr, bus); err != nil { if err := q.qmpMonitorCh.qmp.ExecutePCIVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF, addr, bridge.ID); err != nil {
return err return err
} }
} else { } else {
@ -700,7 +703,7 @@ func (q *qemu) hotplugVFIODevice(device VFIODevice, op operation) error {
func (q *qemu) hotplugDevice(devInfo interface{}, devType deviceType, op operation) error { func (q *qemu) hotplugDevice(devInfo interface{}, devType deviceType, op operation) error {
switch devType { switch devType {
case blockDev: case blockDev:
drive := devInfo.(Drive) drive := devInfo.(*Drive)
return q.hotplugBlockDevice(drive, op) return q.hotplugBlockDevice(drive, op)
case cpuDev: case cpuDev:
vcpus := devInfo.(uint32) vcpus := devInfo.(uint32)

View File

@ -205,7 +205,7 @@ func (q *qemuAmd64) appendBridges(devices []govmmQemu.Device, bridges []Bridge)
t = govmmQemu.PCIEBridge t = govmmQemu.PCIEBridge
} }
b.Addr = bridgePCIStartAddr + idx bridges[idx].Addr = bridgePCIStartAddr + idx
devices = append(devices, devices = append(devices,
govmmQemu.BridgeDevice{ govmmQemu.BridgeDevice{
@ -215,7 +215,7 @@ func (q *qemuAmd64) appendBridges(devices []govmmQemu.Device, bridges []Bridge)
// Each bridge is required to be assigned a unique chassis id > 0 // Each bridge is required to be assigned a unique chassis id > 0
Chassis: (idx + 1), Chassis: (idx + 1),
SHPC: true, SHPC: true,
Addr: strconv.FormatInt(int64(b.Addr), 10), Addr: strconv.FormatInt(int64(bridges[idx].Addr), 10),
}, },
) )
} }

View File

@ -328,7 +328,7 @@ func (q *qemuArchBase) appendBridges(devices []govmmQemu.Device, bridges []Bridg
t = govmmQemu.PCIEBridge t = govmmQemu.PCIEBridge
} }
b.Addr = bridgePCIStartAddr + idx bridges[idx].Addr = bridgePCIStartAddr + idx
devices = append(devices, devices = append(devices,
govmmQemu.BridgeDevice{ govmmQemu.BridgeDevice{
@ -338,7 +338,7 @@ func (q *qemuArchBase) appendBridges(devices []govmmQemu.Device, bridges []Bridg
// Each bridge is required to be assigned a unique chassis id > 0 // Each bridge is required to be assigned a unique chassis id > 0
Chassis: (idx + 1), Chassis: (idx + 1),
SHPC: true, SHPC: true,
Addr: strconv.FormatInt(int64(b.Addr), 10), Addr: strconv.FormatInt(int64(bridges[idx].Addr), 10),
}, },
) )
} }

View File

@ -60,6 +60,9 @@ type State struct {
// Bool to indicate if the drive for a container was hotplugged. // Bool to indicate if the drive for a container was hotplugged.
HotpluggedDrive bool `json:"hotpluggedDrive"` HotpluggedDrive bool `json:"hotpluggedDrive"`
// PCI slot at which the block device backing the container rootfs is attached.
RootfsPCIAddr string `json:"rootfsPCIAddr"`
} }
// valid checks that the sandbox state is valid. // valid checks that the sandbox state is valid.
@ -237,6 +240,9 @@ type Drive struct {
// Index assigned to the drive. In case of virtio-scsi, this is used as SCSI LUN index // Index assigned to the drive. In case of virtio-scsi, this is used as SCSI LUN index
Index int Index int
// PCIAddr is the PCI address used to identify the slot at which the drive is attached.
PCIAddr string
} }
// EnvVar is a key/value structure representing a command // EnvVar is a key/value structure representing a command