Fix up amulet for queens

* Fix up amulet tests to use keystone v3 clients.
* Remove admin_* and auth_* for Queens l3_agent and metadata
  config files as they no longer appears to be used.

Change-Id: Ib952740b0061f76083307d04a772f613a9ba0002
This commit is contained in:
Liam Young 2018-02-25 16:21:22 +00:00
parent b475a397e3
commit 7fd04bba83
9 changed files with 344 additions and 75 deletions

View File

@ -367,13 +367,36 @@ class OpenStackAmuletUtils(AmuletUtils):
project_domain_name=None, project_name=None): project_domain_name=None, project_name=None):
"""Authenticate with Keystone""" """Authenticate with Keystone"""
self.log.debug('Authenticating with keystone...') self.log.debug('Authenticating with keystone...')
port = 5000 if not api_version:
if admin_port: api_version = 2
port = 35357 sess, auth = self.get_keystone_session(
base_ep = "http://{}:{}".format(keystone_ip.strip().decode('utf-8'), keystone_ip=keystone_ip,
port) username=username,
if not api_version or api_version == 2: password=password,
ep = base_ep + "/v2.0" api_version=api_version,
admin_port=admin_port,
user_domain_name=user_domain_name,
domain_name=domain_name,
project_domain_name=project_domain_name,
project_name=project_name
)
if api_version == 2:
client = keystone_client.Client(session=sess)
else:
client = keystone_client_v3.Client(session=sess)
# This populates the client.service_catalog
client.auth_ref = auth.get_access(sess)
return client
def get_keystone_session(self, keystone_ip, username, password,
api_version=False, admin_port=False,
user_domain_name=None, domain_name=None,
project_domain_name=None, project_name=None):
"""Return a keystone session object"""
ep = self.get_keystone_endpoint(keystone_ip,
api_version=api_version,
admin_port=admin_port)
if api_version == 2:
auth = v2.Password( auth = v2.Password(
username=username, username=username,
password=password, password=password,
@ -381,12 +404,7 @@ class OpenStackAmuletUtils(AmuletUtils):
auth_url=ep auth_url=ep
) )
sess = keystone_session.Session(auth=auth) sess = keystone_session.Session(auth=auth)
client = keystone_client.Client(session=sess)
# This populates the client.service_catalog
client.auth_ref = auth.get_access(sess)
return client
else: else:
ep = base_ep + "/v3"
auth = v3.Password( auth = v3.Password(
user_domain_name=user_domain_name, user_domain_name=user_domain_name,
username=username, username=username,
@ -397,10 +415,57 @@ class OpenStackAmuletUtils(AmuletUtils):
auth_url=ep auth_url=ep
) )
sess = keystone_session.Session(auth=auth) sess = keystone_session.Session(auth=auth)
client = keystone_client_v3.Client(session=sess) return (sess, auth)
def get_keystone_endpoint(self, keystone_ip, api_version=None,
admin_port=False):
"""Return keystone endpoint"""
port = 5000
if admin_port:
port = 35357
base_ep = "http://{}:{}".format(keystone_ip.strip().decode('utf-8'),
port)
if api_version == 2:
ep = base_ep + "/v2.0"
else:
ep = base_ep + "/v3"
return ep
def get_default_keystone_session(self, keystone_sentry,
openstack_release=None):
"""Return a keystone session object and client object assuming standard
default settings
Example call in amulet tests:
self.keystone_session, self.keystone = u.get_default_keystone_session(
self.keystone_sentry,
openstack_release=self._get_openstack_release())
The session can then be used to auth other clients:
neutronclient.Client(session=session)
aodh_client.Client(session=session)
eyc
"""
self.log.debug('Authenticating keystone admin...')
api_version = 2
client_class = keystone_client.Client
# 11 => xenial_queens
if openstack_release and openstack_release >= 11:
api_version = 3
client_class = keystone_client_v3.Client
keystone_ip = keystone_sentry.info['public-address']
session, auth = self.get_keystone_session(
keystone_ip,
api_version=api_version,
username='admin',
password='openstack',
project_name='admin',
user_domain_name='admin_domain',
project_domain_name='admin_domain')
client = client_class(session=session)
# This populates the client.service_catalog # This populates the client.service_catalog
client.auth_ref = auth.get_access(sess) client.auth_ref = auth.get_access(session)
return client return session, client
def authenticate_keystone_admin(self, keystone_sentry, user, password, def authenticate_keystone_admin(self, keystone_sentry, user, password,
tenant=None, api_version=None, tenant=None, api_version=None,

View File

@ -182,7 +182,7 @@ SWIFT_CODENAMES = OrderedDict([
('pike', ('pike',
['2.13.0', '2.15.0']), ['2.13.0', '2.15.0']),
('queens', ('queens',
['2.16.0']), ['2.16.0', '2.17.0']),
]) ])
# >= Liberty version->codename mapping # >= Liberty version->codename mapping

