From 4417370b2c4fd4a87e1e059a0edd78c87d1362b5 Mon Sep 17 00:00:00 2001 From: Dima Shulyak Date: Wed, 2 Jul 2014 12:56:29 +0300 Subject: [PATCH] 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 --- fuelweb_test/helpers/http.py | 20 ++++++------ fuelweb_test/models/nailgun_client.py | 44 +++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/fuelweb_test/helpers/http.py b/fuelweb_test/helpers/http.py index 1fecc069d..578dfee8d 100644 --- a/fuelweb_test/helpers/http.py +++ b/fuelweb_test/helpers/http.py @@ -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) diff --git a/fuelweb_test/models/nailgun_client.py b/fuelweb_test/models/nailgun_client.py index 166a589f9..38774b1c6 100644 --- a/fuelweb_test/models/nailgun_client.py +++ b/fuelweb_test/models/nailgun_client.py @@ -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("/")