Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

persist: manage "hypervisor.json" with new store #1889

Merged
merged 4 commits into from
Jul 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions virtcontainers/acrn.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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
}

Expand Down Expand Up @@ -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
}
7 changes: 7 additions & 0 deletions virtcontainers/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
21 changes: 21 additions & 0 deletions virtcontainers/bridgedmacvlan_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -115,3 +116,23 @@ 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() persistapi.NetworkEndpoint {
netpair := saveNetIfPair(&endpoint.NetPair)

return persistapi.NetworkEndpoint{
Type: string(endpoint.Type()),
BridgedMacvlan: &persistapi.BridgedMacvlanEndpoint{
NetPair: *netpair,
},
}
}

func (endpoint *BridgedMacvlanEndpoint) load(s persistapi.NetworkEndpoint) {
endpoint.EndpointType = BridgedMacvlanEndpointType

if s.BridgedMacvlan != nil {
netpair := loadNetIfPair(&s.BridgedMacvlan.NetPair)
endpoint.NetPair = *netpair
}
}
81 changes: 81 additions & 0 deletions virtcontainers/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -102,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),
}
}
42 changes: 42 additions & 0 deletions virtcontainers/endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
package virtcontainers

import (
"io/ioutil"
"net"
"os"
"reflect"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -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))
}
32 changes: 25 additions & 7 deletions virtcontainers/fc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -321,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)
Expand Down Expand Up @@ -388,7 +393,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) {
Expand Down Expand Up @@ -988,3 +996,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
}
4 changes: 4 additions & 0 deletions virtcontainers/hypervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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)
}
21 changes: 21 additions & 0 deletions virtcontainers/ipvlan_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -118,3 +119,23 @@ 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() persistapi.NetworkEndpoint {
netpair := saveNetIfPair(&endpoint.NetPair)

return persistapi.NetworkEndpoint{
Type: string(endpoint.Type()),
IPVlan: &persistapi.IPVlanEndpoint{
NetPair: *netpair,
},
}
}

func (endpoint *IPVlanEndpoint) load(s persistapi.NetworkEndpoint) {
endpoint.EndpointType = IPVlanEndpointType

if s.IPVlan != nil {
netpair := loadNetIfPair(&s.IPVlan.NetPair)
endpoint.NetPair = *netpair
}
}
Loading