mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-30 01:02:33 +00:00
hypervisor: allow to return a slice of pids
so that for qemu, we can save and export virtiofsd pid, and put it to the same cgroup as the qemu process. Fixes: #1972 Signed-off-by: Peng Tao <bergwolf@hyper.sh>
This commit is contained in:
parent
1935bf193c
commit
0075bf85ba
@ -617,8 +617,8 @@ func (a *acrn) cleanup() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *acrn) pid() int {
|
func (a *acrn) getPids() []int {
|
||||||
return a.info.PID
|
return []int{a.info.PID}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *acrn) fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, store *store.VCStore, j []byte) error {
|
func (a *acrn) fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, store *store.VCStore, j []byte) error {
|
||||||
@ -639,7 +639,7 @@ func (a *acrn) storeInfo() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *acrn) save() (s persistapi.HypervisorState) {
|
func (a *acrn) save() (s persistapi.HypervisorState) {
|
||||||
s.Pid = a.pid()
|
s.Pid = a.info.PID
|
||||||
s.Type = string(AcrnHypervisor)
|
s.Type = string(AcrnHypervisor)
|
||||||
s.UUID = a.state.UUID
|
s.UUID = a.state.UUID
|
||||||
return
|
return
|
||||||
@ -651,7 +651,7 @@ func (a *acrn) load(s persistapi.HypervisorState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *acrn) check() error {
|
func (a *acrn) check() error {
|
||||||
if err := syscall.Kill(a.pid(), syscall.Signal(0)); err != nil {
|
if err := syscall.Kill(a.info.PID, syscall.Signal(0)); err != nil {
|
||||||
return errors.Wrapf(err, "failed to ping acrn process")
|
return errors.Wrapf(err, "failed to ping acrn process")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,9 +209,9 @@ func (s *Sandbox) deleteCgroups() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sandbox) constrainHypervisor(cgroup cgroups.Cgroup) error {
|
func (s *Sandbox) constrainHypervisor(cgroup cgroups.Cgroup) error {
|
||||||
pid := s.hypervisor.pid()
|
pids := s.hypervisor.getPids()
|
||||||
if pid <= 0 {
|
if len(pids) == 0 || pids[0] == 0 {
|
||||||
return fmt.Errorf("Invalid hypervisor PID: %d", pid)
|
return fmt.Errorf("Invalid hypervisor PID: %+v", pids)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move hypervisor into cgroups without constraints,
|
// Move hypervisor into cgroups without constraints,
|
||||||
@ -222,10 +222,15 @@ func (s *Sandbox) constrainHypervisor(cgroup cgroups.Cgroup) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Could not create cgroup %v: %v", path, err)
|
return fmt.Errorf("Could not create cgroup %v: %v", path, err)
|
||||||
}
|
}
|
||||||
|
for _, pid := range pids {
|
||||||
|
if pid <= 0 {
|
||||||
|
s.Logger().Warnf("Invalid hypervisor pid: %d", pid)
|
||||||
|
continue
|
||||||
|
}
|
||||||
if err := noConstraintsCgroup.Add(cgroups.Process{Pid: pid}); err != nil {
|
if err := noConstraintsCgroup.Add(cgroups.Process{Pid: pid}); err != nil {
|
||||||
return fmt.Errorf("Could not add hypervisor PID %d to cgroup %v: %v", pid, path, err)
|
return fmt.Errorf("Could not add hypervisor PID %d to cgroup %v: %v", pid, path, err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// when new container joins, new CPU could be hotplugged, so we
|
// when new container joins, new CPU could be hotplugged, so we
|
||||||
// have to query fresh vcpu info from hypervisor for every time.
|
// have to query fresh vcpu info from hypervisor for every time.
|
||||||
|
@ -985,8 +985,8 @@ func (fc *firecracker) cleanup() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *firecracker) pid() int {
|
func (fc *firecracker) getPids() []int {
|
||||||
return fc.info.PID
|
return []int{fc.info.PID}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *firecracker) fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, store *store.VCStore, j []byte) error {
|
func (fc *firecracker) fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, store *store.VCStore, j []byte) error {
|
||||||
@ -998,7 +998,7 @@ func (fc *firecracker) toGrpc() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fc *firecracker) save() (s persistapi.HypervisorState) {
|
func (fc *firecracker) save() (s persistapi.HypervisorState) {
|
||||||
s.Pid = fc.pid()
|
s.Pid = fc.info.PID
|
||||||
s.Type = string(FirecrackerHypervisor)
|
s.Type = string(FirecrackerHypervisor)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1008,7 +1008,7 @@ func (fc *firecracker) load(s persistapi.HypervisorState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fc *firecracker) check() error {
|
func (fc *firecracker) check() error {
|
||||||
if err := syscall.Kill(fc.pid(), syscall.Signal(0)); err != nil {
|
if err := syscall.Kill(fc.info.PID, syscall.Signal(0)); err != nil {
|
||||||
return errors.Wrapf(err, "failed to ping fc process")
|
return errors.Wrapf(err, "failed to ping fc process")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,6 +648,14 @@ func RunningOnVMM(cpuInfoPath string) (bool, error) {
|
|||||||
return false, fmt.Errorf("Couldn't find %q from %q output", flagsField, cpuInfoPath)
|
return false, fmt.Errorf("Couldn't find %q from %q output", flagsField, cpuInfoPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getHypervisorPid(h hypervisor) int {
|
||||||
|
pids := h.getPids()
|
||||||
|
if len(pids) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return pids[0]
|
||||||
|
}
|
||||||
|
|
||||||
// hypervisor is the virtcontainers hypervisor interface.
|
// hypervisor is the virtcontainers hypervisor interface.
|
||||||
// The default hypervisor implementation is Qemu.
|
// The default hypervisor implementation is Qemu.
|
||||||
type hypervisor interface {
|
type hypervisor interface {
|
||||||
@ -668,7 +676,9 @@ type hypervisor interface {
|
|||||||
hypervisorConfig() HypervisorConfig
|
hypervisorConfig() HypervisorConfig
|
||||||
getThreadIDs() (vcpuThreadIDs, error)
|
getThreadIDs() (vcpuThreadIDs, error)
|
||||||
cleanup() error
|
cleanup() error
|
||||||
pid() int
|
// getPids returns a slice of hypervisor related process ids.
|
||||||
|
// The hypervisor pid must be put at index 0.
|
||||||
|
getPids() []int
|
||||||
fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, store *store.VCStore, j []byte) error
|
fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, store *store.VCStore, j []byte) error
|
||||||
toGrpc() ([]byte, error)
|
toGrpc() ([]byte, error)
|
||||||
check() error
|
check() error
|
||||||
|
@ -657,7 +657,7 @@ func (k *kataAgent) startProxy(sandbox *Sandbox) error {
|
|||||||
|
|
||||||
proxyParams := proxyParams{
|
proxyParams := proxyParams{
|
||||||
id: sandbox.id,
|
id: sandbox.id,
|
||||||
hid: sandbox.hypervisor.pid(),
|
hid: getHypervisorPid(sandbox.hypervisor),
|
||||||
path: sandbox.config.ProxyConfig.Path,
|
path: sandbox.config.ProxyConfig.Path,
|
||||||
agentURL: agentURL,
|
agentURL: agentURL,
|
||||||
consoleURL: consoleURL,
|
consoleURL: consoleURL,
|
||||||
|
@ -104,8 +104,8 @@ func (m *mockHypervisor) cleanup() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockHypervisor) pid() int {
|
func (m *mockHypervisor) getPids() []int {
|
||||||
return m.mockPid
|
return []int{m.mockPid}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockHypervisor) fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, store *store.VCStore, j []byte) error {
|
func (m *mockHypervisor) fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, store *store.VCStore, j []byte) error {
|
||||||
|
@ -39,5 +39,6 @@ type HypervisorState struct {
|
|||||||
// HotpluggedCPUs is the list of CPUs that were hot-added
|
// HotpluggedCPUs is the list of CPUs that were hot-added
|
||||||
HotpluggedVCPUs []CPUDevice
|
HotpluggedVCPUs []CPUDevice
|
||||||
HotpluggedMemory int
|
HotpluggedMemory int
|
||||||
|
VirtiofsdPid int
|
||||||
HotplugVFIOOnRootBus bool
|
HotplugVFIOOnRootBus bool
|
||||||
}
|
}
|
||||||
|
@ -15,5 +15,5 @@ const (
|
|||||||
// If you can't be sure if the change in persistapi package
|
// If you can't be sure if the change in persistapi package
|
||||||
// requires a bump of CurPersistVersion or not, do it for peace!
|
// requires a bump of CurPersistVersion or not, do it for peace!
|
||||||
// --@WeiZhang555
|
// --@WeiZhang555
|
||||||
CurPersistVersion uint = 1
|
CurPersistVersion uint = 2
|
||||||
)
|
)
|
||||||
|
@ -67,6 +67,7 @@ type QemuState struct {
|
|||||||
HotpluggedMemory int
|
HotpluggedMemory int
|
||||||
UUID string
|
UUID string
|
||||||
HotplugVFIOOnRootBus bool
|
HotplugVFIOOnRootBus bool
|
||||||
|
VirtiofsdPid int
|
||||||
}
|
}
|
||||||
|
|
||||||
// qemu is an Hypervisor interface implementation for the Linux qemu hypervisor.
|
// qemu is an Hypervisor interface implementation for the Linux qemu hypervisor.
|
||||||
@ -459,14 +460,14 @@ func (q *qemu) setupFileBackedMem(knobs *govmmQemu.Knobs, memory *govmmQemu.Memo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createSandbox is the Hypervisor sandbox creation implementation for govmmQemu.
|
// createSandbox is the Hypervisor sandbox creation implementation for govmmQemu.
|
||||||
func (q *qemu) createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, store *store.VCStore) error {
|
func (q *qemu) createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, vcStore *store.VCStore) error {
|
||||||
// Save the tracing context
|
// Save the tracing context
|
||||||
q.ctx = ctx
|
q.ctx = ctx
|
||||||
|
|
||||||
span, _ := q.trace("createSandbox")
|
span, _ := q.trace("createSandbox")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
if err := q.setup(id, hypervisorConfig, store); err != nil {
|
if err := q.setup(id, hypervisorConfig, vcStore); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,8 +559,6 @@ func (q *qemu) createSandbox(ctx context.Context, id string, networkNS NetworkNa
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pidFile := q.pidFile()
|
|
||||||
|
|
||||||
qemuConfig := govmmQemu.Config{
|
qemuConfig := govmmQemu.Config{
|
||||||
Name: fmt.Sprintf("sandbox-%s", q.id),
|
Name: fmt.Sprintf("sandbox-%s", q.id),
|
||||||
UUID: q.state.UUID,
|
UUID: q.state.UUID,
|
||||||
@ -578,7 +577,7 @@ func (q *qemu) createSandbox(ctx context.Context, id string, networkNS NetworkNa
|
|||||||
VGA: "none",
|
VGA: "none",
|
||||||
GlobalParam: "kvm-pit.lost_tick_policy=discard",
|
GlobalParam: "kvm-pit.lost_tick_policy=discard",
|
||||||
Bios: firmwarePath,
|
Bios: firmwarePath,
|
||||||
PidFile: pidFile,
|
PidFile: filepath.Join(store.RunVMStoragePath, q.id, "pid"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if ioThread != nil {
|
if ioThread != nil {
|
||||||
@ -636,6 +635,8 @@ func (q *qemu) setupVirtiofsd(timeout int) (remain int, err error) {
|
|||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.Process.Kill()
|
cmd.Process.Kill()
|
||||||
|
} else {
|
||||||
|
q.state.VirtiofsdPid = cmd.Process.Pid
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -743,6 +744,9 @@ func (q *qemu) startSandbox(timeout int) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err = q.storeState(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var strErr string
|
var strErr string
|
||||||
@ -1910,24 +1914,26 @@ func (q *qemu) cleanup() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemu) pidFile() string {
|
func (q *qemu) getPids() []int {
|
||||||
return filepath.Join(store.RunVMStoragePath, q.id, "pid")
|
data, err := ioutil.ReadFile(q.qemuConfig.PidFile)
|
||||||
}
|
|
||||||
|
|
||||||
func (q *qemu) pid() int {
|
|
||||||
data, err := ioutil.ReadFile(q.pidFile())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
q.Logger().WithError(err).Error("Could not read qemu pid file")
|
q.Logger().WithError(err).Error("Could not read qemu pid file")
|
||||||
return 0
|
return []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
pid, err := strconv.Atoi(strings.Trim(string(data), "\n\t "))
|
pid, err := strconv.Atoi(strings.Trim(string(data), "\n\t "))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
q.Logger().WithError(err).Error("Could not convert string to int")
|
q.Logger().WithError(err).Error("Could not convert string to int")
|
||||||
return 0
|
return []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pid
|
var pids []int
|
||||||
|
pids = append(pids, pid)
|
||||||
|
if q.state.VirtiofsdPid != 0 {
|
||||||
|
pids = append(pids, q.state.VirtiofsdPid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pids
|
||||||
}
|
}
|
||||||
|
|
||||||
type qemuGrpc struct {
|
type qemuGrpc struct {
|
||||||
@ -1992,7 +1998,11 @@ func (q *qemu) storeState() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemu) save() (s persistapi.HypervisorState) {
|
func (q *qemu) save() (s persistapi.HypervisorState) {
|
||||||
s.Pid = q.pid()
|
pids := q.getPids()
|
||||||
|
if len(pids) != 0 {
|
||||||
|
s.Pid = pids[0]
|
||||||
|
}
|
||||||
|
s.VirtiofsdPid = q.state.VirtiofsdPid
|
||||||
s.Type = string(QemuHypervisor)
|
s.Type = string(QemuHypervisor)
|
||||||
s.UUID = q.state.UUID
|
s.UUID = q.state.UUID
|
||||||
s.HotpluggedMemory = q.state.HotpluggedMemory
|
s.HotpluggedMemory = q.state.HotpluggedMemory
|
||||||
@ -2019,6 +2029,7 @@ func (q *qemu) load(s persistapi.HypervisorState) {
|
|||||||
q.state.UUID = s.UUID
|
q.state.UUID = s.UUID
|
||||||
q.state.HotpluggedMemory = s.HotpluggedMemory
|
q.state.HotpluggedMemory = s.HotpluggedMemory
|
||||||
q.state.HotplugVFIOOnRootBus = s.HotplugVFIOOnRootBus
|
q.state.HotplugVFIOOnRootBus = s.HotplugVFIOOnRootBus
|
||||||
|
q.state.VirtiofsdPid = s.VirtiofsdPid
|
||||||
|
|
||||||
for _, bridge := range s.Bridges {
|
for _, bridge := range s.Bridges {
|
||||||
q.state.Bridges = append(q.state.Bridges, types.PCIBridge{
|
q.state.Bridges = append(q.state.Bridges, types.PCIBridge{
|
||||||
|
@ -568,3 +568,40 @@ func TestQemuWaitVirtiofsd(t *testing.T) {
|
|||||||
assert.NotNil(err)
|
assert.NotNil(err)
|
||||||
assert.True(remain == 0)
|
assert.True(remain == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestQemuGetpids(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
qemuConfig := newQemuConfig()
|
||||||
|
q := &qemu{}
|
||||||
|
pids := q.getPids()
|
||||||
|
assert.NotNil(pids)
|
||||||
|
assert.True(len(pids) == 1)
|
||||||
|
assert.True(pids[0] == 0)
|
||||||
|
|
||||||
|
q = &qemu{
|
||||||
|
config: qemuConfig,
|
||||||
|
}
|
||||||
|
f, err := ioutil.TempFile("", "qemu-test-")
|
||||||
|
assert.Nil(err)
|
||||||
|
tmpfile := f.Name()
|
||||||
|
f.Close()
|
||||||
|
defer os.Remove(tmpfile)
|
||||||
|
|
||||||
|
q.qemuConfig.PidFile = tmpfile
|
||||||
|
pids = q.getPids()
|
||||||
|
assert.True(len(pids) == 1)
|
||||||
|
assert.True(pids[0] == 0)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(tmpfile, []byte("100"), 0)
|
||||||
|
assert.Nil(err)
|
||||||
|
pids = q.getPids()
|
||||||
|
assert.True(len(pids) == 1)
|
||||||
|
assert.True(pids[0] == 100)
|
||||||
|
|
||||||
|
q.state.VirtiofsdPid = 200
|
||||||
|
pids = q.getPids()
|
||||||
|
assert.True(len(pids) == 2)
|
||||||
|
assert.True(pids[0] == 100)
|
||||||
|
assert.True(pids[1] == 200)
|
||||||
|
}
|
||||||
|
@ -475,7 +475,7 @@ func (v *VM) ToGrpc(config VMConfig) (*pb.GrpcVM, error) {
|
|||||||
|
|
||||||
func (v *VM) GetVMStatus() *pb.GrpcVMStatus {
|
func (v *VM) GetVMStatus() *pb.GrpcVMStatus {
|
||||||
return &pb.GrpcVMStatus{
|
return &pb.GrpcVMStatus{
|
||||||
Pid: int64(v.hypervisor.pid()),
|
Pid: int64(getHypervisorPid(v.hypervisor)),
|
||||||
Cpu: v.cpu,
|
Cpu: v.cpu,
|
||||||
Memory: v.memory,
|
Memory: v.memory,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user