devices: remove interface VhostUserDevice

The interface "VhostUserDevice" has duplicate functions and fields with
Device, so we can merge them into one interface and manage them with one
group of interfaces.

Signed-off-by: Wei Zhang <zhangwei555@huawei.com>
This commit is contained in:
Wei Zhang 2018-07-01 10:36:59 +08:00 committed by z00280905
parent 2885eb0532
commit b54df7e127
11 changed files with 172 additions and 124 deletions

View File

@ -35,17 +35,8 @@ type DeviceReceiver interface {
GetAndSetSandboxBlockIndex() (int, error) GetAndSetSandboxBlockIndex() (int, error)
DecrementSandboxBlockIndex() error DecrementSandboxBlockIndex() error
// this is for vhost_user devices // this is for appending device to hypervisor boot params
AddVhostUserDevice(VhostUserDevice, config.DeviceType) error AppendDevice(Device) error
}
// VhostUserDevice represents a vhost-user device. Shared
// attributes of a vhost-user device can be retrieved using
// the Attrs() method. Unique data can be obtained by casting
// the object to the proper type.
type VhostUserDevice interface {
Attrs() *config.VhostUserDeviceAttrs
Type() config.DeviceType
} }
// Device is the virtcontainers device interface. // Device is the virtcontainers device interface.

View File

@ -32,7 +32,7 @@ func (mockDC *MockDeviceReceiver) DecrementSandboxBlockIndex() error {
return nil return nil
} }
// AddVhostUserDevice adds new vhost user device // AppendDevice adds new vhost user device
func (mockDC *MockDeviceReceiver) AddVhostUserDevice(VhostUserDevice, config.DeviceType) error { func (mockDC *MockDeviceReceiver) AppendDevice(Device) error {
return nil return nil
} }

View File

