16046: Replace slash with space for "repo/image" collection name
[arvados.git] / sdk / python / arvados / commands / federation_migrate.py
index a7d9414d9d572a308318d283fbe6f66736c4c758..e74d6215c79cb76af6fdab7170f3cd989a77143e 100755 (executable)
@@ -3,6 +3,15 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
+#
+# Migration tool for merging user accounts belonging to the same user
+# but on separate clusters to use a single user account managed by a
+# specific cluster.
+#
+# If you're working on this, see
+# arvados/sdk/python/tests/fed-migrate/README for information about
+# the testing infrastructure.
+
 import arvados
 import arvados.util
 import arvados.errors
@@ -12,6 +21,7 @@ import argparse
 import hmac
 import urllib.parse
 import os
+import hashlib
 from arvados._version import __version__
 
 EMAIL=0
@@ -67,7 +77,7 @@ def connect_clusters(args):
             continue
 
         if not cur["is_admin"]:
-            errors.append("Not admin of %s" % host)
+            errors.append("User %s is not admin on %s" % (cur["uuid"], arv._rootDesc["uuidPrefix"]))
             continue
 
         for r in clusters:
@@ -187,14 +197,17 @@ def choose_new_user(args, by_email, email, userhome, username, old_user_uuid, cl
             return None
         print("(%s) No user listed with same email to migrate %s to %s, will create new user with username '%s'" % (email, old_user_uuid, userhome, username))
         if not args.dry_run:
+            oldhomecluster = old_user_uuid[0:5]
+            oldhomearv = clusters[oldhomecluster]
             newhomecluster = userhome[0:5]
             homearv = clusters[userhome]
             user = None
             try:
+                olduser = oldhomearv.users().get(uuid=old_user_uuid).execute()
                 conflicts = homearv.users().list(filters=[["username", "=", username]]).execute()
                 if conflicts["items"]:
                     homearv.users().update(uuid=conflicts["items"][0]["uuid"], body={"user": {"username": username+"migrate"}}).execute()
-                user = homearv.users().create(body={"user": {"email": email, "username": username}}).execute()
+                user = homearv.users().create(body={"user": {"email": email, "username": username, "is_active": olduser["is_active"]}}).execute()
             except arvados.errors.ApiError as e:
                 print("(%s) Could not create user: %s" % (email, str(e)))
                 return None
@@ -227,9 +240,16 @@ def activate_remote_user(args, email, homearv, migratearv, old_user_uuid, new_us
         print("(%s) Could not create API token for %s: %s" % (email, new_user_uuid, e))
         return None
 
+    try:
+        olduser = migratearv.users().get(uuid=old_user_uuid).execute()
+    except arvados.errors.ApiError as e:
+        if e.resp.status != 404:
+            print("(%s) Could not retrieve user %s from %s, user may have already been migrated: %s" % (email, old_user_uuid, migratecluster, e))
+        return None
+
     salted = 'v2/' + newtok["uuid"] + '/' + hmac.new(newtok["api_token"].encode(),
                                                      msg=migratecluster.encode(),
-                                                     digestmod='sha1').hexdigest()
+                                                     digestmod=hashlib.sha1).hexdigest()
     try:
         ru = urllib.parse.urlparse(migratearv._rootDesc["rootUrl"])
         if not args.dry_run:
@@ -240,14 +260,7 @@ def activate_remote_user(args, email, homearv, migratearv, old_user_uuid, new_us
         print("(%s) Error getting user info for %s from %s: %s" % (email, new_user_uuid, migratecluster, e))
         return None
 
-    try:
-        olduser = migratearv.users().get(uuid=old_user_uuid).execute()
-    except arvados.errors.ApiError as e:
-        if e.resp.status != 404:
-            print("(%s) Could not retrieve user %s from %s, user may have already been migrated: %s" % (email, old_user_uuid, migratecluster, e))
-        return None
-
-    if not newuser["is_active"]:
+    if not newuser["is_active"] and olduser["is_active"]:
         print("(%s) Activating user %s on %s" % (email, new_user_uuid, migratecluster))
         try:
             if not args.dry_run: