16427: Rename undelete -> recover-collection.
authorTom Clegg <tom@tomclegg.ca>
Wed, 10 Jun 2020 14:26:18 +0000 (10:26 -0400)
committerTom Clegg <tom@tomclegg.ca>
Wed, 10 Jun 2020 14:26:18 +0000 (10:26 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@tomclegg.ca>

cmd/arvados-server/cmd.go
doc/_config.yml
doc/admin/recovering-deleted-collections.html.textile.liquid [moved from doc/admin/undeleting-collections.html.textile.liquid with 72% similarity]
lib/recovercollection/cmd.go [moved from lib/undelete/cmd.go with 82% similarity]
lib/recovercollection/cmd_test.go [moved from lib/undelete/cmd_test.go with 99% similarity]

index 1b2de11accefe995511194c5941f25af3ccd35e4..ff99de75c41ad13f630d0902c2e695c6c17ad5c9 100644 (file)
@@ -15,7 +15,7 @@ import (
        "git.arvados.org/arvados.git/lib/crunchrun"
        "git.arvados.org/arvados.git/lib/dispatchcloud"
        "git.arvados.org/arvados.git/lib/install"
-       "git.arvados.org/arvados.git/lib/undelete"
+       "git.arvados.org/arvados.git/lib/recovercollection"
        "git.arvados.org/arvados.git/services/ws"
 )
 
@@ -25,17 +25,17 @@ var (
                "-version":  cmd.Version,
                "--version": cmd.Version,
 
-               "boot":            boot.Command,
-               "cloudtest":       cloudtest.Command,
-               "config-check":    config.CheckCommand,
-               "config-defaults": config.DumpDefaultsCommand,
-               "config-dump":     config.DumpCommand,
-               "controller":      controller.Command,
-               "crunch-run":      crunchrun.Command,
-               "dispatch-cloud":  dispatchcloud.Command,
-               "install":         install.Command,
-               "undelete":        undelete.Command,
-               "ws":              ws.Command,
+               "boot":               boot.Command,
+               "cloudtest":          cloudtest.Command,
+               "config-check":       config.CheckCommand,
+               "config-defaults":    config.DumpDefaultsCommand,
+               "config-dump":        config.DumpCommand,
+               "controller":         controller.Command,
+               "crunch-run":         crunchrun.Command,
+               "dispatch-cloud":     dispatchcloud.Command,
+               "install":            install.Command,
+               "recover-collection": recovercollection.Command,
+               "ws":                 ws.Command,
        })
 )
 
index 9f016fcc8c01a0aa56283867d44e6a13e2efc1e4..3b59cbca45205983ba4b83429f06b914946a53dd 100644 (file)
@@ -174,7 +174,7 @@ navbar:
       - admin/logs-table-management.html.textile.liquid
       - admin/workbench2-vocabulary.html.textile.liquid
       - admin/storage-classes.html.textile.liquid
-      - admin/undeleting-collections.html.textile.liquid
+      - admin/recovering-deleted-collections.html.textile.liquid
     - Cloud:
       - admin/spot-instances.html.textile.liquid
       - admin/cloudtest.html.textile.liquid
similarity index 72%
rename from doc/admin/undeleting-collections.html.textile.liquid
rename to doc/admin/recovering-deleted-collections.html.textile.liquid
index 461671b53b776d0148250b4f9ab370fec1bcb1ed..59c576ce03c90f08a42426128fcf24afb0a96786 100644 (file)
@@ -1,7 +1,7 @@
 ---
 layout: default
 navsection: admin
-title: Undeleting collections
+title: Recovering deleted collections
 ...
 
 {% comment %}
@@ -18,14 +18,14 @@ Possibility of recovery depends on many factors, including:
 * Whether the data blocks have been unreferenced long enough to be marked for deletion/trash by keep-balance
 * Blob signature TTL, trash lifetime, trash check interval, and other config settings
 
-To attempt recovery of a previous version of a deleted/modified collection, use the @arvados-server undelete@ command. It should be run on one of your server nodes where the @arvados-server@ package is installed and the @/etc/arvados/config.yml@ file is up to date.
+To attempt recovery of a previous version of a deleted/modified collection, use the @arvados-server recover-collection@ command. It should be run on one of your server nodes where the @arvados-server@ package is installed and the @/etc/arvados/config.yml@ file is up to date.
 
 Specify the collection you want to recover by passing either the UUID of an audit log entry, or a file containing the manifest.
 
-If recovery is successful, the undelete program saves the recovered data a new collection belonging to the system user, and print the new collection's UUID on stdout.
+If recovery is successful, the @recover-collection@ program saves the recovered data a new collection belonging to the system user, and prints the new collection's UUID on stdout.
 
 <pre>
