requests module plugged

What is done:
* urllib2 code changed to corresponding from requests
* error handling for APIclient updated in order to exploit requests
  exceptions classes.

Partially implements: blueprint refactoring-for-fuelclient

Change-Id: I7f1c0b390828f4a77daeaca370cfb16a5df3839d
This commit is contained in:
Artem Roma
2014-07-15 16:28:24 +03:00
parent e66223cd0d
commit e577c5c2f4
4 changed files with 78 additions and 80 deletions

View File

@@ -14,8 +14,8 @@
from functools import wraps
from keystoneclient.exceptions import Unauthorized
import requests
import sys
import urllib2
def exit_with_error(message):
@@ -67,40 +67,36 @@ class ParserException(FuelClientException):
"""
def handle_exceptions(exc):
"""handle_exceptions - exception handling manager.
"""
if isinstance(exc, urllib2.HTTPError):
error_body = exc.read()
exit_with_error("{0} {1}".format(
exc,
"({0})".format(error_body or "")
))
elif isinstance(exc, urllib2.URLError):
exit_with_error("""
Can't connect to Nailgun server!
Please modify "SERVER_ADDRESS" and "LISTEN_PORT"
in the file /etc/fuel/client/config.yaml""")
elif isinstance(exc, Unauthorized):
exit_with_error("""
Unauthorized: need authentication!
Please provide user and password via client --os-username --os-password
or modify "KEYSTONE_USER" and "KEYSTONE_PASS" in
/etc/fuel/client/config.yaml""")
elif isinstance(exc, FuelClientException):
exit_with_error(exc.message)
else:
raise
def exceptions_decorator(func):
"""exceptions_decorator - is decorator which intercepts exceptions and
redirects them to handle_exceptions.
"""Handles HTTP errors and expected exceptions that may occur
in methods of APIClient class
"""
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as exc:
handle_exceptions(exc)
# when server returns to us bad request check that
# and print meaningful reason
except requests.HTTPError as exc:
error_body = exc.response.text
exit_with_error("{0} ({1})".format(exc, error_body))
except requests.ConnectionError:
exit_with_error("""
Can't connect to Nailgun server!
Please modify "SERVER_ADDRESS" and "LISTEN_PORT"
in the file /etc/fuel/client/config.yaml""")
except Unauthorized:
exit_with_error("""
Unauthorized: need authentication!
Please provide user and password via client
--os-username --os-password
or modify "KEYSTONE_USER" and "KEYSTONE_PASS" in
/etc/fuel/client/config.yaml""")
except FuelClientException as exc:
exit_with_error(exc.message)
# not all responses return data
except ValueError:
return {}
return wrapper

View File

@@ -15,7 +15,7 @@
import json
import logging
import os
import urllib2
import requests
import yaml
@@ -71,11 +71,14 @@ class Client(object):
return ''
@property
@exceptions_decorator
def auth_required(self):
if self._auth_required is None:
request = urllib2.urlopen(''.join([self.api_root, 'version']))
self._auth_required = json.loads(
request.read()).get('auth_required', False)
url = self.api_root + 'version'
resp = requests.get(url)
resp.raise_for_status()
self._auth_required = resp.json().get('auth_required', False)
return self._auth_required
@property
@@ -107,37 +110,41 @@ class Client(object):
if self.debug:
print(message)
@exceptions_decorator
def delete_request(self, api):
"""Make DELETE request to specific API with some data
"""
url = self.api_root + api
self.print_debug(
"DELETE {0}".format(self.api_root + api)
)
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request(self.api_root + api)
request.add_header('Content-Type', 'application/json')
request.add_header('X-Auth-Token', self.auth_token)
request.get_method = lambda: 'DELETE'
opener.open(request)
return {}
headers = {'content-type': 'application/json',
'x-auth-token': self.auth_token}
resp = requests.delete(url, headers=headers)
resp.raise_for_status()
return resp.json()
@exceptions_decorator
def put_request(self, api, data):
"""Make PUT request to specific API with some data
"""
url = self.api_root + api
data_json = json.dumps(data)
self.print_debug(
"PUT {0} data={1}"
.format(self.api_root + api, data_json)
)
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request(self.api_root + api, data=data_json)
request.add_header('Content-Type', 'application/json')
request.add_header('X-Auth-Token', self.auth_token)
request.get_method = lambda: 'PUT'
return json.loads(
opener.open(request).read()
)
headers = {'content-type': 'application/json',
'x-auth-token': self.auth_token}
resp = requests.put(url, data=data_json, headers=headers)
resp.raise_for_status()
return resp.json()
@exceptions_decorator
def get_request(self, api, ostf=False):
"""Make GET request to specific API
"""
@@ -146,13 +153,14 @@ class Client(object):
"GET {0}"
.format(url)
)
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request(url)
request.add_header('X-Auth-Token', self.auth_token)
return json.loads(
opener.open(request).read()
)
headers = {'x-auth-token': self.auth_token}
resp = requests.get(url, headers=headers)
resp.raise_for_status()
return resp.json()
@exceptions_decorator
def post_request(self, api, data, ostf=False):
"""Make POST request to specific API with some data
"""
@@ -162,22 +170,13 @@ class Client(object):
"POST {0} data={1}"
.format(url, data_json)
)
request = urllib2.Request(
url=url,
data=data_json,
headers={
'Content-Type': 'application/json'
}
)
request.add_header('X-Auth-Token', self.auth_token)
try:
response = json.loads(
urllib2.urlopen(request)
.read()
)
except ValueError:
response = {}
return response
headers = {'content-type': 'application/json',
'x-auth-token': self.auth_token}
resp = requests.post(url, data=data_json, headers=headers)
resp.raise_for_status()
return resp.json()
@exceptions_decorator
def get_fuel_version(self):

View File

@@ -4,6 +4,7 @@ Mako==0.9.1
MarkupSafe==0.18
Paste==1.7.5.1
PyYAML==3.10
requests>=1.2.3
SQLAlchemy==0.7.9
Shotgun==0.1.0
alembic==0.6.2

View File

@@ -102,11 +102,13 @@ class TestHandlers(BaseTestCase):
def test_wrong_credentials(self):
result = self.run_cli_command("--os-username=a --os-password=a node",
check_errors=True)
self.assertEqual(result.stderr,
'\n Unauthorized: need authentication!\n'
' Please provide user and password via client --os-username '
'--os-password\n or modify "KEYSTONE_USER" and "KEYSTONE_PASS" '
'in\n /etc/fuel/client/config.yaml\n')
must_be = ('\n Unauthorized: need authentication!\n '
' Please provide user and password via client\n '
' --os-username --os-password\n or modify '
'"KEYSTONE_USER" and "KEYSTONE_PASS" in\n '
'/etc/fuel/client/config.yaml\n'
)
self.assertEqual(result.stderr, must_be)
def test_destroy_node(self):
self.load_data_to_nailgun_server()
@@ -117,9 +119,9 @@ class TestHandlers(BaseTestCase):
msg = ("Nodes with id [1] has been deleted from fuel db.\n"
"You should still delete node from cobbler\n")
self.check_for_stdout(
"node --node 1 --delete-from-db",
msg
)
"node --node 1 --delete-from-db",
msg
)
def test_for_examples_in_action_help(self):
actions = (