Add auth support nailgun client

- Add keystone auth on Nailgun client initialization
- Add ability to refresh_token if it will expire
- If token is expired - new token will be requested

If no keystone is installed on master node - keystone
will raise exceptions.AuthorizationFailure which is handled,
and in this case NailgunClient will perform requests without auth

related to blueprint access-control-master-node

Change-Id: Ib7ff29e0a40e3075444c557f9c9e574b6ffa0071
This commit is contained in:
Dima Shulyak 2014-07-02 12:56:29 +03:00
parent 79cbcd58e7
commit 4417370b2c
2 changed files with 51 additions and 13 deletions

View File

@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import base64
import json
import urllib2
@ -21,18 +20,16 @@ from fuelweb_test import logger
class HTTPClient(object):
base64string = None
def __init__(self, url, user=None, password=None):
def __init__(self, url, token=None):
logger.info('Initiate HTTPClient with url %s', url)
self.url = url
if user and password:
creds = '{0}:{1}'.format(user, password)
logger.info('Set credentials to %s', creds)
self.base64string = base64.standard_b64encode(creds)
self.token = token
self.opener = urllib2.build_opener(urllib2.HTTPHandler)
def reset_token(self, token):
"""Should be used in case token is expired."""
self.token = token
def get(self, endpoint):
req = urllib2.Request(self.url + endpoint)
return self._open(req)
@ -59,6 +56,7 @@ class HTTPClient(object):
return self._open(req)
def _open(self, req):
if self.base64string:
req.add_header("Authorization", "Basic %s" % self.base64string)
if self.token is not None:
logger.debug('Set X-Auth-Token to %s', self.token)
req.add_header("X-Auth-Token", self.token)
return self.opener.open(req)

View File

@ -18,14 +18,54 @@ from fuelweb_test.helpers.decorators import json_parse
from fuelweb_test.helpers.http import HTTPClient
from fuelweb_test.settings import OPENSTACK_RELEASE
from keystoneclient.v2_0 import Client as keystoneclient
from keystoneclient import exceptions
DEFAULT_CREDS = {'username': 'admin',
'password': 'admin',
'tenant_name': 'admin'}
class NailgunClient(object):
def __init__(self, admin_node_ip, user=None, password=None):
def __init__(self, admin_node_ip, **kwargs):
url = "http://{0}:8000".format(admin_node_ip)
logger.info('Initiate Nailgun client with url %s', url)
self.client = HTTPClient(url=url, user=user, password=password)
self._client = HTTPClient(url=url)
self.keystone_url = "http://{0}:5000/v2.0".format(admin_node_ip)
self.creds = dict(DEFAULT_CREDS, **kwargs)
self.keystone = None
super(NailgunClient, self).__init__()
@property
def client(self):
# keystone will try to authenticate on first client access
if self.keystone is None:
self.authenticate()
self.refresh_token()
return self._client
def authenticate(self):
try:
logger.info('Initialize keystoneclient with url %s',
self.keystone_url)
self.keystone = keystoneclient(
auth_url=self.keystone_url, **self.creds)
# it depends on keystone version, some versions doing auth
# explicitly some dont, but we are making it explicitly always
self.keystone.authenticate()
return self.keystone
except exceptions.AuthorizationFailure:
logger.warning(
'Cant establish connection to keystone with url %s',
self.keystone_url)
self.keystone = None
def refresh_token(self):
if self.keystone is not None:
self._client.reset_token(self.keystone.auth_token)
@logwrap
def get_root(self):
return self.client.get("/")