in main.go [70:151]
func runVMM(ctx context.Context, opts *options) error {
// convert options to a firecracker config
fcCfg, err := opts.getFirecrackerConfig()
if err != nil {
log.Errorf("Error: %s", err)
return err
}
logger := log.New()
if opts.Debug {
log.SetLevel(log.DebugLevel)
logger.SetLevel(log.DebugLevel)
}
vmmCtx, vmmCancel := context.WithCancel(ctx)
defer vmmCancel()
machineOpts := []firecracker.Opt{
firecracker.WithLogger(log.NewEntry(logger)),
}
var firecrackerBinary string
if len(opts.FcBinary) != 0 {
firecrackerBinary = opts.FcBinary
} else {
firecrackerBinary, err = exec.LookPath(firecrackerDefaultPath)
if err != nil {
return err
}
}
finfo, err := os.Stat(firecrackerBinary)
if os.IsNotExist(err) {
return fmt.Errorf("Binary %q does not exist: %v", firecrackerBinary, err)
}
if err != nil {
return fmt.Errorf("Failed to stat binary, %q: %v", firecrackerBinary, err)
}
if finfo.IsDir() {
return fmt.Errorf("Binary, %q, is a directory", firecrackerBinary)
} else if finfo.Mode()&executableMask == 0 {
return fmt.Errorf("Binary, %q, is not executable. Check permissions of binary", firecrackerBinary)
}
// if the jailer is used, the final command will be built in NewMachine()
if fcCfg.JailerCfg == nil {
cmd := firecracker.VMCommandBuilder{}.
WithBin(firecrackerBinary).
WithSocketPath(fcCfg.SocketPath).
WithStdin(os.Stdin).
WithStdout(os.Stdout).
WithStderr(os.Stderr).
Build(ctx)
machineOpts = append(machineOpts, firecracker.WithProcessRunner(cmd))
}
m, err := firecracker.NewMachine(vmmCtx, fcCfg, machineOpts...)
if err != nil {
return fmt.Errorf("Failed creating machine: %s", err)
}
if err := m.Start(vmmCtx); err != nil {
return fmt.Errorf("Failed to start machine: %v", err)
}
defer m.StopVMM()
if opts.validMetadata != nil {
m.SetMetadata(vmmCtx, opts.validMetadata)
}
installSignalHandlers(vmmCtx, m)
// wait for the VMM to exit
if err := m.Wait(vmmCtx); err != nil {
return fmt.Errorf("Wait returned an error %s", err)
}
log.Printf("Start machine was happy")
return nil
}