diff --git a/controller/backing_image_controller.go b/controller/backing_image_controller.go index b2b3e9d6f1..42a9c499a8 100644 --- a/controller/backing_image_controller.go +++ b/controller/backing_image_controller.go @@ -819,7 +819,7 @@ func (bic *BackingImageController) syncBackingImageFileInfo(bi *longhorn.Backing if bi.Status.DiskFileStatusMap[bim.Spec.DiskUUID].State != longhorn.BackingImageStateFailed { msg := fmt.Sprintf("found mismatching size %v reported by backing image manager %v in disk %v, the size recorded in status is %v", info.Size, bim.Name, bim.Spec.DiskUUID, bi.Status.Size) - log.Error(msg) + bic.eventRecorder.Eventf(bi, corev1.EventTypeWarning, constant.EventReasonUpdate, msg) bi.Status.DiskFileStatusMap[bim.Spec.DiskUUID].State = longhorn.BackingImageStateFailed bi.Status.DiskFileStatusMap[bim.Spec.DiskUUID].Message = msg } @@ -834,7 +834,22 @@ func (bic *BackingImageController) syncBackingImageFileInfo(bi *longhorn.Backing if bi.Status.DiskFileStatusMap[bim.Spec.DiskUUID].State != longhorn.BackingImageStateFailed { msg := fmt.Sprintf("found mismatching virtualSize %v reported by backing image manager %v in disk %v, the virtualSize recorded in status is %v", info.VirtualSize, bim.Name, bim.Spec.DiskUUID, bi.Status.VirtualSize) - log.Error(msg) + bic.eventRecorder.Eventf(bi, corev1.EventTypeWarning, constant.EventReasonUpdate, msg) + bi.Status.DiskFileStatusMap[bim.Spec.DiskUUID].State = longhorn.BackingImageStateFailed + bi.Status.DiskFileStatusMap[bim.Spec.DiskUUID].Message = msg + } + } + } + if info.RealSize > 0 { + if bi.Status.RealSize == 0 { + bi.Status.RealSize = info.RealSize + bic.eventRecorder.Eventf(bi, corev1.EventTypeNormal, constant.EventReasonUpdate, "Set realSize to %v", bi.Status.RealSize) + } + if bi.Status.RealSize != info.RealSize { + if bi.Status.DiskFileStatusMap[bim.Spec.DiskUUID].State != longhorn.BackingImageStateFailed { + msg := fmt.Sprintf("found mismatching realSize %v reported by backing image manager %v in disk %v, the realSize recorded in status is %v", + info.RealSize, bim.Name, bim.Spec.DiskUUID, bi.Status.RealSize) + bic.eventRecorder.Eventf(bi, corev1.EventTypeWarning, constant.EventReasonUpdate, msg) bi.Status.DiskFileStatusMap[bim.Spec.DiskUUID].State = longhorn.BackingImageStateFailed bi.Status.DiskFileStatusMap[bim.Spec.DiskUUID].Message = msg } diff --git a/controller/node_controller.go b/controller/node_controller.go index 0d5a4f0dbf..80df567ef4 100644 --- a/controller/node_controller.go +++ b/controller/node_controller.go @@ -814,6 +814,10 @@ func (nc *NodeController) updateDiskStatusSchedulableCondition(node *longhorn.No if err != nil { return err } + backingImages, err := nc.ds.ListBackingImagesRO() + if err != nil { + return err + } for diskName, disk := range node.Spec.Disks { diskStatus := diskStatusMap[diskName] @@ -851,6 +855,7 @@ func (nc *NodeController) updateDiskStatusSchedulableCondition(node *longhorn.No return err } scheduledReplica := map[string]int64{} + scheduledBackingImage := map[string]int64{} storageScheduled := int64(0) for _, replica := range replicas { if replica.Spec.NodeID != node.Name || replica.Spec.DiskPath != disk.Path { @@ -865,8 +870,17 @@ func (nc *NodeController) updateDiskStatusSchedulableCondition(node *longhorn.No storageScheduled += replica.Spec.VolumeSize scheduledReplica[replica.Name] = replica.Spec.VolumeSize } + + for _, backingImage := range backingImages { + if _, exists := backingImage.Spec.DiskFileSpecMap[diskStatus.DiskUUID]; exists { + storageScheduled += backingImage.Status.RealSize + scheduledBackingImage[backingImage.Name] = backingImage.Status.RealSize + } + } + diskStatus.StorageScheduled = storageScheduled diskStatus.ScheduledReplica = scheduledReplica + diskStatus.ScheduledBackingImage = scheduledBackingImage // check disk pressure info, err := nc.scheduler.GetDiskSchedulingInfo(disk, diskStatus) if err != nil { @@ -1676,6 +1690,9 @@ func (nc *NodeController) alignDiskSpecAndStatus(node *longhorn.Node) { if diskStatus.ScheduledReplica == nil { diskStatus.ScheduledReplica = map[string]int64{} } + if diskStatus.ScheduledBackingImage == nil { + diskStatus.ScheduledBackingImage = map[string]int64{} + } // When condition are not ready, the old storage data should be cleaned. diskStatus.StorageMaximum = 0 diskStatus.StorageAvailable = 0 diff --git a/controller/node_controller_test.go b/controller/node_controller_test.go index db72be125a..4d345b8220 100644 --- a/controller/node_controller_test.go +++ b/controller/node_controller_test.go @@ -589,12 +589,13 @@ func (s *NodeControllerSuite) TestUpdateDiskStatus(c *C) { ScheduledReplica: map[string]int64{ fixture.lhReplicas[0].Name: fixture.lhReplicas[0].Spec.VolumeSize, }, - DiskName: TestDiskID1, - DiskUUID: TestDiskID1, - Type: longhorn.DiskTypeFilesystem, - FSType: TestDiskPathFSType, - DiskPath: TestDefaultDataPath, - InstanceManagerName: TestInstanceManagerName, + ScheduledBackingImage: map[string]int64{}, + DiskName: TestDiskID1, + DiskUUID: TestDiskID1, + Type: longhorn.DiskTypeFilesystem, + FSType: TestDiskPathFSType, + DiskPath: TestDefaultDataPath, + InstanceManagerName: TestInstanceManagerName, }, }, }, @@ -739,13 +740,14 @@ func (s *NodeControllerSuite) TestCleanDiskStatus(c *C) { newNodeCondition(longhorn.DiskConditionTypeSchedulable, longhorn.ConditionStatusFalse, string(longhorn.DiskConditionReasonDiskPressure)), newNodeCondition(longhorn.DiskConditionTypeReady, longhorn.ConditionStatusTrue, ""), }, - ScheduledReplica: map[string]int64{}, - DiskName: TestDiskID1, - DiskUUID: TestDiskID1, - Type: longhorn.DiskTypeFilesystem, - FSType: TestDiskPathFSType, - DiskPath: TestDefaultDataPath, - InstanceManagerName: TestInstanceManagerName, + ScheduledReplica: map[string]int64{}, + ScheduledBackingImage: map[string]int64{}, + DiskName: TestDiskID1, + DiskUUID: TestDiskID1, + Type: longhorn.DiskTypeFilesystem, + FSType: TestDiskPathFSType, + DiskPath: TestDefaultDataPath, + InstanceManagerName: TestInstanceManagerName, }, }, }, @@ -897,13 +899,14 @@ func (s *NodeControllerSuite) TestDisableDiskOnFilesystemChange(c *C) { newNodeCondition(longhorn.DiskConditionTypeSchedulable, longhorn.ConditionStatusFalse, string(longhorn.DiskConditionReasonDiskNotReady)), newNodeCondition(longhorn.DiskConditionTypeReady, longhorn.ConditionStatusFalse, string(longhorn.DiskConditionReasonDiskFilesystemChanged)), }, - ScheduledReplica: map[string]int64{}, - DiskName: TestDiskID1, - DiskUUID: "new-uuid", - Type: longhorn.DiskTypeFilesystem, - FSType: TestDiskPathFSType, - DiskPath: TestDefaultDataPath, - InstanceManagerName: TestInstanceManagerName, + ScheduledReplica: map[string]int64{}, + ScheduledBackingImage: map[string]int64{}, + DiskName: TestDiskID1, + DiskUUID: "new-uuid", + Type: longhorn.DiskTypeFilesystem, + FSType: TestDiskPathFSType, + DiskPath: TestDefaultDataPath, + InstanceManagerName: TestInstanceManagerName, }, }, }, @@ -1026,13 +1029,14 @@ func (s *NodeControllerSuite) TestCreateDefaultInstanceManager(c *C) { newNodeCondition(longhorn.DiskConditionTypeSchedulable, longhorn.ConditionStatusFalse, string(longhorn.DiskConditionReasonDiskPressure)), newNodeCondition(longhorn.DiskConditionTypeReady, longhorn.ConditionStatusTrue, ""), }, - DiskName: TestDiskID1, - ScheduledReplica: map[string]int64{}, - DiskUUID: TestDiskID1, - Type: longhorn.DiskTypeFilesystem, - FSType: TestDiskPathFSType, - DiskPath: TestDefaultDataPath, - InstanceManagerName: TestInstanceManagerName, + DiskName: TestDiskID1, + ScheduledReplica: map[string]int64{}, + ScheduledBackingImage: map[string]int64{}, + DiskUUID: TestDiskID1, + Type: longhorn.DiskTypeFilesystem, + FSType: TestDiskPathFSType, + DiskPath: TestDefaultDataPath, + InstanceManagerName: TestInstanceManagerName, }, }, }, @@ -1172,13 +1176,14 @@ func (s *NodeControllerSuite) TestCleanupRedundantInstanceManagers(c *C) { newNodeCondition(longhorn.DiskConditionTypeSchedulable, longhorn.ConditionStatusFalse, string(longhorn.DiskConditionReasonDiskPressure)), newNodeCondition(longhorn.DiskConditionTypeReady, longhorn.ConditionStatusTrue, ""), }, - DiskName: TestDiskID1, - ScheduledReplica: map[string]int64{}, - DiskUUID: TestDiskID1, - Type: longhorn.DiskTypeFilesystem, - FSType: TestDiskPathFSType, - DiskPath: TestDefaultDataPath, - InstanceManagerName: TestInstanceManagerName, + DiskName: TestDiskID1, + ScheduledReplica: map[string]int64{}, + ScheduledBackingImage: map[string]int64{}, + DiskUUID: TestDiskID1, + Type: longhorn.DiskTypeFilesystem, + FSType: TestDiskPathFSType, + DiskPath: TestDefaultDataPath, + InstanceManagerName: TestInstanceManagerName, }, }, }, diff --git a/engineapi/backing_image_manager.go b/engineapi/backing_image_manager.go index 9d7df41ce9..874a7c42ea 100644 --- a/engineapi/backing_image_manager.go +++ b/engineapi/backing_image_manager.go @@ -58,6 +58,7 @@ func (c *BackingImageManagerClient) parseBackingImageFileInfo(bi *bimapi.Backing UUID: bi.UUID, Size: bi.Size, VirtualSize: bi.VirtualSize, + RealSize: bi.RealSize, State: longhorn.BackingImageState(bi.Status.State), CurrentChecksum: bi.Status.CurrentChecksum, diff --git a/k8s/crds.yaml b/k8s/crds.yaml index 783cd2ddd9..92bb90189f 100644 --- a/k8s/crds.yaml +++ b/k8s/crds.yaml @@ -343,6 +343,9 @@ spec: type: string progress: type: integer + realSize: + format: int64 + type: integer senderManagerAddress: type: string sendingReference: @@ -560,6 +563,11 @@ spec: type: object ownerID: type: string + realSize: + description: Real size of image, which may be smaller than the size + when the file is a sparse file. Will be zero until known (e.g. while a backing image is uploading) + format: int64 + type: integer size: format: int64 type: integer @@ -2507,6 +2515,12 @@ spec: type: string instanceManagerName: type: string + scheduledBackingImage: + additionalProperties: + format: int64 + type: integer + nullable: true + type: object scheduledReplica: additionalProperties: format: int64 diff --git a/k8s/pkg/apis/longhorn/v1beta2/backingimage.go b/k8s/pkg/apis/longhorn/v1beta2/backingimage.go index 741bc38052..e43982cce8 100644 --- a/k8s/pkg/apis/longhorn/v1beta2/backingimage.go +++ b/k8s/pkg/apis/longhorn/v1beta2/backingimage.go @@ -80,6 +80,9 @@ type BackingImageStatus struct { // Virtual size of image, which may be larger than physical size. Will be zero until known (e.g. while a backing image is uploading) // +optional VirtualSize int64 `json:"virtualSize"` + // Real size of image, which may be smaller than the size when the file is a sparse file. Will be zero until known (e.g. while a backing image is uploading) + // +optional + RealSize int64 `json:"realSize"` // +optional Checksum string `json:"checksum"` // +optional diff --git a/k8s/pkg/apis/longhorn/v1beta2/backingimagemanager.go b/k8s/pkg/apis/longhorn/v1beta2/backingimagemanager.go index 303b2f81ae..7d0ed0aaeb 100644 --- a/k8s/pkg/apis/longhorn/v1beta2/backingimagemanager.go +++ b/k8s/pkg/apis/longhorn/v1beta2/backingimagemanager.go @@ -22,6 +22,8 @@ type BackingImageFileInfo struct { // +optional VirtualSize int64 `json:"virtualSize"` // +optional + RealSize int64 `json:"realSize"` + // +optional State BackingImageState `json:"state"` // +optional CurrentChecksum string `json:"currentChecksum"` diff --git a/k8s/pkg/apis/longhorn/v1beta2/node.go b/k8s/pkg/apis/longhorn/v1beta2/node.go index f79dbe1c67..cb41f37836 100644 --- a/k8s/pkg/apis/longhorn/v1beta2/node.go +++ b/k8s/pkg/apis/longhorn/v1beta2/node.go @@ -113,6 +113,9 @@ type DiskStatus struct { // +nullable ScheduledReplica map[string]int64 `json:"scheduledReplica"` // +optional + // +nullable + ScheduledBackingImage map[string]int64 `json:"scheduledBackingImage"` + // +optional DiskUUID string `json:"diskUUID"` // +optional DiskName string `json:"diskName"` diff --git a/k8s/pkg/apis/longhorn/v1beta2/zz_generated.deepcopy.go b/k8s/pkg/apis/longhorn/v1beta2/zz_generated.deepcopy.go index a906205877..83ae61fbdb 100644 --- a/k8s/pkg/apis/longhorn/v1beta2/zz_generated.deepcopy.go +++ b/k8s/pkg/apis/longhorn/v1beta2/zz_generated.deepcopy.go @@ -1014,6 +1014,13 @@ func (in *DiskStatus) DeepCopyInto(out *DiskStatus) { (*out)[key] = val } } + if in.ScheduledBackingImage != nil { + in, out := &in.ScheduledBackingImage, &out.ScheduledBackingImage + *out = make(map[string]int64, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } return }