diff --git a/examples/vm/main.hcl b/examples/vm/main.hcl new file mode 100644 index 00000000..9594cce5 --- /dev/null +++ b/examples/vm/main.hcl @@ -0,0 +1,11 @@ +resource "vm" "example" { + kernel = "/home/erik/code/jumppad/cloudhypervisor-go-sdk/examples/files/vmlinuz" + boot_args = "root=/dev/vda1 ro console=tty1 console=ttyS0" + initrd = "/home/erik/code/jumppad/cloudhypervisor-go-sdk/examples/files/initrd" + + disk { + path = "/home/erik/code/jumppad/cloudhypervisor-go-sdk/examples/files/noble.raw" + } + + serial = "/tmp/serial" +} \ No newline at end of file diff --git a/pkg/config/resources/vm/provider.go b/pkg/config/resources/vm/provider.go new file mode 100644 index 00000000..2b33066f --- /dev/null +++ b/pkg/config/resources/vm/provider.go @@ -0,0 +1,123 @@ +package vm + +import ( + "context" + "fmt" + "log" + + htypes "github.com/jumppad-labs/hclconfig/types" + sdk "github.com/jumppad-labs/plugin-sdk" + + hypervisor "github.com/jumppad-labs/cloudhypervisor-go-sdk" + api "github.com/jumppad-labs/cloudhypervisor-go-sdk/api" + "github.com/kr/pretty" +) + +var _ sdk.Provider = &Provider{} + +type Provider struct { + config *VM + log sdk.Logger +} + +func (p *Provider) Init(cfg htypes.Resource, l sdk.Logger) error { + c, ok := cfg.(*VM) + if !ok { + return fmt.Errorf("unable to initialize VM provider, resource is not of type VM") + } + + p.config = c + p.log = l + + return nil +} + +func (p *Provider) Create(ctx context.Context) error { + username := "jumppad" + password := "$6$7125787751a8d18a$sHwGySomUA1PawiNFWVCKYQN.Ec.Wzz0JtPPL1MvzFrkwmop2dq7.4CYf03A5oemPQ4pOFCCrtCelvFBEle/K." // cloud123 + + gateway := "192.168.249.1" + cidr := "192.168.249.2/24" + mac := "12:34:56:78:90:01" + + cloudinit, err := hypervisor.CreateCloudInitDisk("microvm", mac, cidr, gateway, username, password) + if err != nil { + return err + } + + config := api.VmConfig{ + Payload: api.PayloadConfig{ + Kernel: &p.config.Kernel, + Initramfs: &p.config.Initrd, + Cmdline: &p.config.BootArgs, + }, + Disks: &[]api.DiskConfig{ + { + Path: cloudinit, + }, + }, + Net: &[]api.NetConfig{ + { + Mac: &mac, + }, + }, + Cpus: &api.CpusConfig{ + BootVcpus: 1, + MaxVcpus: 1, + }, + Memory: &api.MemoryConfig{ + Size: 1024 * 1000 * 1000, // 1GB + }, + Serial: &api.ConsoleConfig{ + Mode: "File", + File: &p.config.Serial, + }, + } + + disks := []api.DiskConfig{} + for _, disk := range p.config.Disks { + disks = append(disks, api.DiskConfig{ + Path: disk.Path, + }) + } + + config.Disks = &disks + + pretty.Println(config) + + machine, err := hypervisor.NewMachine(ctx, config, log.New(p.log.StandardWriter(), "", log.LstdFlags)) + if err != nil { + return err + } + + err = machine.Start(ctx) + if err != nil { + return err + } + + err = machine.Wait(ctx) + if err != nil { + return err + } + + return nil +} + +func (p *Provider) Destroy(ctx context.Context, force bool) error { + + return nil +} + +func (p *Provider) Lookup() ([]string, error) { + return nil, nil +} + +func (p *Provider) Refresh(ctx context.Context) error { + return nil +} + +func (p *Provider) Changed() (bool, error) { + p.log.Debug("Checking changes", "ref", p.config.Meta.ID) + + return false, nil +} diff --git a/pkg/config/resources/vm/resource.go b/pkg/config/resources/vm/resource.go new file mode 100644 index 00000000..e9f06b5b --- /dev/null +++ b/pkg/config/resources/vm/resource.go @@ -0,0 +1,69 @@ +package vm + +import ( + "path/filepath" + + "github.com/jumppad-labs/hclconfig/types" + "github.com/jumppad-labs/jumppad/pkg/config" +) + +const TypeVM string = "vm" + +type VM struct { + types.ResourceBase `hcl:",remain"` + + Kernel string `hcl:"kernel" json:"kernel"` + BootArgs string `hcl:"boot_args" json:"boot_args"` + Initrd string `hcl:"initrd" json:"initrd"` + + Disks []Disk `hcl:"disk,block" json:"disk"` + + Serial string `hcl:"serial" json:"serial"` +} + +type Disk struct { + Path string `hcl:"path" json:"path"` +} + +func (c *VM) Process() error { + // use this firmware if no kernel is specified + kernel, err := filepath.Abs(c.Kernel) + if err != nil { + return err + } + + c.Kernel = kernel + + initrd, err := filepath.Abs(c.Initrd) + if err != nil { + return err + } + + c.Initrd = initrd + + for index, disk := range c.Disks { + path, err := filepath.Abs(disk.Path) + if err != nil { + return err + } + + c.Disks[index].Path = path + } + + serial, err := filepath.Abs(c.Serial) + if err != nil { + return err + } + + c.Serial = serial + + cfg, err := config.LoadState() + if err == nil { + // try and find the resource in the state + r, _ := cfg.FindResource(c.Meta.ID) + if r != nil { + } + } + + return nil +}