Fix deprecated API usage of keystone client

* Use keystoneauth1 for making session, which is shared throw all clients
* KeystoneClient is now only wrapper over session
Requirements has been updated to meet global requirements for mitaka release:
1. Bumped clients versions
2. requests has blacklisted versions due to bugs

Closes-bug: #1571611

Change-Id: Icc59761b590b76a8d3ddac9b4f219efc097447a5
This commit is contained in:
Alexey Stepanov 2016-04-18 14:36:04 +03:00
parent 35af1c0c39
commit e48d37a518
4 changed files with 139 additions and 100 deletions

View File

@ -16,14 +16,16 @@ import sys
import time
import traceback
from cinderclient import client as cinderclient
from cinderclient.client import Client as CinderClient
from heatclient.v1.client import Client as HeatClient
from glanceclient.v1 import Client as GlanceClient
import ironicclient.client as ironicclient
from ironicclient.client import Client as IronicClient
from keystoneauth1.exceptions import ClientException
from keystoneauth1.identity import V2Password
from keystoneauth1.session import Session as KeystoneSession
from keystoneclient.v2_0 import Client as KeystoneClient
from keystoneclient.exceptions import ClientException
from novaclient.v2 import Client as NovaClient
import neutronclient.v2_0.client as neutronclient
from novaclient.client import Client as NovaClient
from neutronclient.v2_0.client import Client as NeutronClient
from proboscis.asserts import assert_equal
import six
# pylint: disable=redefined-builtin
@ -47,14 +49,16 @@ from fuelweb_test.settings import VERIFY_SSL
class Common(object):
"""Common.""" # TODO documentation
def __make_endpoint(self, endpoint):
parse = urllib.parse.urlparse(endpoint)
return parse._replace(
netloc='{}:{}'.format(
self.controller_ip, parse.port)).geturl()
def __init__(self, controller_ip, user, password, tenant):
self.controller_ip = controller_ip
def make_endpoint(endpoint):
parse = urllib.parse.urlparse(endpoint)
return parse._replace(
netloc='{}:{}'.format(
self.controller_ip, parse.port)).geturl()
self.keystone_session = None
if DISABLE_SSL:
auth_url = 'http://{0}:5000/v2.0/'.format(self.controller_ip)
@ -67,69 +71,90 @@ class Common(object):
logger.debug('Auth URL is {0}'.format(auth_url))
keystone_args = {'username': user, 'password': password,
'tenant_name': tenant, 'auth_url': auth_url,
'ca_cert': path_to_cert, 'insecure': insecure}
self.keystone = self._get_keystoneclient(**keystone_args)
self.__keystone_auth = V2Password(
auth_url=auth_url,
username=user,
password=password,
tenant_name=tenant) # TODO: in v3 project_name
token = self.keystone.auth_token
logger.debug('Token is {0}'.format(token))
self.__start_keystone_session(ca_cert=path_to_cert, insecure=insecure)
neutron_endpoint = self.keystone.service_catalog.url_for(
service_type='network', endpoint_type='publicURL')
neutron_args = {'username': user, 'password': password,
'tenant_name': tenant, 'auth_url': auth_url,
'ca_cert': path_to_cert, 'insecure': insecure,
'endpoint_url': make_endpoint(neutron_endpoint)}
self.neutron = neutronclient.Client(**neutron_args)
@property
def keystone(self):
return KeystoneClient(session=self.keystone_session)
nova_endpoint = self.keystone.service_catalog.url_for(
service_type='compute', endpoint_type='publicURL')
nova_args = {'username': user, 'api_key': password,
'project_id': tenant, 'auth_url': auth_url,
'cacert': path_to_cert, 'insecure': insecure,
'bypass_url': make_endpoint(nova_endpoint),
'auth_token': token}
self.nova = NovaClient(**nova_args)
@property
def glance(self):
endpoint = self.__make_endpoint(
self._get_url_for_svc(service_type='image'))
return GlanceClient(
session=self.keystone_session,
endpoint=endpoint,
endpoint_override=endpoint)
cinder_endpoint = self.keystone.service_catalog.url_for(
service_type='volume', endpoint_type='publicURL')
cinder_args = {'version': 1, 'username': user,
'api_key': password, 'project_id': tenant,
'auth_url': auth_url, 'cacert': path_to_cert,
'insecure': insecure,
'bypass_url': make_endpoint(cinder_endpoint)}
self.cinder = cinderclient.Client(**cinder_args)
@property
def neutron(self):
endpoint = self.__make_endpoint(
self._get_url_for_svc(service_type='network'))
return NeutronClient(
session=self.keystone_session,
endpoint_override=endpoint)
glance_endpoint = self.keystone.service_catalog.url_for(
service_type='image', endpoint_type='publicURL')
logger.debug('Glance endpoint is {0}'.format(
make_endpoint(glance_endpoint)))
glance_args = {'endpoint': make_endpoint(glance_endpoint),
'token': token,
'cacert': path_to_cert,
'insecure': insecure}
self.glance = GlanceClient(**glance_args)
@property
def nova(self):
endpoint = self.__make_endpoint(
self._get_url_for_svc(service_type='compute'))
return NovaClient(
version='2',
session=self.keystone_session,
endpoint_override=endpoint)
heat_endpoint = self.keystone.service_catalog.url_for(
service_type='orchestration', endpoint_type='publicURL')
@property
def cinder(self):
endpoint = self.__make_endpoint(
self._get_url_for_svc(service_type='volume'))
return CinderClient(
version='1',
session=self.keystone_session,
endpoint_override=endpoint)
heat_args = {'endpoint': make_endpoint(heat_endpoint),
'token': token,
'cacert': path_to_cert,
'insecure': insecure}
self.heat = HeatClient(**heat_args)
@property
def heat(self):
endpoint = self.__make_endpoint(
self._get_url_for_svc(service_type='orchestration'))
return HeatClient(
session=self.keystone_session,
endpoint_override=endpoint)
@property
def ironic(self):
try:
ironic_endpoint = self.keystone.service_catalog.url_for(
service_type='baremetal',
endpoint_type='publicURL')
self.ironic = ironicclient.get_client(
api_version=1,
os_auth_token=token,
ironic_url=make_endpoint(ironic_endpoint), insecure=True)
endpoint = self.__make_endpoint(
self._get_url_for_svc(service_type='baremetal'))
return IronicClient(
version='1',
session=self.keystone_session,
insecure=True,
endpoint_override=endpoint
)
except ClientException as e:
logger.warning('Could not initialize ironic client {0}'.format(e))
raise
@property
def keystone_access(self):
return self.__keystone_auth.get_access(session=self.keystone_session)
def _get_url_for_svc(
self, service_type=None, interface='public',
region_name=None, service_name=None,
service_id=None, endpoint_id=None
):
return self.keystone_access.service_catalog.url_for(
service_type=service_type, interface=interface,
region_name=region_name, service_name=service_name,
service_id=service_id, endpoint_id=endpoint_id
)
def goodbye_security(self):
secgroup_list = self.nova.security_groups.list()
@ -164,6 +189,7 @@ class Common(object):
logger.debug('Try to create instance')
start_time = time.time()
exc_type, exc_value, exc_traceback = None, None, None
while time.time() - start_time < 100:
try:
if image_name:
@ -173,9 +199,12 @@ class Common(object):
image = [i.id for i in self.nova.images.list()]
break
except Exception as e:
exc_type, exc_value, exc_traceback = sys.exc_info()
logger.warning('Ignoring exception: {!r}'.format(e))
logger.debug(traceback.format_exc())
else:
if all((exc_type, exc_traceback, exc_value)):
six.reraise(exc_type, exc_value, exc_traceback)
raise Exception('Can not get image')
kwargs = {}
@ -241,28 +270,26 @@ class Common(object):
self.nova.aggregates.remove_host(aggregate, host)
return self.nova.aggregates.delete(aggregate)
@staticmethod
def _get_keystoneclient(username, password, tenant_name, auth_url,
retries=3, ca_cert=None, insecure=False):
def __start_keystone_session(
self, retries=3, ca_cert=None, insecure=not VERIFY_SSL):
exc_type, exc_value, exc_traceback = None, None, None
for i in xrange(retries):
try:
if ca_cert:
return KeystoneClient(username=username,
password=password,
tenant_name=tenant_name,
auth_url=auth_url,
cacert=ca_cert,
insecure=insecure)
if insecure:
self.keystone_session = KeystoneSession(
auth=self.__keystone_auth, verify=False)
elif ca_cert:
self.keystone_session = KeystoneSession(
auth=self.__keystone_auth, verify=ca_cert)
else:
return KeystoneClient(username=username,
password=password,
tenant_name=tenant_name,
auth_url=auth_url)
self.keystone_session = KeystoneSession(
auth=self.__keystone_auth)
self.keystone_session.get_auth_headers()
return
except ClientException as exc:
exc_type, exc_value, exc_traceback = sys.exc_info()
err = "Try nr {0}. Could not get keystone client, error: {1}"
err = "Try nr {0}. Could not get keystone token, error: {1}"
logger.warning(err.format(i + 1, exc))
time.sleep(5)
if exc_type and exc_traceback and exc_value:

