From 7d5e48f1b513965eba36437c349d52c9be70614a Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Mon, 22 Jul 2019 12:00:19 +0800 Subject: [PATCH 1/4] persist: manage "hypervisor.json" with new store Fixes #803 Merge "hypervisor.json" into "persist.json", so the new store can take care of hypervisor data now. Signed-off-by: Wei Zhang --- virtcontainers/acrn.go | 41 ++++++++++-- virtcontainers/fc.go | 22 ++++++- virtcontainers/hypervisor.go | 4 ++ virtcontainers/mock_hypervisor.go | 7 ++ virtcontainers/persist.go | 11 +++- virtcontainers/persist/api/hypervisor.go | 43 ++++++++++++ virtcontainers/persist/api/sandbox.go | 38 ----------- virtcontainers/qemu.go | 84 +++++++++++++++++++++--- virtcontainers/sandbox.go | 35 ++++++++-- 9 files changed, 221 insertions(+), 64 deletions(-) create mode 100644 virtcontainers/persist/api/hypervisor.go diff --git a/virtcontainers/acrn.go b/virtcontainers/acrn.go index 855571ca97..7fdb831bb1 100644 --- a/virtcontainers/acrn.go +++ b/virtcontainers/acrn.go @@ -17,6 +17,7 @@ import ( "time" "github.com/kata-containers/runtime/virtcontainers/device/config" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" "github.com/kata-containers/runtime/virtcontainers/store" "github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/utils" @@ -230,7 +231,18 @@ func (a *acrn) setup(id string, hypervisorConfig *HypervisorConfig, vcStore *sto a.store = vcStore a.config = *hypervisorConfig a.arch = newAcrnArch(a.config) - if err = a.store.Load(store.Hypervisor, &a.state); err != nil { + + var create bool + + if a.store != nil { //use old store + if err = a.store.Load(store.Hypervisor, &a.info); err != nil { + create = true + } + } else if a.info.PID == 0 { // new store + create = true + } + + if create { // acrn currently supports only known UUIDs for security // reasons (FuSa). When launching VM, only these pre-defined // UUID should be used else VM launch will fail. acrn team is @@ -246,15 +258,11 @@ func (a *acrn) setup(id string, hypervisorConfig *HypervisorConfig, vcStore *sto return err } - if err = a.store.Store(store.Hypervisor, a.state); err != nil { + if err = a.storeInfo(); err != nil { return err } } - if err = a.store.Load(store.Hypervisor, &a.info); err != nil { - a.Logger().WithField("function", "setup").WithError(err).Info("No info could be fetched") - } - return nil } @@ -619,3 +627,24 @@ func (a *acrn) fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, func (a *acrn) toGrpc() ([]byte, error) { return nil, errors.New("acrn is not supported by VM cache") } + +func (a *acrn) storeInfo() error { + if a.store != nil { + if err := a.store.Store(store.Hypervisor, a.info); err != nil { + return err + } + } + return nil +} + +func (a *acrn) save() (s persistapi.HypervisorState) { + s.Pid = a.pid() + s.Type = string(AcrnHypervisor) + s.UUID = a.state.UUID + return +} + +func (a *acrn) load(s persistapi.HypervisorState) { + a.info.PID = s.Pid + a.state.UUID = s.UUID +} diff --git a/virtcontainers/fc.go b/virtcontainers/fc.go index 09b83d4fc7..f5e8b8a705 100644 --- a/virtcontainers/fc.go +++ b/virtcontainers/fc.go @@ -22,6 +22,7 @@ import ( httptransport "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" "github.com/kata-containers/runtime/virtcontainers/pkg/firecracker/client" models "github.com/kata-containers/runtime/virtcontainers/pkg/firecracker/client/models" ops "github.com/kata-containers/runtime/virtcontainers/pkg/firecracker/client/operations" @@ -234,8 +235,10 @@ func (fc *firecracker) createSandbox(ctx context.Context, id string, networkNS N // No need to return an error from there since there might be nothing // to fetch if this is the first time the hypervisor is created. - if err := fc.store.Load(store.Hypervisor, &fc.info); err != nil { - fc.Logger().WithField("function", "init").WithError(err).Info("No info could be fetched") + if fc.store != nil { + if err := fc.store.Load(store.Hypervisor, &fc.info); err != nil { + fc.Logger().WithField("function", "init").WithError(err).Info("No info could be fetched") + } } return nil @@ -388,7 +391,10 @@ func (fc *firecracker) fcInit(timeout int) error { fc.state.set(apiReady) // Store VMM information - return fc.store.Store(store.Hypervisor, fc.info) + if fc.store != nil { + return fc.store.Store(store.Hypervisor, fc.info) + } + return nil } func (fc *firecracker) fcEnd() (err error) { @@ -988,3 +994,13 @@ func (fc *firecracker) fromGrpc(ctx context.Context, hypervisorConfig *Hyperviso func (fc *firecracker) toGrpc() ([]byte, error) { return nil, errors.New("firecracker is not supported by VM cache") } + +func (fc *firecracker) save() (s persistapi.HypervisorState) { + s.Pid = fc.pid() + s.Type = string(FirecrackerHypervisor) + return +} + +func (fc *firecracker) load(s persistapi.HypervisorState) { + fc.info.PID = s.Pid +} diff --git a/virtcontainers/hypervisor.go b/virtcontainers/hypervisor.go index 4439d1d611..f12595328b 100644 --- a/virtcontainers/hypervisor.go +++ b/virtcontainers/hypervisor.go @@ -15,6 +15,7 @@ import ( "strings" "github.com/kata-containers/runtime/virtcontainers/device/config" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" "github.com/kata-containers/runtime/virtcontainers/store" "github.com/kata-containers/runtime/virtcontainers/types" ) @@ -670,4 +671,7 @@ type hypervisor interface { pid() int fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, store *store.VCStore, j []byte) error toGrpc() ([]byte, error) + + save() persistapi.HypervisorState + load(persistapi.HypervisorState) } diff --git a/virtcontainers/mock_hypervisor.go b/virtcontainers/mock_hypervisor.go index a429d62578..1c198f47bd 100644 --- a/virtcontainers/mock_hypervisor.go +++ b/virtcontainers/mock_hypervisor.go @@ -10,6 +10,7 @@ import ( "errors" "os" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" "github.com/kata-containers/runtime/virtcontainers/store" "github.com/kata-containers/runtime/virtcontainers/types" ) @@ -114,3 +115,9 @@ func (m *mockHypervisor) fromGrpc(ctx context.Context, hypervisorConfig *Hypervi func (m *mockHypervisor) toGrpc() ([]byte, error) { return nil, errors.New("firecracker is not supported by VM cache") } + +func (m *mockHypervisor) save() (s persistapi.HypervisorState) { + return +} + +func (m *mockHypervisor) load(s persistapi.HypervisorState) {} diff --git a/virtcontainers/persist.go b/virtcontainers/persist.go index eaa1ac489e..394388f45d 100644 --- a/virtcontainers/persist.go +++ b/virtcontainers/persist.go @@ -57,7 +57,9 @@ func (s *Sandbox) dumpState(ss *persistapi.SandboxState, cs map[string]persistap } } -func (s *Sandbox) dumpHypervisor(ss *persistapi.SandboxState, cs map[string]persistapi.ContainerState) { +func (s *Sandbox) dumpHypervisor(ss *persistapi.SandboxState) { + ss.HypervisorState = s.hypervisor.save() + // BlockIndex will be moved from sandbox state to hypervisor state later ss.HypervisorState.BlockIndex = s.state.BlockIndex } @@ -160,7 +162,7 @@ func (s *Sandbox) Save() error { s.dumpVersion(&ss) s.dumpState(&ss, cs) - s.dumpHypervisor(&ss, cs) + s.dumpHypervisor(&ss) s.dumpDevices(&ss, cs) s.dumpProcess(cs) s.dumpMounts(cs) @@ -190,6 +192,10 @@ func (c *Container) loadContState(cs persistapi.ContainerState) { } } +func (s *Sandbox) loadHypervisor(hs persistapi.HypervisorState) { + s.hypervisor.load(hs) +} + func (s *Sandbox) loadDevices(devStates []persistapi.DeviceState) { s.devManager.LoadDevices(devStates) } @@ -237,6 +243,7 @@ func (s *Sandbox) Restore() error { } s.loadState(ss) + s.loadHypervisor(ss.HypervisorState) s.loadDevices(ss.Devices) return nil } diff --git a/virtcontainers/persist/api/hypervisor.go b/virtcontainers/persist/api/hypervisor.go new file mode 100644 index 0000000000..d61917da90 --- /dev/null +++ b/virtcontainers/persist/api/hypervisor.go @@ -0,0 +1,43 @@ +// Copyright (c) 2016 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package persistapi + +// Bridge is a bridge where devices can be hot plugged +type Bridge struct { + // DeviceAddr contains information about devices plugged and its address in the bridge + DeviceAddr map[uint32]string + + // Type is the type of the bridge (pci, pcie, etc) + Type string + + //ID is used to identify the bridge in the hypervisor + ID string + + // Addr is the PCI/e slot of the bridge + Addr int +} + +// CPUDevice represents a CPU device which was hot-added in a running VM +type CPUDevice struct { + // ID is used to identify this CPU in the hypervisor options. + ID string +} + +type HypervisorState struct { + Pid int + // Type of hypervisor, E.g. qemu/firecracker/acrn. + Type string + BlockIndex int + UUID string + + // Belows are qemu specific + // Refs: virtcontainers/qemu.go:QemuState + Bridges []Bridge + // HotpluggedCPUs is the list of CPUs that were hot-added + HotpluggedVCPUs []CPUDevice + HotpluggedMemory int + HotplugVFIOOnRootBus bool +} diff --git a/virtcontainers/persist/api/sandbox.go b/virtcontainers/persist/api/sandbox.go index b78a5a447d..96828df51e 100644 --- a/virtcontainers/persist/api/sandbox.go +++ b/virtcontainers/persist/api/sandbox.go @@ -8,44 +8,6 @@ package persistapi // ============= sandbox level resources ============= -// SetFunc is function hook used for setting sandbox/container state -// It can be registered to dynamically set state files when dump -type SetFunc (func(*SandboxState, map[string]ContainerState) error) - -// Bridge is a bridge where devices can be hot plugged -type Bridge struct { - // DeviceAddr contains information about devices plugged and its address in the bridge - DeviceAddr map[uint32]string - - // Type is the type of the bridge (pci, pcie, etc) - Type string - - //ID is used to identify the bridge in the hypervisor - ID string - - // Addr is the PCI/e slot of the bridge - Addr int -} - -// CPUDevice represents a CPU device which was hot-added in a running VM -type CPUDevice struct { - // ID is used to identify this CPU in the hypervisor options. - ID string -} - -// HypervisorState saves state of hypervisor -// Refs: virtcontainers/qemu.go:QemuState -type HypervisorState struct { - Pid int - Bridges []Bridge - // HotpluggedCPUs is the list of CPUs that were hot-added - HotpluggedVCPUs []CPUDevice - HotpluggedMemory int - UUID string - HotplugVFIOOnRootBus bool - BlockIndex int -} - // ProxyState save proxy state data type ProxyState struct { // Pid of proxy process diff --git a/virtcontainers/qemu.go b/virtcontainers/qemu.go index 8743902f21..af92e64507 100644 --- a/virtcontainers/qemu.go +++ b/virtcontainers/qemu.go @@ -29,9 +29,11 @@ import ( "github.com/sirupsen/logrus" "github.com/kata-containers/runtime/virtcontainers/device/config" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" "github.com/kata-containers/runtime/virtcontainers/store" "github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/utils" + "golang.org/x/sys/unix" ) @@ -252,7 +254,17 @@ func (q *qemu) setup(id string, hypervisorConfig *HypervisorConfig, vcStore *sto q.nvdimmCount = 0 } - if err = q.store.Load(store.Hypervisor, &q.state); err != nil { + var create bool + if q.store != nil { //use old store + if err := q.store.Load(store.Hypervisor, &q.state); err != nil { + // hypervisor doesn't exist, create new one + create = true + } + } else if q.state.UUID == "" { // new store + create = true + } + + if create { q.Logger().Debug("Creating bridges") q.state.Bridges = q.arch.bridges(q.config.DefaultBridges) @@ -267,7 +279,7 @@ func (q *qemu) setup(id string, hypervisorConfig *HypervisorConfig, vcStore *sto return err } - if err = q.store.Store(store.Hypervisor, q.state); err != nil { + if err = q.storeState(); err != nil { return err } } @@ -1222,7 +1234,7 @@ func (q *qemu) hotplugAddDevice(devInfo interface{}, devType deviceType) (interf return data, err } - return data, q.store.Store(store.Hypervisor, q.state) + return data, q.storeState() } func (q *qemu) hotplugRemoveDevice(devInfo interface{}, devType deviceType) (interface{}, error) { @@ -1234,7 +1246,7 @@ func (q *qemu) hotplugRemoveDevice(devInfo interface{}, devType deviceType) (int return data, err } - return data, q.store.Store(store.Hypervisor, q.state) + return data, q.storeState() } func (q *qemu) hotplugCPUs(vcpus uint32, op operation) (uint32, error) { @@ -1314,12 +1326,12 @@ func (q *qemu) hotplugAddCPUs(amount uint32) (uint32, error) { hotpluggedVCPUs++ if hotpluggedVCPUs == amount { // All vCPUs were hotplugged - return amount, q.store.Store(store.Hypervisor, q.state) + return amount, q.storeState() } } // All vCPUs were NOT hotplugged - if err := q.store.Store(store.Hypervisor, q.state); err != nil { + if err := q.storeState(); err != nil { q.Logger().Errorf("failed to save hypervisor state after hotplug %d vCPUs: %v", hotpluggedVCPUs, err) } @@ -1339,7 +1351,7 @@ func (q *qemu) hotplugRemoveCPUs(amount uint32) (uint32, error) { // get the last vCPUs and try to remove it cpu := q.state.HotpluggedVCPUs[len(q.state.HotpluggedVCPUs)-1] if err := q.qmpMonitorCh.qmp.ExecuteDeviceDel(q.qmpMonitorCh.ctx, cpu.ID); err != nil { - _ = q.store.Store(store.Hypervisor, q.state) + q.storeState() return i, fmt.Errorf("failed to hotunplug CPUs, only %d CPUs were hotunplugged: %v", i, err) } @@ -1347,7 +1359,7 @@ func (q *qemu) hotplugRemoveCPUs(amount uint32) (uint32, error) { q.state.HotpluggedVCPUs = q.state.HotpluggedVCPUs[:len(q.state.HotpluggedVCPUs)-1] } - return amount, q.store.Store(store.Hypervisor, q.state) + return amount, q.storeState() } func (q *qemu) hotplugMemory(memDev *memoryDevice, op operation) (int, error) { @@ -1453,7 +1465,7 @@ func (q *qemu) hotplugAddMemory(memDev *memoryDevice) (int, error) { } } q.state.HotpluggedMemory += memDev.sizeMB - return memDev.sizeMB, q.store.Store(store.Hypervisor, q.state) + return memDev.sizeMB, q.storeState() } func (q *qemu) pauseSandbox() error { @@ -1907,3 +1919,57 @@ func (q *qemu) toGrpc() ([]byte, error) { return json.Marshal(&qp) } + +func (q *qemu) storeState() error { + if q.store != nil { + if err := q.store.Store(store.Hypervisor, q.state); err != nil { + return err + } + } + return nil +} + +func (q *qemu) save() (s persistapi.HypervisorState) { + s.Pid = q.pid() + s.Type = string(QemuHypervisor) + s.UUID = q.state.UUID + s.HotpluggedMemory = q.state.HotpluggedMemory + s.HotplugVFIOOnRootBus = q.state.HotplugVFIOOnRootBus + + for _, bridge := range q.state.Bridges { + s.Bridges = append(s.Bridges, persistapi.Bridge{ + DeviceAddr: bridge.Address, + Type: string(bridge.Type), + ID: bridge.ID, + Addr: bridge.Addr, + }) + } + + for _, cpu := range q.state.HotpluggedVCPUs { + s.HotpluggedVCPUs = append(s.HotpluggedVCPUs, persistapi.CPUDevice{ + ID: cpu.ID, + }) + } + return +} + +func (q *qemu) load(s persistapi.HypervisorState) { + q.state.UUID = s.UUID + q.state.HotpluggedMemory = s.HotpluggedMemory + q.state.HotplugVFIOOnRootBus = s.HotplugVFIOOnRootBus + + for _, bridge := range s.Bridges { + q.state.Bridges = append(q.state.Bridges, types.PCIBridge{ + Address: bridge.DeviceAddr, + Type: types.PCIType(bridge.Type), + ID: bridge.ID, + Addr: bridge.Addr, + }) + } + + for _, cpu := range s.HotpluggedVCPUs { + q.state.HotpluggedVCPUs = append(q.state.HotpluggedVCPUs, CPUDevice{ + ID: cpu.ID, + }) + } +} diff --git a/virtcontainers/sandbox.go b/virtcontainers/sandbox.go index 3095891a92..5e3e4e4169 100644 --- a/virtcontainers/sandbox.go +++ b/virtcontainers/sandbox.go @@ -474,12 +474,10 @@ func createSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Fac } if s.supportNewStore() { - s.devManager = deviceManager.NewDeviceManager(sandboxConfig.HypervisorConfig.BlockDeviceDriver, nil) - - if err := s.Restore(); err == nil && s.state.State != "" { + // Restored successfully from newstore before. + if s.state.State != "" { return s, nil } - } else { devices, err := s.store.LoadDevices() if err != nil { @@ -574,8 +572,20 @@ func newSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Factor } }() - if err = s.hypervisor.createSandbox(ctx, s.id, s.networkNS, &sandboxConfig.HypervisorConfig, s.store); err != nil { - return nil, err + if s.supportNewStore() { + s.devManager = deviceManager.NewDeviceManager(sandboxConfig.HypervisorConfig.BlockDeviceDriver, nil) + + // Ignore the error. Restore can fail for a new sandbox + s.Restore() + + // new store doesn't require hypervisor to be stored immediately + if err = s.hypervisor.createSandbox(ctx, s.id, s.networkNS, &sandboxConfig.HypervisorConfig, nil); err != nil { + return nil, err + } + } else { + if err = s.hypervisor.createSandbox(ctx, s.id, s.networkNS, &sandboxConfig.HypervisorConfig, s.store); err != nil { + return nil, err + } } agentConfig, err := newAgentConfig(sandboxConfig.AgentType, sandboxConfig.AgentConfig) @@ -913,6 +923,12 @@ func (s *Sandbox) AddInterface(inf *vcTypes.Interface) (*vcTypes.Interface, erro return nil, err } + if s.supportNewStore() { + if err := s.Save(); err != nil { + return nil, err + } + } + // Add network for vm inf.PciAddr = endpoint.PciAddr() return s.agent.updateInterface(inf) @@ -930,6 +946,13 @@ func (s *Sandbox) RemoveInterface(inf *vcTypes.Interface) (*vcTypes.Interface, e if err := s.store.Store(store.Network, s.networkNS); err != nil { return inf, err } + + if s.supportNewStore() { + if err := s.Save(); err != nil { + return inf, err + } + } + break } } From 99cf3f80d7e005ad502dd8a7356a820ae7ae98f8 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Mon, 22 Jul 2019 12:00:45 +0800 Subject: [PATCH 2/4] persist: merge "agent.json" Manage "agent.json" with new store. Signed-off-by: Wei Zhang --- virtcontainers/agent.go | 7 +++++++ virtcontainers/kata_agent.go | 28 +++++++++++++++++++++------ virtcontainers/noop_agent.go | 9 +++++++++ virtcontainers/persist.go | 14 ++++++++++++++ virtcontainers/persist/api/sandbox.go | 12 ++++++------ 5 files changed, 58 insertions(+), 12 deletions(-) diff --git a/virtcontainers/agent.go b/virtcontainers/agent.go index 050de36aa9..3b162ec591 100644 --- a/virtcontainers/agent.go +++ b/virtcontainers/agent.go @@ -11,6 +11,7 @@ import ( "time" "github.com/kata-containers/agent/protocols/grpc" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types" "github.com/kata-containers/runtime/virtcontainers/types" "github.com/mitchellh/mapstructure" @@ -255,4 +256,10 @@ type agent interface { // cleanup removes all on disk information generated by the agent cleanup(s *Sandbox) + + // return data for saving + save() persistapi.AgentState + + // load data from disk + load(persistapi.AgentState) } diff --git a/virtcontainers/kata_agent.go b/virtcontainers/kata_agent.go index 6e1579ee24..4f52e85a20 100644 --- a/virtcontainers/kata_agent.go +++ b/virtcontainers/kata_agent.go @@ -24,6 +24,7 @@ import ( kataclient "github.com/kata-containers/agent/protocols/client" "github.com/kata-containers/agent/protocols/grpc" "github.com/kata-containers/runtime/virtcontainers/device/config" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations" ns "github.com/kata-containers/runtime/virtcontainers/pkg/nsenter" vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types" @@ -286,8 +287,10 @@ func (k *kataAgent) init(ctx context.Context, sandbox *Sandbox, config interface k.proxyBuiltIn = isProxyBuiltIn(sandbox.config.ProxyType) // Fetch agent runtime info. - if err := sandbox.store.Load(store.Agent, &k.state); err != nil { - k.Logger().Debug("Could not retrieve anything from storage") + if !sandbox.supportNewStore() { + if err := sandbox.store.Load(store.Agent, &k.state); err != nil { + k.Logger().Debug("Could not retrieve anything from storage") + } } return disableVMShutdown, nil @@ -686,7 +689,7 @@ func (k *kataAgent) setProxy(sandbox *Sandbox, proxy proxy, pid int, url string) k.proxy = proxy k.state.ProxyPid = pid k.state.URL = url - if sandbox != nil { + if sandbox != nil && !sandbox.supportNewStore() { if err := sandbox.store.Store(store.Agent, k.state); err != nil { return err } @@ -841,9 +844,11 @@ func (k *kataAgent) stopSandbox(sandbox *Sandbox) error { // clean up agent state k.state.ProxyPid = -1 k.state.URL = "" - if err := sandbox.store.Store(store.Agent, k.state); err != nil { - // ignore error - k.Logger().WithError(err).WithField("sandbox", sandbox.id).Error("failed to clean up agent state") + if !sandbox.supportNewStore() { + if err := sandbox.store.Store(store.Agent, k.state); err != nil { + // ignore error + k.Logger().WithError(err).WithField("sandbox", sandbox.id).Error("failed to clean up agent state") + } } return nil @@ -2074,3 +2079,14 @@ func (k *kataAgent) cleanup(s *Sandbox) { k.Logger().WithError(err).Errorf("failed to cleanup vm share path %s", path) } } + +func (k *kataAgent) save() (s persistapi.AgentState) { + s.ProxyPid = k.state.ProxyPid + s.URL = k.state.URL + return +} + +func (k *kataAgent) load(s persistapi.AgentState) { + k.state.ProxyPid = s.ProxyPid + k.state.URL = s.URL +} diff --git a/virtcontainers/noop_agent.go b/virtcontainers/noop_agent.go index 307caa7f2a..4c1eec3fc2 100644 --- a/virtcontainers/noop_agent.go +++ b/virtcontainers/noop_agent.go @@ -10,6 +10,7 @@ import ( "time" "github.com/kata-containers/agent/protocols/grpc" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types" "github.com/kata-containers/runtime/virtcontainers/types" specs "github.com/opencontainers/runtime-spec/specs-go" @@ -233,3 +234,11 @@ func (n *noopAgent) markDead() { func (n *noopAgent) cleanup(s *Sandbox) { } + +// save is the Noop agent state saver. It does nothing. +func (n *noopAgent) save() (s persistapi.AgentState) { + return +} + +// load is the Noop agent state loader. It does nothing. +func (n *noopAgent) load(s persistapi.AgentState) {} diff --git a/virtcontainers/persist.go b/virtcontainers/persist.go index 394388f45d..ccf9f00557 100644 --- a/virtcontainers/persist.go +++ b/virtcontainers/persist.go @@ -154,6 +154,12 @@ func (s *Sandbox) dumpMounts(cs map[string]persistapi.ContainerState) { } } +func (s *Sandbox) dumpAgent(ss *persistapi.SandboxState) { + if s.agent != nil { + ss.AgentState = s.agent.save() + } +} + func (s *Sandbox) Save() error { var ( ss = persistapi.SandboxState{} @@ -166,6 +172,7 @@ func (s *Sandbox) Save() error { s.dumpDevices(&ss, cs) s.dumpProcess(cs) s.dumpMounts(cs) + s.dumpAgent(&ss) if err := s.newStore.ToDisk(ss, cs); err != nil { return err @@ -196,6 +203,12 @@ func (s *Sandbox) loadHypervisor(hs persistapi.HypervisorState) { s.hypervisor.load(hs) } +func (s *Sandbox) loadAgent(as persistapi.AgentState) { + if s.agent != nil { + s.agent.load(as) + } +} + func (s *Sandbox) loadDevices(devStates []persistapi.DeviceState) { s.devManager.LoadDevices(devStates) } @@ -245,6 +258,7 @@ func (s *Sandbox) Restore() error { s.loadState(ss) s.loadHypervisor(ss.HypervisorState) s.loadDevices(ss.Devices) + s.loadAgent(ss.AgentState) return nil } diff --git a/virtcontainers/persist/api/sandbox.go b/virtcontainers/persist/api/sandbox.go index 96828df51e..65b8df3656 100644 --- a/virtcontainers/persist/api/sandbox.go +++ b/virtcontainers/persist/api/sandbox.go @@ -8,12 +8,12 @@ package persistapi // ============= sandbox level resources ============= -// ProxyState save proxy state data -type ProxyState struct { +// AgentState save agent state data +type AgentState struct { // Pid of proxy process - Pid int + ProxyPid int - // URL to connect to proxy + // URL to connect to agent URL string } @@ -46,8 +46,8 @@ type SandboxState struct { // HypervisorState saves hypervisor specific data HypervisorState HypervisorState - // ProxyState saves state data of proxy process - ProxyState ProxyState + // AgentState saves state data of agent + AgentState AgentState // Network saves network configuration of sandbox Network NetworkInfo From 3bfbbd666d4819c60ef6a928a011e5d1769d72fe Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Mon, 22 Jul 2019 12:01:05 +0800 Subject: [PATCH 3/4] persist: merge "network.json" Merge "network.json" into "persist.json" so that new store can manage network part. Signed-off-by: Wei Zhang --- virtcontainers/bridgedmacvlan_endpoint.go | 50 +++++++++++++ virtcontainers/endpoint.go | 5 ++ virtcontainers/fc.go | 10 +-- virtcontainers/ipvlan_endpoint.go | 50 +++++++++++++ virtcontainers/macvtap_endpoint.go | 16 +++++ virtcontainers/persist.go | 45 ++++++++++++ virtcontainers/persist/api/network.go | 85 +++++++++++++++++++---- virtcontainers/physical_endpoint.go | 20 ++++++ virtcontainers/sandbox.go | 44 ++++++------ virtcontainers/tap_endpoint.go | 33 +++++++++ virtcontainers/veth_endpoint.go | 50 +++++++++++++ virtcontainers/vhostuser_endpoint.go | 18 +++++ 12 files changed, 388 insertions(+), 38 deletions(-) diff --git a/virtcontainers/bridgedmacvlan_endpoint.go b/virtcontainers/bridgedmacvlan_endpoint.go index d2efd56f53..3856ea40dc 100644 --- a/virtcontainers/bridgedmacvlan_endpoint.go +++ b/virtcontainers/bridgedmacvlan_endpoint.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/containernetworking/plugins/pkg/ns" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" ) // BridgedMacvlanEndpoint represents a macvlan endpoint that is bridged to the VM @@ -115,3 +116,52 @@ func (endpoint *BridgedMacvlanEndpoint) HotAttach(h hypervisor) error { func (endpoint *BridgedMacvlanEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error { return fmt.Errorf("BridgedMacvlanEndpoint does not support Hot detach") } + +func (endpoint *BridgedMacvlanEndpoint) save() (s persistapi.NetworkEndpoint) { + s.Type = string(endpoint.Type()) + s.BridgedMacvlan = &persistapi.BridgedMacvlanEndpoint{ + NetPair: persistapi.NetworkInterfacePair{ + TapInterface: persistapi.TapInterface{ + ID: endpoint.NetPair.TapInterface.ID, + Name: endpoint.NetPair.TapInterface.Name, + TAPIface: persistapi.NetworkInterface{ + Name: endpoint.NetPair.TapInterface.TAPIface.Name, + HardAddr: endpoint.NetPair.TapInterface.TAPIface.HardAddr, + Addrs: endpoint.NetPair.TapInterface.TAPIface.Addrs, + }, + }, + VirtIface: persistapi.NetworkInterface{ + Name: endpoint.NetPair.VirtIface.Name, + HardAddr: endpoint.NetPair.VirtIface.HardAddr, + Addrs: endpoint.NetPair.VirtIface.Addrs, + }, + NetInterworkingModel: int(endpoint.NetPair.NetInterworkingModel), + }, + } + return +} + +func (endpoint *BridgedMacvlanEndpoint) load(s persistapi.NetworkEndpoint) { + endpoint.EndpointType = BridgedMacvlanEndpointType + + if s.BridgedMacvlan != nil { + iface := s.BridgedMacvlan + endpoint.NetPair = NetworkInterfacePair{ + TapInterface: TapInterface{ + ID: iface.NetPair.TapInterface.ID, + Name: iface.NetPair.TapInterface.Name, + TAPIface: NetworkInterface{ + Name: iface.NetPair.TapInterface.TAPIface.Name, + HardAddr: iface.NetPair.TapInterface.TAPIface.HardAddr, + Addrs: iface.NetPair.TapInterface.TAPIface.Addrs, + }, + }, + VirtIface: NetworkInterface{ + Name: iface.NetPair.VirtIface.Name, + HardAddr: iface.NetPair.VirtIface.HardAddr, + Addrs: iface.NetPair.VirtIface.Addrs, + }, + NetInterworkingModel: NetInterworkingModel(iface.NetPair.NetInterworkingModel), + } + } +} diff --git a/virtcontainers/endpoint.go b/virtcontainers/endpoint.go index 978da2dc10..da9443e983 100644 --- a/virtcontainers/endpoint.go +++ b/virtcontainers/endpoint.go @@ -7,6 +7,8 @@ package virtcontainers import ( "fmt" + + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" ) // Endpoint represents a physical or virtual network interface. @@ -24,6 +26,9 @@ type Endpoint interface { Detach(netNsCreated bool, netNsPath string) error HotAttach(h hypervisor) error HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error + + save() persistapi.NetworkEndpoint + load(persistapi.NetworkEndpoint) } // EndpointType identifies the type of the network endpoint. diff --git a/virtcontainers/fc.go b/virtcontainers/fc.go index f5e8b8a705..2ef5ffc594 100644 --- a/virtcontainers/fc.go +++ b/virtcontainers/fc.go @@ -324,11 +324,13 @@ func (fc *firecracker) fcInit(timeout int) error { // Fetch sandbox network to be able to access it from the sandbox structure. var networkNS NetworkNamespace - if err := fc.store.Load(store.Network, &networkNS); err == nil { - if networkNS.NetNsPath == "" { - fc.Logger().WithField("NETWORK NAMESPACE NULL", networkNS).Warn() + if fc.store != nil { + if err := fc.store.Load(store.Network, &networkNS); err == nil { + if networkNS.NetNsPath == "" { + fc.Logger().WithField("NETWORK NAMESPACE NULL", networkNS).Warn() + } + fc.netNSPath = networkNS.NetNsPath } - fc.netNSPath = networkNS.NetNsPath } err := os.MkdirAll(fc.jailerRoot, store.DirMode) diff --git a/virtcontainers/ipvlan_endpoint.go b/virtcontainers/ipvlan_endpoint.go index b71bbd0fbe..7e84f42d8c 100644 --- a/virtcontainers/ipvlan_endpoint.go +++ b/virtcontainers/ipvlan_endpoint.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/containernetworking/plugins/pkg/ns" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" ) // IPVlanEndpoint represents a ipvlan endpoint that is bridged to the VM @@ -118,3 +119,52 @@ func (endpoint *IPVlanEndpoint) HotAttach(h hypervisor) error { func (endpoint *IPVlanEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPath string) error { return fmt.Errorf("IPVlanEndpoint does not support Hot detach") } + +func (endpoint *IPVlanEndpoint) save() (s persistapi.NetworkEndpoint) { + s.Type = string(endpoint.Type()) + s.IPVlan = &persistapi.IPVlanEndpoint{ + NetPair: persistapi.NetworkInterfacePair{ + TapInterface: persistapi.TapInterface{ + ID: endpoint.NetPair.TapInterface.ID, + Name: endpoint.NetPair.TapInterface.Name, + TAPIface: persistapi.NetworkInterface{ + Name: endpoint.NetPair.TapInterface.TAPIface.Name, + HardAddr: endpoint.NetPair.TapInterface.TAPIface.HardAddr, + Addrs: endpoint.NetPair.TapInterface.TAPIface.Addrs, + }, + }, + VirtIface: persistapi.NetworkInterface{ + Name: endpoint.NetPair.VirtIface.Name, + HardAddr: endpoint.NetPair.VirtIface.HardAddr, + Addrs: endpoint.NetPair.VirtIface.Addrs, + }, + NetInterworkingModel: int(endpoint.NetPair.NetInterworkingModel), + }, + } + return +} + +func (endpoint *IPVlanEndpoint) load(s persistapi.NetworkEndpoint) { + endpoint.EndpointType = IPVlanEndpointType + + if s.IPVlan != nil { + iface := s.IPVlan + endpoint.NetPair = NetworkInterfacePair{ + TapInterface: TapInterface{ + ID: iface.NetPair.TapInterface.ID, + Name: iface.NetPair.TapInterface.Name, + TAPIface: NetworkInterface{ + Name: iface.NetPair.TapInterface.TAPIface.Name, + HardAddr: iface.NetPair.TapInterface.TAPIface.HardAddr, + Addrs: iface.NetPair.TapInterface.TAPIface.Addrs, + }, + }, + VirtIface: NetworkInterface{ + Name: iface.NetPair.VirtIface.Name, + HardAddr: iface.NetPair.VirtIface.HardAddr, + Addrs: iface.NetPair.VirtIface.Addrs, + }, + NetInterworkingModel: NetInterworkingModel(iface.NetPair.NetInterworkingModel), + } + } +} diff --git a/virtcontainers/macvtap_endpoint.go b/virtcontainers/macvtap_endpoint.go index d35d9c70cb..2eb708b205 100644 --- a/virtcontainers/macvtap_endpoint.go +++ b/virtcontainers/macvtap_endpoint.go @@ -8,6 +8,8 @@ package virtcontainers import ( "fmt" "os" + + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" ) // MacvtapEndpoint represents a macvtap endpoint @@ -102,3 +104,17 @@ func (endpoint *MacvtapEndpoint) SetPciAddr(pciAddr string) { func (endpoint *MacvtapEndpoint) NetworkPair() *NetworkInterfacePair { return nil } + +func (endpoint *MacvtapEndpoint) save() (s persistapi.NetworkEndpoint) { + s.Type = string(endpoint.Type()) + s.Macvtap = &persistapi.MacvtapEndpoint{ + PCIAddr: endpoint.PCIAddr, + } + return +} +func (endpoint *MacvtapEndpoint) load(s persistapi.NetworkEndpoint) { + endpoint.EndpointType = MacvtapEndpointType + if s.Macvtap != nil { + endpoint.PCIAddr = s.Macvtap.PCIAddr + } +} diff --git a/virtcontainers/persist.go b/virtcontainers/persist.go index ccf9f00557..3569c52d5c 100644 --- a/virtcontainers/persist.go +++ b/virtcontainers/persist.go @@ -160,6 +160,17 @@ func (s *Sandbox) dumpAgent(ss *persistapi.SandboxState) { } } +func (s *Sandbox) dumpNetwork(ss *persistapi.SandboxState) { + ss.Network = persistapi.NetworkInfo{ + NetNsPath: s.networkNS.NetNsPath, + NetmonPID: s.networkNS.NetmonPID, + NetNsCreated: s.networkNS.NetNsCreated, + } + for _, e := range s.networkNS.Endpoints { + ss.Network.Endpoints = append(ss.Network.Endpoints, e.save()) + } +} + func (s *Sandbox) Save() error { var ( ss = persistapi.SandboxState{} @@ -173,6 +184,7 @@ func (s *Sandbox) Save() error { s.dumpProcess(cs) s.dumpMounts(cs) s.dumpAgent(&ss) + s.dumpNetwork(&ss) if err := s.newStore.ToDisk(ss, cs); err != nil { return err @@ -248,6 +260,38 @@ func (c *Container) loadContProcess(cs persistapi.ContainerState) { } } +func (s *Sandbox) loadNetwork(netInfo persistapi.NetworkInfo) { + s.networkNS = NetworkNamespace{ + NetNsPath: netInfo.NetNsPath, + NetmonPID: netInfo.NetmonPID, + NetNsCreated: netInfo.NetNsCreated, + } + + for _, e := range netInfo.Endpoints { + var ep Endpoint + switch EndpointType(e.Type) { + case PhysicalEndpointType: + ep = &PhysicalEndpoint{} + case VethEndpointType: + ep = &VethEndpoint{} + case VhostUserEndpointType: + ep = &VhostUserEndpoint{} + case BridgedMacvlanEndpointType: + ep = &BridgedMacvlanEndpoint{} + case MacvtapEndpointType: + ep = &MacvtapEndpoint{} + case TapEndpointType: + ep = &TapEndpoint{} + case IPVlanEndpointType: + ep = &IPVlanEndpoint{} + default: + continue + } + ep.load(e) + s.networkNS.Endpoints = append(s.networkNS.Endpoints, ep) + } +} + // Restore will restore sandbox data from persist file on disk func (s *Sandbox) Restore() error { ss, _, err := s.newStore.FromDisk(s.id) @@ -259,6 +303,7 @@ func (s *Sandbox) Restore() error { s.loadHypervisor(ss.HypervisorState) s.loadDevices(ss.Devices) s.loadAgent(ss.AgentState) + s.loadNetwork(ss.Network) return nil } diff --git a/virtcontainers/persist/api/network.go b/virtcontainers/persist/api/network.go index c9744682db..2efebf978b 100644 --- a/virtcontainers/persist/api/network.go +++ b/virtcontainers/persist/api/network.go @@ -6,27 +6,86 @@ package persistapi +import ( + "github.com/vishvananda/netlink" +) + // ============= sandbox level resources ============= +type NetworkInterface struct { + Name string + HardAddr string + Addrs []netlink.Addr +} + +// TapInterface defines a tap interface +type TapInterface struct { + ID string + Name string + TAPIface NetworkInterface + // remove VMFds and VhostFds +} + +// NetworkInterfacePair defines a pair between VM and virtual network interfaces. +type NetworkInterfacePair struct { + TapInterface + VirtIface NetworkInterface + NetInterworkingModel int +} + +type PhysicalEndpoint struct { + BDF string + Driver string + VendorDeviceID string +} + +type MacvtapEndpoint struct { + // This is for showing information. + // Remove this field won't impact anything. + PCIAddr string +} + +type TapEndpoint struct { + TapInterface TapInterface +} + +type BridgedMacvlanEndpoint struct { + NetPair NetworkInterfacePair +} + +type VethEndpoint struct { + NetPair NetworkInterfacePair +} + +type IPVlanEndpoint struct { + NetPair NetworkInterfacePair +} + +type VhostUserEndpoint struct { + // This is for showing information. + // Remove these fields won't impact anything. + IfaceName string + PCIAddr string +} + // NetworkEndpoint contains network interface information type NetworkEndpoint struct { Type string - // ID used to pass the netdev option to qemu - ID string - - // Name of the interface - Name string - - // Index of interface - Index int + // One and only one of these below are not nil according to Type. + Physical *PhysicalEndpoint `json:",omitempty"` + Veth *VethEndpoint `json:",omitempty"` + VhostUser *VhostUserEndpoint `json:",omitempty"` + BridgedMacvlan *BridgedMacvlanEndpoint `json:",omitempty"` + Macvtap *MacvtapEndpoint `json:",omitempty"` + Tap *TapEndpoint `json:",omitempty"` + IPVlan *IPVlanEndpoint `json:",omitempty"` } // NetworkInfo contains network information of sandbox type NetworkInfo struct { - NetNsPath string - NetmonPID int - NetNsCreated bool - InterworkingModel string - Endpoints []NetworkEndpoint + NetNsPath string + NetmonPID int + NetNsCreated bool + Endpoints []NetworkEndpoint } diff --git a/virtcontainers/physical_endpoint.go b/virtcontainers/physical_endpoint.go index 989233f158..90c4593b3a 100644 --- a/virtcontainers/physical_endpoint.go +++ b/virtcontainers/physical_endpoint.go @@ -14,6 +14,7 @@ import ( "github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/drivers" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" "github.com/safchain/ethtool" ) @@ -200,3 +201,22 @@ func bindNICToVFIO(endpoint *PhysicalEndpoint) error { func bindNICToHost(endpoint *PhysicalEndpoint) error { return drivers.BindDevicetoHost(endpoint.BDF, endpoint.Driver, endpoint.VendorDeviceID) } + +func (endpoint *PhysicalEndpoint) save() (s persistapi.NetworkEndpoint) { + s.Type = string(endpoint.Type()) + s.Physical = &persistapi.PhysicalEndpoint{ + BDF: endpoint.BDF, + Driver: endpoint.Driver, + VendorDeviceID: endpoint.VendorDeviceID, + } + return +} + +func (endpoint *PhysicalEndpoint) load(s persistapi.NetworkEndpoint) { + endpoint.EndpointType = PhysicalEndpointType + if s.Physical != nil { + endpoint.BDF = s.Physical.BDF + endpoint.Driver = s.Physical.Driver + endpoint.VendorDeviceID = s.Physical.VendorDeviceID + } +} diff --git a/virtcontainers/sandbox.go b/virtcontainers/sandbox.go index 5e3e4e4169..f8f744fd5a 100644 --- a/virtcontainers/sandbox.go +++ b/virtcontainers/sandbox.go @@ -467,18 +467,18 @@ func createSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Fac s.Logger().WithField("features", s.config.Experimental).Infof("Enable experimental features") } - // Fetch sandbox network to be able to access it from the sandbox structure. - var networkNS NetworkNamespace - if err := s.store.Load(store.Network, &networkNS); err == nil { - s.networkNS = networkNS - } - if s.supportNewStore() { // Restored successfully from newstore before. if s.state.State != "" { return s, nil } } else { + // Fetch sandbox network to be able to access it from the sandbox structure. + var networkNS NetworkNamespace + if err := s.store.Load(store.Network, &networkNS); err == nil { + s.networkNS = networkNS + } + devices, err := s.store.LoadDevices() if err != nil { s.Logger().WithError(err).WithField("sandboxid", s.id).Warning("load sandbox devices failed") @@ -563,11 +563,6 @@ func newSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Factor if err != nil { s.Logger().WithError(err).WithField("sandboxid", s.id).Error("Create new sandbox failed") globalSandboxList.removeSandbox(s.id) - } - }() - - defer func() { - if err != nil { s.store.Delete() } }() @@ -846,7 +841,10 @@ func (s *Sandbox) createNetwork() error { } // Store the network - return s.store.Store(store.Network, s.networkNS) + if !s.supportNewStore() { + return s.store.Store(store.Network, s.networkNS) + } + return nil } func (s *Sandbox) postCreatedNetwork() error { @@ -919,14 +917,14 @@ func (s *Sandbox) AddInterface(inf *vcTypes.Interface) (*vcTypes.Interface, erro // Update the sandbox storage s.networkNS.Endpoints = append(s.networkNS.Endpoints, endpoint) - if err := s.store.Store(store.Network, s.networkNS); err != nil { - return nil, err - } - if s.supportNewStore() { if err := s.Save(); err != nil { return nil, err } + } else { + if err := s.store.Store(store.Network, s.networkNS); err != nil { + return nil, err + } } // Add network for vm @@ -943,14 +941,15 @@ func (s *Sandbox) RemoveInterface(inf *vcTypes.Interface) (*vcTypes.Interface, e return inf, err } s.networkNS.Endpoints = append(s.networkNS.Endpoints[:i], s.networkNS.Endpoints[i+1:]...) - if err := s.store.Store(store.Network, s.networkNS); err != nil { - return inf, err - } if s.supportNewStore() { if err := s.Save(); err != nil { return inf, err } + } else { + if err := s.store.Store(store.Network, s.networkNS); err != nil { + return inf, err + } } break @@ -1024,8 +1023,11 @@ func (s *Sandbox) startVM() (err error) { return err } } - if err := s.store.Store(store.Network, s.networkNS); err != nil { - return err + + if !s.supportNewStore() { + if err := s.store.Store(store.Network, s.networkNS); err != nil { + return err + } } } diff --git a/virtcontainers/tap_endpoint.go b/virtcontainers/tap_endpoint.go index c3cd3c34cc..2a59a27615 100644 --- a/virtcontainers/tap_endpoint.go +++ b/virtcontainers/tap_endpoint.go @@ -11,6 +11,7 @@ import ( "github.com/containernetworking/plugins/pkg/ns" "github.com/vishvananda/netlink" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" "github.com/kata-containers/runtime/virtcontainers/pkg/uuid" ) @@ -187,3 +188,35 @@ func unTapNetwork(name string) error { } return nil } + +func (endpoint *TapEndpoint) save() (s persistapi.NetworkEndpoint) { + s.Type = string(endpoint.Type()) + s.Tap = &persistapi.TapEndpoint{ + TapInterface: persistapi.TapInterface{ + ID: endpoint.TapInterface.ID, + Name: endpoint.TapInterface.Name, + TAPIface: persistapi.NetworkInterface{ + Name: endpoint.TapInterface.TAPIface.Name, + HardAddr: endpoint.TapInterface.TAPIface.HardAddr, + Addrs: endpoint.TapInterface.TAPIface.Addrs, + }, + }, + } + return +} +func (endpoint *TapEndpoint) load(s persistapi.NetworkEndpoint) { + endpoint.EndpointType = TapEndpointType + + if s.Tap != nil { + iface := s.Tap + endpoint.TapInterface = TapInterface{ + ID: iface.TapInterface.ID, + Name: iface.TapInterface.Name, + TAPIface: NetworkInterface{ + Name: iface.TapInterface.TAPIface.Name, + HardAddr: iface.TapInterface.TAPIface.HardAddr, + Addrs: iface.TapInterface.TAPIface.Addrs, + }, + } + } +} diff --git a/virtcontainers/veth_endpoint.go b/virtcontainers/veth_endpoint.go index cafb454c10..d57110ea44 100644 --- a/virtcontainers/veth_endpoint.go +++ b/virtcontainers/veth_endpoint.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/containernetworking/plugins/pkg/ns" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" ) // VethEndpoint gathers a network pair and its properties. @@ -141,3 +142,52 @@ func (endpoint *VethEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPa } return nil } + +func (endpoint *VethEndpoint) save() (s persistapi.NetworkEndpoint) { + s.Type = string(endpoint.Type()) + s.Veth = &persistapi.VethEndpoint{ + NetPair: persistapi.NetworkInterfacePair{ + TapInterface: persistapi.TapInterface{ + ID: endpoint.NetPair.TapInterface.ID, + Name: endpoint.NetPair.TapInterface.Name, + TAPIface: persistapi.NetworkInterface{ + Name: endpoint.NetPair.TapInterface.TAPIface.Name, + HardAddr: endpoint.NetPair.TapInterface.TAPIface.HardAddr, + Addrs: endpoint.NetPair.TapInterface.TAPIface.Addrs, + }, + }, + VirtIface: persistapi.NetworkInterface{ + Name: endpoint.NetPair.VirtIface.Name, + HardAddr: endpoint.NetPair.VirtIface.HardAddr, + Addrs: endpoint.NetPair.VirtIface.Addrs, + }, + NetInterworkingModel: int(endpoint.NetPair.NetInterworkingModel), + }, + } + return +} + +func (endpoint *VethEndpoint) load(s persistapi.NetworkEndpoint) { + endpoint.EndpointType = VethEndpointType + + if s.Veth != nil { + iface := s.Veth + endpoint.NetPair = NetworkInterfacePair{ + TapInterface: TapInterface{ + ID: iface.NetPair.TapInterface.ID, + Name: iface.NetPair.TapInterface.Name, + TAPIface: NetworkInterface{ + Name: iface.NetPair.TapInterface.TAPIface.Name, + HardAddr: iface.NetPair.TapInterface.TAPIface.HardAddr, + Addrs: iface.NetPair.TapInterface.TAPIface.Addrs, + }, + }, + VirtIface: NetworkInterface{ + Name: iface.NetPair.VirtIface.Name, + HardAddr: iface.NetPair.VirtIface.HardAddr, + Addrs: iface.NetPair.VirtIface.Addrs, + }, + NetInterworkingModel: NetInterworkingModel(iface.NetPair.NetInterworkingModel), + } + } +} diff --git a/virtcontainers/vhostuser_endpoint.go b/virtcontainers/vhostuser_endpoint.go index 4960dba1be..9dc6967845 100644 --- a/virtcontainers/vhostuser_endpoint.go +++ b/virtcontainers/vhostuser_endpoint.go @@ -11,6 +11,7 @@ import ( "os" "github.com/kata-containers/runtime/virtcontainers/device/config" + persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" "github.com/kata-containers/runtime/virtcontainers/utils" ) @@ -149,3 +150,20 @@ func vhostUserSocketPath(info interface{}) (string, error) { } } + +func (endpoint *VhostUserEndpoint) save() (s persistapi.NetworkEndpoint) { + s.Type = string(endpoint.Type()) + s.VhostUser = &persistapi.VhostUserEndpoint{ + IfaceName: endpoint.IfaceName, + PCIAddr: endpoint.PCIAddr, + } + return +} + +func (endpoint *VhostUserEndpoint) load(s persistapi.NetworkEndpoint) { + endpoint.EndpointType = VhostUserEndpointType + if s.VhostUser != nil { + endpoint.IfaceName = s.VhostUser.IfaceName + endpoint.PCIAddr = s.VhostUser.PCIAddr + } +} From f3d0978c3f8e509598ed4a77aebef648946dc388 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Tue, 23 Jul 2019 10:49:11 +0800 Subject: [PATCH 4/4] persist: improve readability Address some comments for code readability, also add some unit tests. Signed-off-by: Wei Zhang --- virtcontainers/bridgedmacvlan_endpoint.go | 47 +++----------- virtcontainers/endpoint.go | 76 +++++++++++++++++++++++ virtcontainers/endpoint_test.go | 42 +++++++++++++ virtcontainers/ipvlan_endpoint.go | 47 +++----------- virtcontainers/kata_agent.go | 9 +-- virtcontainers/macvtap_endpoint.go | 13 ++-- virtcontainers/persist.go | 1 + virtcontainers/persist/api/hypervisor.go | 2 +- virtcontainers/persist_test.go | 2 +- virtcontainers/physical_endpoint.go | 17 ++--- virtcontainers/tap_endpoint.go | 31 +++------ virtcontainers/veth_endpoint.go | 47 +++----------- virtcontainers/vhostuser_endpoint.go | 14 +++-- 13 files changed, 188 insertions(+), 160 deletions(-) diff --git a/virtcontainers/bridgedmacvlan_endpoint.go b/virtcontainers/bridgedmacvlan_endpoint.go index 3856ea40dc..700aea345d 100644 --- a/virtcontainers/bridgedmacvlan_endpoint.go +++ b/virtcontainers/bridgedmacvlan_endpoint.go @@ -117,51 +117,22 @@ func (endpoint *BridgedMacvlanEndpoint) HotDetach(h hypervisor, netNsCreated boo return fmt.Errorf("BridgedMacvlanEndpoint does not support Hot detach") } -func (endpoint *BridgedMacvlanEndpoint) save() (s persistapi.NetworkEndpoint) { - s.Type = string(endpoint.Type()) - s.BridgedMacvlan = &persistapi.BridgedMacvlanEndpoint{ - NetPair: persistapi.NetworkInterfacePair{ - TapInterface: persistapi.TapInterface{ - ID: endpoint.NetPair.TapInterface.ID, - Name: endpoint.NetPair.TapInterface.Name, - TAPIface: persistapi.NetworkInterface{ - Name: endpoint.NetPair.TapInterface.TAPIface.Name, - HardAddr: endpoint.NetPair.TapInterface.TAPIface.HardAddr, - Addrs: endpoint.NetPair.TapInterface.TAPIface.Addrs, - }, - }, - VirtIface: persistapi.NetworkInterface{ - Name: endpoint.NetPair.VirtIface.Name, - HardAddr: endpoint.NetPair.VirtIface.HardAddr, - Addrs: endpoint.NetPair.VirtIface.Addrs, - }, - NetInterworkingModel: int(endpoint.NetPair.NetInterworkingModel), +func (endpoint *BridgedMacvlanEndpoint) save() persistapi.NetworkEndpoint { + netpair := saveNetIfPair(&endpoint.NetPair) + + return persistapi.NetworkEndpoint{ + Type: string(endpoint.Type()), + BridgedMacvlan: &persistapi.BridgedMacvlanEndpoint{ + NetPair: *netpair, }, } - return } func (endpoint *BridgedMacvlanEndpoint) load(s persistapi.NetworkEndpoint) { endpoint.EndpointType = BridgedMacvlanEndpointType if s.BridgedMacvlan != nil { - iface := s.BridgedMacvlan - endpoint.NetPair = NetworkInterfacePair{ - TapInterface: TapInterface{ - ID: iface.NetPair.TapInterface.ID, - Name: iface.NetPair.TapInterface.Name, - TAPIface: NetworkInterface{ - Name: iface.NetPair.TapInterface.TAPIface.Name, - HardAddr: iface.NetPair.TapInterface.TAPIface.HardAddr, - Addrs: iface.NetPair.TapInterface.TAPIface.Addrs, - }, - }, - VirtIface: NetworkInterface{ - Name: iface.NetPair.VirtIface.Name, - HardAddr: iface.NetPair.VirtIface.HardAddr, - Addrs: iface.NetPair.VirtIface.Addrs, - }, - NetInterworkingModel: NetInterworkingModel(iface.NetPair.NetInterworkingModel), - } + netpair := loadNetIfPair(&s.BridgedMacvlan.NetPair) + endpoint.NetPair = *netpair } } diff --git a/virtcontainers/endpoint.go b/virtcontainers/endpoint.go index da9443e983..ff39e6861d 100644 --- a/virtcontainers/endpoint.go +++ b/virtcontainers/endpoint.go @@ -107,3 +107,79 @@ func (endpointType *EndpointType) String() string { return "" } } + +func saveTapIf(tapif *TapInterface) *persistapi.TapInterface { + if tapif == nil { + return nil + } + + return &persistapi.TapInterface{ + ID: tapif.ID, + Name: tapif.Name, + TAPIface: persistapi.NetworkInterface{ + Name: tapif.TAPIface.Name, + HardAddr: tapif.TAPIface.HardAddr, + Addrs: tapif.TAPIface.Addrs, + }, + } +} + +func loadTapIf(tapif *persistapi.TapInterface) *TapInterface { + if tapif == nil { + return nil + } + + return &TapInterface{ + ID: tapif.ID, + Name: tapif.Name, + TAPIface: NetworkInterface{ + Name: tapif.TAPIface.Name, + HardAddr: tapif.TAPIface.HardAddr, + Addrs: tapif.TAPIface.Addrs, + }, + } +} + +func saveNetIfPair(pair *NetworkInterfacePair) *persistapi.NetworkInterfacePair { + if pair == nil { + return nil + } + + epVirtIf := pair.VirtIface + + tapif := saveTapIf(&pair.TapInterface) + + virtif := persistapi.NetworkInterface{ + Name: epVirtIf.Name, + HardAddr: epVirtIf.HardAddr, + Addrs: epVirtIf.Addrs, + } + + return &persistapi.NetworkInterfacePair{ + TapInterface: *tapif, + VirtIface: virtif, + NetInterworkingModel: int(pair.NetInterworkingModel), + } +} + +func loadNetIfPair(pair *persistapi.NetworkInterfacePair) *NetworkInterfacePair { + if pair == nil { + return nil + } + + savedVirtIf := pair.VirtIface + + tapif := loadTapIf(&pair.TapInterface) + + virtif := NetworkInterface{ + Name: savedVirtIf.Name, + HardAddr: savedVirtIf.HardAddr, + Addrs: savedVirtIf.Addrs, + } + + return &NetworkInterfacePair{ + TapInterface: *tapif, + VirtIface: virtif, + NetInterworkingModel: NetInterworkingModel(pair.NetInterworkingModel), + } +} diff --git a/virtcontainers/endpoint_test.go b/virtcontainers/endpoint_test.go index a27ae13820..e3ea5d906d 100644 --- a/virtcontainers/endpoint_test.go +++ b/virtcontainers/endpoint_test.go @@ -6,6 +6,10 @@ package virtcontainers import ( + "io/ioutil" + "net" + "os" + "reflect" "testing" "github.com/stretchr/testify/assert" @@ -79,3 +83,41 @@ func TestIncorrectEndpointTypeString(t *testing.T) { var endpointType EndpointType testEndpointTypeString(t, &endpointType, "") } + +func TestSaveLoadIfPair(t *testing.T) { + macAddr := net.HardwareAddr{0x02, 0x00, 0xCA, 0xFE, 0x00, 0x04} + + tmpfile, err := ioutil.TempFile("", "vc-save-load-net-") + assert.Nil(t, err) + defer os.Remove(tmpfile.Name()) + + netPair := &NetworkInterfacePair{ + TapInterface: TapInterface{ + ID: "uniqueTestID-4", + Name: "br4_kata", + TAPIface: NetworkInterface{ + Name: "tap4_kata", + HardAddr: macAddr.String(), + }, + VMFds: []*os.File{tmpfile}, // won't be saved to disk + VhostFds: []*os.File{tmpfile}, // won't be saved to disk + }, + VirtIface: NetworkInterface{ + Name: "eth4", + HardAddr: macAddr.String(), + }, + NetInterworkingModel: DefaultNetInterworkingModel, + } + + // Save to disk then load it back. + savedIfPair := saveNetIfPair(netPair) + loadedIfPair := loadNetIfPair(savedIfPair) + + // Since VMFds and VhostFds are't saved, netPair and loadedIfPair are not equal. + assert.False(t, reflect.DeepEqual(netPair, loadedIfPair)) + + netPair.TapInterface.VMFds = nil + netPair.TapInterface.VhostFds = nil + // They are equal now. + assert.True(t, reflect.DeepEqual(netPair, loadedIfPair)) +} diff --git a/virtcontainers/ipvlan_endpoint.go b/virtcontainers/ipvlan_endpoint.go index 7e84f42d8c..6e924a744e 100644 --- a/virtcontainers/ipvlan_endpoint.go +++ b/virtcontainers/ipvlan_endpoint.go @@ -120,51 +120,22 @@ func (endpoint *IPVlanEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNs return fmt.Errorf("IPVlanEndpoint does not support Hot detach") } -func (endpoint *IPVlanEndpoint) save() (s persistapi.NetworkEndpoint) { - s.Type = string(endpoint.Type()) - s.IPVlan = &persistapi.IPVlanEndpoint{ - NetPair: persistapi.NetworkInterfacePair{ - TapInterface: persistapi.TapInterface{ - ID: endpoint.NetPair.TapInterface.ID, - Name: endpoint.NetPair.TapInterface.Name, - TAPIface: persistapi.NetworkInterface{ - Name: endpoint.NetPair.TapInterface.TAPIface.Name, - HardAddr: endpoint.NetPair.TapInterface.TAPIface.HardAddr, - Addrs: endpoint.NetPair.TapInterface.TAPIface.Addrs, - }, - }, - VirtIface: persistapi.NetworkInterface{ - Name: endpoint.NetPair.VirtIface.Name, - HardAddr: endpoint.NetPair.VirtIface.HardAddr, - Addrs: endpoint.NetPair.VirtIface.Addrs, - }, - NetInterworkingModel: int(endpoint.NetPair.NetInterworkingModel), +func (endpoint *IPVlanEndpoint) save() persistapi.NetworkEndpoint { + netpair := saveNetIfPair(&endpoint.NetPair) + + return persistapi.NetworkEndpoint{ + Type: string(endpoint.Type()), + IPVlan: &persistapi.IPVlanEndpoint{ + NetPair: *netpair, }, } - return } func (endpoint *IPVlanEndpoint) load(s persistapi.NetworkEndpoint) { endpoint.EndpointType = IPVlanEndpointType if s.IPVlan != nil { - iface := s.IPVlan - endpoint.NetPair = NetworkInterfacePair{ - TapInterface: TapInterface{ - ID: iface.NetPair.TapInterface.ID, - Name: iface.NetPair.TapInterface.Name, - TAPIface: NetworkInterface{ - Name: iface.NetPair.TapInterface.TAPIface.Name, - HardAddr: iface.NetPair.TapInterface.TAPIface.HardAddr, - Addrs: iface.NetPair.TapInterface.TAPIface.Addrs, - }, - }, - VirtIface: NetworkInterface{ - Name: iface.NetPair.VirtIface.Name, - HardAddr: iface.NetPair.VirtIface.HardAddr, - Addrs: iface.NetPair.VirtIface.Addrs, - }, - NetInterworkingModel: NetInterworkingModel(iface.NetPair.NetInterworkingModel), - } + netpair := loadNetIfPair(&s.IPVlan.NetPair) + endpoint.NetPair = *netpair } } diff --git a/virtcontainers/kata_agent.go b/virtcontainers/kata_agent.go index 4f52e85a20..9306ee05d2 100644 --- a/virtcontainers/kata_agent.go +++ b/virtcontainers/kata_agent.go @@ -2080,10 +2080,11 @@ func (k *kataAgent) cleanup(s *Sandbox) { } } -func (k *kataAgent) save() (s persistapi.AgentState) { - s.ProxyPid = k.state.ProxyPid - s.URL = k.state.URL - return +func (k *kataAgent) save() persistapi.AgentState { + return persistapi.AgentState{ + ProxyPid: k.state.ProxyPid, + URL: k.state.URL, + } } func (k *kataAgent) load(s persistapi.AgentState) { diff --git a/virtcontainers/macvtap_endpoint.go b/virtcontainers/macvtap_endpoint.go index 2eb708b205..4b59d7fc9b 100644 --- a/virtcontainers/macvtap_endpoint.go +++ b/virtcontainers/macvtap_endpoint.go @@ -105,15 +105,18 @@ func (endpoint *MacvtapEndpoint) NetworkPair() *NetworkInterfacePair { return nil } -func (endpoint *MacvtapEndpoint) save() (s persistapi.NetworkEndpoint) { - s.Type = string(endpoint.Type()) - s.Macvtap = &persistapi.MacvtapEndpoint{ - PCIAddr: endpoint.PCIAddr, +func (endpoint *MacvtapEndpoint) save() persistapi.NetworkEndpoint { + return persistapi.NetworkEndpoint{ + Type: string(endpoint.Type()), + + Macvtap: &persistapi.MacvtapEndpoint{ + PCIAddr: endpoint.PCIAddr, + }, } - return } func (endpoint *MacvtapEndpoint) load(s persistapi.NetworkEndpoint) { endpoint.EndpointType = MacvtapEndpointType + if s.Macvtap != nil { endpoint.PCIAddr = s.Macvtap.PCIAddr } diff --git a/virtcontainers/persist.go b/virtcontainers/persist.go index 3569c52d5c..c8ec42a484 100644 --- a/virtcontainers/persist.go +++ b/virtcontainers/persist.go @@ -285,6 +285,7 @@ func (s *Sandbox) loadNetwork(netInfo persistapi.NetworkInfo) { case IPVlanEndpointType: ep = &IPVlanEndpoint{} default: + s.Logger().WithField("endpoint-type", e.Type).Error("unknown endpoint type") continue } ep.load(e) diff --git a/virtcontainers/persist/api/hypervisor.go b/virtcontainers/persist/api/hypervisor.go index d61917da90..75e7c315c5 100644 --- a/virtcontainers/persist/api/hypervisor.go +++ b/virtcontainers/persist/api/hypervisor.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Intel Corporation +// Copyright (c) 2019 Huawei Corporation // // SPDX-License-Identifier: Apache-2.0 // diff --git a/virtcontainers/persist_test.go b/virtcontainers/persist_test.go index 5e55394a21..3f98e71fc3 100644 --- a/virtcontainers/persist_test.go +++ b/virtcontainers/persist_test.go @@ -83,7 +83,7 @@ func TestSandboxRestore(t *testing.T) { assert.NoError(err) assert.NotNil(sandbox.newStore) - // if we don't call ToDisk, we can get nothing from disk + // if we don't call Save(), we can get nothing from disk err = sandbox.Restore() assert.NotNil(t, err) assert.True(os.IsNotExist(err)) diff --git a/virtcontainers/physical_endpoint.go b/virtcontainers/physical_endpoint.go index 90c4593b3a..d6f8537218 100644 --- a/virtcontainers/physical_endpoint.go +++ b/virtcontainers/physical_endpoint.go @@ -202,18 +202,21 @@ func bindNICToHost(endpoint *PhysicalEndpoint) error { return drivers.BindDevicetoHost(endpoint.BDF, endpoint.Driver, endpoint.VendorDeviceID) } -func (endpoint *PhysicalEndpoint) save() (s persistapi.NetworkEndpoint) { - s.Type = string(endpoint.Type()) - s.Physical = &persistapi.PhysicalEndpoint{ - BDF: endpoint.BDF, - Driver: endpoint.Driver, - VendorDeviceID: endpoint.VendorDeviceID, +func (endpoint *PhysicalEndpoint) save() persistapi.NetworkEndpoint { + return persistapi.NetworkEndpoint{ + Type: string(endpoint.Type()), + + Physical: &persistapi.PhysicalEndpoint{ + BDF: endpoint.BDF, + Driver: endpoint.Driver, + VendorDeviceID: endpoint.VendorDeviceID, + }, } - return } func (endpoint *PhysicalEndpoint) load(s persistapi.NetworkEndpoint) { endpoint.EndpointType = PhysicalEndpointType + if s.Physical != nil { endpoint.BDF = s.Physical.BDF endpoint.Driver = s.Physical.Driver diff --git a/virtcontainers/tap_endpoint.go b/virtcontainers/tap_endpoint.go index 2a59a27615..cb441b8733 100644 --- a/virtcontainers/tap_endpoint.go +++ b/virtcontainers/tap_endpoint.go @@ -189,34 +189,21 @@ func unTapNetwork(name string) error { return nil } -func (endpoint *TapEndpoint) save() (s persistapi.NetworkEndpoint) { - s.Type = string(endpoint.Type()) - s.Tap = &persistapi.TapEndpoint{ - TapInterface: persistapi.TapInterface{ - ID: endpoint.TapInterface.ID, - Name: endpoint.TapInterface.Name, - TAPIface: persistapi.NetworkInterface{ - Name: endpoint.TapInterface.TAPIface.Name, - HardAddr: endpoint.TapInterface.TAPIface.HardAddr, - Addrs: endpoint.TapInterface.TAPIface.Addrs, - }, +func (endpoint *TapEndpoint) save() persistapi.NetworkEndpoint { + tapif := saveTapIf(&endpoint.TapInterface) + + return persistapi.NetworkEndpoint{ + Type: string(endpoint.Type()), + Tap: &persistapi.TapEndpoint{ + TapInterface: *tapif, }, } - return } func (endpoint *TapEndpoint) load(s persistapi.NetworkEndpoint) { endpoint.EndpointType = TapEndpointType if s.Tap != nil { - iface := s.Tap - endpoint.TapInterface = TapInterface{ - ID: iface.TapInterface.ID, - Name: iface.TapInterface.Name, - TAPIface: NetworkInterface{ - Name: iface.TapInterface.TAPIface.Name, - HardAddr: iface.TapInterface.TAPIface.HardAddr, - Addrs: iface.TapInterface.TAPIface.Addrs, - }, - } + tapif := loadTapIf(&s.Tap.TapInterface) + endpoint.TapInterface = *tapif } } diff --git a/virtcontainers/veth_endpoint.go b/virtcontainers/veth_endpoint.go index d57110ea44..9ece6a7410 100644 --- a/virtcontainers/veth_endpoint.go +++ b/virtcontainers/veth_endpoint.go @@ -143,51 +143,22 @@ func (endpoint *VethEndpoint) HotDetach(h hypervisor, netNsCreated bool, netNsPa return nil } -func (endpoint *VethEndpoint) save() (s persistapi.NetworkEndpoint) { - s.Type = string(endpoint.Type()) - s.Veth = &persistapi.VethEndpoint{ - NetPair: persistapi.NetworkInterfacePair{ - TapInterface: persistapi.TapInterface{ - ID: endpoint.NetPair.TapInterface.ID, - Name: endpoint.NetPair.TapInterface.Name, - TAPIface: persistapi.NetworkInterface{ - Name: endpoint.NetPair.TapInterface.TAPIface.Name, - HardAddr: endpoint.NetPair.TapInterface.TAPIface.HardAddr, - Addrs: endpoint.NetPair.TapInterface.TAPIface.Addrs, - }, - }, - VirtIface: persistapi.NetworkInterface{ - Name: endpoint.NetPair.VirtIface.Name, - HardAddr: endpoint.NetPair.VirtIface.HardAddr, - Addrs: endpoint.NetPair.VirtIface.Addrs, - }, - NetInterworkingModel: int(endpoint.NetPair.NetInterworkingModel), +func (endpoint *VethEndpoint) save() persistapi.NetworkEndpoint { + netpair := saveNetIfPair(&endpoint.NetPair) + + return persistapi.NetworkEndpoint{ + Type: string(endpoint.Type()), + Veth: &persistapi.VethEndpoint{ + NetPair: *netpair, }, } - return } func (endpoint *VethEndpoint) load(s persistapi.NetworkEndpoint) { endpoint.EndpointType = VethEndpointType if s.Veth != nil { - iface := s.Veth - endpoint.NetPair = NetworkInterfacePair{ - TapInterface: TapInterface{ - ID: iface.NetPair.TapInterface.ID, - Name: iface.NetPair.TapInterface.Name, - TAPIface: NetworkInterface{ - Name: iface.NetPair.TapInterface.TAPIface.Name, - HardAddr: iface.NetPair.TapInterface.TAPIface.HardAddr, - Addrs: iface.NetPair.TapInterface.TAPIface.Addrs, - }, - }, - VirtIface: NetworkInterface{ - Name: iface.NetPair.VirtIface.Name, - HardAddr: iface.NetPair.VirtIface.HardAddr, - Addrs: iface.NetPair.VirtIface.Addrs, - }, - NetInterworkingModel: NetInterworkingModel(iface.NetPair.NetInterworkingModel), - } + netpair := loadNetIfPair(&s.Veth.NetPair) + endpoint.NetPair = *netpair } } diff --git a/virtcontainers/vhostuser_endpoint.go b/virtcontainers/vhostuser_endpoint.go index 9dc6967845..bb4a67beb8 100644 --- a/virtcontainers/vhostuser_endpoint.go +++ b/virtcontainers/vhostuser_endpoint.go @@ -151,17 +151,19 @@ func vhostUserSocketPath(info interface{}) (string, error) { } -func (endpoint *VhostUserEndpoint) save() (s persistapi.NetworkEndpoint) { - s.Type = string(endpoint.Type()) - s.VhostUser = &persistapi.VhostUserEndpoint{ - IfaceName: endpoint.IfaceName, - PCIAddr: endpoint.PCIAddr, +func (endpoint *VhostUserEndpoint) save() persistapi.NetworkEndpoint { + return persistapi.NetworkEndpoint{ + Type: string(endpoint.Type()), + VhostUser: &persistapi.VhostUserEndpoint{ + IfaceName: endpoint.IfaceName, + PCIAddr: endpoint.PCIAddr, + }, } - return } func (endpoint *VhostUserEndpoint) load(s persistapi.NetworkEndpoint) { endpoint.EndpointType = VhostUserEndpointType + if s.VhostUser != nil { endpoint.IfaceName = s.VhostUser.IfaceName endpoint.PCIAddr = s.VhostUser.PCIAddr