139 lines
3.4 KiB
Go
139 lines
3.4 KiB
Go
package command
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/cirruslabs/tart-guest-agent/internal/diskresizer"
|
|
"github.com/cirruslabs/tart-guest-agent/internal/logginglevel"
|
|
"github.com/cirruslabs/tart-guest-agent/internal/rpc"
|
|
"github.com/cirruslabs/tart-guest-agent/internal/spice/vdagent"
|
|
"github.com/cirruslabs/tart-guest-agent/internal/tart"
|
|
"github.com/cirruslabs/tart-guest-agent/internal/version"
|
|
"github.com/cirruslabs/tart-guest-agent/internal/vsock"
|
|
"github.com/spf13/cobra"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
"golang.org/x/sys/unix"
|
|
"os"
|
|
"syscall"
|
|
)
|
|
|
|
var resizeDisk bool
|
|
var runVdagent bool
|
|
var runRPC bool
|
|
|
|
var runDaemon bool
|
|
var runAgent bool
|
|
|
|
var debug bool
|
|
|
|
func NewRootCommand() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "tart-guest-agent",
|
|
Short: "Guest agent for Tart VMs",
|
|
Version: version.FullVersion,
|
|
SilenceUsage: true,
|
|
SilenceErrors: true,
|
|
PersistentPreRunE: func(_ *cobra.Command, _ []string) error {
|
|
if debug {
|
|
logginglevel.Level.SetLevel(zapcore.DebugLevel)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
RunE: run,
|
|
}
|
|
|
|
// Individual components
|
|
cmd.Flags().BoolVar(&resizeDisk, "resize-disk", false, "resize disk")
|
|
cmd.Flags().BoolVar(&runVdagent, "run-vdagent", false, "run vdagent")
|
|
cmd.Flags().BoolVar(&runRPC, "run-rpc", false, "run RPC service (currently required "+
|
|
"to support \"tart exec\" functionality)")
|
|
|
|
// Component groups
|
|
cmd.Flags().BoolVar(&runDaemon, "run-daemon", false, "identical to running the agent"+
|
|
"with \"--resize-disk\" command-line argument")
|
|
cmd.Flags().BoolVar(&runAgent, "run-agent", false, "identical to running the agent "+
|
|
"with \"--run-vdagent\" and \"--run-rpc\" command-line arguments")
|
|
|
|
cmd.Flags().BoolVar(&debug, "debug", false, "enable debug logging")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func run(cmd *cobra.Command, args []string) error {
|
|
// Component groups automatically enable certain individual components
|
|
if runDaemon {
|
|
resizeDisk = true
|
|
}
|
|
|
|
if runAgent {
|
|
runVdagent = true
|
|
runRPC = true
|
|
}
|
|
|
|
// Terminate to prevent corruption on systems with disk layouts other than Tart's
|
|
communicationPoint, ok := tart.LocateCommunicationPoint()
|
|
if !ok {
|
|
return unix.Kill(os.Getppid(), syscall.SIGTERM)
|
|
}
|
|
|
|
zap.S().Infof("successfully located host communication point %s, proceeding...",
|
|
communicationPoint)
|
|
|
|
// Perform disk resizing
|
|
if resizeDisk {
|
|
zap.S().Info("attempting to resize disk...")
|
|
|
|
if err := diskresizer.Resize(); err != nil {
|
|
if errors.Is(err, diskresizer.ErrUnsupported) || errors.Is(err, diskresizer.ErrAlreadyResized) {
|
|
zap.S().Infof("skipping disk resizing: %v", err)
|
|
} else {
|
|
zap.S().Warnf("failed to resize disk: %v", err)
|
|
}
|
|
} else {
|
|
zap.S().Infof("successfully resized the disk")
|
|
}
|
|
}
|
|
|
|
if runVdagent {
|
|
zap.S().Infof("running vdagent...")
|
|
|
|
vdAgent, err := vdagent.New()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
go func() {
|
|
if err := vdAgent.Run(cmd.Context()); err != nil {
|
|
zap.S().Fatalf("vdagent failed: %v", err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
if runRPC {
|
|
listener, err := vsock.Listen(8080)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to listen on AF_VSOCK port 8080: %v", err)
|
|
}
|
|
|
|
zap.S().Info("running RPC server on AF_VSOCK port 8080...")
|
|
|
|
rpcServer, err := rpc.New(listener)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
go func() {
|
|
if err := rpcServer.Run(); err != nil {
|
|
zap.S().Fatalf("RPC server failed: %v", err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
// Wait indefinitely
|
|
<-cmd.Context().Done()
|
|
|
|
return cmd.Context().Err()
|
|
}
|