Repository: rucio/rucio

Issue:
rucio client fails if username not defined
Motivation
----------
When running in a container, the name and uid of the local user account are largely arbitrary and meaningless. In commonly used containers, the username is often left undefined by convention. However if the Rucio client is used , it tries to look up the name of the current user and fails if there is no name. This job is running with uid 1000.
https://aipanda047.cern.ch:25443/cache/129755.out

```
2019-10-23 23:18:12| 3467|Mover.py    | ERROR: Mover get data failed [stagein]: exception caught: 'getpwuid(): uid not found: 1000'
2019-10-23 23:18:12| 3467|Mover.py    | Traceback (most recent call last):
  File \"/tmp/workdir/condorg_FgXUogoB/Panda_Pilot_3299_1571872670/PandaJob/Mover.py\", line 334, in get_data_new
    output = mover.stagein(files=files, analyjob=job.isAnalysisJob())
  File \"/tmp/workdir/condorg_FgXUogoB/Panda_Pilot_3299_1571872670/PandaJob/movers/mover.py\", line 503, in stagein
    transferred_files, failed_transfers = self.stagein_real(files=normal_files, activity='pr', analyjob=analyjob, skip_transfer_failure=allowRemoteInputs)
  File \"/tmp/workdir/condorg_FgXUogoB/Panda_Pilot_3299_1571872670/PandaJob/movers/mover.py\", line 675, in stagein_real
    self.resolve_replicas(files) ## do populate fspec.replicas for each entry in files
  File \"/tmp/workdir/condorg_FgXUogoB/Panda_Pilot_3299_1571872670/PandaJob/movers/mover.py\", line 246, in resolve_replicas
    from rucio.client import Client
  File \"/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/rucio-clients/1.20.2.post1/lib/python2.7/site-packages/rucio/client/__init__.py\", line 19, in <module>
    from rucio.client.client import *  # NOQA pylint: disable=wildcard-import
  File \"/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/rucio-clients/1.20.2.post1/lib/python2.7/site-packages/rucio/client/client.py\", line 29, in <module>
    from rucio.client.accountclient import AccountClient
  File \"/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/rucio-clients/1.20.2.post1/lib/python2.7/site-packages/rucio/client/accountclient.py\", line 32, in <module>
    from rucio.client.baseclient import BaseClient
  File \"/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/rucio-clients/1.20.2.post1/lib/python2.7/site-packages/rucio/client/baseclient.py\", line 103, in <module>
    class BaseClient(object):
  File \"/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/rucio-clients/1.20.2.post1/lib/python2.7/site-packages/rucio/client/baseclient.py\", line 108, in BaseClient
    TOKEN_PATH_PREFIX = get_tmp_dir() + '/.rucio_'
  File \"/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/rucio-clients/1.20.2.post1/lib/python2.7/site-packages/rucio/common/utils.py\", line 627, in get_tmp_dir
    user = getuser()
  File \"/usr/lib64/python2.7/getpass.py\", line 158, in getuser
    return pwd.getpwuid(os.getuid())[0]
KeyError: 'getpwuid(): uid not found: 1000'
```

This causes jobs to fail when running on Kubernetes.

Modification
------------

It looks like the Rucio client is just trying to find some descriptive string to name a temporary directory:
```
File \"/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/rucio-clients/1.20.2.post1/lib/python2.7/site-packages/rucio/common/utils.py\", line 627, in get_tmp_dir
    user = getuser()
```
If a username is not defined, can it simply use the uid instead when choosing a name for the temporary directory? This would make the Rucio client more container-friendly.

Thanks.


Discussion:
Thanks, @TWAtGH can you please have a look.

Resolving patch:
diff --git a/lib/rucio/common/utils.py b/lib/rucio/common/utils.py
--- a/lib/rucio/common/utils.py
+++ b/lib/rucio/common/utils.py
@@ -33,20 +33,21 @@
 import base64
 import datetime
 import errno
+import getpass
 import hashlib
 import imp
 import json
 import os
-import pwd
+import os.path
 import re
 import requests
 import socket
 import subprocess
+import tempfile
 import threading
 import time
 import zlib
 
-from getpass import getuser
 from logging import getLogger, Formatter
 from logging.handlers import RotatingFileHandler
 from uuid import uuid4 as uuid
@@ -616,24 +617,18 @@ def get_tmp_dir():
 
     :return: A path.
     """
-    user, tmp_dir = None, None
+    base_dir = os.path.abspath(tempfile.gettempdir())
     try:
-        user = pwd.getpwuid(os.getuid()).pw_name
+        return os.path.join(base_dir, getpass.getuser())
     except Exception:
         pass
 
-    for env_var in ('TMP', 'TMPDIR', 'TEMP'):
-        if env_var in os.environ:
-            tmp_dir = os.environ[env_var]
-            break
-
-    if not user:
-        user = getuser()
-
-    if not tmp_dir:
-        return '/tmp/' + user + '/'
+    try:
+        return os.path.join(base_dir, str(os.getuid()))
+    except Exception:
+        pass
 
-    return tmp_dir + '/' + user + '/'
+    return base_dir
 
 
 def is_archive(name):


Test patch: