Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / errors.py @ 023d5ada

History | View | Annotate | Download (6.3 kB)

1 e3f01d64 Stavros Sachtouris
# Copyright 2013 GRNET S.A. All rights reserved.
2 c9e706b2 Stavros Sachtouris
#
3 c9e706b2 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 c9e706b2 Stavros Sachtouris
# without modification, are permitted provided that the following
5 c9e706b2 Stavros Sachtouris
# conditions are met:
6 c9e706b2 Stavros Sachtouris
#
7 c9e706b2 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 c9e706b2 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 c9e706b2 Stavros Sachtouris
#      disclaimer.
10 c9e706b2 Stavros Sachtouris
#
11 c9e706b2 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 c9e706b2 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 c9e706b2 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 c9e706b2 Stavros Sachtouris
#      provided with the distribution.
15 c9e706b2 Stavros Sachtouris
#
16 c9e706b2 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 c9e706b2 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 c9e706b2 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 c9e706b2 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 c9e706b2 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 c9e706b2 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 c9e706b2 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 c9e706b2 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 c9e706b2 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 c9e706b2 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 c9e706b2 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 c9e706b2 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 c9e706b2 Stavros Sachtouris
#
29 c9e706b2 Stavros Sachtouris
# The views and conclusions contained in the software and
30 c9e706b2 Stavros Sachtouris
# documentation are those of the authors and should not be
31 c9e706b2 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 c9e706b2 Stavros Sachtouris
# or implied, of GRNET S.A.
33 c9e706b2 Stavros Sachtouris
34 137c51f5 Stavros Sachtouris
from kamaki.cli.logger import get_logger
35 6069b53b Stavros Sachtouris
36 9986e569 Stavros Sachtouris
log = get_logger('kamaki.cli')
37 de4f08ef Stavros Sachtouris
38 fd5db045 Stavros Sachtouris
39 c9e706b2 Stavros Sachtouris
class CLIError(Exception):
40 c1558584 Stavros Sachtouris
41 0238c167 Stavros Sachtouris
    def __init__(self, message, details=[], importance=0):
42 c9e706b2 Stavros Sachtouris
        """
43 f10cef01 Stavros Sachtouris
        :param message: is the main message of the Error
44 f10cef01 Stavros Sachtouris
        :param defaults: is a list of previous errors
45 f10cef01 Stavros Sachtouris
        :param importance: of the output for the user (0, 1, 2, 3)
46 0238c167 Stavros Sachtouris
        """
47 f10cef01 Stavros Sachtouris
        message += '' if message and message.endswith('\n') else '\n'
48 0238c167 Stavros Sachtouris
        super(CLIError, self).__init__(message)
49 f10cef01 Stavros Sachtouris
        self.details = (list(details) if (
50 f10cef01 Stavros Sachtouris
            isinstance(details, list) or isinstance(details, tuple)) else [
51 f10cef01 Stavros Sachtouris
                '%s' % details]) if details else []
52 0238c167 Stavros Sachtouris
        try:
53 f10cef01 Stavros Sachtouris
            self.importance = int(importance or 0)
54 0238c167 Stavros Sachtouris
        except ValueError:
55 0238c167 Stavros Sachtouris
            self.importance = 0
56 c9e706b2 Stavros Sachtouris
57 fd5db045 Stavros Sachtouris
58 362adf50 Stavros Sachtouris
class CLIUnimplemented(CLIError):
59 362adf50 Stavros Sachtouris
    def __init__(
60 362adf50 Stavros Sachtouris
            self,
61 362adf50 Stavros Sachtouris
            message='I \'M SORRY, DAVE.\nI \'M AFRAID I CAN\'T DO THAT.',
62 362adf50 Stavros Sachtouris
            details=[
63 362adf50 Stavros Sachtouris
                '      _        |',
64 362adf50 Stavros Sachtouris
                '   _-- --_     |',
65 362adf50 Stavros Sachtouris
                '  --     --    |',
66 362adf50 Stavros Sachtouris
                ' --   .   --   |',
67 362adf50 Stavros Sachtouris
                ' -_       _-   |',
68 362adf50 Stavros Sachtouris
                '   -_   _-     |',
69 362adf50 Stavros Sachtouris
                '      -        |'],
70 362adf50 Stavros Sachtouris
            importance=3):
