Skip to content

Commit

Permalink
Merge pull request #16 from beringresearch/debian
Browse files Browse the repository at this point in the history
disable mount by default, better qc, enable custom images, enable cus…
  • Loading branch information
idroz authored Jun 6, 2022
2 parents ef65c4e + 0993d23 commit 226c56b
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 70 deletions.
39 changes: 18 additions & 21 deletions cmd/launch.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,29 @@ var launchCmd = &cobra.Command{
Run: launch,
}

var machineArch, machineVersion, machineCPU, machineMemory, machineDisk, machinePort, sshPort, machineName, machineMount string
var machineArch, imageVersion, machineCPU, machineMemory, machineDisk, machinePort, sshPort, machineName, machineMount string

func init() {
includeLaunchFlags(launchCmd)
}

func includeLaunchFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&machineVersion, "version", "v", "3.16.0", "Alpine image version.")
cmd.Flags().StringVarP(&imageVersion, "image", "i", "alpine_3.16.0", "Image to be launched.")
cmd.Flags().StringVarP(&machineArch, "arch", "a", "x86_64", "Machine architecture.")
cmd.Flags().StringVarP(&machineCPU, "cpu", "c", "4", "Number of CPUs to allocate.")
cmd.Flags().StringVarP(&machineMemory, "memory", "m", "2048", "Amount of memory to allocate. Positive integers, in kilobytes.")
cmd.Flags().StringVarP(&machineDisk, "disk", "d", "10G", "Disk space to allocate. Positive integers, in bytes, or with K, M, G suffix.")
cmd.Flags().StringVarP(&machineMount, "mount", "", "", "Path to host directory to be exposed on guest. (default $HOME)")
cmd.Flags().StringVarP(&machineMount, "mount", "", "", "Path to host directory to be exposed on guest.")
cmd.Flags().StringVarP(&sshPort, "ssh", "s", "22", "Forward VM SSH port to host.")
cmd.Flags().StringVarP(&machinePort, "port", "p", "", "Forward VM ports to host. Multiple ports can be separated by `,`.")
cmd.Flags().StringVarP(&machineName, "name", "n", "", "Name for the instance")
}

