diff --git a/cmd/osbuild-worker/main.go b/cmd/osbuild-worker/main.go index d4365b583..1913f068e 100644 --- a/cmd/osbuild-worker/main.go +++ b/cmd/osbuild-worker/main.go @@ -11,6 +11,7 @@ import ( "io/ioutil" "log" "os" + "os/exec" "path" "time" @@ -65,6 +66,26 @@ func (e *TargetsError) Error() string { return errString } +func openAsStreamOptimizedVmdk(imagePath string) (*os.File, error) { + newPath := imagePath + ".stream" + cmd := exec.Command( + "/usr/bin/qemu-img", "convert", "-O", "vmdk", "-o", "subformat=streamOptimized", + imagePath, newPath) + err := cmd.Run() + if err != nil { + return nil, err + } + f, err := os.Open(newPath) + if err != nil { + return nil, err + } + err = os.Remove(newPath) + if err != nil { + return nil, err + } + return f, err +} + func RunJob(job *worker.Job, store string, uploadFunc func(uuid.UUID, string, io.Reader) error) (*common.ComposeResult, error) { outputDirectory, err := ioutil.TempDir("/var/tmp", "osbuild-worker-*") if err != nil { @@ -87,10 +108,20 @@ func RunJob(job *worker.Job, store string, uploadFunc func(uuid.UUID, string, io for _, t := range job.Targets { switch options := t.Options.(type) { case *target.LocalTargetOptions: - f, err := os.Open(path.Join(outputDirectory, options.Filename)) - if err != nil { - r = append(r, err) - continue + var f *os.File + imagePath := path.Join(outputDirectory, options.Filename) + if options.StreamOptimized { + f, err = openAsStreamOptimizedVmdk(imagePath) + if err != nil { + r = append(r, err) + continue + } + } else { + f, err = os.Open(imagePath) + if err != nil { + r = append(r, err) + continue + } } err = uploadFunc(job.Id, options.Filename, f) diff --git a/golang-github-osbuild-composer.spec b/golang-github-osbuild-composer.spec index 6fa19fd16..b38dae55c 100644 --- a/golang-github-osbuild-composer.spec +++ b/golang-github-osbuild-composer.spec @@ -47,6 +47,7 @@ Requires: %{name}-worker = %{version}-%{release} Requires: systemd Requires: osbuild >= 18 Requires: osbuild-ostree >= 18 +Requires: qemu-img Provides: osbuild-composer Provides: weldr diff --git a/internal/target/local_target.go b/internal/target/local_target.go index 6e57f5d20..49083a84f 100644 --- a/internal/target/local_target.go +++ b/internal/target/local_target.go @@ -3,9 +3,10 @@ package target import "github.com/google/uuid" type LocalTargetOptions struct { - ComposeId uuid.UUID `json:"compose_id"` - ImageBuildId int `json:"image_build_id"` - Filename string `json:"filename"` + ComposeId uuid.UUID `json:"compose_id"` + ImageBuildId int `json:"image_build_id"` + Filename string `json:"filename"` + StreamOptimized bool `json:"stream_optimized"` // return image as stream optimized } func (LocalTargetOptions) isTargetOptions() {} diff --git a/internal/weldr/api.go b/internal/weldr/api.go index 6a8988377..243242a1b 100644 --- a/internal/weldr/api.go +++ b/internal/weldr/api.go @@ -1753,9 +1753,10 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request targets = append(targets, target.NewLocalTarget( &target.LocalTargetOptions{ - ComposeId: composeID, - ImageBuildId: 0, - Filename: imageType.Filename(), + ComposeId: composeID, + ImageBuildId: 0, + Filename: imageType.Filename(), + StreamOptimized: imageType.Name() == "vmdk", // TODO: move conversion to osbuild }, )) diff --git a/osbuild-composer.spec b/osbuild-composer.spec index 7129640e0..fa6837d96 100644 --- a/osbuild-composer.spec +++ b/osbuild-composer.spec @@ -52,6 +52,7 @@ Requires: %{name}-worker = %{version}-%{release} Requires: systemd Requires: osbuild >= 18 Requires: osbuild-ostree >= 18 +Requires: qemu-img Provides: weldr