-# arvados-server undelete 9tee4-57u5n-nb5awmk1pahac2t
+# arvados-server recover-collection 9tee4-57u5n-nb5awmk1pahac2t
 INFO[2020-06-05T19:52:29.557761245Z] loaded log entry                              logged_event_time="2020-06-05 16:48:01.438791 +0000 UTC" logged_event_type=update old_collection_uuid=9tee4-4zz18-1ex26g95epmgw5w src=9tee4-57u5n-nb5awmk1pahac2t
 INFO[2020-06-05T19:52:29.642145127Z] recovery succeeded                            UUID=9tee4-4zz18-5trfp4k4xxg97f1 src=9tee4-57u5n-nb5awmk1pahac2t
 9tee4-4zz18-5trfp4k4xxg97f1
@@ -34,4 +34,4 @@ INFO[2020-06-05T19:52:29.644699436Z] exiting
 
 In this example, the original data has been restored and saved in a new collection with UUID @9tee4-4zz18-5trfp4k4xxg97f1@.
 
-For more options, run @arvados-server undelete -help@.
+For more options, run @arvados-server recover-collection -help@.
similarity index 82%
rename from lib/undelete/cmd.go
rename to lib/recovercollection/cmd.go
index 9d4bc84eaca42756bc48e0cfd10f5084c3459735..d19bf311680814fa612b2ac6f22a56b4d026e4e7 100644 (file)
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-package undelete
+package recovercollection
 
 import (
        "context"
@@ -103,7 +103,7 @@ Options:
                return 1
        }
        client.AuthToken = cluster.SystemRootToken
-       und := undeleter{
+       rcvr := recoverer{
                client:  client,
                cluster: cluster,
                logger:  logger,
@@ -145,7 +145,7 @@ Options:
                        }
                        mtxt = string(buf)
                }
-               uuid, err := und.RecoverManifest(string(mtxt))
+               uuid, err := rcvr.RecoverManifest(string(mtxt))
                if err != nil {
                        logger.WithError(err).Error("recovery failed")
                        exitcode = 1
@@ -157,7 +157,7 @@ Options:
        return exitcode
 }
 