71 362adf50 Stavros Sachtouris
        super(CLIUnimplemented, self).__init__(message, details, importance)
72 362adf50 Stavros Sachtouris
73 362adf50 Stavros Sachtouris
74 8cec3671 Stavros Sachtouris
class CLIBaseUrlError(CLIError):
75 8cec3671 Stavros Sachtouris
    def __init__(self, message='', details=[], importance=2, service=None):
76 f10cef01 Stavros Sachtouris
        service = '%s' % (service or '')
77 031ca67d Stavros Sachtouris
        message = message or 'No URL for %s' % service.lower()
78 8cec3671 Stavros Sachtouris
        details = details or [
79 f10cef01 Stavros Sachtouris
            'Two ways to resolve this:',
80 c825ddc9 Stavros Sachtouris
            '(Use the correct cloud name, instead of "default")',
81 f10cef01 Stavros Sachtouris
            'A. (recommended) Let kamaki discover endpoint URLs for all',
82 362adf50 Stavros Sachtouris
            'services by setting a single Authentication URL and token:',
83 144b3551 Stavros Sachtouris
            '  /config set cloud.default.url <AUTH_URL>',
84 144b3551 Stavros Sachtouris
            '  /config set cloud.default.token <t0k3n>',
85 f10cef01 Stavros Sachtouris
            'B. (advanced users) Explicitly set an %s endpoint URL' % (
86 8cec3671 Stavros Sachtouris
                service.upper()),
87 031ca67d Stavros Sachtouris
            'Note: URL option has a higher priority, so delete it to',
88 8cec3671 Stavros Sachtouris
            'make that work',
89 144b3551 Stavros Sachtouris
            '  /config delete cloud.default.url',
90 144b3551 Stavros Sachtouris
            '  /config set cloud.%s.url <%s_URL>' % (
91 362adf50 Stavros Sachtouris
                service, service.upper())]
92 8cec3671 Stavros Sachtouris
        super(CLIBaseUrlError, self).__init__(message, details, importance)
93 8cec3671 Stavros Sachtouris
94 8cec3671 Stavros Sachtouris
95 c9e706b2 Stavros Sachtouris
class CLISyntaxError(CLIError):
96 0238c167 Stavros Sachtouris
    def __init__(self, message='Syntax Error', details=[], importance=1):
97 0238c167 Stavros Sachtouris
        super(CLISyntaxError, self).__init__(message, details, importance)
98 8694bdad Stavros Sachtouris
99 8694bdad Stavros Sachtouris
100 8694bdad Stavros Sachtouris
class CLIInvalidArgument(CLISyntaxError):
101 8694bdad Stavros Sachtouris
    def __init__(self, message='Invalid Argument', details=[], importance=1):
102 8694bdad Stavros Sachtouris
        super(CLIInvalidArgument, self).__init__(message, details, importance)
103 fd5db045 Stavros Sachtouris
104 c9e706b2 Stavros Sachtouris
105 c9e706b2 Stavros Sachtouris
class CLIUnknownCommand(CLIError):
106 0238c167 Stavros Sachtouris
    def __init__(self, message='Unknown Command', details=[], importance=1):
107 0238c167 Stavros Sachtouris
        super(CLIUnknownCommand, self).__init__(message, details, importance)
108 fd5db045 Stavros Sachtouris
109 c9e706b2 Stavros Sachtouris
110 926d6863 Stavros Sachtouris
class CLICmdSpecError(CLIError):
111 de73876b Stavros Sachtouris
    def __init__(
112 24ff0a35 Stavros Sachtouris
            self, message='Command Specification Error',
113 24ff0a35 Stavros Sachtouris
            details=[], importance=0):
114 0238c167 Stavros Sachtouris
        super(CLICmdSpecError, self).__init__(message, details, importance)
