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:
parent
35af1c0c39
commit
e48d37a518
|
@ -16,14 +16,16 @@ import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from cinderclient import client as cinderclient
|
from cinderclient.client import Client as CinderClient
|
||||||
from heatclient.v1.client import Client as HeatClient
|
from heatclient.v1.client import Client as HeatClient
|
||||||
from glanceclient.v1 import Client as GlanceClient
|
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.v2_0 import Client as KeystoneClient
|
||||||
from keystoneclient.exceptions import ClientException
|
from novaclient.client import Client as NovaClient
|
||||||
from novaclient.v2 import Client as NovaClient
|
from neutronclient.v2_0.client import Client as NeutronClient
|
||||||
import neutronclient.v2_0.client as neutronclient
|
|
||||||
from proboscis.asserts import assert_equal
|
from proboscis.asserts import assert_equal
|
||||||
import six
|
import six
|
||||||
# pylint: disable=redefined-builtin
|
# pylint: disable=redefined-builtin
|
||||||
|
@ -47,14 +49,16 @@ from fuelweb_test.settings import VERIFY_SSL
|
||||||
class Common(object):
|
class Common(object):
|
||||||
"""Common.""" # TODO documentation
|
"""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):
|
def __init__(self, controller_ip, user, password, tenant):
|
||||||
self.controller_ip = controller_ip
|
self.controller_ip = controller_ip
|
||||||
|
|
||||||
def make_endpoint(endpoint):
|
self.keystone_session = None
|
||||||
parse = urllib.parse.urlparse(endpoint)
|
|
||||||
return parse._replace(
|
|
||||||
netloc='{}:{}'.format(
|
|
||||||
self.controller_ip, parse.port)).geturl()
|
|
||||||
|
|
||||||
if DISABLE_SSL:
|
if DISABLE_SSL:
|
||||||
auth_url = 'http://{0}:5000/v2.0/'.format(self.controller_ip)
|
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))
|
logger.debug('Auth URL is {0}'.format(auth_url))
|
||||||
|
|
||||||
keystone_args = {'username': user, 'password': password,
|
self.__keystone_auth = V2Password(
|
||||||
'tenant_name': tenant, 'auth_url': auth_url,
|
auth_url=auth_url,
|
||||||
'ca_cert': path_to_cert, 'insecure': insecure}
|
username=user,
|
||||||
self.keystone = self._get_keystoneclient(**keystone_args)
|
password=password,
|
||||||
|
tenant_name=tenant) # TODO: in v3 project_name
|
||||||
|
|
||||||
token = self.keystone.auth_token
|
self.__start_keystone_session(ca_cert=path_to_cert, insecure=insecure)
|
||||||
logger.debug('Token is {0}'.format(token))
|
|
||||||
|
|
||||||
neutron_endpoint = self.keystone.service_catalog.url_for(
|
@property
|
||||||
service_type='network', endpoint_type='publicURL')
|
def keystone(self):
|
||||||
neutron_args = {'username': user, 'password': password,
|
return KeystoneClient(session=self.keystone_session)
|
||||||
'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)
|
|
||||||
|
|
||||||
nova_endpoint = self.keystone.service_catalog.url_for(
|
@property
|
||||||
service_type='compute', endpoint_type='publicURL')
|
def glance(self):
|
||||||
nova_args = {'username': user, 'api_key': password,
|
endpoint = self.__make_endpoint(
|
||||||
'project_id': tenant, 'auth_url': auth_url,
|
self._get_url_for_svc(service_type='image'))
|
||||||
'cacert': path_to_cert, 'insecure': insecure,
|
return GlanceClient(
|
||||||
'bypass_url': make_endpoint(nova_endpoint),
|
session=self.keystone_session,
|
||||||
'auth_token': token}
|
endpoint=endpoint,
|
||||||
self.nova = NovaClient(**nova_args)
|
endpoint_override=endpoint)
|
||||||
|
|
||||||
cinder_endpoint = self.keystone.service_catalog.url_for(
|
@property
|
||||||
service_type='volume', endpoint_type='publicURL')
|
def neutron(self):
|
||||||
cinder_args = {'version': 1, 'username': user,
|
endpoint = self.__make_endpoint(
|
||||||
'api_key': password, 'project_id': tenant,
|
self._get_url_for_svc(service_type='network'))
|
||||||
'auth_url': auth_url, 'cacert': path_to_cert,
|
return NeutronClient(
|
||||||
'insecure': insecure,
|
session=self.keystone_session,
|
||||||
'bypass_url': make_endpoint(cinder_endpoint)}
|
endpoint_override=endpoint)
|
||||||
self.cinder = cinderclient.Client(**cinder_args)
|
|
||||||
|
|
||||||
glance_endpoint = self.keystone.service_catalog.url_for(
|
@property
|
||||||
service_type='image', endpoint_type='publicURL')
|
def nova(self):
|
||||||
logger.debug('Glance endpoint is {0}'.format(
|
endpoint = self.__make_endpoint(
|
||||||
make_endpoint(glance_endpoint)))
|
self._get_url_for_svc(service_type='compute'))
|
||||||
glance_args = {'endpoint': make_endpoint(glance_endpoint),
|
return NovaClient(
|
||||||
'token': token,
|
version='2',
|
||||||
'cacert': path_to_cert,
|
session=self.keystone_session,
|
||||||
'insecure': insecure}
|
endpoint_override=endpoint)
|
||||||
self.glance = GlanceClient(**glance_args)
|
|
||||||
|
|
||||||
heat_endpoint = self.keystone.service_catalog.url_for(
|
@property
|
||||||
service_type='orchestration', endpoint_type='publicURL')
|
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),
|
@property
|
||||||
'token': token,
|
def heat(self):
|
||||||
'cacert': path_to_cert,
|
endpoint = self.__make_endpoint(
|
||||||
'insecure': insecure}
|
self._get_url_for_svc(service_type='orchestration'))
|
||||||
self.heat = HeatClient(**heat_args)
|
return HeatClient(
|
||||||
|
session=self.keystone_session,
|
||||||
|
endpoint_override=endpoint)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ironic(self):
|
||||||
try:
|
try:
|
||||||
ironic_endpoint = self.keystone.service_catalog.url_for(
|
endpoint = self.__make_endpoint(
|
||||||
service_type='baremetal',
|
self._get_url_for_svc(service_type='baremetal'))
|
||||||
endpoint_type='publicURL')
|
return IronicClient(
|
||||||
self.ironic = ironicclient.get_client(
|
version='1',
|
||||||
api_version=1,
|
session=self.keystone_session,
|
||||||
os_auth_token=token,
|
insecure=True,
|
||||||
ironic_url=make_endpoint(ironic_endpoint), insecure=True)
|
endpoint_override=endpoint
|
||||||
|
)
|
||||||
except ClientException as e:
|
except ClientException as e:
|
||||||
logger.warning('Could not initialize ironic client {0}'.format(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):
|
def goodbye_security(self):
|
||||||
secgroup_list = self.nova.security_groups.list()
|
secgroup_list = self.nova.security_groups.list()
|
||||||
|
@ -164,6 +189,7 @@ class Common(object):
|
||||||
logger.debug('Try to create instance')
|
logger.debug('Try to create instance')
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
exc_type, exc_value, exc_traceback = None, None, None
|
||||||
while time.time() - start_time < 100:
|
while time.time() - start_time < 100:
|
||||||
try:
|
try:
|
||||||
if image_name:
|
if image_name:
|
||||||
|
@ -173,9 +199,12 @@ class Common(object):
|
||||||
image = [i.id for i in self.nova.images.list()]
|
image = [i.id for i in self.nova.images.list()]
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
logger.warning('Ignoring exception: {!r}'.format(e))
|
logger.warning('Ignoring exception: {!r}'.format(e))
|
||||||
logger.debug(traceback.format_exc())
|
logger.debug(traceback.format_exc())
|
||||||
else:
|
else:
|
||||||
|
if all((exc_type, exc_traceback, exc_value)):
|
||||||
|
six.reraise(exc_type, exc_value, exc_traceback)
|
||||||
raise Exception('Can not get image')
|
raise Exception('Can not get image')
|
||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
@ -241,28 +270,26 @@ class Common(object):
|
||||||
self.nova.aggregates.remove_host(aggregate, host)
|
self.nova.aggregates.remove_host(aggregate, host)
|
||||||
return self.nova.aggregates.delete(aggregate)
|
return self.nova.aggregates.delete(aggregate)
|
||||||
|
|
||||||
@staticmethod
|
def __start_keystone_session(
|
||||||
def _get_keystoneclient(username, password, tenant_name, auth_url,
|
self, retries=3, ca_cert=None, insecure=not VERIFY_SSL):
|
||||||
retries=3, ca_cert=None, insecure=False):
|
|
||||||
exc_type, exc_value, exc_traceback = None, None, None
|
exc_type, exc_value, exc_traceback = None, None, None
|
||||||
for i in xrange(retries):
|
for i in xrange(retries):
|
||||||
try:
|
try:
|
||||||
if ca_cert:
|
if insecure:
|
||||||
return KeystoneClient(username=username,
|
self.keystone_session = KeystoneSession(
|
||||||
password=password,
|
auth=self.__keystone_auth, verify=False)
|
||||||
tenant_name=tenant_name,
|
elif ca_cert:
|
||||||
auth_url=auth_url,
|
self.keystone_session = KeystoneSession(
|
||||||
cacert=ca_cert,
|
auth=self.__keystone_auth, verify=ca_cert)
|
||||||
insecure=insecure)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return KeystoneClient(username=username,
|
self.keystone_session = KeystoneSession(
|
||||||
password=password,
|
auth=self.__keystone_auth)
|
||||||
tenant_name=tenant_name,
|
self.keystone_session.get_auth_headers()
|
||||||
auth_url=auth_url)
|
return
|
||||||
|
|
||||||
except ClientException as exc:
|
except ClientException as exc:
|
||||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
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))
|
logger.warning(err.format(i + 1, exc))
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
if exc_type and exc_traceback and exc_value:
|
if exc_type and exc_traceback and exc_value:
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
import json
|
import json
|
||||||
import traceback
|
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.v2_0 import Client as KeystoneClient
|
||||||
from keystoneclient import exceptions
|
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
from six.moves.urllib import request
|
from six.moves.urllib import request
|
||||||
|
@ -38,17 +40,21 @@ class HTTPClient(object):
|
||||||
self.keystone_url = keystone_url
|
self.keystone_url = keystone_url
|
||||||
self.creds = dict(credentials, **kwargs)
|
self.creds = dict(credentials, **kwargs)
|
||||||
self.keystone = None
|
self.keystone = None
|
||||||
|
self.session = None
|
||||||
self.opener = request.build_opener(request.HTTPHandler)
|
self.opener = request.build_opener(request.HTTPHandler)
|
||||||
|
|
||||||
def authenticate(self):
|
def authenticate(self):
|
||||||
try:
|
try:
|
||||||
logger.info('Initialize keystoneclient with url %s',
|
logger.info('Initialize keystoneclient with url %s',
|
||||||
self.keystone_url)
|
self.keystone_url)
|
||||||
self.keystone = KeystoneClient(
|
auth = V2Password(
|
||||||
auth_url=self.keystone_url, **self.creds)
|
auth_url=self.keystone_url,
|
||||||
# it depends on keystone version, some versions doing auth
|
username=self.creds['username'],
|
||||||
# explicitly some don't, but we are making it explicitly always
|
password=self.creds['password'],
|
||||||
self.keystone.authenticate()
|
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')
|
logger.debug('Authorization token is successfully updated')
|
||||||
except exceptions.AuthorizationFailure:
|
except exceptions.AuthorizationFailure:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
@ -59,7 +65,7 @@ class HTTPClient(object):
|
||||||
def token(self):
|
def token(self):
|
||||||
if self.keystone is not None:
|
if self.keystone is not None:
|
||||||
try:
|
try:
|
||||||
return self.keystone.auth_token
|
return self.session.get_token()
|
||||||
except exceptions.AuthorizationFailure:
|
except exceptions.AuthorizationFailure:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'Cant establish connection to keystone with url %s',
|
'Cant establish connection to keystone with url %s',
|
||||||
|
@ -68,7 +74,7 @@ class HTTPClient(object):
|
||||||
logger.warning("Keystone returned unauthorized error, trying "
|
logger.warning("Keystone returned unauthorized error, trying "
|
||||||
"to pass authentication.")
|
"to pass authentication.")
|
||||||
self.authenticate()
|
self.authenticate()
|
||||||
return self.keystone.auth_token
|
return self.session.get_token()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get(self, endpoint):
|
def get(self, endpoint):
|
||||||
|
|
|
@ -150,9 +150,9 @@ class OpenStackActions(common.Common):
|
||||||
logger.info("Error opening file: {:s}".format(exc))
|
logger.info("Error opening file: {:s}".format(exc))
|
||||||
raise Exception()
|
raise Exception()
|
||||||
image_id = self._get_cirros_image().id
|
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()
|
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:
|
if neutron:
|
||||||
net_label = label if label else 'net04'
|
net_label = label if label else 'net04'
|
||||||
|
|
|
@ -1,20 +1,26 @@
|
||||||
nose==1.2.1
|
nose==1.2.1
|
||||||
git+git://github.com/openstack/fuel-devops.git@2.9.20
|
git+git://github.com/openstack/fuel-devops.git@2.9.20
|
||||||
anyjson==0.3.1
|
anyjson>=0.3.3 # BSD
|
||||||
paramiko
|
paramiko>=1.16.0 # LGPL
|
||||||
proboscis==1.2.6.0
|
proboscis==1.2.6.0
|
||||||
junitxml>=0.7.0
|
junitxml>=0.7.0
|
||||||
netaddr>=0.7.12,!=0.7.16
|
netaddr>=0.7.12,!=0.7.16 # BSD
|
||||||
python-glanceclient==0.17.1
|
pyOpenSSL>=0.14 # Apache-2.0
|
||||||
python-keystoneclient>=0.3.2
|
Sphinx # BSD # Not required for tests, but required to build docs (pbr)
|
||||||
python-novaclient>=2.15.0
|
docutils # Not required for tests, but required to build docs (pbr)
|
||||||
python-cinderclient>=1.0.5
|
markupsafe # Not required for tests, but required to build docs (pbr)
|
||||||
python-neutronclient>=2.0
|
pytz>=2013.6 # MIT # Not required for tests, but required to build docs (pbr)
|
||||||
python-ironicclient>=0.8.0
|
keystoneauth1>=2.1.0 # Apache-2.0
|
||||||
python-heatclient>=0.6.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
|
oslo.i18n>=3.1.0
|
||||||
six
|
six>=1.9.0 # MIT
|
||||||
Jinja2
|
Jinja2>=2.8 # BSD License (3 clause)
|
||||||
AllPairs==2.0.1
|
AllPairs==2.0.1
|
||||||
launchpadlib
|
launchpadlib
|
||||||
beautifulsoup4>=4.2.0
|
beautifulsoup4>=4.2.0
|
||||||
|
|
Loading…
Reference in New Issue