Skip to content

Commit

Permalink
Fix OVA generation
Browse files Browse the repository at this point in the history
- Flush after last header
- rename the VM to MigrationAssessment
- Send Content-Type and Content-length headers

Signed-off-by: Ondra Machacek <[email protected]>
  • Loading branch information
machacekondra committed Dec 16, 2024
1 parent b3dcc8f commit be8b922
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 8 deletions.
4 changes: 2 additions & 2 deletions data/AgentVM.ovf → data/MigrationAssessment.ovf
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<?xml version='1.0' encoding='UTF-8'?>
<Envelope xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" xmlns:vmw="http://www.vmware.com/schema/ovf" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData">
<References>
<File ovf:id="file1" ovf:href="AgentVM-1.iso" ovf:size="1220542464"/>
<File ovf:id="file1" ovf:href="MigrationAssessment.iso" ovf:size="1220542464"/>
</References>
<NetworkSection>
<Info>The list of logical networks</Info>
<Network ovf:name="routable-network">
<Description>Routable network</Description>
</Network>
</NetworkSection>
<VirtualSystem ovf:id="AgentVM">
<VirtualSystem ovf:id="MigrationAssessment">
<Info>A Virtual system</Info>
<Name>MigrationAssessment</Name>
<OperatingSystemSection ovf:id="80" ovf:version="8" vmw:osType="rhel9_64Guest">
Expand Down
69 changes: 65 additions & 4 deletions internal/image/ova.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,31 @@ func (o *Ova) Validate() error {
return nil
}

func calculateTarSize(contentSize int) int {
const blockSize = 512

// Size of the tar header block
size := blockSize

// Size of the file content, rounded up to nearest 512 bytes
size += ((contentSize + blockSize - 1) / blockSize) * blockSize

return size
}

func (o *Ova) OvaSize() (int, error) {
isoSize, err := o.isoSize()
if err != nil {
return -1, err
}
ovfSize, err := o.ovfSize()
if err != nil {
return -1, err
}

return ovfSize + isoSize, nil
}

func (o *Ova) Generate() error {
tw := tar.NewWriter(o.Writer)

Expand All @@ -64,6 +89,8 @@ func (o *Ova) Generate() error {
return err
}

tw.Flush()

return nil
}

Expand All @@ -88,13 +115,13 @@ func (o *Ova) writeIso(tw *tar.Writer) error {
if err != nil {
return err
}
// Create a header for AgentVM-1.iso
// Create a header for MigrationAssessment.iso
length, err := reader.Seek(0, io.SeekEnd)
if err != nil {
return err
}
header := &tar.Header{
Name: "AgentVM-1.iso",
Name: "MigrationAssessment.iso",
Size: length,
Mode: 0600,
ModTime: time.Now(),
Expand All @@ -118,14 +145,48 @@ func (o *Ova) writeIso(tw *tar.Writer) error {
return nil
}

func (o *Ova) isoSize() (int, error) {
// Get ISO reader
reader, err := o.isoReader()
if err != nil {
return -1, err
}
length, err := reader.Seek(0, io.SeekEnd)
if err != nil {
return -1, err
}

// Reset the reader to start
_, err = reader.Seek(0, io.SeekStart)
if err != nil {
return -1, err
}

return calculateTarSize(int(length)), nil
}

func (o *Ova) ovfSize() (int, error) {
file, err := os.Open("data/MigrationAssessment.ovf")
if err != nil {
return -1, err
}
defer file.Close()
fileInfo, err := file.Stat()
if err != nil {
return -1, err
}

return calculateTarSize(int(fileInfo.Size())), nil
}

func writeOvf(tw *tar.Writer) error {
ovfContent, err := os.ReadFile("data/AgentVM.ovf")
ovfContent, err := os.ReadFile("data/MigrationAssessment.ovf")
if err != nil {
return err
}
// Create a header for AgentVM.ovf
header := &tar.Header{
Name: "AgentVM.ovf",
Name: "MigrationAssessment.ovf",
Size: int64(len(ovfContent)),
Mode: 0600,
ModTime: time.Now(),
Expand Down
15 changes: 14 additions & 1 deletion internal/service/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"fmt"
"net/http"
"strconv"

"github.com/kubev2v/migration-planner/internal/api/server"
"github.com/kubev2v/migration-planner/internal/auth"
Expand All @@ -16,12 +17,24 @@ func (h *ServiceHandler) GetImage(ctx context.Context, request server.GetImageRe
if !ok {
return server.GetImage500JSONResponse{Message: "error creating the HTTP stream"}, nil
}

ova := &image.Ova{SshKey: request.Params.SshKey, Writer: writer}

// get token if any
if user, found := auth.UserFromContext(ctx); found {
ova.Jwt = user.Token
}

// Calculate the size of the OVA, so the download show estimated time:
size, err := ova.OvaSize()
if err != nil {
return server.GetImage500JSONResponse{Message: "error creating the HTTP stream"}, nil
}

// Set proper headers of the OVA file:
writer.Header().Set("Content-Type", "application/ovf")
writer.Header().Set("Content-Length", strconv.Itoa(size))

// Generate the OVA image
if err := ova.Generate(); err != nil {
return server.GetImage500JSONResponse{Message: fmt.Sprintf("error generating image %s", err)}, nil
}
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/e2e_agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (p *plannerAgentLibvirt) prepareImage() error {
}

// Untar ISO from OVA
if err = Untar(file, defaultIsoPath, "AgentVM-1.iso"); err != nil {
if err = Untar(file, defaultIsoPath, "MigrationAssessment.iso"); err != nil {
return fmt.Errorf("error uncompressing the file: %w", err)
}

Expand Down

0 comments on commit be8b922

Please sign in to comment.