Skip to content

Commit

Permalink
Initial vfkit import
Browse files Browse the repository at this point in the history
vfkit is already working fairly well, it's been extracted from a
messier project.
  • Loading branch information
cfergeau committed Jan 27, 2022
0 parents commit 30c7c35
Show file tree
Hide file tree
Showing 11 changed files with 1,643 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.PHONY: all
all: build codesign

.PHONY: codesign
codesign:
codesign --entitlements vf.entitlements -s - ./vfkit

.PHONY: build
build:
go build -o vfkit ./cmd/vfkit
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
vfkit - Simple command line tool to start VMs through virtualization framework
====

vfkit offers a command-line interface to start virtual machines using virtualization framework

The work in this repository makes use of https://github.com/Code-Hex/vz to create a Linux virtual machine with virtualization.framework using go.
130 changes: 130 additions & 0 deletions cmd/vfkit/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// +build darwin

/*
Copyright 2021, Red Hat, Inc - All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"fmt"
"time"

"github.com/Code-Hex/vz"
"github.com/code-ready/vfkit/pkg/config"
"github.com/code-ready/vfkit/pkg/vf"
"github.com/docker/go-units"
log "github.com/sirupsen/logrus"
)

type cmdlineOptions struct {
vcpus uint
memoryMiB uint

vmlinuzPath string
kernelCmdline string
initrdPath string

devices []string
}

func newVMConfiguration(opts *cmdlineOptions) (*config.VirtualMachine, error) {
log.Info(opts)
bootLoader := config.NewBootloader(
opts.vmlinuzPath,
opts.kernelCmdline,
opts.initrdPath,
)
log.Info("boot parameters:")
log.Infof("\tkernel: %s", opts.vmlinuzPath)
log.Infof("\tkernel command line:%s", opts.kernelCmdline)
log.Infof("\tinitrd: %s", opts.initrdPath)
log.Info()

vmConfig := config.NewVirtualMachine(
opts.vcpus,
uint64(opts.memoryMiB*units.MiB),
bootLoader,
)
log.Info("virtual machine parameters:")
log.Infof("\tvCPUs: %d", opts.vcpus)
log.Infof("\tmemory: %d MiB", opts.memoryMiB)
log.Info()

if err := vmConfig.AddDevicesFromCmdLine(opts.devices); err != nil {
return nil, err
}

return vmConfig, nil
}

func waitForVMState(vm *vz.VirtualMachine, state vz.VirtualMachineState) error {
for {
select {
case newState := <-vm.StateChangedNotify():
if newState == state {
return nil
}
case <-time.After(5 * time.Second):
return fmt.Errorf("timeout waiting for VM state %v", state)
}
}
}

func runVirtualMachine(vmConfig *config.VirtualMachine) error {
vsockDevs := vmConfig.VirtioVsockDevices()
if len(vsockDevs) > 1 {
return fmt.Errorf("Can only configure one virtio-vsock device")
}

vzVMConfig, err := vmConfig.ToVzVirtualMachineConfig()
if err != nil {
return err
}

vm := vz.NewVirtualMachine(vzVMConfig)

errCh := make(chan error, 1)
vm.Start(func(err error) {
if err != nil {
errCh <- err
}
errCh <- waitForVMState(vm, vz.VirtualMachineStateRunning)
})

err = <-errCh
if err != nil {
return err
}
log.Infof("virtual machine is running")

if len(vsockDevs) == 1 {
port := vsockDevs[0].Port
socketURL := vsockDevs[0].SocketURL
log.Infof("Exposing vsock port %d on %s", port, socketURL)
if err := vf.ExposeVsock(vm, port, socketURL); err != nil {
log.Warnf("error listening on vsock: %v", err)
}
}
log.Infof("waiting for VM to stop")
for {
err := waitForVMState(vm, vz.VirtualMachineStateStopped)
if err == nil {
log.Infof("VM is stopped")
return nil
}
}

}
53 changes: 53 additions & 0 deletions cmd/vfkit/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

const vfkitVersion = "0.0.1"

var opts = &cmdlineOptions{}

var rootCmd = &cobra.Command{
Use: "vfkit",
Short: "vfkit is a simple hypervisor using Apple's virtualization framework",
Long: `A hypervisor written in Go using Apple's virtualization framework to run linux virtual machines.
Complete documentation is available at https://github.com/code-ready/vfkit`,
RunE: func(cmd *cobra.Command, args []string) error {
vmConfig, err := newVMConfiguration(opts)
if err != nil {
return err
}
return runVirtualMachine(vmConfig)
},
Version: vfkitVersion,
}

func init() {
rootCmd.Flags().StringVarP(&opts.vmlinuzPath, "kernel", "k", "", "path to the virtual machine linux kernel")
rootCmd.Flags().StringVarP(&opts.kernelCmdline, "kernel-cmdline", "C", "", "linux kernel command line")
rootCmd.Flags().StringVarP(&opts.initrdPath, "initrd", "i", "", "path to the virtual machine initrd")
rootCmd.MarkFlagRequired("kernel")
rootCmd.MarkFlagRequired("kernel-cmdline")
rootCmd.MarkFlagRequired("initrd")

rootCmd.Flags().UintVarP(&opts.vcpus, "cpus", "c", 1, "number of virtual CPUs")
// FIXME: use go-units for parsing
rootCmd.Flags().UintVarP(&opts.memoryMiB, "memory", "m", 512, "virtual machine RAM size in mibibytes")

rootCmd.Flags().StringArrayVarP(&opts.devices, "device", "d", []string{}, "devices")
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

func main() {
Execute()
}
13 changes: 13 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module github.com/code-ready/vfkit

go 1.16

require (
github.com/Code-Hex/vz v0.0.5-0.20211218053248-d70a0533bf8e
github.com/docker/go-units v0.4.0
github.com/rs/xid v1.3.0 // indirect
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.3.0
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
inet.af/tcpproxy v0.0.0-20210824174053-2e577fef49e2
)
Loading

0 comments on commit 30c7c35

Please sign in to comment.