From e14a17be348c6bfbe32d1d15e448801c1a0c6711 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 31 Mar 2025 12:25:57 +0300 Subject: [PATCH] [#9999] adm: Add `move` flag to `zombie scan` command Add `move` flag to confirm that objects must be moved from storage engine to quarantine. Without this flag only object addresses will be printed. This allows to just print object addresses that should be moved to quarantine. Change-Id: I551979d8bffaf45fe21d92f6edadfaadcb5d6e25 Signed-off-by: Dmitrii Stepanov --- .../modules/maintenance/zombie/root.go | 4 ++ .../modules/maintenance/zombie/scan.go | 58 +++++++++++-------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go index 6990a0030..9ef18f7f8 100644 --- a/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go @@ -18,6 +18,8 @@ const ( walletFlagUsage = "Path to the wallet or binary key" addressFlag = "address" addressFlagUsage = "Address of wallet account" + moveFlag = "move" + moveFlagUsage = "Move objects from storage engine to quarantine" ) var ( @@ -36,6 +38,7 @@ var ( _ = viper.BindPFlag(walletFlag, cmd.Flags().Lookup(walletFlag)) _ = viper.BindPFlag(addressFlag, cmd.Flags().Lookup(addressFlag)) _ = viper.BindPFlag(flagBatchSize, cmd.Flags().Lookup(flagBatchSize)) + _ = viper.BindPFlag(moveFlag, cmd.Flags().Lookup(moveFlag)) }, Run: scan, } @@ -92,6 +95,7 @@ func initScanCmd() { scanCmd.Flags().Uint32(flagBatchSize, 1000, flagBatchSizeUsage) scanCmd.Flags().StringP(walletFlag, walletFlagShorthand, "", walletFlagUsage) scanCmd.Flags().String(addressFlag, "", addressFlagUsage) + scanCmd.Flags().Bool(moveFlag, false, moveFlagUsage) } func initListCmd() { diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/scan.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/scan.go index 18a29ca8d..393ccd027 100644 --- a/cmd/frostfs-adm/internal/modules/maintenance/zombie/scan.go +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/scan.go @@ -34,6 +34,7 @@ func scan(cmd *cobra.Command, _ []string) { if batchSize == 0 { commonCmd.ExitOnErr(cmd, "invalid batch size: %w", errors.New("batch size must be positive value")) } + move, _ := cmd.Flags().GetBool(moveFlag) storageEngine := newEngine(cmd, appCfg) morphClient := createMorphClient(cmd, appCfg) @@ -76,7 +77,7 @@ func scan(cmd *cobra.Command, _ []string) { }() go func() { defer wg.Done() - err = scanStorageEngine(cmd.Context(), batchSize, storageEngine, ps, appCfg, cnrCli, nmCli, q, pk) + err = scanStorageEngine(cmd, batchSize, storageEngine, ps, appCfg, cnrCli, nmCli, q, pk, move) close(stopCh) }() wg.Wait() @@ -156,8 +157,8 @@ func checkAddr(ctx context.Context, cnrCli *cntClient.Client, nmCli *netmap.Clie return statusQuarantine, nil } -func scanStorageEngine(ctx context.Context, batchSize uint32, storageEngine *engine.StorageEngine, ps *processStatus, - appCfg *config.Config, cnrCli *cntClient.Client, nmCli *netmap.Client, q *quarantine, pk *ecdsa.PrivateKey, +func scanStorageEngine(cmd *cobra.Command, batchSize uint32, storageEngine *engine.StorageEngine, ps *processStatus, + appCfg *config.Config, cnrCli *cntClient.Client, nmCli *netmap.Client, q *quarantine, pk *ecdsa.PrivateKey, move bool, ) error { cc := cache.NewSDKClientCache(cache.ClientCacheOpts{ DialTimeout: apiclientconfig.DialTimeout(appCfg), @@ -166,6 +167,7 @@ func scanStorageEngine(ctx context.Context, batchSize uint32, storageEngine *eng Key: pk, AllowExternal: apiclientconfig.AllowExternal(appCfg), }) + ctx := cmd.Context() var cursor *engine.Cursor for { @@ -197,30 +199,17 @@ func scanStorageEngine(ctx context.Context, batchSize uint32, storageEngine *eng eg.Go(func() error { result, err := checkAddr(egCtx, cnrCli, nmCli, cc, addr.Address) if err != nil { - return fmt.Errorf("check object %s status: %w", addr, err) + return fmt.Errorf("check object %s status: %w", addr.Address, err) } ps.add(result) + if !move && result == statusQuarantine { + cmd.Println(addr) + return nil + } + if result == statusQuarantine { - var getPrm engine.GetPrm - getPrm.WithAddress(addr.Address) - res, err := storageEngine.Get(egCtx, getPrm) - if err != nil { - return fmt.Errorf("get object %s from storage engine: %w", addr, err) - } - - if err := q.Put(egCtx, res.Object()); err != nil { - return fmt.Errorf("put object %s to quarantine: %w", addr, err) - } - - var delPrm engine.DeletePrm - delPrm.WithForceRemoval() - delPrm.WithAddress(addr.Address) - - _, err = storageEngine.Delete(egCtx, delPrm) - if err != nil { - return fmt.Errorf("delete object %s from storage engine: %w", addr, err) - } + return moveToQuarantine(egCtx, storageEngine, q, addr.Address) } return nil }) @@ -231,6 +220,29 @@ func scanStorageEngine(ctx context.Context, batchSize uint32, storageEngine *eng } } +func moveToQuarantine(ctx context.Context, storageEngine *engine.StorageEngine, q *quarantine, addr oid.Address) error { + var getPrm engine.GetPrm + getPrm.WithAddress(addr) + res, err := storageEngine.Get(ctx, getPrm) + if err != nil { + return fmt.Errorf("get object %s from storage engine: %w", addr, err) + } + + if err := q.Put(ctx, res.Object()); err != nil { + return fmt.Errorf("put object %s to quarantine: %w", addr, err) + } + + var delPrm engine.DeletePrm + delPrm.WithForceRemoval() + delPrm.WithAddress(addr) + + _, err = storageEngine.Delete(ctx, delPrm) + if err != nil { + return fmt.Errorf("delete object %s from storage engine: %w", addr, err) + } + return nil +} + type processStatus struct { guard sync.RWMutex statusCount map[status]uint64