Skip to content

Commit

Permalink
Expose virtual size of VM images
Browse files Browse the repository at this point in the history
This requires:

- longhorn/backing-image-manager#208
- longhorn/longhorn-manager#2680

With this change, we can do this:

  # kubectl get vmimages
  NAME          DISPLAY-NAME                                         SIZE          VIRTUALSIZE   AGE
  image-26r4s   sles15-sp5-minimal-vm.x86_64-kvm-and-xen-qu1.qcow2   267845632     25769803776   6m36s
  image-bgnhb   sle-micro.x86_64-5.5.0-default-qcow-gm.qcow2         1001652224    21474836480   20m
  image-nmmvj   sle-15-sp5-full-x86_64-gm-media1.iso                 14548992000   14548992000   19m

Related issue: harvester#4905

Signed-off-by: Tim Serong <[email protected]>
  • Loading branch information
tserong committed Mar 18, 2024
1 parent 61d9ecd commit 46124b2
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ spec:
- jsonPath: .status.size
name: SIZE
type: integer
- jsonPath: .status.virtualSize
name: VIRTUALSIZE
type: integer
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
Expand Down Expand Up @@ -123,6 +126,9 @@ spec:
type: integer
storageClassName:
type: string
virtualSize:
format: int64
type: integer
type: object
required:
- spec
Expand Down
4 changes: 4 additions & 0 deletions pkg/apis/harvesterhci.io/v1beta1/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
// +kubebuilder:resource:shortName=vmimage;vmimages,scope=Namespaced
// +kubebuilder:printcolumn:name="DISPLAY-NAME",type=string,JSONPath=`.spec.displayName`
// +kubebuilder:printcolumn:name="SIZE",type=integer,JSONPath=`.status.size`
// +kubebuilder:printcolumn:name="VIRTUALSIZE",type=integer,JSONPath=`.status.virtualSize`
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=`.metadata.creationTimestamp`

type VirtualMachineImage struct {
Expand Down Expand Up @@ -77,6 +78,9 @@ type VirtualMachineImageStatus struct {
// +optional
Size int64 `json:"size,omitempty"`

// +optional
VirtualSize int64 `json:"virtualSize,omitempty"`

// +optional
StorageClassName string `json:"storageClassName,omitempty"`

Expand Down
32 changes: 28 additions & 4 deletions pkg/controller/master/image/backing_image_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,26 @@ func (h *backingImageHandler) OnChanged(_ string, backingImage *lhv1beta2.Backin
} else if err != nil {
return nil, err
}
if !harvesterv1beta1.ImageInitialized.IsTrue(vmImage) || !harvesterv1beta1.ImageImported.IsUnknown(vmImage) {
// There are two states that we care about here:
// - ImageInitialized
// - ImageImported
// If ImageInitialized isn't yet true, it means there's no backing
// image or storage class, so we've got nothing to work with yet and
// should return immediately.
if !harvesterv1beta1.ImageInitialized.IsTrue(vmImage) {
return nil, nil
}
// If ImageImported is not unknown, it means the backing image has
// been imported, and we think we know everything about it, i.e. we've
// now been through a series of progress updates during image download,
// and those are finally done, so let's not worry about further updates.
// The problem with this logic is that when we add new fields (e.g.
// VirtualSize), existing images won't pick up those newly added fields
// if we return here immediately. So, now there's an additional check
// for that new field. Another, simpler, alternative would be to just
// drop the ImageImported.IsUnknown check entirely, and let the following
// loop run through on every OnChanged event.
if !harvesterv1beta1.ImageImported.IsUnknown(vmImage) && vmImage.Status.VirtualSize == backingImage.Status.VirtualSize {
return nil, nil
}
toUpdate := vmImage.DeepCopy()
Expand All @@ -46,11 +65,16 @@ func (h *backingImageHandler) OnChanged(_ string, backingImage *lhv1beta2.Backin
toUpdate = handleFail(toUpdate, condition.Cond(harvesterv1beta1.ImageImported), fmt.Errorf(status.Message))
toUpdate.Status.Progress = status.Progress
} else if status.State == lhv1beta2.BackingImageStateReady || status.State == lhv1beta2.BackingImageStateReadyForTransfer {
harvesterv1beta1.ImageImported.True(toUpdate)
harvesterv1beta1.ImageImported.Reason(toUpdate, "Imported")
harvesterv1beta1.ImageImported.Message(toUpdate, status.Message)
toUpdate.Status.Progress = status.Progress
toUpdate.Status.Size = backingImage.Status.Size
toUpdate.Status.VirtualSize = backingImage.Status.VirtualSize
if toUpdate.Status.VirtualSize > 0 {
// We can't set ImageImported to True until we know the VirtualSize,
// which may happen one update after the image becomes ready.
harvesterv1beta1.ImageImported.True(toUpdate)
harvesterv1beta1.ImageImported.Reason(toUpdate, "Imported")
harvesterv1beta1.ImageImported.Message(toUpdate, status.Message)
}
} else if status.Progress != toUpdate.Status.Progress {
harvesterv1beta1.ImageImported.Unknown(toUpdate)
harvesterv1beta1.ImageImported.Reason(toUpdate, "Importing")
Expand Down

0 comments on commit 46124b2

Please sign in to comment.