Skip to content

Commit

Permalink
Allow specifying download format in vmexport
Browse files Browse the repository at this point in the history
This commit adds a new "--raw" flag in virtctl vmexport, so users can request downloading the raw image instead of the compressed one.

Signed-off-by: Alvaro Romero <alromero@redhat.com>
  • Loading branch information
alromeros committed Sep 7, 2023
1 parent 2ce34a3 commit 2913913
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 6 deletions.
4 changes: 4 additions & 0 deletions pkg/virtctl/memorydump/memorydump.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const (
storageClassArg = "storage-class"
accessModeArg = "access-mode"
portForwardArg = "port-forward"
rawArg = "raw"
localPortArg = "local-port"

configName = "config"
Expand All @@ -64,6 +65,7 @@ var (
claimName string
createClaim bool
portForward bool
rawImg bool
localPort string
storageClass string
accessMode string
Expand Down Expand Up @@ -118,6 +120,7 @@ func NewMemoryDumpCommand(clientConfig clientcmd.ClientConfig) *cobra.Command {
cmd.Flags().StringVar(&claimName, claimNameArg, "", "pvc name to contain the memory dump")
cmd.Flags().BoolVar(&createClaim, createClaimArg, false, "Create the pvc that will conatin the memory dump")
cmd.Flags().BoolVar(&portForward, portForwardArg, false, "Configure and set port-forward in a random port to download the memory dump")
cmd.Flags().BoolVar(&rawImg, rawArg, false, "Downloads in raw format.")
cmd.Flags().StringVar(&localPort, localPortArg, "0", "Specify port for port-forward")
cmd.Flags().StringVar(&storageClass, storageClassArg, "", "The storage class for the PVC.")
cmd.Flags().StringVar(&accessMode, accessModeArg, "", "The access mode for the PVC.")
Expand Down Expand Up @@ -335,6 +338,7 @@ func downloadMemoryDump(namespace, vmName string, virtClient kubecli.KubevirtCli
ExportSource: exportSource,
PortForward: portForward,
LocalPort: localPort,
RawImg: rawImg,
}

if portForward {
Expand Down
17 changes: 15 additions & 2 deletions pkg/virtctl/vmexport/vmexport.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const (
SNAPSHOT_FLAG = "--snapshot"
INSECURE_FLAG = "--insecure"
KEEP_FLAG = "--keep-vme"
RAW_FLAG = "--raw"
PVC_FLAG = "--pvc"
TTL_FLAG = "--ttl"
MANIFEST_FLAG = "--manifest"
Expand Down Expand Up @@ -127,6 +128,7 @@ var (
shouldCreate bool
includeSecret bool
exportManifest bool
rawImg bool
portForward bool
localPort string
serviceUrl string
Expand All @@ -153,6 +155,7 @@ type VMExportInfo struct {
KeepVme bool
IncludeSecret bool
ExportManifest bool
RawImg bool
PortForward bool
LocalPort string
OutputFile string
Expand Down Expand Up @@ -261,6 +264,7 @@ func NewVirtualMachineExportCommand(clientConfig clientcmd.ClientConfig) *cobra.
cmd.Flags().StringVar(&localPort, "local-port", "0", "Defines the specific port to be used in port-forward.")
cmd.Flags().BoolVar(&includeSecret, "include-secret", false, "When used with manifest and set to true include a secret that contains proper headers for CDI to import using the manifest")
cmd.Flags().BoolVar(&exportManifest, "manifest", false, "Instead of downloading a volume, retrieve the VM manifest")
cmd.Flags().BoolVar(&rawImg, "raw", false, "Used to download the raw image. By default, we always attempt to download the compressed one")
cmd.SetUsageTemplate(templates.UsageTemplate())

return cmd
Expand Down Expand Up @@ -350,6 +354,7 @@ func (c *command) initVMExportInfo(vmeInfo *VMExportInfo) error {
vmeInfo.ShouldCreate = shouldCreate
vmeInfo.Insecure = insecure
vmeInfo.KeepVme = keepVme
vmeInfo.RawImg = rawImg
vmeInfo.VolumeName = volumeName
vmeInfo.ServiceURL = serviceUrl
vmeInfo.OutputFormat = manifestOutputFormat
Expand Down Expand Up @@ -598,14 +603,16 @@ func GetUrlFromVirtualMachineExport(vmexport *exportv1.VirtualMachineExport, vme
// Access the requested volume
if volumeNumber == 1 || exportVolume.Name == vmeInfo.VolumeName {
for _, format := range exportVolume.Formats {
// We always attempt to find and get the compressed file URL, so we only break the loop when one is found
if format.Format == exportv1.KubeVirtGz || format.Format == exportv1.ArchiveGz || format.Format == exportv1.KubeVirtRaw {
downloadUrl, err = replaceUrlWithServiceUrl(format.Url, vmeInfo)
if err != nil {
return "", err
}
}
if format.Format == exportv1.KubeVirtGz || format.Format == exportv1.ArchiveGz {
// By default, we always attempt to find and get the compressed file URL, so we only break the loop when one is found.
// If --raw is set to true, we attempt to return the raw URL instead.
if (vmeInfo.RawImg && format.Format == exportv1.KubeVirtRaw) ||
(!vmeInfo.RawImg && (format.Format == exportv1.KubeVirtGz || format.Format == exportv1.ArchiveGz)) {
break
}
}
Expand Down Expand Up @@ -854,6 +861,9 @@ func handleCreateFlags() error {
if localPort != "0" {
return fmt.Errorf(ErrIncompatibleFlag, LOCAL_PORT_FLAG, CREATE)
}
if rawImg {
return fmt.Errorf(ErrIncompatibleFlag, RAW_FLAG, CREATE)
}
if serviceUrl != "" {
return fmt.Errorf(ErrIncompatibleFlag, SERVICE_URL_FLAG, CREATE)
}
Expand Down Expand Up @@ -885,6 +895,9 @@ func handleDeleteFlags() error {
if localPort != "0" {
return fmt.Errorf(ErrIncompatibleFlag, LOCAL_PORT_FLAG, DELETE)
}
if rawImg {
return fmt.Errorf(ErrIncompatibleFlag, RAW_FLAG, DELETE)
}
if serviceUrl != "" {
return fmt.Errorf(ErrIncompatibleFlag, SERVICE_URL_FLAG, DELETE)
}
Expand Down
59 changes: 55 additions & 4 deletions pkg/virtctl/vmexport/vmexport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,23 @@ var _ = Describe("vmexport", func() {
Expect(err).ToNot(HaveOccurred())
})

It("VirtualMachineExport download succeeds when --raw is used but only compressed is available", func() {
testInit(http.StatusOK)
vme := utils.VMExportSpecPVC(vmexportName, metav1.NamespaceDefault, "test-pvc", secretName)
vme.Status = utils.GetVMEStatus([]exportv1.VirtualMachineExportVolume{
{
Name: "no-test-volume",
Formats: utils.GetExportVolumeFormat(server.URL, exportv1.KubeVirtGz),
},
}, secretName)
utils.HandleSecretGet(kubeClient, secretName)
utils.HandleVMExportGet(vmExportClient, vme, vmexportName)

cmd := clientcmd.NewRepeatableVirtctlCommand(commandName, virtctlvmexport.DOWNLOAD, vmexportName, virtctlvmexport.RAW_FLAG, setflag(virtctlvmexport.OUTPUT_FLAG, "disk.img"), setflag(virtctlvmexport.VOLUME_FLAG, volumeName))
err := cmd()
Expect(err).ToNot(HaveOccurred())
})

It("VirtualMachineExport download succeeds when there's only one volume and no --volume has been specified", func() {
testInit(http.StatusOK)
vme := utils.VMExportSpecPVC(vmexportName, metav1.NamespaceDefault, "test-pvc", secretName)
Expand Down Expand Up @@ -439,10 +456,13 @@ var _ = Describe("vmexport", func() {

Context("getUrlFromVirtualMachineExport", func() {
// Mocking the minimum viable VMExportInfo struct
vmeinfo := &virtctlvmexport.VMExportInfo{
Name: vmexportName,
VolumeName: volumeName,
}
var vmeinfo *virtctlvmexport.VMExportInfo
BeforeEach(func() {
vmeinfo = &virtctlvmexport.VMExportInfo{
Name: vmexportName,
VolumeName: volumeName,
}
})

It("Should get compressed URL even when there's multiple URLs", func() {
vmExport := utils.VMExportSpecPVC(vmexportName, metav1.NamespaceDefault, "test-pvc", secretName)
Expand Down Expand Up @@ -487,6 +507,37 @@ var _ = Describe("vmexport", func() {
Expect(url).Should(Equal("raw"))
})

It("Should get raw URL if --raw is specified", func() {
vmExport := utils.VMExportSpecPVC(vmexportName, metav1.NamespaceDefault, "test-pvc", secretName)
vmExport.Status = utils.GetVMEStatus([]exportv1.VirtualMachineExportVolume{
{
Name: volumeName,
Formats: []exportv1.VirtualMachineExportVolumeFormat{
{
Format: exportv1.KubeVirtRaw,
Url: "raw",
},
{
Format: exportv1.KubeVirtRaw,
Url: "raw",
},
{
Format: exportv1.KubeVirtGz,
Url: "compressed",
},
{
Format: exportv1.KubeVirtRaw,
Url: "raw",
},
},
},
}, secretName)
vmeinfo.RawImg = true
url, err := virtctlvmexport.GetUrlFromVirtualMachineExport(vmExport, vmeinfo)
Expect(err).ToNot(HaveOccurred())
Expect(url).Should(Equal("raw"))
})

It("Should not get any URL when there's no valid options", func() {
vmExport := utils.VMExportSpecPVC(vmexportName, metav1.NamespaceDefault, "test-pvc", secretName)
vmExport.Status = utils.GetVMEStatus([]exportv1.VirtualMachineExportVolume{
Expand Down

0 comments on commit 2913913

Please sign in to comment.