constellation/cli/internal/libvirt/libvirt.go

98 lines
2.3 KiB
Go
Raw Normal View History

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package libvirt
import (
"context"
"errors"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
docker "github.com/docker/docker/client"
"github.com/edgelesssys/constellation/v2/internal/file"
"github.com/spf13/afero"
)
// Runner handles starting and stopping of containerized libvirt instances.
type Runner struct {
nameFile string
file file.Handler
}
// New creates a new LibvirtRunner.
func New() *Runner {
return &Runner{
nameFile: "libvirt.name",
file: file.NewHandler(afero.NewOsFs()),
}
}
// Start starts a containerized libvirt instance.
func (r *Runner) Start(ctx context.Context, name, imageName string) error {
docker, err := docker.NewClientWithOpts(docker.FromEnv, docker.WithAPIVersionNegotiation())
if err != nil {
return err
}
defer docker.Close()
containerName := name + "-libvirt"
if _, err := docker.ContainerCreate(ctx,
&container.Config{
Image: imageName,
},
&container.HostConfig{
NetworkMode: container.NetworkMode("host"),
AutoRemove: true,
// container has to be "privileged" so libvirt has access to proc fs
Privileged: true,
},
nil,
nil,
containerName,
); err != nil {
return err
}
if err := docker.ContainerStart(ctx, containerName, types.ContainerStartOptions{}); err != nil {
_ = docker.ContainerRemove(ctx, containerName, types.ContainerRemoveOptions{Force: true})
return err
}
if err := r.file.Write(r.nameFile, []byte(containerName)); err != nil {
_ = docker.ContainerRemove(ctx, containerName, types.ContainerRemoveOptions{Force: true})
return err
}
// time.Sleep(15 * time.Second)
return nil
}
// Stop stops a containerized libvirt instance.
func (r *Runner) Stop(ctx context.Context) error {
name, err := r.file.Read(r.nameFile)
if err != nil {
if errors.Is(err, afero.ErrFileNotFound) {
return nil
}
return err
}
docker, err := docker.NewClientWithOpts(docker.FromEnv, docker.WithAPIVersionNegotiation())
if err != nil {
return err
}
defer docker.Close()
if err := docker.ContainerRemove(ctx, string(name), types.ContainerRemoveOptions{Force: true}); err != nil {
return err
}
if err := r.file.Remove(r.nameFile); err != nil && !errors.Is(err, afero.ErrFileNotFound) {
return err
}
return nil
}