View File

@ -15,8 +15,10 @@
import json
import traceback
from keystoneauth1 import exceptions
from keystoneauth1.identity import V2Password
from keystoneauth1.session import Session as KeystoneSession
from keystoneclient.v2_0 import Client as KeystoneClient
from keystoneclient import exceptions
# pylint: disable=import-error
# noinspection PyUnresolvedReferences
from six.moves.urllib import request
@ -38,17 +40,21 @@ class HTTPClient(object):
self.keystone_url = keystone_url
self.creds = dict(credentials, **kwargs)
self.keystone = None
self.session = None
self.opener = request.build_opener(request.HTTPHandler)
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 don't, but we are making it explicitly always
self.keystone.authenticate()
auth = V2Password(
auth_url=self.keystone_url,
username=self.creds['username'],
password=self.creds['password'],
tenant_name=self.creds['tenant_name'])
# TODO: in v3 project_name
self.session = KeystoneSession(auth=auth, verify=False)
self.keystone = KeystoneClient(session=self.session)
logger.debug('Authorization token is successfully updated')
except exceptions.AuthorizationFailure:
logger.warning(
@ -59,7 +65,7 @@ class HTTPClient(object):
def token(self):
if self.keystone is not None:
try:
return self.keystone.auth_token
return self.session.get_token()
except exceptions.AuthorizationFailure:
logger.warning(
'Cant establish connection to keystone with url %s',
@ -68,7 +74,7 @@ class HTTPClient(object):
logger.warning("Keystone returned unauthorized error, trying "
"to pass authentication.")
self.authenticate()
return self.keystone.auth_token
return self.session.get_token()
return None
def get(self, endpoint):

View File

@ -150,9 +150,9 @@ class OpenStackActions(common.Common):
logger.info("Error opening file: {:s}".format(exc))
raise Exception()
image_id = self._get_cirros_image().id
security_group[self.keystone.tenant_id] =\
security_group[self.keystone_access.tenant_id] =\
self.create_sec_group_for_ssh()
security_groups = [security_group[self.keystone.tenant_id].name]
security_groups = [security_group[self.keystone_access.tenant_id].name]
if neutron:
net_label = label if label else 'net04'

View File

@ -1,20 +1,26 @@
nose==1.2.1
git+git://github.com/openstack/fuel-devops.git@2.9.20
anyjson==0.3.1
paramiko
anyjson>=0.3.3 # BSD
paramiko>=1.16.0 # LGPL
proboscis==1.2.6.0
junitxml>=0.7.0
netaddr>=0.7.12,!=0.7.16
python-glanceclient==0.17.1
python-keystoneclient>=0.3.2
python-novaclient>=2.15.0
python-cinderclient>=1.0.5
python-neutronclient>=2.0
python-ironicclient>=0.8.0
python-heatclient>=0.6.0
netaddr>=0.7.12,!=0.7.16 # BSD
pyOpenSSL>=0.14 # Apache-2.0
Sphinx # BSD # Not required for tests, but required to build docs (pbr)
docutils # Not required for tests, but required to build docs (pbr)
markupsafe # Not required for tests, but required to build docs (pbr)
pytz>=2013.6 # MIT # Not required for tests, but required to build docs (pbr)
keystoneauth1>=2.1.0 # Apache-2.0
python-glanceclient>=2.0.0 # Apache-2.0
python-keystoneclient>=1.6.0,!=1.8.0,!=2.1.0 # Apache-2.0
python-novaclient>=2.29.0,!=2.33.0 # Apache-2.0
python-cinderclient>=1.3.1 # Apache-2.0
python-neutronclient>=2.6.0,!=4.1.0 # Apache-2.0
python-ironicclient>=1.1.0 # Apache-2.0
python-heatclient>=0.6.0 # Apache-2.0
oslo.i18n>=3.1.0
six
Jinja2
six>=1.9.0 # MIT
Jinja2>=2.8 # BSD License (3 clause)
AllPairs==2.0.1
launchpadlib
beautifulsoup4>=4.2.0