-type undeleter struct {
+type recoverer struct {
        client  *arvados.Client
        cluster *arvados.Cluster
        logger  logrus.FieldLogger
@@ -167,8 +167,8 @@ var errNotFound = errors.New("not found")
 
 // Finds the timestamp of the newest copy of blk on svc. Returns
 // errNotFound if blk is not on svc at all.
-func (und undeleter) newestMtime(logger logrus.FieldLogger, blk string, svc arvados.KeepService) (time.Time, error) {
-       found, err := svc.Index(und.client, blk)
+func (rcvr recoverer) newestMtime(logger logrus.FieldLogger, blk string, svc arvados.KeepService) (time.Time, error) {
+       found, err := svc.Index(rcvr.client, blk)
        if err != nil {
                logger.WithError(err).Warn("error getting index")
                return time.Time{}, err
@@ -198,17 +198,17 @@ var errTouchIneffective = errors.New("(BUG?) touch succeeded but had no effect -
 // decide to trash it, all before our recovered collection gets
 // saved. But if the block's timestamp is more recent than blobsigttl,
 // keepstore will refuse to trash it even if told to by keep-balance.
-func (und undeleter) ensureSafe(ctx context.Context, logger logrus.FieldLogger, blk string, svc arvados.KeepService, blobsigttl time.Duration, blobsigexp time.Time) error {
-       if latest, err := und.newestMtime(logger, blk, svc); err != nil {
+func (rcvr recoverer) ensureSafe(ctx context.Context, logger logrus.FieldLogger, blk string, svc arvados.KeepService, blobsigttl time.Duration, blobsigexp time.Time) error {
+       if latest, err := rcvr.newestMtime(logger, blk, svc); err != nil {
                return err
        } else if latest.Add(blobsigttl).After(blobsigexp) {
                return nil
        }
-       if err := svc.Touch(ctx, und.client, blk); err != nil {
+       if err := svc.Touch(ctx, rcvr.client, blk); err != nil {
                return fmt.Errorf("error updating timestamp: %s", err)
        }
        logger.Debug("updated timestamp")
-       if latest, err := und.newestMtime(logger, blk, svc); err == errNotFound {
+       if latest, err := rcvr.newestMtime(logger, blk, svc); err == errNotFound {
                return fmt.Errorf("(BUG?) touch succeeded, but then block did not appear in index")
        } else if err != nil {
                return err
@@ -222,7 +222,7 @@ func (und undeleter) ensureSafe(ctx context.Context, logger logrus.FieldLogger,
 // Untrash and update GC timestamps (as needed) on blocks referenced
 // by the given manifest, save a new collection and return the new
 // collection's UUID.
-func (und undeleter) RecoverManifest(mtxt string) (string, error) {
+func (rcvr recoverer) RecoverManifest(mtxt string) (string, error) {
        ctx, cancel := context.WithCancel(context.Background())
        defer cancel()
 
@@ -238,9 +238,9 @@ func (und undeleter) RecoverManifest(mtxt string) (string, error) {
        go close(todo)
 
        var services []arvados.KeepService
-       err = und.client.EachKeepService(func(svc arvados.KeepService) error {
+       err = rcvr.client.EachKeepService(func(svc arvados.KeepService) error {
                if svc.ServiceType == "proxy" {
-                       und.logger.WithField("service", svc).Debug("ignore proxy service")
+                       rcvr.logger.WithField("service", svc).Debug("ignore proxy service")
                } else {
                        services = append(services, svc)
                }
@@ -249,7 +249,7 @@ func (und undeleter) RecoverManifest(mtxt string) (string, error) {
        if err != nil {
                return "", fmt.Errorf("error getting list of keep services: %s", err)
        }
-       und.logger.WithField("services", services).Debug("got list of services")
+       rcvr.logger.WithField("services", services).Debug("got list of services")
 
        // blobsigexp is our deadline for saving the rescued
        // collection. This must be less than BlobSigningTTL
@@ -263,9 +263,9 @@ func (und undeleter) RecoverManifest(mtxt string) (string, error) {
        // would have lived long enough anyway if left alone.
        // BlobSigningTTL/2 (typically around 1 week) is much longer
        // than than we need to recover even a very large collection.
-       blobsigttl := und.cluster.Collections.BlobSigningTTL.Duration()
+       blobsigttl := rcvr.cluster.Collections.BlobSigningTTL.Duration()
        blobsigexp := time.Now().Add(blobsigttl / 2)
-       und.logger.WithField("blobsigexp", blobsigexp).Debug("chose save deadline")
+       rcvr.logger.WithField("blobsigexp", blobsigexp).Debug("chose save deadline")
 
        // We'll start a number of threads, each working on
        // checking/recovering one block at a time. The threads
@@ -283,18 +283,18 @@ func (und undeleter) RecoverManifest(mtxt string) (string, error) {
                nextblk:
                        for idx := range todo {
                                blk := strings.SplitN(string(blks[idx]), "+", 2)[0]
-                               logger := und.logger.WithField("block", blk)
+                               logger := rcvr.logger.WithField("block", blk)
                                for _, untrashing := range []bool{false, true} {
                                        for _, svc := range services {
                                                logger := logger.WithField("service", fmt.Sprintf("%s:%d", svc.ServiceHost, svc.ServicePort))
                                                if untrashing {
-                                                       if err := svc.Untrash(ctx, und.client, blk); err != nil {
+                                                       if err := svc.Untrash(ctx, rcvr.client, blk); err != nil {
                                                                logger.WithError(err).Debug("untrash failed")
                                                                continue
                                                        }
                                                        logger.Info("untrashed")
                                                }
-                                               err := und.ensureSafe(ctx, logger, blk, svc, blobsigttl, blobsigexp)
+                                               err := rcvr.ensureSafe(ctx, logger, blk, svc, blobsigttl, blobsigexp)
                                                if err == errNotFound {
                                                        logger.Debug(err)
                                                } else if err != nil {
@@ -321,17 +321,17 @@ func (und undeleter) RecoverManifest(mtxt string) (string, error) {
        }
        if havenot > 0 {
                if have > 0 {
-                       und.logger.Warn("partial recovery is not implemented")
+                       rcvr.logger.Warn("partial recovery is not implemented")
                }
                return "", fmt.Errorf("unable to recover %d of %d blocks", havenot, have+havenot)
        }
 
-       if und.cluster.Collections.BlobSigning {
-               key := []byte(und.cluster.Collections.BlobSigningKey)
-               coll.ManifestText = arvados.SignManifest(coll.ManifestText, und.client.AuthToken, blobsigexp, blobsigttl, key)
+       if rcvr.cluster.Collections.BlobSigning {
+               key := []byte(rcvr.cluster.Collections.BlobSigningKey)
+               coll.ManifestText = arvados.SignManifest(coll.ManifestText, rcvr.client.AuthToken, blobsigexp, blobsigttl, key)
        }
-       und.logger.WithField("manifest", coll.ManifestText).Debug("updated blob signatures in manifest")
-       err = und.client.RequestAndDecodeContext(ctx, &coll, "POST", "arvados/v1/collections", nil, map[string]interface{}{
+       rcvr.logger.WithField("manifest", coll.ManifestText).Debug("updated blob signatures in manifest")
+       err = rcvr.client.RequestAndDecodeContext(ctx, &coll, "POST", "arvados/v1/collections", nil, map[string]interface{}{
                "collection": map[string]interface{}{
                        "manifest_text": coll.ManifestText,
                },
@@ -339,6 +339,6 @@ func (und undeleter) RecoverManifest(mtxt string) (string, error) {
        if err != nil {
                return "", fmt.Errorf("error saving new collection: %s", err)
        }
-       und.logger.WithField("UUID", coll.UUID).Debug("created new collection")
+       rcvr.logger.WithField("UUID", coll.UUID).Debug("created new collection")
        return coll.UUID, nil
 }
similarity index 99%
rename from lib/undelete/cmd_test.go
rename to lib/recovercollection/cmd_test.go
index a5edaf90b3190d305b09a7f019e34b92992ab609..a6bf19de2db361f5b8425e914d655ef91160368b 100644 (file)
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-package undelete
+package recovercollection
 
 import (
        "bytes"