@ -123,10 +123,12 @@ type VFIODrive struct {
// VhostUserDeviceAttrs represents data shared by most vhost-user devices // VhostUserDeviceAttrs represents data shared by most vhost-user devices
type VhostUserDeviceAttrs struct { type VhostUserDeviceAttrs struct {
DevType DeviceType
DeviceInfo DeviceInfo
SocketPath string
ID string ID string
SocketPath string
Type DeviceType
// MacAddress is only meaningful for vhost user net device
MacAddress string
} }
// GetHostPathFunc is function pointer used to mock GetHostPath in tests. // GetHostPathFunc is function pointer used to mock GetHostPath in tests.

View File

@ -1,29 +0,0 @@
// Copyright (c) 2017-2018 Intel Corporation
// Copyright (c) 2018 Huawei Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package drivers
import (
"encoding/hex"
"github.com/kata-containers/runtime/virtcontainers/device/api"
"github.com/kata-containers/runtime/virtcontainers/utils"
)
// vhostUserAttach handles the common logic among all of the vhost-user device's
// attach functions
func vhostUserAttach(device api.VhostUserDevice, devReceiver api.DeviceReceiver) error {
// generate a unique ID to be used for hypervisor commandline fields
randBytes, err := utils.GenerateRandomBytes(8)
if err != nil {
return err
}
id := hex.EncodeToString(randBytes)
device.Attrs().ID = id
return devReceiver.AddVhostUserDevice(device, device.Type())
}

View File

@ -7,23 +7,17 @@
package drivers package drivers
import ( import (
"encoding/hex"
"github.com/kata-containers/runtime/virtcontainers/device/api" "github.com/kata-containers/runtime/virtcontainers/device/api"
"github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/utils"
) )
// VhostUserBlkDevice is a block vhost-user based device // VhostUserBlkDevice is a block vhost-user based device
type VhostUserBlkDevice struct { type VhostUserBlkDevice struct {
config.VhostUserDeviceAttrs config.VhostUserDeviceAttrs
} DeviceInfo *config.DeviceInfo
// Attrs returns the VhostUserDeviceAttrs associated with the vhost-user device
func (vhostUserBlkDevice *VhostUserBlkDevice) Attrs() *config.VhostUserDeviceAttrs {
return &vhostUserBlkDevice.VhostUserDeviceAttrs
}
// Type returns the type associated with the vhost-user device
func (vhostUserBlkDevice *VhostUserBlkDevice) Type() config.DeviceType {
return config.VhostUserBlk
} }
// //
@ -32,17 +26,54 @@ func (vhostUserBlkDevice *VhostUserBlkDevice) Type() config.DeviceType {
// Attach is standard interface of api.Device, it's used to add device to some // Attach is standard interface of api.Device, it's used to add device to some
// DeviceReceiver // DeviceReceiver
func (vhostUserBlkDevice *VhostUserBlkDevice) Attach(devReceiver api.DeviceReceiver) (err error) { func (device *VhostUserBlkDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
return vhostUserAttach(vhostUserBlkDevice, devReceiver) // generate a unique ID to be used for hypervisor commandline fields
randBytes, err := utils.GenerateRandomBytes(8)
if err != nil {
return err
}
id := hex.EncodeToString(randBytes)
device.ID = id
device.Type = device.DeviceType()
defer func() {
if err == nil {
device.DeviceInfo.Hotplugged = true
}
}()
return devReceiver.AppendDevice(device)
} }
// Detach is standard interface of api.Device, it's used to remove device from some // Detach is standard interface of api.Device, it's used to remove device from some
// DeviceReceiver // DeviceReceiver
func (vhostUserBlkDevice *VhostUserBlkDevice) Detach(devReceiver api.DeviceReceiver) error { func (device *VhostUserBlkDevice) Detach(devReceiver api.DeviceReceiver) error {
device.DeviceInfo.Hotplugged = false
return nil return nil
} }
// DeviceType is standard interface of api.Device, it returns device type // IsAttached checks if the device is attached
func (vhostUserBlkDevice *VhostUserBlkDevice) DeviceType() config.DeviceType { func (device *VhostUserBlkDevice) IsAttached() bool {
return vhostUserBlkDevice.DevType return device.DeviceInfo.Hotplugged
}
// DeviceID returns device ID
func (device *VhostUserBlkDevice) DeviceID() string {
return device.ID
}
// DeviceType is standard interface of api.Device, it returns device type
func (device *VhostUserBlkDevice) DeviceType() config.DeviceType {
return config.VhostUserBlk
}
// GetDeviceInfo returns device information that the device is created based on
func (device *VhostUserBlkDevice) GetDeviceInfo() *config.DeviceInfo {
return device.DeviceInfo
}
// GetDeviceDrive returns device information used for creating
func (device *VhostUserBlkDevice) GetDeviceDrive() interface{} {
device.Type = device.DeviceType()
return &device.VhostUserDeviceAttrs
} }

View File

@ -7,24 +7,17 @@
package drivers package drivers
import ( import (
"encoding/hex"
"github.com/kata-containers/runtime/virtcontainers/device/api" "github.com/kata-containers/runtime/virtcontainers/device/api"
"github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/utils"
) )
// VhostUserNetDevice is a network vhost-user based device // VhostUserNetDevice is a network vhost-user based device
type VhostUserNetDevice struct { type VhostUserNetDevice struct {
config.VhostUserDeviceAttrs config.VhostUserDeviceAttrs
MacAddress string DeviceInfo *config.DeviceInfo
}
// Attrs returns the VhostUserDeviceAttrs associated with the vhost-user device
func (vhostUserNetDevice *VhostUserNetDevice) Attrs() *config.VhostUserDeviceAttrs {
return &vhostUserNetDevice.VhostUserDeviceAttrs
}
// Type returns the type associated with the vhost-user device
func (vhostUserNetDevice *VhostUserNetDevice) Type() config.DeviceType {
return config.VhostUserNet
} }
// //
@ -33,17 +26,54 @@ func (vhostUserNetDevice *VhostUserNetDevice) Type() config.DeviceType {
// Attach is standard interface of api.Device, it's used to add device to some // Attach is standard interface of api.Device, it's used to add device to some
// DeviceReceiver // DeviceReceiver
func (vhostUserNetDevice *VhostUserNetDevice) Attach(devReceiver api.DeviceReceiver) (err error) { func (device *VhostUserNetDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
return vhostUserAttach(vhostUserNetDevice, devReceiver) // generate a unique ID to be used for hypervisor commandline fields
randBytes, err := utils.GenerateRandomBytes(8)
if err != nil {
return err
}
id := hex.EncodeToString(randBytes)
device.ID = id
device.Type = device.DeviceType()
defer func() {
if err == nil {
device.DeviceInfo.Hotplugged = true
}
}()
return devReceiver.AppendDevice(device)
} }
// Detach is standard interface of api.Device, it's used to remove device from some // Detach is standard interface of api.Device, it's used to remove device from some
// DeviceReceiver // DeviceReceiver
func (vhostUserNetDevice *VhostUserNetDevice) Detach(devReceiver api.DeviceReceiver) error { func (device *VhostUserNetDevice) Detach(devReceiver api.DeviceReceiver) error {
device.DeviceInfo.Hotplugged = false
return nil return nil
} }
// DeviceType is standard interface of api.Device, it returns device type // IsAttached checks if the device is attached
func (vhostUserNetDevice *VhostUserNetDevice) DeviceType() config.DeviceType { func (device *VhostUserNetDevice) IsAttached() bool {
return vhostUserNetDevice.DevType return device.DeviceInfo.Hotplugged
}
// DeviceID returns device ID
func (device *VhostUserNetDevice) DeviceID() string {
return device.ID
}
// DeviceType is standard interface of api.Device, it returns device type
func (device *VhostUserNetDevice) DeviceType() config.DeviceType {
return config.VhostUserNet
}
// GetDeviceInfo returns device information that the device is created based on
func (device *VhostUserNetDevice) GetDeviceInfo() *config.DeviceInfo {
return device.DeviceInfo
}
// GetDeviceDrive returns device information used for creating
func (device *VhostUserNetDevice) GetDeviceDrive() interface{} {
device.Type = device.DeviceType()
return &device.VhostUserDeviceAttrs
} }

View File

@ -7,23 +7,17 @@
package drivers package drivers
import ( import (
"encoding/hex"
"github.com/kata-containers/runtime/virtcontainers/device/api" "github.com/kata-containers/runtime/virtcontainers/device/api"
"github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/utils"
) )
// VhostUserSCSIDevice is a SCSI vhost-user based device // VhostUserSCSIDevice is a SCSI vhost-user based device
type VhostUserSCSIDevice struct { type VhostUserSCSIDevice struct {
config.VhostUserDeviceAttrs config.VhostUserDeviceAttrs
} DeviceInfo *config.DeviceInfo
// Attrs returns the VhostUserDeviceAttrs associated with the vhost-user device
func (vhostUserSCSIDevice *VhostUserSCSIDevice) Attrs() *config.VhostUserDeviceAttrs {
return &vhostUserSCSIDevice.VhostUserDeviceAttrs
}
// Type returns the type associated with the vhost-user device
func (vhostUserSCSIDevice *VhostUserSCSIDevice) Type() config.DeviceType {
return config.VhostUserSCSI
} }
// //
@ -32,17 +26,54 @@ func (vhostUserSCSIDevice *VhostUserSCSIDevice) Type() config.DeviceType {
// Attach is standard interface of api.Device, it's used to add device to some // Attach is standard interface of api.Device, it's used to add device to some
// DeviceReceiver // DeviceReceiver
func (vhostUserSCSIDevice *VhostUserSCSIDevice) Attach(devReceiver api.DeviceReceiver) (err error) { func (device *VhostUserSCSIDevice) Attach(devReceiver api.DeviceReceiver) (err error) {
return vhostUserAttach(vhostUserSCSIDevice, devReceiver) // generate a unique ID to be used for hypervisor commandline fields
randBytes, err := utils.GenerateRandomBytes(8)
if err != nil {
return err
}
id := hex.EncodeToString(randBytes)
device.ID = id
device.Type = device.DeviceType()
defer func() {
if err == nil {
device.DeviceInfo.Hotplugged = true
}
}()
return devReceiver.AppendDevice(device)
} }
// Detach is standard interface of api.Device, it's used to remove device from some // Detach is standard interface of api.Device, it's used to remove device from some
// DeviceReceiver // DeviceReceiver
func (vhostUserSCSIDevice *VhostUserSCSIDevice) Detach(devReceiver api.DeviceReceiver) error { func (device *VhostUserSCSIDevice) Detach(devReceiver api.DeviceReceiver) error {
device.DeviceInfo.Hotplugged = false
return nil return nil
} }
// DeviceType is standard interface of api.Device, it returns device type // IsAttached checks if the device is attached
func (vhostUserSCSIDevice *VhostUserSCSIDevice) DeviceType() config.DeviceType { func (device *VhostUserSCSIDevice) IsAttached() bool {
return vhostUserSCSIDevice.DevType return device.DeviceInfo.Hotplugged
}
// DeviceID returns device ID
func (device *VhostUserSCSIDevice) DeviceID() string {
return device.ID
}
// DeviceType is standard interface of api.Device, it returns device type
func (device *VhostUserSCSIDevice) DeviceType() config.DeviceType {
return config.VhostUserSCSI
}
// GetDeviceInfo returns device information that the device is created based on
func (device *VhostUserSCSIDevice) GetDeviceInfo() *config.DeviceInfo {
return device.DeviceInfo
}
// GetDeviceDrive returns device information used for creating
func (device *VhostUserSCSIDevice) GetDeviceDrive() interface{} {
device.Type = device.DeviceType()
return &device.VhostUserDeviceAttrs
} }

View File

@ -281,11 +281,11 @@ func (endpoint *VhostUserEndpoint) Attach(h hypervisor) error {
} }
id := hex.EncodeToString(randBytes) id := hex.EncodeToString(randBytes)
d := &drivers.VhostUserNetDevice{ d := config.VhostUserDeviceAttrs{
ID: id,
SocketPath: endpoint.SocketPath,
MacAddress: endpoint.HardAddr, MacAddress: endpoint.HardAddr,
} }
d.SocketPath = endpoint.SocketPath
d.ID = id
return h.addDevice(d, vhostuserDev) return h.addDevice(d, vhostuserDev)
} }

View File

@ -19,7 +19,6 @@ import (
"github.com/kata-containers/runtime/virtcontainers/pkg/uuid" "github.com/kata-containers/runtime/virtcontainers/pkg/uuid"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/kata-containers/runtime/virtcontainers/device/api"
"github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/utils" "github.com/kata-containers/runtime/virtcontainers/utils"
) )
@ -942,13 +941,6 @@ func (q *qemu) resumeSandbox() error {
// addDevice will add extra devices to Qemu command line. // addDevice will add extra devices to Qemu command line.
func (q *qemu) addDevice(devInfo interface{}, devType deviceType) error { func (q *qemu) addDevice(devInfo interface{}, devType deviceType) error {
switch devType {
case vhostuserDev:
vhostDev := devInfo.(api.VhostUserDevice)
q.qemuConfig.Devices = q.arch.appendVhostUserDevice(q.qemuConfig.Devices, vhostDev)
return nil
}
switch v := devInfo.(type) { switch v := devInfo.(type) {
case Volume: case Volume:
q.qemuConfig.Devices = q.arch.append9PVolume(q.qemuConfig.Devices, v) q.qemuConfig.Devices = q.arch.append9PVolume(q.qemuConfig.Devices, v)
@ -958,7 +950,8 @@ func (q *qemu) addDevice(devInfo interface{}, devType deviceType) error {
q.qemuConfig.Devices = q.arch.appendNetwork(q.qemuConfig.Devices, v) q.qemuConfig.Devices = q.arch.appendNetwork(q.qemuConfig.Devices, v)
case config.BlockDrive: case config.BlockDrive:
q.qemuConfig.Devices = q.arch.appendBlockDevice(q.qemuConfig.Devices, v) q.qemuConfig.Devices = q.arch.appendBlockDevice(q.qemuConfig.Devices, v)
case config.VhostUserDeviceAttrs:
q.qemuConfig.Devices = q.arch.appendVhostUserDevice(q.qemuConfig.Devices, v)
case config.VFIODrive: case config.VFIODrive:
q.qemuConfig.Devices = q.arch.appendVFIODevice(q.qemuConfig.Devices, v) q.qemuConfig.Devices = q.arch.appendVFIODevice(q.qemuConfig.Devices, v)
default: default:

View File

@ -13,9 +13,7 @@ import (
govmmQemu "github.com/intel/govmm/qemu" govmmQemu "github.com/intel/govmm/qemu"
"github.com/kata-containers/runtime/virtcontainers/device/api"
"github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/device/drivers"
"github.com/kata-containers/runtime/virtcontainers/utils" "github.com/kata-containers/runtime/virtcontainers/utils"
) )
@ -76,7 +74,7 @@ type qemuArch interface {
appendBlockDevice(devices []govmmQemu.Device, drive config.BlockDrive) []govmmQemu.Device appendBlockDevice(devices []govmmQemu.Device, drive config.BlockDrive) []govmmQemu.Device
// appendVhostUserDevice appends a vhost user device to devices // appendVhostUserDevice appends a vhost user device to devices
appendVhostUserDevice(devices []govmmQemu.Device, vhostUserDevice api.VhostUserDevice) []govmmQemu.Device appendVhostUserDevice(devices []govmmQemu.Device, drive config.VhostUserDeviceAttrs) []govmmQemu.Device
// appendVFIODevice appends a VFIO device to devices // appendVFIODevice appends a VFIO device to devices
appendVFIODevice(devices []govmmQemu.Device, vfioDevice config.VFIODrive) []govmmQemu.Device appendVFIODevice(devices []govmmQemu.Device, vfioDevice config.VFIODrive) []govmmQemu.Device
@ -455,22 +453,22 @@ func (q *qemuArchBase) appendBlockDevice(devices []govmmQemu.Device, drive confi
return devices return devices
} }
func (q *qemuArchBase) appendVhostUserDevice(devices []govmmQemu.Device, vhostUserDevice api.VhostUserDevice) []govmmQemu.Device { func (q *qemuArchBase) appendVhostUserDevice(devices []govmmQemu.Device, attr config.VhostUserDeviceAttrs) []govmmQemu.Device {
qemuVhostUserDevice := govmmQemu.VhostUserDevice{} qemuVhostUserDevice := govmmQemu.VhostUserDevice{}
// TODO: find a way to remove dependency of drivers package // TODO: find a way to remove dependency of drivers package
switch vhostUserDevice := vhostUserDevice.(type) { switch attr.Type {
case *drivers.VhostUserNetDevice: case config.VhostUserNet:
qemuVhostUserDevice.TypeDevID = utils.MakeNameID("net", vhostUserDevice.ID, maxDevIDSize) qemuVhostUserDevice.TypeDevID = utils.MakeNameID("net", attr.ID, maxDevIDSize)
qemuVhostUserDevice.Address = vhostUserDevice.MacAddress qemuVhostUserDevice.Address = attr.MacAddress
case *drivers.VhostUserSCSIDevice: case config.VhostUserSCSI:
qemuVhostUserDevice.TypeDevID = utils.MakeNameID("scsi", vhostUserDevice.ID, maxDevIDSize) qemuVhostUserDevice.TypeDevID = utils.MakeNameID("scsi", attr.ID, maxDevIDSize)
case *drivers.VhostUserBlkDevice: case config.VhostUserBlk:
} }
qemuVhostUserDevice.VhostUserType = govmmQemu.VhostUserDeviceType(vhostUserDevice.Type()) qemuVhostUserDevice.VhostUserType = govmmQemu.VhostUserDeviceType(attr.Type)
qemuVhostUserDevice.SocketPath = vhostUserDevice.Attrs().SocketPath qemuVhostUserDevice.SocketPath = attr.SocketPath
qemuVhostUserDevice.CharDevID = utils.MakeNameID("char", vhostUserDevice.Attrs().ID, maxDevIDSize) qemuVhostUserDevice.CharDevID = utils.MakeNameID("char", attr.ID, maxDevIDSize)
devices = append(devices, qemuVhostUserDevice) devices = append(devices, qemuVhostUserDevice)

View File

@ -1503,12 +1503,13 @@ func (s *Sandbox) DecrementSandboxBlockIndex() error {
return s.decrementSandboxBlockIndex() return s.decrementSandboxBlockIndex()
} }
// AddVhostUserDevice adds a vhost user device to sandbox // AppendDevice can only handle vhost user device currently, it adds a
// vhost user device to sandbox
// Sandbox implement DeviceReceiver interface from device/api/interface.go // Sandbox implement DeviceReceiver interface from device/api/interface.go
func (s *Sandbox) AddVhostUserDevice(devInfo api.VhostUserDevice, devType config.DeviceType) error { func (s *Sandbox) AppendDevice(device api.Device) error {
switch devType { switch device.DeviceType() {
case config.VhostUserSCSI, config.VhostUserNet, config.VhostUserBlk: case config.VhostUserSCSI, config.VhostUserNet, config.VhostUserBlk:
return s.hypervisor.addDevice(devInfo, vhostuserDev) return s.hypervisor.addDevice(device.GetDeviceDrive().(*config.VhostUserDeviceAttrs), vhostuserDev)
} }
return fmt.Errorf("unsupported device type") return fmt.Errorf("unsupported device type")
} }