diff options
Diffstat (limited to 'reddwarfclient/client.py')
| -rw-r--r-- | reddwarfclient/client.py | 370 |
1 files changed, 0 insertions, 370 deletions
diff --git a/reddwarfclient/client.py b/reddwarfclient/client.py deleted file mode 100644 index f602afb..0000000 --- a/reddwarfclient/client.py +++ /dev/null @@ -1,370 +0,0 @@ -# Copyright (c) 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. - -import httplib2 -import logging -import os -import time -import urlparse -import sys - -try: - import json -except ImportError: - import simplejson as json - -# Python 2.5 compat fix -if not hasattr(urlparse, 'parse_qsl'): - import cgi - urlparse.parse_qsl = cgi.parse_qsl - -from reddwarfclient import auth -from reddwarfclient import exceptions - - -_logger = logging.getLogger(__name__) -RDC_PP = os.environ.get("RDC_PP", "False") == "True" - - -expected_errors = (400, 401, 403, 404, 408, 409, 413, 422, 500, 501) - - -def log_to_streamhandler(stream=None): - stream = stream or sys.stderr - ch = logging.StreamHandler(stream) - _logger.setLevel(logging.DEBUG) - _logger.addHandler(ch) - - -if 'REDDWARFCLIENT_DEBUG' in os.environ and os.environ['REDDWARFCLIENT_DEBUG']: - log_to_streamhandler() - - -class ReddwarfHTTPClient(httplib2.Http): - - USER_AGENT = 'python-reddwarfclient' - - def __init__(self, user, password, tenant, auth_url, service_name, - service_url=None, - auth_strategy=None, insecure=False, - timeout=None, proxy_tenant_id=None, - proxy_token=None, region_name=None, - endpoint_type='publicURL', service_type=None, - timings=False): - - super(ReddwarfHTTPClient, self).__init__(timeout=timeout) - - self.username = user - self.password = password - self.tenant = tenant - if auth_url: - self.auth_url = auth_url.rstrip('/') - else: - self.auth_url = None - self.region_name = region_name - self.endpoint_type = endpoint_type - self.service_url = service_url - self.service_type = service_type - self.service_name = service_name - self.timings = timings - - self.times = [] # [("item", starttime, endtime), ...] - - self.auth_token = None - self.proxy_token = proxy_token - self.proxy_tenant_id = proxy_tenant_id - - # httplib2 overrides - self.force_exception_to_status_code = True - self.disable_ssl_certificate_validation = insecure - - auth_cls = auth.get_authenticator_cls(auth_strategy) - - self.authenticator = auth_cls(self, auth_strategy, - self.auth_url, self.username, - self.password, self.tenant, - region=region_name, - service_type=service_type, - service_name=service_name, - service_url=service_url) - - def get_timings(self): - return self.times - - def http_log(self, args, kwargs, resp, body): - if not RDC_PP: - self.simple_log(args, kwargs, resp, body) - else: - self.pretty_log(args, kwargs, resp, body) - - def simple_log(self, args, kwargs, resp, body): - if not _logger.isEnabledFor(logging.DEBUG): - return - - string_parts = ['curl -i'] - for element in args: - if element in ('GET', 'POST'): - string_parts.append(' -X %s' % element) - else: - string_parts.append(' %s' % element) - - for element in kwargs['headers']: - header = ' -H "%s: %s"' % (element, kwargs['headers'][element]) - string_parts.append(header) - - _logger.debug("REQ: %s\n" % "".join(string_parts)) - if 'body' in kwargs: - _logger.debug("REQ BODY: %s\n" % (kwargs['body'])) - _logger.debug("RESP:%s %s\n", resp, body) - - def pretty_log(self, args, kwargs, resp, body): - from reddwarfclient import common - if not _logger.isEnabledFor(logging.DEBUG): - return - - string_parts = ['curl -i'] - for element in args: - if element in ('GET', 'POST'): - string_parts.append(' -X %s' % element) - else: - string_parts.append(' %s' % element) - - for element in kwargs['headers']: - header = ' -H "%s: %s"' % (element, kwargs['headers'][element]) - string_parts.append(header) - - curl_cmd = "".join(string_parts) - _logger.debug("REQUEST:") - if 'body' in kwargs: - _logger.debug("%s -d '%s'" % (curl_cmd, kwargs['body'])) - try: - req_body = json.dumps(json.loads(kwargs['body']), - sort_keys=True, indent=4) - except: - req_body = kwargs['body'] - _logger.debug("BODY: %s\n" % (req_body)) - else: - _logger.debug(curl_cmd) - - try: - resp_body = json.dumps(json.loads(body), sort_keys=True, indent=4) - except: - resp_body = body - _logger.debug("RESPONSE HEADERS: %s" % resp) - _logger.debug("RESPONSE BODY : %s" % resp_body) - - def request(self, *args, **kwargs): - kwargs.setdefault('headers', kwargs.get('headers', {})) - kwargs['headers']['User-Agent'] = self.USER_AGENT - self.morph_request(kwargs) - - resp, body = super(ReddwarfHTTPClient, self).request(*args, **kwargs) - - # Save this in case anyone wants it. - self.last_response = (resp, body) - self.http_log(args, kwargs, resp, body) - - if body: - try: - body = self.morph_response_body(body) - except exceptions.ResponseFormatError: - # Acceptable only if the response status is an error code. - # Otherwise its the API or client misbehaving. - self.raise_error_from_status(resp, None) - raise # Not accepted! - else: - body = None - - if resp.status in expected_errors: - raise exceptions.from_response(resp, body) - - return resp, body - - def raise_error_from_status(self, resp, body): - if resp.status in expected_errors: - raise exceptions.from_response(resp, body) - - def morph_request(self, kwargs): - kwargs['headers']['Accept'] = 'application/json' - kwargs['headers']['Content-Type'] = 'application/json' - if 'body' in kwargs: - kwargs['body'] = json.dumps(kwargs['body']) - - def morph_response_body(self, body_string): - try: - return json.loads(body_string) - except ValueError: - raise exceptions.ResponseFormatError() - - def _time_request(self, url, method, **kwargs): - start_time = time.time() - resp, body = self.request(url, method, **kwargs) - self.times.append(("%s %s" % (method, url), - start_time, time.time())) - return resp, body - - def _cs_request(self, url, method, **kwargs): - def request(): - kwargs.setdefault('headers', {})['X-Auth-Token'] = self.auth_token - if self.tenant: - kwargs['headers']['X-Auth-Project-Id'] = self.tenant - - resp, body = self._time_request(self.service_url + url, method, - **kwargs) - return resp, body - - if not self.auth_token or not self.service_url: - self.authenticate() - - # Perform the request once. If we get a 401 back then it - # might be because the auth token expired, so try to - # re-authenticate and try again. If it still fails, bail. - try: - return request() - except exceptions.Unauthorized, ex: - self.authenticate() - return request() - - def get(self, url, **kwargs): - return self._cs_request(url, 'GET', **kwargs) - - def post(self, url, **kwargs): - return self._cs_request(url, 'POST', **kwargs) - - def put(self, url, **kwargs): - return self._cs_request(url, 'PUT', **kwargs) - - def delete(self, url, **kwargs): - return self._cs_request(url, 'DELETE', **kwargs) - - def authenticate(self): - """Auths the client and gets a token. May optionally set a service url. - - The client will get auth errors until the authentication step - occurs. Additionally, if a service_url was not explicitly given in - the clients __init__ method, one will be obtained from the auth - service. - - """ - catalog = self.authenticator.authenticate() - if self.service_url: - possible_service_url = None - else: - if self.endpoint_type == "publicURL": - possible_service_url = catalog.get_public_url() - elif self.endpoint_type == "adminURL": - possible_service_url = catalog.get_management_url() - self.authenticate_with_token(catalog.get_token(), possible_service_url) - - def authenticate_with_token(self, token, service_url=None): - self.auth_token = token - if not self.service_url: - if not service_url: - raise exceptions.ServiceUrlNotGiven() - else: - self.service_url = service_url - - -class Dbaas(object): - """ - Top-level object to access the Rackspace Database as a Service API. - - Create an instance with your creds:: - - >>> red = Dbaas(USERNAME, API_KEY, TENANT, AUTH_URL, SERVICE_NAME, - SERVICE_URL) - - Then call methods on its managers:: - - >>> red.instances.list() - ... - >>> red.flavors.list() - ... - - &c. - """ - - def __init__(self, username, api_key, tenant=None, auth_url=None, - service_type='database', service_name='reddwarf', - service_url=None, insecure=False, auth_strategy='keystone', - region_name=None, client_cls=ReddwarfHTTPClient): - from reddwarfclient.versions import Versions - from reddwarfclient.databases import Databases - from reddwarfclient.flavors import Flavors - from reddwarfclient.instances import Instances - from reddwarfclient.limits import Limits - from reddwarfclient.users import Users - from reddwarfclient.root import Root - from reddwarfclient.hosts import Hosts - from reddwarfclient.quota import Quotas - from reddwarfclient.backups import Backups - from reddwarfclient.security_groups import SecurityGroups - from reddwarfclient.security_groups import SecurityGroupRules - from reddwarfclient.storage import StorageInfo - from reddwarfclient.management import Management - from reddwarfclient.accounts import Accounts - from reddwarfclient.diagnostics import DiagnosticsInterrogator - from reddwarfclient.diagnostics import HwInfoInterrogator - - self.client = client_cls(username, api_key, tenant, auth_url, - service_type=service_type, - service_name=service_name, - service_url=service_url, - insecure=insecure, - auth_strategy=auth_strategy, - region_name=region_name) - self.versions = Versions(self) - self.databases = Databases(self) - self.flavors = Flavors(self) - self.instances = Instances(self) - self.limits = Limits(self) - self.users = Users(self) - self.root = Root(self) - self.hosts = Hosts(self) - self.quota = Quotas(self) - self.backups = Backups(self) - self.security_groups = SecurityGroups(self) - self.security_group_rules = SecurityGroupRules(self) - self.storage = StorageInfo(self) - self.management = Management(self) - self.accounts = Accounts(self) - self.diagnostics = DiagnosticsInterrogator(self) - self.hwinfo = HwInfoInterrogator(self) - - class Mgmt(object): - def __init__(self, dbaas): - self.instances = dbaas.management - self.hosts = dbaas.hosts - self.accounts = dbaas.accounts - self.storage = dbaas.storage - - self.mgmt = Mgmt(self) - - def set_management_url(self, url): - self.client.management_url = url - - def get_timings(self): - return self.client.get_timings() - - def authenticate(self): - """ - Authenticate against the server. - - This is called to perform an authentication to retrieve a token. - - Returns on success; raises :exc:`exceptions.Unauthorized` if the - credentials are wrong. - """ - self.client.authenticate() |