View File

@ -0,0 +1,30 @@
# newton
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
###############################################################################
[DEFAULT]
interface_driver = openvswitch
root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
handle_internal_only_routers = {{ handle_internal_only_router }}
{% if plugin == 'n1kv' %}
l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport
external_network_bridge = br-int
ovs_use_veth = False
use_namespaces = True
{% else %}
ovs_use_veth = True
{% endif %}
{% if external_configuration_new -%}
gateway_external_network_id =
external_network_bridge =
{% elif ext_net_id %}
gateway_external_network_id = {{ ext_net_id }}
{% else %}
# Set default to deprecated external networking config
external_network_bridge = br-ex
{% endif -%}
agent_mode = {{ agent_mode }}
[AGENT]
extensions = fwaas

View File

@ -0,0 +1,15 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
###############################################################################
# Metadata service seems to cache neutron api url from keystone so trigger
# restart if it changes: {{ quantum_url }}
[DEFAULT]
root_helper = sudo neutron-rootwrap /etc/neutron/rootwrap.conf
state_path = /var/lib/neutron
# Gateway runs a metadata API server locally
nova_metadata_ip = {{ local_ip }}
nova_metadata_port = 8775
metadata_proxy_shared_secret = {{ shared_secret }}
cache_url = memory://?default_ttl=5
metadata_workers = {{ workers }}

View File

