Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / errors.py @ a0a61f30

History | View | Annotate | Download (6.2 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 0238c167 Stavros Sachtouris
        @message is the main message of the Error
44 0238c167 Stavros Sachtouris
        @detauls is a list of previous errors
45 0238c167 Stavros Sachtouris
        @importance of the output for the user
46 0238c167 Stavros Sachtouris
            Suggested values: 0, 1, 2, 3
47 0238c167 Stavros Sachtouris
        """
48 6069b53b Stavros Sachtouris
        message += '' if message and message[-1] == '\n' else '\n'
49 0238c167 Stavros Sachtouris
        super(CLIError, self).__init__(message)
50 c1558584 Stavros Sachtouris
        self.details = list(details) if isinstance(details, list)\
51 0238c167 Stavros Sachtouris
            else [] if details is None else ['%s' % details]
52 0238c167 Stavros Sachtouris
        try:
53 0238c167 Stavros Sachtouris
            self.importance = int(importance)
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 031ca67d Stavros Sachtouris
        message = message or 'No URL for %s' % service.lower()
77 8cec3671 Stavros Sachtouris
        details = details or [
78 8cec3671 Stavros Sachtouris
            'Two options to resolve this:',
79 c825ddc9 Stavros Sachtouris
            '(Use the correct cloud name, instead of "default")',
80 8cec3671 Stavros Sachtouris
            'A. (recommended) Let kamaki discover the endpoint URLs for all',
81 362adf50 Stavros Sachtouris
            'services by setting a single Authentication URL and token:',
82 144b3551 Stavros Sachtouris
            '  /config set cloud.default.url <AUTH_URL>',
83 144b3551 Stavros Sachtouris
            '  /config set cloud.default.token <t0k3n>',
84 8cec3671 Stavros Sachtouris
            'B. (advanced users) Explicitly set a valid %s endpoint URL' % (
85 8cec3671 Stavros Sachtouris
                service.upper()),
86 031ca67d Stavros Sachtouris
            'Note: URL option has a higher priority, so delete it to',
87 8cec3671 Stavros Sachtouris
            'make that work',
88 144b3551 Stavros Sachtouris
            '  /config delete cloud.default.url',
89 144b3551 Stavros Sachtouris
            '  /config set cloud.%s.url <%s_URL>' % (
90 362adf50 Stavros Sachtouris
                service, service.upper())]
91 8cec3671 Stavros Sachtouris
        super(CLIBaseUrlError, self).__init__(message, details, importance)
92 8cec3671 Stavros Sachtouris
93 8cec3671 Stavros Sachtouris
94 c9e706b2 Stavros Sachtouris
class CLISyntaxError(CLIError):
95 0238c167 Stavros Sachtouris
    def __init__(self, message='Syntax Error', details=[], importance=1):
96 0238c167 Stavros Sachtouris
        super(CLISyntaxError, self).__init__(message, details, importance)
97 fd5db045 Stavros Sachtouris
98 c9e706b2 Stavros Sachtouris
99 c9e706b2 Stavros Sachtouris
class CLIUnknownCommand(CLIError):
100 0238c167 Stavros Sachtouris
    def __init__(self, message='Unknown Command', details=[], importance=1):
101 0238c167 Stavros Sachtouris
        super(CLIUnknownCommand, self).__init__(message, details, importance)
102 fd5db045 Stavros Sachtouris
103 c9e706b2 Stavros Sachtouris
104 926d6863 Stavros Sachtouris
class CLICmdSpecError(CLIError):
105 de73876b Stavros Sachtouris
    def __init__(
106 24ff0a35 Stavros Sachtouris
            self, message='Command Specification Error',
107 24ff0a35 Stavros Sachtouris
            details=[], importance=0):
108 0238c167 Stavros Sachtouris
        super(CLICmdSpecError, self).__init__(message, details, importance)
109 fd5db045 Stavros Sachtouris
110 c9e706b2 Stavros Sachtouris
111 017d37ce Stavros Sachtouris
class CLICmdIncompleteError(CLICmdSpecError):
112 de73876b Stavros Sachtouris
    def __init__(
113 24ff0a35 Stavros Sachtouris
            self, message='Incomplete Command Error',
114 24ff0a35 Stavros Sachtouris
            details=[], importance=1):
115 0238c167 Stavros Sachtouris
        super(CLICmdSpecError, self).__init__(message, details, importance)
116 fd5db045 Stavros Sachtouris
117 017d37ce Stavros Sachtouris
118 6069b53b Stavros Sachtouris
def raiseCLIError(err, message='', importance=0, details=[]):
119 83ba5545 Stavros Sachtouris
    """
120 83ba5545 Stavros Sachtouris
    :param err: (Exception) the original error message, if None, a new
121 83ba5545 Stavros Sachtouris
        CLIError is born which is conceptually bind to raiser
122 83ba5545 Stavros Sachtouris

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

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

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

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