func correctArguments(machineVersion string, machineArch string, machineCPU string,
func correctArguments(imageVersion string, machineArch string, machineCPU string,
machineMemory string, machineDisk string, sshPort string, machinePort string) error {

if machineVersion != "3.16.0" {
return errors.New("unsupported version. only -v 3.16.0 is currently available")
if !utils.StringSliceContains([]string{"alpine_3.16.0", "debian_11.3.0"}, imageVersion) {
return errors.New("unsupported image. only -i alpine_3.16.0 | debian_11.3.0 are currently available")
}

if machineArch != "aarch64" && machineArch != "x86_64" {
Expand Down Expand Up @@ -107,7 +107,7 @@ func correctArguments(machineVersion string, machineArch string, machineCPU stri

func launch(cmd *cobra.Command, args []string) {

err := correctArguments(machineVersion, machineArch, machineCPU, machineMemory, machineDisk, sshPort, machinePort)
err := correctArguments(imageVersion, machineArch, machineCPU, machineMemory, machineDisk, sshPort, machinePort)
if err != nil {
log.Fatal("parameter format: " + err.Error())
}
Expand All @@ -131,21 +131,18 @@ func launch(cmd *cobra.Command, args []string) {
log.Fatal("machine " + machineName + " exists")
}

if machineMount == "" {
machineMount = userHomeDir
}

machineConfig := qemu.MachineConfig{
Alias: machineName,
Image: "alpine_" + machineVersion + "-" + machineArch + ".qcow2",
Arch: machineArch,
Version: machineVersion,
CPU: machineCPU,
Memory: machineMemory,
Disk: machineDisk,
Mount: machineMount,
Port: machinePort,
SSHPort: sshPort,
Alias: machineName,
Image: imageVersion + "-" + machineArch + ".qcow2",
Arch: machineArch,
CPU: machineCPU,
Memory: machineMemory,
Disk: machineDisk,
Mount: machineMount,
Port: machinePort,
SSHPort: sshPort,
SSHUser: "root",
SSHPassword: "root",
}
machineConfig.Location = filepath.Join(userHomeDir, ".macpine", machineConfig.Alias)

Expand Down
5 changes: 3 additions & 2 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log"
"os"
"path/filepath"
"strings"
"text/tabwriter"

"github.com/beringresearch/macpine/host"
Expand Down Expand Up @@ -58,9 +59,9 @@ func list(cmd *cobra.Command, args []string) {
}

w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
fmt.Fprintln(w, "NAME\tSTATUS\tSSH\tPORTS\tARCH\tPID\t")
fmt.Fprintln(w, "NAME\tOS\tSTATUS\tSSH\tPORTS\tARCH\tPID\t")
for i, machine := range config {
fmt.Fprintln(w, machine.Alias+" \t"+status[i]+" \t"+machine.SSHPort+" \t"+machine.Port+" \t"+machine.Arch+" \t"+fmt.Sprint(pid[i])+" \t")
fmt.Fprintln(w, machine.Alias+" \t"+strings.Split(machine.Image, "_")[0]+" \t"+status[i]+" \t"+machine.SSHPort+" \t"+machine.Port+" \t"+machine.Arch+" \t"+fmt.Sprint(pid[i])+" \t")
}
w.Flush()

Expand Down
85 changes: 42 additions & 43 deletions qemu/ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@ import (
)

type MachineConfig struct {
Alias string `yaml:"alias"`
Image string `yaml:"image"`
Arch string `yaml:"arch"`
Version string `yaml:"version"`
CPU string `yaml:"cpu"`
Memory string `yaml:"memory"`
Disk string `yaml:"disk"`
Mount string `yaml:"mount"`
Port string `yaml:"port"`
SSHPort string `yaml:"sshport"`
Location string `yaml:"location"`
Alias string `yaml:"alias"`
Image string `yaml:"image"`
Arch string `yaml:"arch"`
CPU string `yaml:"cpu"`
Memory string `yaml:"memory"`
Disk string `yaml:"disk"`
Mount string `yaml:"mount"`
Port string `yaml:"port"`
SSHPort string `yaml:"sshport"`
SSHUser string `yaml:"sshuser"`
SSHPassword string `yaml:"sshpassword"`
Location string `yaml:"location"`
}

//ExecShell starts an interactive shell terminal in VM
func (c *MachineConfig) ExecShell() error {

host := "localhost:" + c.SSHPort
user := "root"
pwd := "root"
user := c.SSHUser
pwd := c.SSHPassword

var err error

Expand Down Expand Up @@ -102,10 +103,10 @@ func (c *MachineConfig) ExecShell() error {
func (c *MachineConfig) Exec(cmd string) error {

config := &ssh.ClientConfig{
User: "root",
User: c.SSHUser,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Auth: []ssh.AuthMethod{
ssh.Password("root"),
ssh.Password(c.SSHPassword),
},
}

Expand Down Expand Up @@ -189,15 +190,6 @@ func (c *MachineConfig) Stop() error {
// Start starts up an Alpine VM
func (c *MachineConfig) Start() error {

userHomeDir, err := os.UserHomeDir()
if err != nil {
log.Fatal(err)
}

if c.Mount == "" {
c.Mount = userHomeDir
}

exposedPorts := "user,id=net0,hostfwd=tcp::" + c.SSHPort + "-:22"

if c.Port != "" {
Expand All @@ -213,7 +205,7 @@ func (c *MachineConfig) Start() error {

accelAarch64 := "hvf"

_, err = syscall.Sysctl("sysctl.proc_translated")
_, err := syscall.Sysctl("sysctl.proc_translated")
appleSilicon := true
if err != nil && err.Error() == "no such file or directory" {
accelAarch64 = "tcg"
Expand Down Expand Up @@ -241,7 +233,10 @@ func (c *MachineConfig) Start() error {

x86Args := []string{"-accel", accelx86}

commonArgs := []string{"-m", c.Memory, "-global", "ICH9-LPC.disable_s3=1",
mountArgs := []string{"-fsdev", "local,path=" + c.Mount + ",security_model=none,id=host0",
"-device", "virtio-9p-pci,fsdev=host0,mount_tag=host0"}

commonArgs := []string{"-m", c.Memory,
"-smp", c.CPU + ",sockets=1,cores=" + c.CPU + ",threads=1",
"-hda", filepath.Join(c.Location, c.Image),
"-nographic",
Expand All @@ -255,9 +250,7 @@ func (c *MachineConfig) Start() error {
"-qmp", "chardev:char-qmp",
"-parallel", "none",
//"-virtfs", "local,path=" + c.Mount + ",security_model=none,mount_tag=Home",
"-fsdev", "local,path=" + c.Mount + ",security_model=none,id=host0",
"-device", "virtio-9p-pci,fsdev=host0,mount_tag=host0",
"-name", "alpine"}
"-name", c.Alias}

if c.Arch == "aarch64" {
qemuArgs = append(aarch64Args, commonArgs...)
Expand All @@ -266,6 +259,10 @@ func (c *MachineConfig) Start() error {
qemuArgs = append(x86Args, commonArgs...)
}

if c.Mount != "" {
qemuArgs = append(qemuArgs, mountArgs...)
}

cmd := exec.Command(qemuCmd, qemuArgs...,
)

Expand All @@ -282,20 +279,22 @@ func (c *MachineConfig) Start() error {

time.Sleep(1 * time.Second)

err = utils.Retry(10, 2*time.Second, func() error {
err := c.Exec("mkdir -p /root/mnt/; mount -t 9p -o trans=virtio host0 /root/mnt/")
if c.Mount != "" {
err = utils.Retry(10, 2*time.Second, func() error {
err := c.Exec("mkdir -p /root/mnt/; mount -t 9p -o trans=virtio host0 /root/mnt/")
if err != nil {
return err
}
return nil
})

if err != nil {
return err
return errors.New("unable to mount: " + err.Error())
}
return nil
})

if err != nil {
return errors.New("unable to mount: " + err.Error())
log.Printf("Mounted " + c.Mount + ": /root/mnt/")
}

log.Printf("Mounted " + c.Mount + ": /root/mnt/")

status, _ := c.Status()

if status == "Stopped" {
Expand All @@ -319,12 +318,12 @@ func (c *MachineConfig) Launch() error {
return err
}

imageName, alpineURL := utils.GetAlpineURL(c.Version, c.Arch)
imageURL := utils.GetImageURL(c.Image)

if _, err := os.Stat(filepath.Join(cacheDir, imageName)); errors.Is(err, os.ErrNotExist) {
err = utils.DownloadFile(filepath.Join(cacheDir, imageName), alpineURL)
if _, err := os.Stat(filepath.Join(cacheDir, c.Image)); errors.Is(err, os.ErrNotExist) {
err = utils.DownloadFile(filepath.Join(cacheDir, c.Image), imageURL)
if err != nil {
return errors.New("unable to download Alpine " + c.Version + " for " + c.Arch + ": " + err.Error())
return errors.New("unable to download " + c.Image + " for " + c.Arch + ": " + err.Error())
}
}

Expand All @@ -344,7 +343,7 @@ func (c *MachineConfig) Launch() error {
return err
}

_, err = utils.CopyFile(filepath.Join(cacheDir, imageName), filepath.Join(targetDir, imageName))
_, err = utils.CopyFile(filepath.Join(cacheDir, c.Image), filepath.Join(targetDir, c.Image))
if err != nil {
os.RemoveAll(targetDir)
return err
Expand Down
11 changes: 7 additions & 4 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"
)
Expand Down Expand Up @@ -206,6 +207,9 @@ func DownloadFile(filepath string, url string) error {
}

resp, err := http.Get(url)
if resp.StatusCode != 200 {
return errors.New("requested image download is not supported: StatusCode " + strconv.Itoa(resp.StatusCode))
}
if err != nil {
out.Close()
return err
Expand All @@ -227,10 +231,9 @@ func DownloadFile(filepath string, url string) error {
return nil
}

func GetAlpineURL(version string, arch string) (string, string) {
imageFile := "alpine_" + version + "-" + arch + ".qcow2"
url := "https://github.com/beringresearch/macpine/releases/download/v.01/" + imageFile
return imageFile, url
func GetImageURL(version string) string {
url := "https://github.com/beringresearch/macpine/releases/download/v.01/" + version
return url
}

func DirExists(path string) (bool, error) {
Expand Down

0 comments on commit 226c56b

Please sign in to comment.