@ -155,19 +155,12 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment):
self.neutron_api_sentry = self.d.sentry['neutron-api'][0] self.neutron_api_sentry = self.d.sentry['neutron-api'][0]
# Authenticate admin with keystone # Authenticate admin with keystone
self.keystone = u.authenticate_keystone_admin(self.keystone_sentry, self.keystone_session, self.keystone = u.get_default_keystone_session(
user='admin', self.keystone_sentry,
password='openstack', openstack_release=self._get_openstack_release())
tenant='admin')
# Authenticate admin with neutron # Authenticate admin with neutron
ep = self.keystone.service_catalog.url_for(service_type='identity', self.neutron = neutronclient.Client(session=self.keystone_session)
interface='publicURL')
self.neutron = neutronclient.Client(auth_url=ep,
username='admin',
password='openstack',
tenant_name='admin',
region_name='RegionOne')
def get_private_address(self, unit): def get_private_address(self, unit):
"""Return the private address of the given sentry unit.""" """Return the private address of the given sentry unit."""
@ -220,7 +213,10 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment):
} }
actual = self.keystone.service_catalog.get_endpoints() actual = self.keystone.service_catalog.get_endpoints()
ret = u.validate_svc_catalog_endpoint_data(expected, actual) ret = u.validate_svc_catalog_endpoint_data(
expected,
actual,
openstack_release=self._get_openstack_release())
if ret: if ret:
amulet.raise_status(amulet.FAIL, msg=ret) amulet.raise_status(amulet.FAIL, msg=ret)
@ -237,8 +233,13 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment):
'publicurl': u.valid_url, 'publicurl': u.valid_url,
'service_id': u.not_null 'service_id': u.not_null
} }
ret = u.validate_endpoint_data(endpoints, admin_port, internal_port, ret = u.validate_endpoint_data(
public_port, expected) endpoints,
admin_port,
internal_port,
public_port,
expected,
openstack_release=self._get_openstack_release())
if ret: if ret:
amulet.raise_status(amulet.FAIL, amulet.raise_status(amulet.FAIL,
@ -657,11 +658,6 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment):
"""Verify the data in the l3 agent config file.""" """Verify the data in the l3 agent config file."""
u.log.debug('Checking neutron gateway l3 agent config file data...') u.log.debug('Checking neutron gateway l3 agent config file data...')
unit = self.neutron_gateway_sentry unit = self.neutron_gateway_sentry
ncc_ng_rel = self.nova_cc_sentry.relation(
'quantum-network-service',
'neutron-gateway:quantum-network-service')
ep = self.keystone.service_catalog.url_for(service_type='identity',
interface='publicURL')
conf = '/etc/neutron/l3_agent.ini' conf = '/etc/neutron/l3_agent.ini'
@ -675,11 +671,6 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment):
'OVSInterfaceDriver') 'OVSInterfaceDriver')
expected = { expected = {
'interface_driver': interface_driver, 'interface_driver': interface_driver,
'auth_url': ep,
'auth_region': 'RegionOne',
'admin_tenant_name': 'services',
'admin_password': ncc_ng_rel['service_password'],
'admin_user': ncc_ng_rel['service_username'],
'root_helper': 'sudo /usr/bin/neutron-rootwrap ' 'root_helper': 'sudo /usr/bin/neutron-rootwrap '
'/etc/neutron/rootwrap.conf', '/etc/neutron/rootwrap.conf',
'ovs_use_veth': 'True', 'ovs_use_veth': 'True',
@ -745,19 +736,9 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment):
u.log.debug('Checking neutron gateway metadata agent ' u.log.debug('Checking neutron gateway metadata agent '
'config file data...') 'config file data...')
unit = self.neutron_gateway_sentry unit = self.neutron_gateway_sentry
ep = self.keystone.service_catalog.url_for(service_type='identity',
interface='publicURL')
nova_cc_relation = self.nova_cc_sentry.relation(
'quantum-network-service',
'neutron-gateway:quantum-network-service')
conf = '/etc/neutron/metadata_agent.ini' conf = '/etc/neutron/metadata_agent.ini'
expected = { expected = {
'auth_url': ep,
'auth_region': 'RegionOne',
'admin_tenant_name': 'services',
'admin_password': nova_cc_relation['service_password'],
'admin_user': nova_cc_relation['service_username'],
'root_helper': 'sudo neutron-rootwrap ' 'root_helper': 'sudo neutron-rootwrap '
'/etc/neutron/rootwrap.conf', '/etc/neutron/rootwrap.conf',
'state_path': '/var/lib/neutron', 'state_path': '/var/lib/neutron',

View File

@ -21,6 +21,9 @@ from collections import OrderedDict
from charmhelpers.contrib.amulet.deployment import ( from charmhelpers.contrib.amulet.deployment import (
AmuletDeployment AmuletDeployment
) )
from charmhelpers.contrib.openstack.amulet.utils import (
OPENSTACK_RELEASES_PAIRS
)
DEBUG = logging.DEBUG DEBUG = logging.DEBUG
ERROR = logging.ERROR ERROR = logging.ERROR
@ -271,11 +274,8 @@ class OpenStackAmuletDeployment(AmuletDeployment):
release. release.
""" """
# Must be ordered by OpenStack release (not by Ubuntu release): # Must be ordered by OpenStack release (not by Ubuntu release):
(self.trusty_icehouse, self.trusty_kilo, self.trusty_liberty, for i, os_pair in enumerate(OPENSTACK_RELEASES_PAIRS):
self.trusty_mitaka, self.xenial_mitaka, self.xenial_newton, setattr(self, os_pair, i)
self.yakkety_newton, self.xenial_ocata, self.zesty_ocata,
self.xenial_pike, self.artful_pike, self.xenial_queens,
self.bionic_queens,) = range(13)
releases = { releases = {
('trusty', None): self.trusty_icehouse, ('trusty', None): self.trusty_icehouse,

View File

@ -50,6 +50,13 @@ ERROR = logging.ERROR
NOVA_CLIENT_VERSION = "2" NOVA_CLIENT_VERSION = "2"
OPENSTACK_RELEASES_PAIRS = [
'trusty_icehouse', 'trusty_kilo', 'trusty_liberty',
'trusty_mitaka', 'xenial_mitaka', 'xenial_newton',
'yakkety_newton', 'xenial_ocata', 'zesty_ocata',
'xenial_pike', 'artful_pike', 'xenial_queens',
'bionic_queens']
class OpenStackAmuletUtils(AmuletUtils): class OpenStackAmuletUtils(AmuletUtils):
"""OpenStack amulet utilities. """OpenStack amulet utilities.
@ -63,6 +70,33 @@ class OpenStackAmuletUtils(AmuletUtils):
super(OpenStackAmuletUtils, self).__init__(log_level) super(OpenStackAmuletUtils, self).__init__(log_level)
def validate_endpoint_data(self, endpoints, admin_port, internal_port, def validate_endpoint_data(self, endpoints, admin_port, internal_port,
public_port, expected, openstack_release=None):
"""Validate endpoint data. Pick the correct validator based on
OpenStack release. Expected data should be in the v2 format:
{
'id': id,
'region': region,
'adminurl': adminurl,
'internalurl': internalurl,
'publicurl': publicurl,
'service_id': service_id}
"""
validation_function = self.validate_v2_endpoint_data
xenial_queens = OPENSTACK_RELEASES_PAIRS.index('xenial_queens')
if openstack_release and openstack_release >= xenial_queens:
validation_function = self.validate_v3_endpoint_data
expected = {
'id': expected['id'],
'region': expected['region'],
'region_id': 'RegionOne',
'url': self.valid_url,
'interface': self.not_null,
'service_id': expected['service_id']}
return validation_function(endpoints, admin_port, internal_port,
public_port, expected)
def validate_v2_endpoint_data(self, endpoints, admin_port, internal_port,
public_port, expected): public_port, expected):
"""Validate endpoint data. """Validate endpoint data.
@ -141,7 +175,86 @@ class OpenStackAmuletUtils(AmuletUtils):
if len(found) != expected_num_eps: if len(found) != expected_num_eps:
return 'Unexpected number of endpoints found' return 'Unexpected number of endpoints found'
def validate_svc_catalog_endpoint_data(self, expected, actual): def convert_svc_catalog_endpoint_data_to_v3(self, ep_data):
"""Convert v2 endpoint data into v3.
{
'service_name1': [
{
'adminURL': adminURL,
'id': id,
'region': region.
'publicURL': publicURL,
'internalURL': internalURL
}],
'service_name2': [
{
'adminURL': adminURL,
'id': id,
'region': region.
'publicURL': publicURL,
'internalURL': internalURL
}],
}
"""
self.log.warn("Endpoint ID and Region ID validation is limited to not "
"null checks after v2 to v3 conversion")
for svc in ep_data.keys():
assert len(ep_data[svc]) == 1, "Unknown data format"
svc_ep_data = ep_data[svc][0]
ep_data[svc] = [
{
'url': svc_ep_data['adminURL'],
'interface': 'admin',
'region': svc_ep_data['region'],
'region_id': self.not_null,
'id': self.not_null},
{
'url': svc_ep_data['publicURL'],
'interface': 'public',
'region': svc_ep_data['region'],
'region_id': self.not_null,
'id': self.not_null},
{
'url': svc_ep_data['internalURL'],
'interface': 'internal',
'region': svc_ep_data['region'],
'region_id': self.not_null,
'id': self.not_null}]
return ep_data
def validate_svc_catalog_endpoint_data(self, expected, actual,
openstack_release=None):
"""Validate service catalog endpoint data. Pick the correct validator
for the OpenStack version. Expected data should be in the v2 format:
{
'service_name1': [
{
'adminURL': adminURL,
'id': id,
'region': region.
'publicURL': publicURL,
'internalURL': internalURL
}],
'service_name2': [
{
'adminURL': adminURL,
'id': id,
'region': region.
'publicURL': publicURL,
'internalURL': internalURL
}],
}
"""
validation_function = self.validate_v2_svc_catalog_endpoint_data
xenial_queens = OPENSTACK_RELEASES_PAIRS.index('xenial_queens')
if openstack_release and openstack_release >= xenial_queens:
validation_function = self.validate_v3_svc_catalog_endpoint_data
expected = self.convert_svc_catalog_endpoint_data_to_v3(expected)
return validation_function(expected, actual)
def validate_v2_svc_catalog_endpoint_data(self, expected, actual):
"""Validate service catalog endpoint data. """Validate service catalog endpoint data.
Validate a list of actual service catalog endpoints vs a list of Validate a list of actual service catalog endpoints vs a list of
@ -367,13 +480,36 @@ class OpenStackAmuletUtils(AmuletUtils):
project_domain_name=None, project_name=None): project_domain_name=None, project_name=None):
"""Authenticate with Keystone""" """Authenticate with Keystone"""
self.log.debug('Authenticating with keystone...') self.log.debug('Authenticating with keystone...')
port = 5000 if not api_version:
if admin_port: api_version = 2
port = 35357 sess, auth = self.get_keystone_session(
base_ep = "http://{}:{}".format(keystone_ip.strip().decode('utf-8'), keystone_ip=keystone_ip,
port) username=username,
if not api_version or api_version == 2: password=password,
ep = base_ep + "/v2.0" api_version=api_version,
admin_port=admin_port,
user_domain_name=user_domain_name,
domain_name=domain_name,
project_domain_name=project_domain_name,
project_name=project_name
)
if api_version == 2:
client = keystone_client.Client(session=sess)
else:
client = keystone_client_v3.Client(session=sess)
# This populates the client.service_catalog
client.auth_ref = auth.get_access(sess)
return client
def get_keystone_session(self, keystone_ip, username, password,
api_version=False, admin_port=False,
user_domain_name=None, domain_name=None,
project_domain_name=None, project_name=None):
"""Return a keystone session object"""
ep = self.get_keystone_endpoint(keystone_ip,
api_version=api_version,
admin_port=admin_port)
if api_version == 2:
auth = v2.Password( auth = v2.Password(
username=username, username=username,
password=password, password=password,
@ -381,12 +517,7 @@ class OpenStackAmuletUtils(AmuletUtils):
auth_url=ep auth_url=ep
) )
sess = keystone_session.Session(auth=auth) sess = keystone_session.Session(auth=auth)
client = keystone_client.Client(session=sess)
# This populates the client.service_catalog
client.auth_ref = auth.get_access(sess)
return client
else: else:
ep = base_ep + "/v3"
auth = v3.Password( auth = v3.Password(
user_domain_name=user_domain_name, user_domain_name=user_domain_name,
username=username, username=username,
@ -397,10 +528,57 @@ class OpenStackAmuletUtils(AmuletUtils):
auth_url=ep auth_url=ep
) )
sess = keystone_session.Session(auth=auth) sess = keystone_session.Session(auth=auth)
client = keystone_client_v3.Client(session=sess) return (sess, auth)
def get_keystone_endpoint(self, keystone_ip, api_version=None,
admin_port=False):
"""Return keystone endpoint"""
port = 5000
if admin_port:
port = 35357
base_ep = "http://{}:{}".format(keystone_ip.strip().decode('utf-8'),
port)
if api_version == 2:
ep = base_ep + "/v2.0"
else:
ep = base_ep + "/v3"
return ep
def get_default_keystone_session(self, keystone_sentry,
openstack_release=None):
"""Return a keystone session object and client object assuming standard
default settings
Example call in amulet tests:
self.keystone_session, self.keystone = u.get_default_keystone_session(
self.keystone_sentry,
openstack_release=self._get_openstack_release())
The session can then be used to auth other clients:
neutronclient.Client(session=session)
aodh_client.Client(session=session)
eyc
"""
self.log.debug('Authenticating keystone admin...')
api_version = 2
client_class = keystone_client.Client
# 11 => xenial_queens
if openstack_release and openstack_release >= 11:
api_version = 3
client_class = keystone_client_v3.Client
keystone_ip = keystone_sentry.info['public-address']
session, auth = self.get_keystone_session(
keystone_ip,
api_version=api_version,
username='admin',
password='openstack',
project_name='admin',
user_domain_name='admin_domain',
project_domain_name='admin_domain')
client = client_class(session=session)
# This populates the client.service_catalog # This populates the client.service_catalog
client.auth_ref = auth.get_access(sess) client.auth_ref = auth.get_access(session)
return client return session, client
def authenticate_keystone_admin(self, keystone_sentry, user, password, def authenticate_keystone_admin(self, keystone_sentry, user, password,
tenant=None, api_version=None, tenant=None, api_version=None,

View File

@ -182,7 +182,7 @@ SWIFT_CODENAMES = OrderedDict([
('pike', ('pike',
['2.13.0', '2.15.0']), ['2.13.0', '2.15.0']),
('queens', ('queens',
['2.16.0']), ['2.16.0', '2.17.0']),
]) ])
# >= Liberty version->codename mapping # >= Liberty version->codename mapping