115 lines
2.4 KiB
Go
115 lines
2.4 KiB
Go
package image
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"github.com/abdfnx/gosh"
|
|
"github.com/rayaman/go-qemu/pkg/v1/types"
|
|
"github.com/rayaman/go-qemu/pkg/v1/types/disk"
|
|
)
|
|
|
|
// create [--object OBJECTDEF] [-q] [-f FMT] [-b BACKING_FILE [-F BACKING_FMT]] [-u] [-o OPTIONS] FILENAME [SIZE]
|
|
|
|
// Creates an image based of the supplied image structure
|
|
func Create(i Image, size disk.Size, opts ...Options) error {
|
|
|
|
data := getMap(i)
|
|
|
|
var imagename string
|
|
var ok bool
|
|
|
|
if imagename, ok = getData(data, "image_name"); !(ok && imagename != "") {
|
|
return fmt.Errorf("invalid image data, ImageName is not optional")
|
|
}
|
|
|
|
os.MkdirAll(filepath.Join(filepath.Dir(imagename), "/base"), os.ModePerm)
|
|
basepath := filepath.Dir(imagename)
|
|
basename := filepath.Base(imagename)
|
|
|
|
if len(opts) > 0 && opts[0].IsBaseImage {
|
|
imagename = filepath.Join(basepath, "base", basename)
|
|
}
|
|
|
|
additional := []string{}
|
|
if backing_file, ok := getData(data, "backing_file"); ok {
|
|
additional = append(additional, "-b "+backing_file+" ")
|
|
}
|
|
|
|
if backing_fmt, ok := getData(data, "backing_fmt"); ok {
|
|
additional = append(additional, "-F "+backing_fmt+" ")
|
|
}
|
|
|
|
format := string(strings.ReplaceAll(strings.ToLower(reflect.TypeOf(i).String()), "*formats.", ""))
|
|
cmd := fmt.Sprintf("qemu-img create -f %s %v%v%v %v", format, strings.Join(additional, ""), getOptions(data), imagename, size)
|
|
|
|
// Todo remove this when done testing
|
|
fmt.Println(cmd)
|
|
err, _, errout := gosh.RunOutput(cmd)
|
|
|
|
if errout != "" {
|
|
return fmt.Errorf("%v", errout)
|
|
}
|
|
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Loads a saved image structure into memory
|
|
func LoadImage(path string) (Image, error) {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var h = &holder{}
|
|
|
|
err = json.Unmarshal(data, h)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data, err = json.Marshal(h.Image)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
t := reflect.New(reflect.TypeOf(types.GetTypes()[h.Format])).Interface()
|
|
err = json.Unmarshal(data, t)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return t, nil
|
|
}
|
|
|
|
// Saves an image structure to disk
|
|
func SaveImage(path string, img Image) error {
|
|
|
|
data, err := json.MarshalIndent(holder{
|
|
Format: strings.ReplaceAll(strings.ToLower(reflect.TypeOf(img).String()), "*formats.", ""),
|
|
Image: img,
|
|
}, "", "\t")
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
file, err := os.Create(path)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = file.Write(data)
|
|
|
|
return err
|
|
}
|