virtcontainers: refactor device.go to device manager#282
virtcontainers: refactor device.go to device manager#282egernst merged 4 commits intokata-containers:masterfrom
Conversation
|
CI should still have some problems, working on resolving the test case problems. |
98ce4fd to
caebef2
Compare
|
I think the code is ready for reviewing, but CI is still failing, guess I broke something but I can't find what's the exact problem. Does anyone happens to know why? @sboeuf @amshinde @jodh-intel |
|
@WeiZhang555 I've seen such error with other non-relevant PR too. I think it is a transient error since it disappeared after jenkins jobs are re-triggered. |
caebef2 to
0353901
Compare
Codecov Report
@@ Coverage Diff @@
## master #282 +/- ##
==========================================
- Coverage 65.36% 64.62% -0.74%
==========================================
Files 76 84 +8
Lines 8185 8043 -142
==========================================
- Hits 5350 5198 -152
- Misses 2262 2284 +22
+ Partials 573 561 -12
Continue to review full report at Codecov.
|
|
@bergwolf @sboeuf @amshinde @egernst Can you help review so I can go on with the work of #245 ? I know this PR is large and most of us don't hope to merge refactoring before 1.0, but without this #245 could be too ugly and I believe you won't want to merge it in. |
|
|
||
| // DeviceReceiver is an interface used for accepting devices | ||
| // a device should be attached/added/plugged to a DeviceReceiver | ||
| type DeviceReceiver interface { |
There was a problem hiding this comment.
@WeiZhang555 I'm trying to understand why you need Sandbox to implement these interfaces. Is it because we do not export proper hypervisor APIs? The layering looks a bit strange but if it is temporary until we have a hypervisor module, I'm ok with it.
There was a problem hiding this comment.
Yes, this is temporary, if we can make a good hypervisor module things can be easier.
We need more refactor including seperating hypervisor management part.
And existence of GetAndSetSandboxBlockIndex() and DecrementSandboxBlockIndex() means we have to use Sandbox as DeviceReceiver. But actually a Hypervisor will be a better DeviceReceiver.
The implementation is not complete and perfect, we need more furthur works. But I don't have enough time to do more.
There was a problem hiding this comment.
Agree, this interface currently looks strange and forced, combining the calls for Sandbox and Hypervisor.
@WeiZhang555 I understand that you are trying to decouple devices completely from the rest of the virtcontainers components, but I would like to understand more clearly why this is required and how this will help the storage hotplug case. How storage hotplug will look without this decoupling.
Like you pointed out, devices do depend on calls from the sandbox and the hypervisor as well. I am not sure if we can get way with decoupling from the hypervisor completely, as we may have to call into some hypervisor specific details.
There was a problem hiding this comment.
@amshinde devices should be able to only depend on hypervisor, once we have a hypervisor module there. It calls from the sandbox only because hypervisor is part of sandbox right now. There are two dependences on sandbox, hotplug api and virtio-scsi device index management. The hotplug api is just a wrapper of hypervisor hotplug api. And the virtio-scsi device index should be just put inside the hypervisor as well because it is hypervisor specific data.
If we all agree this code needs refactoring/decoupling, it looks to be a reasonable step towards a proper shape of modular components in virtcontainers.
There was a problem hiding this comment.
Thanks @bergwolf for answering this for me! You said exactly what I want to say!
The problem I met while doing the storage hotplug feature is that the devices, sandbox, hypervisor and containers are all coupled closely. What I only want to do is add a "device" to "hypervisor", while at this time I don't even need a container, so first thing I want to do is remove "container" from the device manager API.
This PR is trying to separate the "hotplug device to hypervisor" part, but as @bergwolf said, the block index is put in sandbox structure, so I have to use both sandbox and sandbox.hypervisor, that's why the sandbox is a "DeviceReceiver" but not the hypervisor, in my head hypervisor could a good enough DeviceReceiver, that can be done in future and needs more modifications.
There was a problem hiding this comment.
@bergwolf @WeiZhang555 Thanks for the explanation, it makes sense to me now. I agree we should move the virtio-scsi index to the hypervisor.
@WeiZhang555 Can we create an issue for this, so that we can keep track.
| HotplugAddDevice(Device, config.DeviceType) error | ||
| HotplugRemoveDevice(Device, config.DeviceType) error | ||
|
|
||
| // this is only for virtio-blk support |
There was a problem hiding this comment.
This is really only needed for virtio-scsi now that we have merged #267. And hopefully we can remove this in future by refactoring the scsi lun management code.
There was a problem hiding this comment.
I agree with you. These two interfaces are truly not good being here.
This part would need more refactor as you said, I am trying to make this PR a little bit simplier so that it won't be too hard to review.
There was a problem hiding this comment.
@WeiZhang555 This comments needs to be updated then to mention virtio-scsi.
| var devices []api.Device | ||
|
|
||
| for _, devInfo := range devInfos { | ||
| hostPath, err := config.GetHostPathFunc(devInfo) |
There was a problem hiding this comment.
Please move this inside dm.CreateDevice() so that the two dm APIs accept the same DeviceInfo structure.
There was a problem hiding this comment.
There's one thing I'm not sure here, config.GetHostPathFunc would give a different hostPath, and NewDevices() will modify devInfo.HostPath, and CreateDevice() won't modify devInfo . This is a difference between NewDevices() and CreateDevice() (modify hostPath or not).
Are these two APIs designed so? Because I'm not certain on this so I didn't modify it.
Do you think it's safe to move it inside dm.CreateDevice()?
There was a problem hiding this comment.
CreateDevice() is only called inside NewDevices(). So I think it is safe and we should let them share a similar semantics w.r.t. deviceinfo, unless you have other plans to use CreateDevice() differently in your storage hotplug PR.
There was a problem hiding this comment.
Oh, you're right! And I think then we only need to expose NewDevices and don't need to expose CreateDevice now!
Great suggestion! I will modify this part.
e3456c9 to
6458833
Compare
| ) | ||
|
|
||
| // Defining these as a variable instead of a const, to allow | ||
| // overriding this in the tests. |
There was a problem hiding this comment.
not sure if this comment was there in original code, but wanted to comment that I appreciate being explicit here on why you're not using a const! Thanks!
There was a problem hiding this comment.
Haha, this is from original code. But I also appreciate this, that's why I keep it after the refactor :-)
| // FIXME: this is duplicate code from virtcontainers/hypervisor.go | ||
| const maxDevIDSize = 31 | ||
|
|
||
| // FIXME: this is duplicate code from virtcontainers/hypervisor.go |
There was a problem hiding this comment.
Sorry; why can't we remove this from hypervisor.go @WeiZhang555
There was a problem hiding this comment.
Because my original idea is we don't expose virtcontainers/device/drivers package directly to hypervisor at all (or at least not expose too much), and I don't want to let hypervisor.go invoke a drivers.MakeNameID() call, that's why I didn't remove it from hypervisor.go.
Maybe we can find a better way to handle these common functions with more refactor and further works, currently I don't have a certain thought for this.
There was a problem hiding this comment.
@WeiZhang555 This is really a generic function for creating name ids that will be used by the hypervisor, not just for device specific name-ids.
| return devices, nil | ||
| } | ||
|
|
||
| // NewDeviceManager creates a deviceManager object bahaved as DeviceManager |
There was a problem hiding this comment.
Oh, nice catch! Will modify!
egernst
left a comment
There was a problem hiding this comment.
Looks pretty good to me, minus a couple queries/nits; I still have a bit more I want to look into for this (large) change, but definitely will need @amshinde to review.
Thanks for the big effort, @WeiZhang555
a7e9a33 to
7a0e23d
Compare
|
|
||
| var devLogger = logrus.FieldLogger(logrus.New()) | ||
|
|
||
| // SetLogger sets the logger for virtcontainers package. |
There was a problem hiding this comment.
s/virtcontainers/device api/? package
| HotplugAddDevice(Device, config.DeviceType) error | ||
| HotplugRemoveDevice(Device, config.DeviceType) error | ||
|
|
||
| // this is only for virtio-blk support |
There was a problem hiding this comment.
@WeiZhang555 This comments needs to be updated then to mention virtio-scsi.
| } | ||
|
|
||
| // FIXME: this is duplicate code from virtcontainers/hypervisor.go | ||
| const maxDevIDSize = 31 |
There was a problem hiding this comment.
This lived in virtcontainers/qemu_arch_base.go. Different hypervisor implementations will have their own specific limits, this should really be living in the hypervisor implementations.
There was a problem hiding this comment.
I'll move makeNameID and maxDevIDSize to the virtcontainers/utils package then, or there will be dependency cycle problem if I use if from virtcontainers package, later if we get a hypervisor management package, we can set different maxDevIDSize there if necessary.
| // FIXME: this is duplicate code from virtcontainers/hypervisor.go | ||
| const maxDevIDSize = 31 | ||
|
|
||
| // FIXME: this is duplicate code from virtcontainers/hypervisor.go |
There was a problem hiding this comment.
@WeiZhang555 This is really a generic function for creating name ids that will be used by the hypervisor, not just for device specific name-ids.
virtcontainers/network.go
Outdated
|
|
||
| // bindDevicetoVFIO binds the device to vfio driver after unbinding from host. | ||
| // Will be called by a network interface or a generic pcie device. | ||
| func bindDevicetoVFIO(bdf, hostDriver, vendorDeviceID string) error { |
There was a problem hiding this comment.
@WeiZhang555 This should live in the driver for vfio. Though this is currently just being used by network.go, this will potentially be used by other devices in the future.
| // Sandbox implement DeviceReceiver interface from device/api/interface.go | ||
| func (s *Sandbox) HotplugAddDevice(device api.Device, devType config.DeviceType) error { | ||
| switch devType { | ||
| case config.DeviceVFIO: |
There was a problem hiding this comment.
Could you add an assertion on VFIODevice here?
virtcontainers/sandbox.go
Outdated
| func (s *Sandbox) HotplugRemoveDevice(device api.Device, devType config.DeviceType) error { | ||
| switch devType { | ||
| case config.DeviceVFIO: | ||
| return s.hypervisor.hotplugRemoveDevice(device, vfioDev) |
There was a problem hiding this comment.
same as above, missing assertion.
|
|
||
| // DeviceReceiver is an interface used for accepting devices | ||
| // a device should be attached/added/plugged to a DeviceReceiver | ||
| type DeviceReceiver interface { |
There was a problem hiding this comment.
Agree, this interface currently looks strange and forced, combining the calls for Sandbox and Hypervisor.
@WeiZhang555 I understand that you are trying to decouple devices completely from the rest of the virtcontainers components, but I would like to understand more clearly why this is required and how this will help the storage hotplug case. How storage hotplug will look without this decoupling.
Like you pointed out, devices do depend on calls from the sandbox and the hypervisor as well. I am not sure if we can get way with decoupling from the hypervisor completely, as we may have to call into some hypervisor specific details.
6b1b92e to
bf43163
Compare
|
@amshinde Your comments are addressed. |
bf43163 to
5d9589f
Compare
|
@WeiZhang555 Thanks for addressing comments, can you rebase your changes? |
Fixes kata-containers#50 This is done for decoupling device management part from other parts. It seperate device.go to several dirs and files: ``` virtcontainers/device ├── api │ └── interface.go ├── config │ └── config.go ├── drivers │ ├── block.go │ ├── generic.go │ ├── utils.go │ ├── vfio.go │ ├── vhost_user_blk.go │ ├── vhost_user.go │ ├── vhost_user_net.go │ └── vhost_user_scsi.go └── manager ├── manager.go └── utils.go ``` * `api` contains interface definition of device management, so upper level caller should import and use the interface, and lower level should implement the interface. it's bridge to device drivers and callers. * `config` contains structed exported data. * `drivers` contains specific device drivers including block, vfio and vhost user devices. * `manager` exposes an external management package with a `DeviceManager`. Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
CreateDevice() is only used by `NewDevices()` so we can make it private and there's no need to export it. Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
Fix typo. Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
* Move makeNameID() func to virtcontainers/utils file as it's a generic function for making name and ID. * Move bindDevicetoVFIO() and bindDevicetoHost() to vfio driver package. Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
5d9589f to
f4a453b
Compare
|
statically looks fine - was going to wait for CI to finish up (wow, it is taking >51 minutes?) |
Now cgroups are mounted at /sys/fs/cgroup, in the past when initrd was used cgroups were mounted at /proc/cgroups fixes kata-containers#282 Signed-off-by: Julio Montes <julio.montes@intel.com>
Fixes #50
This is done for decoupling device management part from other parts.
It seperate device.go to several dirs and files:
apicontains interface definition of device management, so upper level callershould import and use the interface, and lower level should implement the interface.
it's bridge to device drivers and callers.
configcontains structed exported data.driverscontains specific device drivers including block, vfio and vhost userdevices.
managerexposes an external management package with aDeviceManager.Signed-off-by: Zhang Wei zhangwei555@huawei.com