From a7d888febc43d7e981d973c21225018ba655c370 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Fri, 13 Jul 2018 17:39:23 +0800 Subject: [PATCH] virtconainers: add SetFactory API Add SetFactory to allow virtcontainers consumers to set a vm factory. And use it to create new VMs whenever the factory is set. Signed-off-by: Peng Tao --- virtcontainers/api.go | 12 ++--- virtcontainers/api_test.go | 70 +++++++++++++------------- virtcontainers/example_pod_run_test.go | 2 +- virtcontainers/hack/virtc/main.go | 4 +- virtcontainers/implementation.go | 10 +++- virtcontainers/interfaces.go | 1 + virtcontainers/noop_agent_test.go | 2 +- virtcontainers/pkg/vcmock/mock.go | 7 +++ virtcontainers/pkg/vcmock/mock_test.go | 37 +++++++++++++- virtcontainers/pkg/vcmock/types.go | 3 +- virtcontainers/sandbox.go | 32 ++++++++++-- virtcontainers/sandbox_test.go | 2 +- 12 files changed, 128 insertions(+), 54 deletions(-) diff --git a/virtcontainers/api.go b/virtcontainers/api.go index dfaf0c881a..abaebb50ed 100644 --- a/virtcontainers/api.go +++ b/virtcontainers/api.go @@ -34,13 +34,13 @@ func SetLogger(logger logrus.FieldLogger) { // CreateSandbox is the virtcontainers sandbox creation entry point. // CreateSandbox creates a sandbox and its containers. It does not start them. -func CreateSandbox(sandboxConfig SandboxConfig) (VCSandbox, error) { - return createSandboxFromConfig(sandboxConfig) +func CreateSandbox(sandboxConfig SandboxConfig, factory Factory) (VCSandbox, error) { + return createSandboxFromConfig(sandboxConfig, factory) } -func createSandboxFromConfig(sandboxConfig SandboxConfig) (*Sandbox, error) { +func createSandboxFromConfig(sandboxConfig SandboxConfig, factory Factory) (*Sandbox, error) { // Create the sandbox. - s, err := createSandbox(sandboxConfig) + s, err := createSandbox(sandboxConfig, factory) if err != nil { return nil, err } @@ -206,8 +206,8 @@ func StopSandbox(sandboxID string) (VCSandbox, error) { // RunSandbox is the virtcontainers sandbox running entry point. // RunSandbox creates a sandbox and its containers and then it starts them. -func RunSandbox(sandboxConfig SandboxConfig) (VCSandbox, error) { - s, err := createSandboxFromConfig(sandboxConfig) +func RunSandbox(sandboxConfig SandboxConfig, factory Factory) (VCSandbox, error) { + s, err := createSandboxFromConfig(sandboxConfig, factory) if err != nil { return nil, err } diff --git a/virtcontainers/api_test.go b/virtcontainers/api_test.go index a7dc007033..c7a5ebe8d3 100644 --- a/virtcontainers/api_test.go +++ b/virtcontainers/api_test.go @@ -244,7 +244,7 @@ func TestCreateSandboxNoopAgentSuccessful(t *testing.T) { config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -289,7 +289,7 @@ func TestCreateSandboxHyperstartAgentSuccessful(t *testing.T) { proxy.Start() defer proxy.Stop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -330,7 +330,7 @@ func TestCreateSandboxKataAgentSuccessful(t *testing.T) { } defer kataProxyMock.Stop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -347,7 +347,7 @@ func TestCreateSandboxFailing(t *testing.T) { config := SandboxConfig{} - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p.(*Sandbox) != nil || err == nil { t.Fatal() } @@ -358,7 +358,7 @@ func TestDeleteSandboxNoopAgentSuccessful(t *testing.T) { config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -401,7 +401,7 @@ func TestDeleteSandboxHyperstartAgentSuccessful(t *testing.T) { proxy.Start() defer proxy.Stop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -452,7 +452,7 @@ func TestDeleteSandboxKataAgentSuccessful(t *testing.T) { } defer kataProxyMock.Stop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -751,7 +751,7 @@ func TestRunSandboxNoopAgentSuccessful(t *testing.T) { config := newTestSandboxConfigNoop() - p, err := RunSandbox(config) + p, err := RunSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -787,7 +787,7 @@ func TestRunSandboxHyperstartAgentSuccessful(t *testing.T) { hyperConfig := config.AgentConfig.(HyperConfig) config.AgentConfig = hyperConfig - p, err := RunSandbox(config) + p, err := RunSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -833,7 +833,7 @@ func TestRunSandboxKataAgentSuccessful(t *testing.T) { } defer kataProxyMock.Stop() - p, err := RunSandbox(config) + p, err := RunSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -855,7 +855,7 @@ func TestRunSandboxFailing(t *testing.T) { config := SandboxConfig{} - p, err := RunSandbox(config) + p, err := RunSandbox(config, nil) if p != nil || err == nil { t.Fatal() } @@ -868,7 +868,7 @@ func TestListSandboxSuccessful(t *testing.T) { config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -928,7 +928,7 @@ func TestStatusSandboxSuccessfulStateReady(t *testing.T) { }, } - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -985,7 +985,7 @@ func TestStatusSandboxSuccessfulStateRunning(t *testing.T) { }, } - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1014,7 +1014,7 @@ func TestStatusSandboxFailingFetchSandboxConfig(t *testing.T) { config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1034,7 +1034,7 @@ func TestStatusPodSandboxFailingFetchSandboxState(t *testing.T) { config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1069,7 +1069,7 @@ func TestCreateContainerSuccessful(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1100,7 +1100,7 @@ func TestCreateContainerFailingNoSandbox(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1130,7 +1130,7 @@ func TestDeleteContainerSuccessful(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1184,7 +1184,7 @@ func TestDeleteContainerFailingNoContainer(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1249,7 +1249,7 @@ func TestStartContainerFailingNoContainer(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1272,7 +1272,7 @@ func TestStartContainerFailingSandboxNotStarted(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1493,7 +1493,7 @@ func TestStopContainerFailingNoContainer(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1674,7 +1674,7 @@ func TestEnterContainerFailingNoContainer(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1731,7 +1731,7 @@ func TestStatusContainerSuccessful(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1782,7 +1782,7 @@ func TestStatusContainerStateReady(t *testing.T) { contID := "101" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1845,7 +1845,7 @@ func TestStatusContainerStateRunning(t *testing.T) { contID := "101" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1917,7 +1917,7 @@ func TestStatusContainerFailing(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1940,7 +1940,7 @@ func TestStatsContainerFailing(t *testing.T) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if p == nil || err != nil { t.Fatal(err) } @@ -1973,7 +1973,7 @@ func TestStatsContainer(t *testing.T) { assert.Error(err) config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) assert.NoError(err) assert.NotNil(p) @@ -2023,7 +2023,7 @@ func TestProcessListContainer(t *testing.T) { assert.Error(err) config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) assert.NoError(err) assert.NotNil(p) @@ -2117,7 +2117,7 @@ func createAndStartSandbox(config SandboxConfig) (sandbox VCSandbox, sandboxDir err error) { // Create sandbox - sandbox, err = CreateSandbox(config) + sandbox, err = CreateSandbox(config, nil) if sandbox == nil || err != nil { return nil, "", err } @@ -2158,7 +2158,7 @@ func createStartStopDeleteSandbox(b *testing.B, sandboxConfig SandboxConfig) { func createStartStopDeleteContainers(b *testing.B, sandboxConfig SandboxConfig, contConfigs []ContainerConfig) { // Create sandbox - p, err := CreateSandbox(sandboxConfig) + p, err := CreateSandbox(sandboxConfig, nil) if err != nil { b.Fatalf("Could not create sandbox: %s", err) } @@ -2326,7 +2326,7 @@ func TestFetchSandbox(t *testing.T) { config := newTestSandboxConfigNoop() - s, err := CreateSandbox(config) + s, err := CreateSandbox(config, nil) if s == nil || err != nil { t.Fatal(err) } @@ -2348,7 +2348,7 @@ func TestReleaseSandbox(t *testing.T) { config := newTestSandboxConfigNoop() - s, err := CreateSandbox(config) + s, err := CreateSandbox(config, nil) if s == nil || err != nil { t.Fatal(err) } diff --git a/virtcontainers/example_pod_run_test.go b/virtcontainers/example_pod_run_test.go index 7ac0658cff..55e32e03e8 100644 --- a/virtcontainers/example_pod_run_test.go +++ b/virtcontainers/example_pod_run_test.go @@ -68,7 +68,7 @@ func Example_createAndStartSandbox() { Containers: []vc.ContainerConfig{container}, } - _, err := vc.RunSandbox(sandboxConfig) + _, err := vc.RunSandbox(sandboxConfig, nil) if err != nil { fmt.Printf("Could not run sandbox: %s", err) } diff --git a/virtcontainers/hack/virtc/main.go b/virtcontainers/hack/virtc/main.go index f4aa95a075..cf6457f9f8 100644 --- a/virtcontainers/hack/virtc/main.go +++ b/virtcontainers/hack/virtc/main.go @@ -324,7 +324,7 @@ func runSandbox(context *cli.Context) error { return fmt.Errorf("Could not build sandbox config: %s", err) } - _, err = vc.RunSandbox(sandboxConfig) + _, err = vc.RunSandbox(sandboxConfig, nil) if err != nil { return fmt.Errorf("Could not run sandbox: %s", err) } @@ -338,7 +338,7 @@ func createSandbox(context *cli.Context) error { return fmt.Errorf("Could not build sandbox config: %s", err) } - p, err := vc.CreateSandbox(sandboxConfig) + p, err := vc.CreateSandbox(sandboxConfig, nil) if err != nil { return fmt.Errorf("Could not create sandbox: %s", err) } diff --git a/virtcontainers/implementation.go b/virtcontainers/implementation.go index f75348fa9e..8e5f8fa039 100644 --- a/virtcontainers/implementation.go +++ b/virtcontainers/implementation.go @@ -18,6 +18,7 @@ import ( // VCImpl is the official virtcontainers function of the same name. type VCImpl struct { + factory Factory } // SetLogger implements the VC function of the same name. @@ -25,9 +26,14 @@ func (impl *VCImpl) SetLogger(logger logrus.FieldLogger) { SetLogger(logger) } +// SetFactory implements the VC function of the same name. +func (impl *VCImpl) SetFactory(factory Factory) { + impl.factory = factory +} + // CreateSandbox implements the VC function of the same name. func (impl *VCImpl) CreateSandbox(sandboxConfig SandboxConfig) (VCSandbox, error) { - return CreateSandbox(sandboxConfig) + return CreateSandbox(sandboxConfig, impl.factory) } // DeleteSandbox implements the VC function of the same name. @@ -47,7 +53,7 @@ func (impl *VCImpl) StopSandbox(sandboxID string) (VCSandbox, error) { // RunSandbox implements the VC function of the same name. func (impl *VCImpl) RunSandbox(sandboxConfig SandboxConfig) (VCSandbox, error) { - return RunSandbox(sandboxConfig) + return RunSandbox(sandboxConfig, impl.factory) } // ListSandbox implements the VC function of the same name. diff --git a/virtcontainers/interfaces.go b/virtcontainers/interfaces.go index 4a9f2a239d..fc74b97992 100644 --- a/virtcontainers/interfaces.go +++ b/virtcontainers/interfaces.go @@ -16,6 +16,7 @@ import ( // VC is the Virtcontainers interface type VC interface { SetLogger(logger logrus.FieldLogger) + SetFactory(Factory) CreateSandbox(sandboxConfig SandboxConfig) (VCSandbox, error) DeleteSandbox(sandboxID string) (VCSandbox, error) diff --git a/virtcontainers/noop_agent_test.go b/virtcontainers/noop_agent_test.go index 1453bbfc65..7b30d425c1 100644 --- a/virtcontainers/noop_agent_test.go +++ b/virtcontainers/noop_agent_test.go @@ -14,7 +14,7 @@ func testCreateNoopContainer() (*Sandbox, *Container, error) { contID := "100" config := newTestSandboxConfigNoop() - p, err := CreateSandbox(config) + p, err := CreateSandbox(config, nil) if err != nil { return nil, nil, err } diff --git a/virtcontainers/pkg/vcmock/mock.go b/virtcontainers/pkg/vcmock/mock.go index a4e0bcab3b..c0413591b8 100644 --- a/virtcontainers/pkg/vcmock/mock.go +++ b/virtcontainers/pkg/vcmock/mock.go @@ -35,6 +35,13 @@ func (m *VCMock) SetLogger(logger logrus.FieldLogger) { } } +// SetFactory implements the VC function of the same name. +func (m *VCMock) SetFactory(factory vc.Factory) { + if m.SetFactoryFunc != nil { + m.SetFactoryFunc(factory) + } +} + // CreateSandbox implements the VC function of the same name. func (m *VCMock) CreateSandbox(sandboxConfig vc.SandboxConfig) (vc.VCSandbox, error) { if m.CreateSandboxFunc != nil { diff --git a/virtcontainers/pkg/vcmock/mock_test.go b/virtcontainers/pkg/vcmock/mock_test.go index 22ae00b584..67c7bfe644 100644 --- a/virtcontainers/pkg/vcmock/mock_test.go +++ b/virtcontainers/pkg/vcmock/mock_test.go @@ -11,6 +11,7 @@ import ( "testing" vc "github.com/kata-containers/runtime/virtcontainers" + "github.com/kata-containers/runtime/virtcontainers/factory" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" ) @@ -20,7 +21,10 @@ const ( testContainerID = "testContainerID" ) -var loggerTriggered = 0 +var ( + loggerTriggered = 0 + factoryTriggered = 0 +) func TestVCImplementations(t *testing.T) { // official implementation @@ -675,3 +679,34 @@ func TestVCMockResumeContainer(t *testing.T) { assert.Error(err) assert.True(IsMockError(err)) } + +func TestVCMockSetVMFactory(t *testing.T) { + assert := assert.New(t) + + m := &VCMock{} + assert.Nil(m.SetFactoryFunc) + + hyperConfig := vc.HypervisorConfig{ + KernelPath: "foobar", + ImagePath: "foobar", + } + vmConfig := vc.VMConfig{ + HypervisorType: vc.MockHypervisor, + AgentType: vc.NoopAgentType, + HypervisorConfig: hyperConfig, + } + + f, err := factory.NewFactory(factory.Config{VMConfig: vmConfig}, false) + assert.Nil(err) + + assert.Equal(factoryTriggered, 0) + m.SetFactory(f) + assert.Equal(factoryTriggered, 0) + + m.SetFactoryFunc = func(factory vc.Factory) { + factoryTriggered = 1 + } + + m.SetFactory(f) + assert.Equal(factoryTriggered, 1) +} diff --git a/virtcontainers/pkg/vcmock/types.go b/virtcontainers/pkg/vcmock/types.go index c223526034..83b6546ccf 100644 --- a/virtcontainers/pkg/vcmock/types.go +++ b/virtcontainers/pkg/vcmock/types.go @@ -35,7 +35,8 @@ type Container struct { // VCMock is a type that provides an implementation of the VC interface. // It is used for testing. type VCMock struct { - SetLoggerFunc func(logger logrus.FieldLogger) + SetLoggerFunc func(logger logrus.FieldLogger) + SetFactoryFunc func(factory vc.Factory) CreateSandboxFunc func(sandboxConfig vc.SandboxConfig) (vc.VCSandbox, error) DeleteSandboxFunc func(sandboxID string) (vc.VCSandbox, error) diff --git a/virtcontainers/sandbox.go b/virtcontainers/sandbox.go index 098bcaa32e..316dbd72cc 100644 --- a/virtcontainers/sandbox.go +++ b/virtcontainers/sandbox.go @@ -440,6 +440,7 @@ type Sandbox struct { id string sync.Mutex + factory Factory hypervisor hypervisor agent agent storage resourceStorage @@ -679,12 +680,12 @@ func createAssets(sandboxConfig *SandboxConfig) error { // It will create and store the sandbox structure, and then ask the hypervisor // to physically create that sandbox i.e. starts a VM for that sandbox to eventually // be started. -func createSandbox(sandboxConfig SandboxConfig) (*Sandbox, error) { +func createSandbox(sandboxConfig SandboxConfig, factory Factory) (*Sandbox, error) { if err := createAssets(&sandboxConfig); err != nil { return nil, err } - s, err := newSandbox(sandboxConfig) + s, err := newSandbox(sandboxConfig, factory) if err != nil { return nil, err } @@ -718,7 +719,7 @@ func createSandbox(sandboxConfig SandboxConfig) (*Sandbox, error) { return s, nil } -func newSandbox(sandboxConfig SandboxConfig) (*Sandbox, error) { +func newSandbox(sandboxConfig SandboxConfig, factory Factory) (*Sandbox, error) { if sandboxConfig.valid() == false { return nil, fmt.Errorf("Invalid sandbox configuration") } @@ -734,6 +735,7 @@ func newSandbox(sandboxConfig SandboxConfig) (*Sandbox, error) { s := &Sandbox{ id: sandboxConfig.ID, + factory: factory, hypervisor: hypervisor, agent: agent, storage: &filesystem{}, @@ -821,7 +823,8 @@ func fetchSandbox(sandboxID string) (sandbox *Sandbox, err error) { return nil, err } - sandbox, err = createSandbox(config) + // fetchSandbox is not suppose to create new sandbox VM. + sandbox, err = createSandbox(config, nil) if err != nil { return nil, fmt.Errorf("failed to create sandbox with config %+v: %v", config, err) } @@ -935,7 +938,28 @@ func (s *Sandbox) removeNetwork() error { func (s *Sandbox) startVM() error { s.Logger().Info("Starting VM") + // FIXME: This would break cached VMs. We need network hotplug and move + // oci hooks and netns handling to cli. See #273. if err := s.network.run(s.networkNS.NetNsPath, func() error { + if s.factory != nil { + vm, err := s.factory.GetVM(VMConfig{ + HypervisorType: s.config.HypervisorType, + HypervisorConfig: s.config.HypervisorConfig, + AgentType: s.config.AgentType, + AgentConfig: s.config.AgentConfig, + }) + if err != nil { + return err + } + err = vm.assignSandbox(s) + if err != nil { + return err + } + // FIXME: factory vm needs network hotplug to add Nics. + s.networkNS.NetNsPath = "" + return nil + } + return s.hypervisor.startSandbox() }); err != nil { return err diff --git a/virtcontainers/sandbox_test.go b/virtcontainers/sandbox_test.go index eec5a0d2aa..d2f3517428 100644 --- a/virtcontainers/sandbox_test.go +++ b/virtcontainers/sandbox_test.go @@ -52,7 +52,7 @@ func testCreateSandbox(t *testing.T, id string, Containers: containers, } - sandbox, err := createSandbox(sconfig) + sandbox, err := createSandbox(sconfig, nil) if err != nil { return nil, fmt.Errorf("Could not create sandbox: %s", err) }