From 04730e6f409e94a8b41c296e9e660d147bf0a17f Mon Sep 17 00:00:00 2001 From: Dean Troyer Date: Fri, 27 Apr 2012 11:53:06 -0500 Subject: [PATCH] Add 'list service' command and common modules --- openstackclient/common/command.py | 35 ++++++ openstackclient/common/exceptions.py | 147 ++++++++++++++++++++++ openstackclient/identity/v2_0/__init__.py | 0 openstackclient/identity/v2_0/service.py | 44 +++++++ setup.py | 1 + 5 files changed, 227 insertions(+) create mode 100644 openstackclient/common/command.py create mode 100644 openstackclient/common/exceptions.py create mode 100644 openstackclient/identity/v2_0/__init__.py create mode 100644 openstackclient/identity/v2_0/service.py diff --git a/openstackclient/common/command.py b/openstackclient/common/command.py new file mode 100644 index 000000000..c57d7876d --- /dev/null +++ b/openstackclient/common/command.py @@ -0,0 +1,35 @@ +# Copyright 2011 OpenStack LLC. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +""" +OpenStack base command +""" + +from cliff.command import Command + + +class OpenStackCommand(Command): + """Base class for OpenStack commands + """ + + api = None + + def run(self, parsed_args): + if not self.api: + return + else: + return super(OpenStackCommand, self).run(parsed_args) diff --git a/openstackclient/common/exceptions.py b/openstackclient/common/exceptions.py new file mode 100644 index 000000000..4b4a0fb43 --- /dev/null +++ b/openstackclient/common/exceptions.py @@ -0,0 +1,147 @@ +# Copyright 2012 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +""" +Exception definitions. +""" + + +class CommandError(Exception): + pass + + +class AuthorizationFailure(Exception): + pass + + +class NoTokenLookupException(Exception): + """This form of authentication does not support looking up + endpoints from an existing token.""" + pass + + +class EndpointNotFound(Exception): + """Could not find Service or Region in Service Catalog.""" + pass + + +class ClientException(Exception): + """ + The base exception class for all exceptions this library raises. + """ + def __init__(self, code, message=None, details=None): + self.code = code + self.message = message or self.__class__.message + self.details = details + + def __str__(self): + return "%s (HTTP %s)" % (self.message, self.code) + + +class BadRequest(ClientException): + """ + HTTP 400 - Bad request: you sent some malformed data. + """ + http_status = 400 + message = "Bad request" + + +class Unauthorized(ClientException): + """ + HTTP 401 - Unauthorized: bad credentials. + """ + http_status = 401 + message = "Unauthorized" + + +class Forbidden(ClientException): + """ + HTTP 403 - Forbidden: your credentials don't give you access to this + resource. + """ + http_status = 403 + message = "Forbidden" + + +class NotFound(ClientException): + """ + HTTP 404 - Not found + """ + http_status = 404 + message = "Not found" + + +class Conflict(ClientException): + """ + HTTP 409 - Conflict + """ + http_status = 409 + message = "Conflict" + + +class OverLimit(ClientException): + """ + HTTP 413 - Over limit: you're over the API limits for this time period. + """ + http_status = 413 + message = "Over limit" + + +# NotImplemented is a python keyword. +class HTTPNotImplemented(ClientException): + """ + HTTP 501 - Not Implemented: the server does not support this operation. + """ + http_status = 501 + message = "Not Implemented" + + +# In Python 2.4 Exception is old-style and thus doesn't have a __subclasses__() +# so we can do this: +# _code_map = dict((c.http_status, c) +# for c in ClientException.__subclasses__()) +# +# Instead, we have to hardcode it: +_code_map = dict((c.http_status, c) for c in [BadRequest, Unauthorized, + Forbidden, NotFound, OverLimit, HTTPNotImplemented]) + + +def from_response(response, body): + """ + Return an instance of an ClientException or subclass + based on an httplib2 response. + + Usage:: + + resp, body = http.request(...) + if resp.status != 200: + raise exception_from_response(resp, body) + """ + cls = _code_map.get(response.status, ClientException) + if body: + if hasattr(body, 'keys'): + error = body[body.keys()[0]] + message = error.get('message', None) + details = error.get('details', None) + else: + # If we didn't get back a properly formed error message we + # probably couldn't communicate with Keystone at all. + message = "Unable to communicate with image service: %s." % body + details = None + return cls(code=response.status, message=message, details=details) + else: + return cls(code=response.status) diff --git a/openstackclient/identity/v2_0/__init__.py b/openstackclient/identity/v2_0/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/openstackclient/identity/v2_0/service.py b/openstackclient/identity/v2_0/service.py new file mode 100644 index 000000000..24ead9281 --- /dev/null +++ b/openstackclient/identity/v2_0/service.py @@ -0,0 +1,44 @@ +# Copyright 2012 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +""" +Service action implementations +""" + +import logging + +from openstackclient.common import command +from openstackclient.common import utils + + +class List_Service(command.OpenStackCommand): + "List service command." + + api = 'identity' + log = logging.getLogger(__name__) + + def get_parser(self, prog_name): + parser = super(List_Service, self).get_parser(prog_name) + parser.add_argument( + '--long', + action='store_true', + default=False, + help='Additional fields are listed in output') + return parser + + def run(self, parsed_args): + self.log.info('v2.List_Service.run(%s)' % parsed_args) diff --git a/setup.py b/setup.py index 6dbf5e1ee..93e8f0155 100644 --- a/setup.py +++ b/setup.py @@ -49,6 +49,7 @@ setup( 'openstack.cli': [ 'list_server = openstackclient.compute.v2.server:List_Server', 'show_server = openstackclient.compute.v2.server:Show_Server', + 'list_service = openstackclient.identity.v2_0.service:List_Service', ] } )