Make SSL verification failures recommend spack -k

- Adds optional long message to SpackError
- tty now wraps long message text.
This commit is contained in:
Todd Gamblin 2014-04-13 16:38:15 -07:00
parent 980c1f0e47
commit 59a3b8dc67
5 changed files with 33 additions and 14 deletions

View File

@ -96,8 +96,10 @@ except SpackError, e:
if spack.debug: if spack.debug:
# In debug mode, raise with a full stack trace. # In debug mode, raise with a full stack trace.
raise raise
elif e.long_message:
tty.die(e.message, e.long_message)
else: else:
# Otherwise print a nice simple message.
tty.die(e.message) tty.die(e.message)
except KeyboardInterrupt: except KeyboardInterrupt:
tty.die("Got a keyboard interrupt from the user.") tty.die("Got a keyboard interrupt from the user.")

View File

@ -23,6 +23,7 @@
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import sys import sys
import textwrap
from llnl.util.tty.color import * from llnl.util.tty.color import *
debug = False debug = False
@ -39,7 +40,10 @@ def info(message, *args, **kwargs):
format = kwargs.get('format', '*b') format = kwargs.get('format', '*b')
cprint("@%s{==>} %s" % (format, cescape(str(message)))) cprint("@%s{==>} %s" % (format, cescape(str(message))))
for arg in args: for arg in args:
print indent + str(arg) lines = textwrap.wrap(
str(arg), initial_indent=indent, subsequent_indent=indent)
for line in lines:
print line
def verbose(message, *args): def verbose(message, *args):

View File

@ -27,8 +27,9 @@ class SpackError(Exception):
"""This is the superclass for all Spack errors. """This is the superclass for all Spack errors.
Subclasses can be found in the modules they have to do with. Subclasses can be found in the modules they have to do with.
""" """
def __init__(self, message): def __init__(self, message, long_message=None):
super(SpackError, self).__init__(message) super(SpackError, self).__init__(message)
self.long_message = long_message
class UnsupportedPlatformError(SpackError): class UnsupportedPlatformError(SpackError):

View File

@ -215,17 +215,27 @@ def chdir(self):
def fetch_from_url(self, url): def fetch_from_url(self, url):
try: # Run curl but grab the mime type from the http headers
# Run curl but grab the mime type from the http headers headers = spack.curl('-#', # status bar
headers = spack.curl('-#', # status bar '-O', # save file to disk
'-O', # save file to disk '-D', '-', # print out HTML headers
'-D', '-', # print out HTML headers '-L', url,
'-L', url, return_output=True) return_output=True, fail_on_error=False)
except:
if spack.curl.returncode != 0:
# clean up archive on failure. # clean up archive on failure.
if self.archive_file: if self.archive_file:
os.remove(self.archive_file) os.remove(self.archive_file)
raise
if spack.curl.returncode == 60:
# This is a certificate error. Suggest spack -k
raise FailedDownloadError(
url,
"Curl was unable to fetch due to invalid certificate. "
"This is either an attack, or your cluster's SSL configuration "
"is bad. If you believe your SSL configuration is bad, you "
"can try running spack -k, which will not check SSL certificates."
"Use this at your own risk.")
# Check if we somehow got an HTML file rather than the archive we # Check if we somehow got an HTML file rather than the archive we
# asked for. We only look at the last content type, to handle # asked for. We only look at the last content type, to handle
@ -358,7 +368,7 @@ def find_tmp_root():
class FailedDownloadError(serr.SpackError): class FailedDownloadError(serr.SpackError):
"""Raised wen a download fails.""" """Raised wen a download fails."""
def __init__(self, url): def __init__(self, url, msg=""):
super(FailedDownloadError, self).__init__( super(FailedDownloadError, self).__init__(
"Failed to fetch file from URL: " + url) "Failed to fetch file from URL: %s" % url, msg)
self.url = url self.url = url

View File

@ -35,7 +35,7 @@ class Executable(object):
"""Class representing a program that can be run on the command line.""" """Class representing a program that can be run on the command line."""
def __init__(self, name): def __init__(self, name):
self.exe = name.split(' ') self.exe = name.split(' ')
self.returncode = None
def add_default_arg(self, arg): def add_default_arg(self, arg):
self.exe.append(arg) self.exe.append(arg)
@ -68,6 +68,8 @@ def __call__(self, *args, **kwargs):
stderr=sys.stderr, stderr=sys.stderr,
stdout=subprocess.PIPE if return_output else sys.stdout) stdout=subprocess.PIPE if return_output else sys.stdout)
out, err = proc.communicate() out, err = proc.communicate()
self.returncode = proc.returncode
if fail_on_error and proc.returncode != 0: if fail_on_error and proc.returncode != 0:
raise SpackError("command '%s' returned error code %d" raise SpackError("command '%s' returned error code %d"
% (" ".join(cmd), proc.returncode)) % (" ".join(cmd), proc.returncode))