115 fd5db045 Stavros Sachtouris
116 c9e706b2 Stavros Sachtouris
117 6069b53b Stavros Sachtouris
def raiseCLIError(err, message='', importance=0, details=[]):
118 83ba5545 Stavros Sachtouris
    """
119 83ba5545 Stavros Sachtouris
    :param err: (Exception) the original error message, if None, a new
120 83ba5545 Stavros Sachtouris
        CLIError is born which is conceptually bind to raiser
121 83ba5545 Stavros Sachtouris

122 83ba5545 Stavros Sachtouris
    :param message: (str) a custom error message that overrides err's
123 83ba5545 Stavros Sachtouris

124 83ba5545 Stavros Sachtouris
    :param importance: (int) instruction to called application (e.g. for
125 83ba5545 Stavros Sachtouris
        coloring printed error messages)
126 83ba5545 Stavros Sachtouris

127 83ba5545 Stavros Sachtouris
    :param details: (list) various information on the error
128 83ba5545 Stavros Sachtouris

129 83ba5545 Stavros Sachtouris
    :raises CLIError: it is the purpose of this method
130 83ba5545 Stavros Sachtouris
    """
131 6069b53b Stavros Sachtouris
    from traceback import format_stack
132 c1558584 Stavros Sachtouris
133 83ba5545 Stavros Sachtouris
    stack = ['%s' % type(err)] if err else ['<kamaki.cli.errors.CLIError>']
134 3667e969 Stavros Sachtouris
    stack += format_stack()
135 83ba5545 Stavros Sachtouris
136 f10cef01 Stavros Sachtouris
    details = list(details) if (
137 f10cef01 Stavros Sachtouris
        isinstance(details, list) or isinstance(details, tuple)) else [
138 f10cef01 Stavros Sachtouris
            '%s' % details]
139 e8d3b957 Stavros Sachtouris
    err_details = getattr(err, 'details', [])
140 fa7d08b6 Stavros Sachtouris
    if isinstance(err_details, list) or isinstance(err_details, tuple):
141 e8d3b957 Stavros Sachtouris
        details += list(err_details)
142 fa7d08b6 Stavros Sachtouris
    else:
143 fa7d08b6 Stavros Sachtouris
        details.append('%s' % err_details)
144 6069b53b Stavros Sachtouris
145 f10cef01 Stavros Sachtouris
    origerr = (('%s' % err) or '%s' % type(err)) if err else stack[0]
146 f10cef01 Stavros Sachtouris
    message = '%s' % message or origerr
147 6069b53b Stavros Sachtouris
148 6069b53b Stavros Sachtouris
    try:
149 dc6fc88e Stavros Sachtouris
        status = err.status or err.errno
150 6069b53b Stavros Sachtouris
    except AttributeError:
151 f10cef01 Stavros Sachtouris
        try:
152 f10cef01 Stavros Sachtouris
            status = err.errno
153 f10cef01 Stavros Sachtouris
        except AttributeError:
154 f10cef01 Stavros Sachtouris
            status = None
155 6069b53b Stavros Sachtouris
156 3667e969 Stavros Sachtouris
    if origerr not in details + [message]:
157 3667e969 Stavros Sachtouris
        details.append(origerr)
158 6069b53b Stavros Sachtouris
159 f10cef01 Stavros Sachtouris
    message += '' if message and message.endswith('\n') else '\n'
160 6069b53b Stavros Sachtouris
    if status:
161 f10cef01 Stavros Sachtouris
        message = '(%s) %s' % (status, message)
162 0238c167 Stavros Sachtouris
        try:
163 f10cef01 Stavros Sachtouris
            status = int(status)
164 0238c167 Stavros Sachtouris
        except ValueError:
165 f10cef01 Stavros Sachtouris
            raise CLIError(message, details, importance or 0)
166 f10cef01 Stavros Sachtouris
        importance = importance or status // 100
167 c1558584 Stavros Sachtouris
    importance = getattr(err, 'importance', importance)
168 6069b53b Stavros Sachtouris
    raise CLIError(message, details, importance)