Repository: spack/spack

Issue:
Spack broken on Blue Waters
On the current develop, no Spack command works on Blue Waters.

### Steps to reproduce the issue

Any Spack command:
```console
$ spack help
```

### Error Message

```
Traceback (most recent call last):
  File "/u/sciteam/stewart1/spack/bin/spack", line 48, in <module>
    sys.exit(spack.main.main())
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/main.py", line 704, in main
    if spack.config.get('config:debug'):
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/config.py", line 627, in get
    return config.get(path, default, scope)
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/llnl/util/lang.py", line 558, in __getattr__
    return getattr(self.instance, name)
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/llnl/util/lang.py", line 554, in instance
    self._instance = self.factory()
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/config.py", line 609, in _config
    _add_platform_scope(cfg, ConfigScope, name, path)
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/config.py", line 562, in _add_platform_scope
    platform = spack.architecture.platform().name
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/llnl/util/lang.py", line 184, in _memoized_function
    func.cache[args] = func(*args)
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/architecture.py", line 388, in platform
    return platform_cls()
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/platforms/cray.py", line 76, in __init__
    back_distro = Cnl()
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/operating_systems/cnl.py", line 57, in __init__
    version = self._detect_crayos_version()
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/operating_systems/cnl.py", line 66, in _detect_crayos_version
    release_attrs = read_cle_release_file()
  File "/mnt/a/u/sciteam/stewart1/spack/lib/spack/spack/operating_systems/cnl.py", line 37, in read_cle_release_file
    with open(_cle_release_file) as release_file:
IOError: [Errno 2] No such file or directory: '/etc/opt/cray/release/cle-release'
```

### Information on your system

```console
$ cat /etc/*-release
Cluster Manager v6.1
slave
LSB_VERSION="core-2.0-noarch:core-3.2-noarch:core-4.0-noarch:core-2.0-x86_64:core-3.2-x86_64:core-4.0-x86_64"
SUSE Linux Enterprise Server 11 (x86_64)
VERSION = 11
PATCHLEVEL = 3
$ uname -a
Linux h2ologin2 3.0.101-0.47.106.59-default #1 SMP Wed Jan 23 09:00:24 UTC 2019 (624897e) x86_64 x86_64 x86_64 GNU/Linux
```


Discussion:
It looks like the correct name of the file does not contain a dash:
```
$ cat /etc/opt/cray/release/clerelease
5.2.UP04
```
The file also doesn't have the format that `operating_systems/cnl.py` expects.
@tgamblin This bug was introduced in #11906.
FWIW, in CMake we use a set of heuristics to determine the CLE version:

1. `CRAYOS_VERSION` environment variable
2.  `XTOS_VERSION` environment variable
3.  `RELEASE=(.*)` in the `/etc/opt/cray/release/cle-release` file
4.  Direct contents of `/etc/opt/cray/release/clerelease`

Resolving patch:
diff --git a/lib/spack/spack/operating_systems/cnl.py b/lib/spack/spack/operating_systems/cnl.py
--- a/lib/spack/spack/operating_systems/cnl.py
+++ b/lib/spack/spack/operating_systems/cnl.py
@@ -3,22 +3,27 @@
 #
 # SPDX-License-Identifier: (Apache-2.0 OR MIT)
 
+import os
 import re
 
 import llnl.util.tty as tty
 
+import spack.error
 import spack.version
 from spack.architecture import OperatingSystem
 from spack.util.module_cmd import module
 
-#: Location of the Cray CLE release file, which we look at to get the CNL
-#: OS version.
+#: Possible locations of the Cray CLE release file,
+#: which we look at to get the CNL OS version.
 _cle_release_file = '/etc/opt/cray/release/cle-release'
+_clerelease_file  = '/etc/opt/cray/release/clerelease'
 
 
 def read_cle_release_file():
     """Read the CLE release file and return a dict with its attributes.
 
+    This file is present on newer versions of Cray.
+
     The release file looks something like this::
 
         RELEASE=6.0.UP07
@@ -33,6 +38,8 @@ def read_cle_release_file():
           ...
         }
 
+    Returns:
+        dict: dictionary of release attributes
     """
     with open(_cle_release_file) as release_file:
         result = {}
@@ -44,8 +51,25 @@ def read_cle_release_file():
         return result
 
 
+def read_clerelease_file():
+    """Read the CLE release file and return the Cray OS version.
+
+    This file is present on older versions of Cray.
+
+    The release file looks something like this::
+
+        5.2.UP04
+
+    Returns:
+        str: the Cray OS version
+    """
+    with open(_clerelease_file) as release_file:
+        for line in release_file:
+            return line.strip()
+
+
 class Cnl(OperatingSystem):
-    """ Compute Node Linux (CNL) is the operating system used for the Cray XC
+    """Compute Node Linux (CNL) is the operating system used for the Cray XC
     series super computers. It is a very stripped down version of GNU/Linux.
     Any compilers found through this operating system will be used with
     modules. If updated, user must make sure that version and name are
@@ -63,9 +87,16 @@ def __str__(self):
 
     @classmethod
     def _detect_crayos_version(cls):
-        release_attrs = read_cle_release_file()
-        v = spack.version.Version(release_attrs['RELEASE'])
-        return v[0]
+        if os.path.isfile(_cle_release_file):
+            release_attrs = read_cle_release_file()
+            v = spack.version.Version(release_attrs['RELEASE'])
+            return v[0]
+        elif os.path.isfile(_clerelease_file):
+            v = read_clerelease_file()
+            return spack.version.Version(v)[0]
+        else:
+            raise spack.error.UnsupportedPlatformError(
+                'Unable to detect Cray OS version')
 
     def arguments_to_detect_version_fn(self, paths):
         import spack.compilers


Test patch:
diff --git a/lib/spack/spack/test/operating_system.py b/lib/spack/spack/test/operating_system.py
--- a/lib/spack/spack/test/operating_system.py
+++ b/lib/spack/spack/test/operating_system.py
@@ -32,3 +32,42 @@ def test_read_cle_release_file(tmpdir, monkeypatch):
     assert attrs['DUMMY'] == 'foo=bar'
 
     assert cnl.Cnl._detect_crayos_version() == 6
+
+
+def test_read_clerelease_file(tmpdir, monkeypatch):
+    """test reading the Cray clerelease file"""
+    clerelease_path = tmpdir.join('clerelease')
+    with clerelease_path.open('w') as f:
+        f.write('5.2.UP04\n')
+
+    monkeypatch.setattr(cnl, '_clerelease_file', str(clerelease_path))
+    v = cnl.read_clerelease_file()
+
+    assert v == '5.2.UP04'
+
+    assert cnl.Cnl._detect_crayos_version() == 5
+
+
+def test_cle_release_precedence(tmpdir, monkeypatch):
+    """test that cle-release file takes precedence over clerelease file."""
+    cle_release_path = tmpdir.join('cle-release')
+    clerelease_path = tmpdir.join('clerelease')
+
+    with cle_release_path.open('w') as f:
+        f.write("""\
+RELEASE=6.0.UP07
+BUILD=6.0.7424
+DATE=20190611
+ARCH=noarch
+NETWORK=ari
+PATCHSET=35-201906112304
+DUMMY=foo=bar
+""")
+
+    with clerelease_path.open('w') as f:
+        f.write('5.2.UP04\n')
+
+    monkeypatch.setattr(cnl, '_clerelease_file', str(clerelease_path))
+    monkeypatch.setattr(cnl, '_cle_release_file', str(cle_release_path))
+
+    assert cnl.Cnl._detect_crayos_version() == 6