yakumo.session

Package yakumo :: Module session |
[hide private]
[frames] | no frames]

# Source Code for Module yakumo.session

      1  #   Copyright 2014 Akira Yoshiyama
      2  #
      3  #   Licensed under the Apache License, Version 2.0 (the "License"); you may
      4  #   not use this file except in compliance with the License. You may obtain
      5  #   a copy of the License at
      6  #
      7  #       http://www.apache.org/licenses/LICENSE-2.0
      8  #
      9  #   Unless required by applicable law or agreed to in writing, software
     10  #   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     11  #   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     12  #   License for the specific language governing permissions and limitations
     13  #   under the License.
     14
     15  """
     16  utility function(s) for session
     17  """
     18  from contextlib import contextmanager
     19  import functools
     20  import json
     21  import os
     22  import os_client_config
     23  from os_client_config import cloud_config
     24  import random
     25  import requests
     26  from simplejson.scanner import JSONDecodeError
     27
     28  from . import exception
     29  from . import patch
     30  from . import utils
     31
     32
     33  CHUNK_SIZE = 4096
     34
     35
     36  # Patch it!
     37  cloud_config.CloudConfig.get_session_endpoint = patch.get_session_endpoint
     38
     39
     40 -def get_session(**kwargs):
     41      """
     42      Session class dispatcher
     43
     44      :return: Session class
     45      """
     46      config = os_client_config.OpenStackConfig()
     47      cloud_config = config.get_one_cloud(**kwargs)
     48      if cloud_config.config.get('insecure'):
     49          cloud_config.config['verify'] = False
     50          cloud_config.config['cacert'] = None
     51      if 'timeout' not in cloud_config.config:
     52          cloud_config.config['timeout'] = 600
     53
     54      return Session(cloud_config)
     55
     56
     57 -class SessionProxy(object):
     58
     59 -    def __init__(self, session, service):
     60          self.session = session
     61          self.service = service
     62
     63 -    def has_endpoint(self, service):
     64          return self.session.has_endpoint(service)
     65
     66 -    def get(self, *args, **kwargs):
     67          return self.session.get(self.service, *args, **kwargs)
     68
     69 -    def head(self, *args, **kwargs):
     70          return self.session.head(self.service, *args, **kwargs)
     71
     72 -    def delete(self, *args, **kwargs):
     73          return self.session.delete(self.service, *args, **kwargs)
     74
     75 -    def patch(self, *args, **kwargs):
     76          return self.session.patch(self.service, *args, **kwargs)
     77
     78 -    def post(self, *args, **kwargs):
     79          return self.session.post(self.service, *args, **kwargs)
     80
     81 -    def put(self, *args, **kwargs):
     82          return self.session.put(self.service, *args, **kwargs)
     83
     84 -    def get_raw(self, *args, **kwargs):
     85          return self.session.get_raw(self.service, *args, **kwargs)
     86
     87 -    def post_raw(self, *args, **kwargs):
     88          return self.session.post_raw(self.service, *args, **kwargs)
     89
     90 -    def put_raw(self, *args, **kwargs):
     91          return self.session.put_raw(self.service, *args, **kwargs)
     92
     93 -    def get_file(self, *args, **kwargs):
     94          return self.session.get_file(self.service, *args, **kwargs)
     95
     96 -    def post_file(self, *args, **kwargs):
     97          return self.session.post_file(self.service, *args, **kwargs)
     98
     99 -    def put_file(self, *args, **kwargs):
    100          return self.session.put_file(self.service, *args, **kwargs)
    101
    102
    103 -def reauth(func):
    104
    105      @functools.wraps(func)
    106      def _wrapper(self, *args, **kwargs):
    107          try:
    108              return func(self, *args, **kwargs)
    109          except exception.NotFound:
    110              self.get_token()
    111              return func(self, *args, **kwargs)
    112
    113      return _wrapper
    114
    115
    116 -def exception_translator(func):
    117
    118      @functools.wraps(func)
    119      def _wrapper(self, *args, **kwargs):
    120          try:
    121              return func(self, *args, **kwargs)
    122          except exception.HTTPError as e:
    123              raise exception.mapping[e.response.status_code]()
    124
    125      return _wrapper
    126
    127
    128 -def safe_json_load(func):
    129
    130      @functools.wraps(func)
    131      def _wrapper(*args, **kwargs):
    132          try:
    133              return func(*args, **kwargs)
    134          except JSONDecodeError:
    135              return None
    136
    137      return _wrapper
    138
    139
    140 -class Session(object):
    141
    142 -    def __init__(self, config):
    143          self.config = config.config
    144          self.keystone_session = config.get_session()
    145          self.get_token()
    146          self.endpoints = {}
    147          for service in config.get_services():
    148              try:
    149                  self.endpoints[service] = config.get_session_endpoint(service)
    150              except:
    151                  pass
    152
    153 -    def has_endpoint(self, service):
    154          return service in self.endpoints
    155
    156 -    def get_proxy(self, service):
    157          return SessionProxy(self, service)
    158
    159 -    def get_token(self):
    160          self.token = self.keystone_session.get_token()
    161
    162      @staticmethod
    163 -    def json_body(kwargs):
    164          jsondata = json.dumps(kwargs.get('data', {}))
    165          kwargs['data'] = jsondata
    166
    167 -    def make_headers(self, kwargs, content_type=None,
    168                       accept='application/json'):
    169          kwargs.setdefault('headers', {})
    170          headers = kwargs['headers']
    171          if 'Content-Type' not in headers:
    172              if content_type:
    173                  headers['Content-Type'] = content_type
    174              else:
    175                  headers['Content-Type'] = "application/json; charset=UTF-8"
    176          if 'Accept' not in headers:
    177              headers['Accept'] = accept
    178          headers['Accept-Encoding'] = 'identity'
    179          headers['X-Auth-Token'] = self.token
    180
    181      @reauth
    182      @exception_translator
    183      @safe_json_load
    184 -    def get(self, service, *args, **kwargs):
    185          url = utils.join_path(self.endpoints[service], *args)
    186          self.make_headers(kwargs)
    187          response = requests.get(url, **kwargs)
    188          response.raise_for_status()
    189          return response.json()
    190
    191      @reauth
    192      @exception_translator
    193 -    def head(self, service, *args, **kwargs):
    194          url = utils.join_path(self.endpoints[service], *args)
    195          self.make_headers(kwargs)
    196          response = requests.head(url, **kwargs)
    197          response.raise_for_status()
    198          return response.headers
    199
    200      @reauth
    201      @exception_translator
    202 -    def delete(self, service, *args, **kwargs):
    203          url = utils.join_path(self.endpoints[service], *args)
    204          self.make_headers(kwargs)
    205          response = requests.delete(url, **kwargs)
    206          response.raise_for_status()
    207
    208      @reauth
    209      @exception_translator
    210      @safe_json_load
    211 -    def patch(self, service, *args, **kwargs):
    212          url = utils.join_path(self.endpoints[service], *args)
    213          self.make_headers(kwargs)
    214          self.json_body(kwargs)
    215          response = requests.patch(url, **kwargs)
    216          response.raise_for_status()
    217          return response.json()
    218
    219      @reauth
    220      @exception_translator
    221      @safe_json_load
    222 -    def post(self, service, *args, **kwargs):
    223          url = utils.join_path(self.endpoints[service], *args)
    224          self.make_headers(kwargs)
    225          self.json_body(kwargs)
    226          response = requests.post(url, **kwargs)
    227          response.raise_for_status()
    228          return response.json()
    229
    230      @reauth
    231      @exception_translator
    232      @safe_json_load
    233 -    def put(self, service, *args, **kwargs):
    234          url = utils.join_path(self.endpoints[service], *args)
    235          self.make_headers(kwargs)
    236          self.json_body(kwargs)
    237          response = requests.put(url, **kwargs)
    238          response.raise_for_status()
    239          return response.json()
    240
    241      @reauth
    242      @exception_translator
    243 -    def get_raw(self, service, *args, **kwargs):
    244          url = utils.join_path(self.endpoints[service], *args)
    245          self.make_headers(kwargs)
    246          response = requests.get(url, **kwargs)
    247          response.raise_for_status()
    248          return response.content
    249
    250      @reauth
    251      @exception_translator
    252      @safe_json_load
    253 -    def post_raw(self, service, *args, **kwargs):
    254          url = utils.join_path(self.endpoints[service], *args)
    255          self.make_headers(kwargs, content_type="application/octet-stream")
    256          response = requests.post(url, **kwargs)
    257          response.raise_for_status()
    258          return response.json()
    259
    260      @reauth
    261      @exception_translator
    262      @safe_json_load
    263 -    def put_raw(self, service, *args, **kwargs):
    264          url = utils.join_path(self.endpoints[service], *args)
    265          self.make_headers(kwargs, content_type="application/octet-stream")
    266          response = requests.put(url, **kwargs)
    267          response.raise_for_status()
    268          return response.json()
    269
    270      @reauth
    271      @exception_translator
    272      @safe_json_load
    273 -    def get_file(self, service, *args, **kwargs):
    274          url = utils.join_path(self.endpoints[service], *args)
    275          file = kwargs.pop('file')
    276          self.make_headers(kwargs)
    277          response = requests.get(url, stream=True, **kwargs)
    278          response.raise_for_status()
    279          with open(file, 'wb') as f:
    280              for c in response.iter_content(chunk_size=CHUNK_SIZE):
    281                  f.write(c)
    282                  f.flush()
    283          return response.headers
    284
    285      @reauth
    286      @exception_translator
    287      @safe_json_load
    288 -    def post_file(self, service, *args, **kwargs):
    289          url = utils.join_path(self.endpoints[service], *args)
    290          with open(kwargs.pop('file'), 'rb') as f:
    291              kwargs['files'] = {'file': f}
    292              self.make_headers(kwargs)
    293              response = requests.post(url, **kwargs)
    294          response.raise_for_status()
    295          return response.json()
    296
    297      @reauth
    298      @exception_translator
    299      @safe_json_load
    300 -    def put_file(self, service, *args, **kwargs):
    301          url = utils.join_path(self.endpoints[service], *args)
    302          with open(kwargs.pop('file'), 'rb') as f:
    303              kwargs['files'] = {'file': f}
    304              self.make_headers(kwargs)
    305              response = requests.put(url, **kwargs)
    306          response.raise_for_status()
    307          return response.json()
    308