ilm: Update action count only on success (#19093)

It also fixes a long-standing bug in expiring transitioned objects.
The expiration action was deleting the current version in the case'
of tiered objects instead of adding a delete marker.
This commit is contained in:
Krishnan Parthasarathi 2024-02-22 15:00:32 -08:00 committed by GitHub
parent fa68efb1e7
commit ee158e1610
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 20 deletions

View File

@ -395,12 +395,15 @@ func enqueueTransitionImmediate(obj ObjectInfo, src lcEventSrc) {
// //
// 1. when a restored (via PostRestoreObject API) object expires. // 1. when a restored (via PostRestoreObject API) object expires.
// 2. when a transitioned object expires (based on an ILM rule). // 2. when a transitioned object expires (based on an ILM rule).
func expireTransitionedObject(ctx context.Context, objectAPI ObjectLayer, oi *ObjectInfo, lcOpts lifecycle.ObjectOpts, lcEvent lifecycle.Event, src lcEventSrc) error { func expireTransitionedObject(ctx context.Context, objectAPI ObjectLayer, oi *ObjectInfo, lcEvent lifecycle.Event, src lcEventSrc) error {
traceFn := globalLifecycleSys.trace(*oi) traceFn := globalLifecycleSys.trace(*oi)
var opts ObjectOptions opts := ObjectOptions{
opts.Versioned = globalBucketVersioningSys.PrefixEnabled(oi.Bucket, oi.Name) Versioned: globalBucketVersioningSys.PrefixEnabled(oi.Bucket, oi.Name),
opts.VersionID = lcOpts.VersionID Expiration: ExpirationOptions{Expire: true},
opts.Expiration = ExpirationOptions{Expire: true} }
if lcEvent.Action.DeleteVersioned() {
opts.VersionID = oi.VersionID
}
tags := newLifecycleAuditEvent(src, lcEvent).Tags() tags := newLifecycleAuditEvent(src, lcEvent).Tags()
if lcEvent.Action.DeleteRestored() { if lcEvent.Action.DeleteRestored() {
// delete locally restored copy of object or object version // delete locally restored copy of object or object version
@ -435,13 +438,13 @@ func expireTransitionedObject(ctx context.Context, objectAPI ObjectLayer, oi *Ob
defer auditLogLifecycle(ctx, *oi, ILMExpiry, tags, traceFn) defer auditLogLifecycle(ctx, *oi, ILMExpiry, tags, traceFn)
eventName := event.ObjectRemovedDelete eventName := event.ObjectRemovedDelete
if lcOpts.DeleteMarker { if oi.DeleteMarker {
eventName = event.ObjectRemovedDeleteMarkerCreated eventName = event.ObjectRemovedDeleteMarkerCreated
} }
objInfo := ObjectInfo{ objInfo := ObjectInfo{
Name: oi.Name, Name: oi.Name,
VersionID: lcOpts.VersionID, VersionID: oi.VersionID,
DeleteMarker: lcOpts.DeleteMarker, DeleteMarker: oi.DeleteMarker,
} }
// Notify object deleted event. // Notify object deleted event.
sendEvent(eventArgs{ sendEvent(eventArgs{
@ -471,7 +474,14 @@ func genTransitionObjName(bucket string) (string, error) {
// storage specified by the transition ARN, the metadata is left behind on source cluster and original content // storage specified by the transition ARN, the metadata is left behind on source cluster and original content
// is moved to the transition tier. Note that in the case of encrypted objects, entire encrypted stream is moved // is moved to the transition tier. Note that in the case of encrypted objects, entire encrypted stream is moved
// to the transition tier without decrypting or re-encrypting. // to the transition tier without decrypting or re-encrypting.
func transitionObject(ctx context.Context, objectAPI ObjectLayer, oi ObjectInfo, lae lcAuditEvent) error { func transitionObject(ctx context.Context, objectAPI ObjectLayer, oi ObjectInfo, lae lcAuditEvent) (err error) {
defer func() {
if err != nil {
return
}
globalScannerMetrics.timeILM(lae.Action)(1)
}()
opts := ObjectOptions{ opts := ObjectOptions{
Transition: TransitionOptions{ Transition: TransitionOptions{
Status: lifecycle.TransitionPending, Status: lifecycle.TransitionPending,

View File

@ -963,15 +963,6 @@ func (i *scannerItem) applyLifecycle(ctx context.Context, o ObjectLayer, oi Obje
console.Debugf(applyActionsLogPrefix+" lifecycle: %q Initial scan: %v\n", i.objectPath(), lcEvt.Action) console.Debugf(applyActionsLogPrefix+" lifecycle: %q Initial scan: %v\n", i.objectPath(), lcEvt.Action)
} }
} }
defer func() {
if lcEvt.Action != lifecycle.NoneAction {
numVersions := uint64(1)
if lcEvt.Action == lifecycle.DeleteAllVersionsAction {
numVersions = uint64(oi.NumVersions)
}
globalScannerMetrics.timeILM(lcEvt.Action)(numVersions)
}
}()
switch lcEvt.Action { switch lcEvt.Action {
// This version doesn't contribute towards sizeS only when it is permanently deleted. // This version doesn't contribute towards sizeS only when it is permanently deleted.
@ -1228,7 +1219,17 @@ func applyTransitionRule(event lifecycle.Event, src lcEventSrc, obj ObjectInfo)
} }
func applyExpiryOnTransitionedObject(ctx context.Context, objLayer ObjectLayer, obj ObjectInfo, lcEvent lifecycle.Event, src lcEventSrc) bool { func applyExpiryOnTransitionedObject(ctx context.Context, objLayer ObjectLayer, obj ObjectInfo, lcEvent lifecycle.Event, src lcEventSrc) bool {
if err := expireTransitionedObject(ctx, objLayer, &obj, obj.ToLifecycleOpts(), lcEvent, src); err != nil { var err error
defer func() {
if err != nil {
return
}
// Note: DeleteAllVersions action is not supported for
// transitioned objects
globalScannerMetrics.timeILM(lcEvent.Action)(1)
}()
if err = expireTransitionedObject(ctx, objLayer, &obj, lcEvent, src); err != nil {
if isErrObjectNotFound(err) || isErrVersionNotFound(err) { if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
return false return false
} }
@ -1255,8 +1256,25 @@ func applyExpiryOnNonTransitionedObjects(ctx context.Context, objLayer ObjectLay
if lcEvent.Action.DeleteAll() { if lcEvent.Action.DeleteAll() {
opts.DeletePrefix = true opts.DeletePrefix = true
} }
var (
dobj ObjectInfo
err error
)
defer func() {
if err != nil {
return
}
dobj, err := objLayer.DeleteObject(ctx, obj.Bucket, obj.Name, opts) if lcEvent.Action != lifecycle.NoneAction {
numVersions := uint64(1)
if lcEvent.Action == lifecycle.DeleteAllVersionsAction {
numVersions = uint64(obj.NumVersions)
}
globalScannerMetrics.timeILM(lcEvent.Action)(numVersions)
}
}()
dobj, err = objLayer.DeleteObject(ctx, obj.Bucket, obj.Name, opts)
if err != nil { if err != nil {
if isErrObjectNotFound(err) || isErrVersionNotFound(err) { if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
return false return false