Fix up amulet for queens
Queens ceilometer requires a number of different services and relations, the amulet functional tests have been updated for that. Also move to using charmhelper keystone v3 api helpers. Change-Id: I432c8937693fb47e7ca52e6dafe143a0143c437d Requires: https://github.com/juju/charm-helpers/pull/119
This commit is contained in:
parent
3438d424b0
commit
8f5babe429
@ -367,13 +367,36 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||
project_domain_name=None, project_name=None):
|
||||
"""Authenticate with Keystone"""
|
||||
self.log.debug('Authenticating with keystone...')
|
||||
port = 5000
|
||||
if admin_port:
|
||||
port = 35357
|
||||
base_ep = "http://{}:{}".format(keystone_ip.strip().decode('utf-8'),
|
||||
port)
|
||||
if not api_version or api_version == 2:
|
||||
ep = base_ep + "/v2.0"
|
||||
if not api_version:
|
||||
api_version = 2
|
||||
sess, auth = self.get_keystone_session(
|
||||
keystone_ip=keystone_ip,
|
||||
username=username,
|
||||
password=password,
|
||||
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(
|
||||
username=username,
|
||||
password=password,
|
||||
@ -381,12 +404,7 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||
auth_url=ep
|
||||
)
|
||||
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:
|
||||
ep = base_ep + "/v3"
|
||||
auth = v3.Password(
|
||||
user_domain_name=user_domain_name,
|
||||
username=username,
|
||||
@ -397,10 +415,57 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||
auth_url=ep
|
||||
)
|
||||
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
|
||||
client.auth_ref = auth.get_access(sess)
|
||||
return client
|
||||
client.auth_ref = auth.get_access(session)
|
||||
return session, client
|
||||
|
||||
def authenticate_keystone_admin(self, keystone_sentry, user, password,
|
||||
tenant=None, api_version=None,
|
||||
|
@ -182,7 +182,7 @@ SWIFT_CODENAMES = OrderedDict([
|
||||
('pike',
|
||||
['2.13.0', '2.15.0']),
|
||||
('queens',
|
||||
['2.16.0']),
|
||||
['2.16.0', '2.17.0']),
|
||||
])
|
||||
|
||||
# >= Liberty version->codename mapping
|
||||
|
@ -32,6 +32,9 @@ u = OpenStackAmuletUtils(DEBUG)
|
||||
class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
"""Amulet tests on a basic ceilometer deployment."""
|
||||
|
||||
no_origin = ['memcached', 'percona-cluster', 'rabbitmq-server',
|
||||
'ceph-mon', 'ceph-osd']
|
||||
|
||||
def __init__(self, series, openstack=None, source=None, stable=False):
|
||||
"""Deploy the entire test environment."""
|
||||
super(CeilometerBasicDeployment, self).__init__(series, openstack,
|
||||
@ -42,7 +45,7 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
self._deploy()
|
||||
|
||||
u.log.info('Waiting on extended status checks...')
|
||||
exclude_services = ['mongodb']
|
||||
exclude_services = ['mongodb', 'memcached']
|
||||
self._auto_wait_for_status(exclude_services=exclude_services)
|
||||
|
||||
self.d.sentry.wait()
|
||||
@ -62,21 +65,29 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
{'name': 'percona-cluster', 'constraints': {'mem': '3072M'}},
|
||||
{'name': 'rabbitmq-server'},
|
||||
{'name': 'keystone'},
|
||||
{'name': 'mongodb',
|
||||
'location': 'cs:~thedac/{}/mongodb'.format(self.series)},
|
||||
{'name': 'glance'}, # to satisfy workload status
|
||||
{'name': 'ceilometer-agent'},
|
||||
{'name': 'nova-compute'}
|
||||
]
|
||||
super(CeilometerBasicDeployment, self)._add_services(this_service,
|
||||
other_services)
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
other_services.extend([
|
||||
{'name': 'gnocchi'},
|
||||
{'name': 'memcached', 'location': 'cs:memcached'},
|
||||
{'name': 'ceph-mon', 'units': 3},
|
||||
{'name': 'ceph-osd', 'units': 3}])
|
||||
else:
|
||||
other_services.append({
|
||||
'name': 'mongodb',
|
||||
'location': 'cs:~thedac/{}/mongodb'.format(self.series)})
|
||||
super(CeilometerBasicDeployment, self)._add_services(
|
||||
this_service,
|
||||
other_services,
|
||||
no_origin=self.no_origin)
|
||||
|
||||
def _add_relations(self):
|
||||
"""Add all of the relations for the services."""
|
||||
relations = {
|
||||
'ceilometer:shared-db': 'mongodb:database',
|
||||
'ceilometer:amqp': 'rabbitmq-server:amqp',
|
||||
'ceilometer:identity-service': 'keystone:identity-service',
|
||||
'ceilometer:identity-notifications': 'keystone:'
|
||||
'identity-notifications',
|
||||
'keystone:shared-db': 'percona-cluster:shared-db',
|
||||
@ -90,6 +101,25 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
'glance:amqp': 'rabbitmq-server:amqp',
|
||||
'nova-compute:image-service': 'glance:image-service'
|
||||
}
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
additional_relations = {
|
||||
'ceilometer:identity-credentials': 'keystone:'
|
||||
'identity-credentials',
|
||||
'ceilometer:identity-notifications': 'keystone:'
|
||||
'identity-notifications',
|
||||
'ceilometer:metric-service': 'gnocchi:metric-service',
|
||||
'ceph-mon:osd': 'ceph-osd:mon',
|
||||
'gnocchi:identity-service': 'keystone:identity-service',
|
||||
'gnocchi:shared-db': 'percona-cluster:shared-db',
|
||||
'gnocchi:storage-ceph': 'ceph-mon:client',
|
||||
'gnocchi:coordinator-memcached': 'memcached:cache',
|
||||
}
|
||||
else:
|
||||
additional_relations = {
|
||||
'ceilometer:shared-db': 'mongodb:database',
|
||||
'ceilometer:identity-service': 'keystone:identity-service'}
|
||||
relations.update(additional_relations)
|
||||
print(relations)
|
||||
super(CeilometerBasicDeployment, self)._add_relations(relations)
|
||||
|
||||
def _configure_services(self):
|
||||
@ -106,6 +136,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
'keystone': keystone_config,
|
||||
'percona-cluster': pxc_config,
|
||||
}
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
configs['ceph-osd'] = {'osd-devices': '/dev/vdb',
|
||||
'osd-reformat': 'yes',
|
||||
'ephemeral-unmount': '/mnt'}
|
||||
super(CeilometerBasicDeployment, self)._configure_services(configs)
|
||||
|
||||
def _get_token(self):
|
||||
@ -119,42 +153,50 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
self.pxc_sentry = self.d.sentry['percona-cluster'][0]
|
||||
self.keystone_sentry = self.d.sentry['keystone'][0]
|
||||
self.rabbitmq_sentry = self.d.sentry['rabbitmq-server'][0]
|
||||
self.mongodb_sentry = self.d.sentry['mongodb'][0]
|
||||
self.nova_sentry = self.d.sentry['nova-compute'][0]
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
self.gnocchi_sentry = self.d.sentry['gnocchi'][0]
|
||||
else:
|
||||
self.mongodb_sentry = self.d.sentry['mongodb'][0]
|
||||
u.log.debug('openstack release val: {}'.format(
|
||||
self._get_openstack_release()))
|
||||
u.log.debug('openstack release str: {}'.format(
|
||||
self._get_openstack_release_string()))
|
||||
|
||||
# Authenticate admin with keystone endpoint
|
||||
self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
|
||||
user='admin',
|
||||
password='openstack',
|
||||
tenant='admin')
|
||||
self.keystone_session, self.keystone = u.get_default_keystone_session(
|
||||
self.keystone_sentry,
|
||||
openstack_release=self._get_openstack_release())
|
||||
|
||||
self.log.debug('Instantiating ceilometer client...')
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
self.ceil = ceilo_client.Client(session=self.keystone_session,)
|
||||
else:
|
||||
# Authenticate admin with ceilometer endpoint
|
||||
ep = self.keystone.service_catalog.url_for(service_type='metering',
|
||||
interface='publicURL')
|
||||
os_token = self.keystone.auth_token
|
||||
self.log.debug('Instantiating ceilometer client...')
|
||||
self.ceil = ceilo_client.Client(endpoint=ep, token=os_token)
|
||||
|
||||
def test_100_services(self):
|
||||
"""Verify the expected services are running on the corresponding
|
||||
service units."""
|
||||
u.log.debug('Checking system services on units...')
|
||||
|
||||
release = self._get_openstack_release()
|
||||
ceilometer_svcs = [
|
||||
'ceilometer-agent-central',
|
||||
'ceilometer-collector',
|
||||
'ceilometer-agent-notification',
|
||||
]
|
||||
if self._get_openstack_release() >= self.xenial_ocata:
|
||||
if release < self.xenial_queens:
|
||||
ceilometer_svcs.append('ceilometer-collector')
|
||||
|
||||
if (release >= self.xenial_ocata and release < self.xenial_queens):
|
||||
ceilometer_svcs.append('apache2')
|
||||
else:
|
||||
|
||||
if release < self.xenial_ocata:
|
||||
ceilometer_svcs.append('ceilometer-api')
|
||||
|
||||
if self._get_openstack_release() < self.trusty_mitaka:
|
||||
if release < self.trusty_mitaka:
|
||||
ceilometer_svcs.append('ceilometer-alarm-evaluator')
|
||||
ceilometer_svcs.append('ceilometer-alarm-notifier')
|
||||
|
||||
@ -169,6 +211,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
u.log.debug('OK')
|
||||
|
||||
def test_105_memcache(self):
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
u.log.debug('Skipping memcache test as memcache server is external'
|
||||
' to ceilometer')
|
||||
return
|
||||
u.validate_memcache(self.ceil_sentry,
|
||||
'/etc/ceilometer/ceilometer.conf',
|
||||
self._get_openstack_release(),
|
||||
@ -176,6 +222,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
|
||||
def test_110_service_catalog(self):
|
||||
"""Verify that the service catalog endpoint data is valid."""
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
u.log.debug('Skipping catalogue checks as ceilometer no longer '
|
||||
'registers endpoints')
|
||||
return
|
||||
u.log.debug('Checking keystone service catalog data...')
|
||||
endpoint_check = {
|
||||
'adminURL': u.valid_url,
|
||||
@ -190,7 +240,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
}
|
||||
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:
|
||||
amulet.raise_status(amulet.FAIL, msg=ret)
|
||||
|
||||
@ -198,6 +251,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
|
||||
def test_112_keystone_api_endpoint(self):
|
||||
"""Verify the ceilometer api endpoint data."""
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
u.log.debug('Skipping catalogue checks as ceilometer no longer '
|
||||
'registers endpoints')
|
||||
return
|
||||
u.log.debug('Checking keystone api endpoint data...')
|
||||
endpoints = self.keystone.endpoints.list()
|
||||
u.log.debug(endpoints)
|
||||
@ -210,8 +267,13 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
'publicurl': u.valid_url,
|
||||
'service_id': u.not_null}
|
||||
|
||||
ret = u.validate_endpoint_data(endpoints, admin_port, internal_port,
|
||||
public_port, expected)
|
||||
ret = u.validate_endpoint_data(
|
||||
endpoints,
|
||||
admin_port,
|
||||
internal_port,
|
||||
public_port,
|
||||
expected,
|
||||
openstack_release=self._get_openstack_release())
|
||||
if ret:
|
||||
message = 'Keystone endpoint: {}'.format(ret)
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
@ -220,6 +282,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
|
||||
def test_114_ceilometer_api_endpoint(self):
|
||||
"""Verify the ceilometer api endpoint data."""
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
u.log.debug('Skipping catalogue checks as ceilometer no longer '
|
||||
'registers endpoints')
|
||||
return
|
||||
u.log.debug('Checking ceilometer api endpoint data...')
|
||||
endpoints = self.keystone.endpoints.list()
|
||||
u.log.debug(endpoints)
|
||||
@ -241,6 +307,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
|
||||
def test_200_ceilometer_identity_relation(self):
|
||||
"""Verify the ceilometer to keystone identity-service relation data"""
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
u.log.debug('Skipping identity-service checks as ceilometer no '
|
||||
'longer has this rerlation')
|
||||
return
|
||||
u.log.debug('Checking ceilometer to keystone identity-service '
|
||||
'relation data...')
|
||||
unit = self.ceil_sentry
|
||||
@ -268,6 +338,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
|
||||
def test_201_keystone_ceilometer_identity_relation(self):
|
||||
"""Verify the keystone to ceilometer identity-service relation data"""
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
u.log.debug('Skipping identity-service checks as ceilometer no '
|
||||
'longer has this rerlation')
|
||||
return
|
||||
u.log.debug('Checking keystone:ceilometer identity relation data...')
|
||||
unit = self.keystone_sentry
|
||||
relation = ['identity-service', 'ceilometer:identity-service']
|
||||
@ -304,7 +378,7 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
# May be glance- or keystone- or another endpoint-changed value, so
|
||||
# check that at least one ???-endpoint-changed value exists.
|
||||
unit = self.keystone_sentry
|
||||
relation_data = unit.relation('identity-service',
|
||||
relation_data = unit.relation('identity-notifications',
|
||||
'ceilometer:identity-notifications')
|
||||
|
||||
expected = '-endpoint-changed'
|
||||
@ -358,42 +432,6 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
|
||||
u.log.debug('OK')
|
||||
|
||||
def test_205_ceilometer_to_mongodb_relation(self):
|
||||
"""Verify the ceilometer to mongodb relation data"""
|
||||
u.log.debug('Checking ceilometer:mongodb relation data...')
|
||||
unit = self.ceil_sentry
|
||||
relation = ['shared-db', 'mongodb:database']
|
||||
expected = {
|
||||
'ceilometer_database': 'ceilometer',
|
||||
'private-address': u.valid_ip,
|
||||
}
|
||||
|
||||
ret = u.validate_relation_data(unit, relation, expected)
|
||||
if ret:
|
||||
message = u.relation_error('ceilometer shared-db', ret)
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
|
||||
u.log.debug('OK')
|
||||
|
||||
def test_206_mongodb_to_ceilometer_relation(self):
|
||||
"""Verify the mongodb to ceilometer relation data"""
|
||||
u.log.debug('Checking mongodb:ceilometer relation data...')
|
||||
unit = self.mongodb_sentry
|
||||
relation = ['database', 'ceilometer:shared-db']
|
||||
expected = {
|
||||
'hostname': u.valid_ip,
|
||||
'port': '27017',
|
||||
'private-address': u.valid_ip,
|
||||
'type': 'database',
|
||||
}
|
||||
|
||||
ret = u.validate_relation_data(unit, relation, expected)
|
||||
if ret:
|
||||
message = u.relation_error('mongodb database', ret)
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
|
||||
u.log.debug('OK')
|
||||
|
||||
def test_207_ceilometer_ceilometer_agent_relation(self):
|
||||
"""Verify the ceilometer to ceilometer-agent relation data"""
|
||||
u.log.debug('Checking ceilometer:ceilometer-agent relation data...')
|
||||
@ -404,18 +442,22 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
'rabbitmq_user': 'ceilometer',
|
||||
'verbose': 'False',
|
||||
'rabbitmq_host': u.valid_ip,
|
||||
'service_ports': "{'ceilometer_api': [8777, 8767]}",
|
||||
'use_syslog': 'False',
|
||||
'metering_secret': u.not_null,
|
||||
'rabbitmq_virtual_host': 'openstack',
|
||||
'db_port': '27017',
|
||||
'private-address': u.valid_ip,
|
||||
'db_name': 'ceilometer',
|
||||
'db_host': u.valid_ip,
|
||||
'debug': 'False',
|
||||
'rabbitmq_password': u.not_null,
|
||||
'port': '8767'
|
||||
}
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
expected['gnocchi_url'] = u.valid_url
|
||||
expected['port'] = '8777'
|
||||
else:
|
||||
expected['db_port'] = '27017'
|
||||
expected['db_name'] = 'ceilometer'
|
||||
expected['db_host'] = u.valid_ip
|
||||
expected['service_ports'] = "{'ceilometer_api': [8777, 8767]}"
|
||||
|
||||
ret = u.validate_relation_data(unit, relation, expected)
|
||||
if ret:
|
||||
@ -442,12 +484,6 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
"""Verify the data in the ceilometer config file."""
|
||||
u.log.debug('Checking ceilometer config file data...')
|
||||
unit = self.ceil_sentry
|
||||
ks_rel = self.keystone_sentry.relation('identity-service',
|
||||
'ceilometer:identity-service')
|
||||
db_relation = self.mongodb_sentry.relation('database',
|
||||
'ceilometer:shared-db')
|
||||
db_conn = 'mongodb://%s:%s/ceilometer' % (db_relation['hostname'],
|
||||
db_relation['port'])
|
||||
conf = '/etc/ceilometer/ceilometer.conf'
|
||||
expected = {
|
||||
'DEFAULT': {
|
||||
@ -458,10 +494,26 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
'api': {
|
||||
'port': '8767',
|
||||
},
|
||||
'database': {
|
||||
'connection': db_conn,
|
||||
},
|
||||
}
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
relation = self.gnocchi_sentry.relation(
|
||||
'metric-service',
|
||||
'ceilometer:metric-service')
|
||||
expected['dispatcher_gnocchi'] = {'url': relation['gnocchi_url']}
|
||||
ks_rel = self.keystone_sentry.relation(
|
||||
'identity-credentials',
|
||||
'ceilometer:identity-credentials')
|
||||
ks_key_prefix = 'credentials'
|
||||
else:
|
||||
db_relation = self.mongodb_sentry.relation('database',
|
||||
'ceilometer:shared-db')
|
||||
db_conn = 'mongodb://%s:%s/ceilometer' % (db_relation['hostname'],
|
||||
db_relation['port'])
|
||||
expected['database'] = {'connection': db_conn}
|
||||
ks_rel = self.keystone_sentry.relation(
|
||||
'identity-service',
|
||||
'ceilometer:identity-service')
|
||||
ks_key_prefix = 'service'
|
||||
|
||||
if self._get_openstack_release() < self.trusty_mitaka:
|
||||
auth_uri = '%s://%s:%s/v2.0' % (ks_rel['service_protocol'],
|
||||
@ -473,9 +525,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
'os_password':
|
||||
ks_rel['service_password']}
|
||||
else:
|
||||
auth_uri = '%s://%s:%s' % (ks_rel['service_protocol'],
|
||||
ks_rel['service_host'],
|
||||
ks_rel['service_port'])
|
||||
auth_uri = '%s://%s:%s' % (
|
||||
ks_rel['{}_protocol'.format(ks_key_prefix)],
|
||||
ks_rel['{}_host'.format(ks_key_prefix)],
|
||||
ks_rel['{}_port'.format(ks_key_prefix)])
|
||||
# NOTE(dosaboy): os_ prefix is deprecated and no longer used as
|
||||
# of Mitaka.
|
||||
project_domain_name = 'default'
|
||||
@ -483,25 +536,21 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
if 'api_version' in ks_rel and float(ks_rel['api_version']) > 2:
|
||||
project_domain_name = 'service_domain'
|
||||
user_domain_name = 'service_domain'
|
||||
expected['service_credentials'] = {'auth_url': auth_uri,
|
||||
expected['service_credentials'] = {
|
||||
'auth_url': auth_uri,
|
||||
'project_name': 'services',
|
||||
'project_domain_name':
|
||||
project_domain_name,
|
||||
'user_domain_name':
|
||||
user_domain_name,
|
||||
'project_domain_name': project_domain_name,
|
||||
'user_domain_name': user_domain_name,
|
||||
'username': 'ceilometer',
|
||||
'password':
|
||||
ks_rel['service_password']}
|
||||
expected['keystone_authtoken'] = {'auth_uri': auth_uri,
|
||||
'password': ks_rel['{}_password'.format(ks_key_prefix)]}
|
||||
expected['keystone_authtoken'] = {
|
||||
'auth_uri': auth_uri,
|
||||
'auth_type': 'password',
|
||||
'project_domain_name':
|
||||
project_domain_name,
|
||||
'user_domain_name':
|
||||
user_domain_name,
|
||||
'project_domain_name': project_domain_name,
|
||||
'user_domain_name': user_domain_name,
|
||||
'project_name': 'services',
|
||||
'username': 'ceilometer',
|
||||
'password':
|
||||
ks_rel['service_password']}
|
||||
'password': ks_rel['{}_password'.format(ks_key_prefix)]}
|
||||
|
||||
if self._get_openstack_release() >= self.xenial_ocata:
|
||||
del expected['api']
|
||||
@ -516,6 +565,10 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
|
||||
def test_400_api_connection(self):
|
||||
"""Simple api calls to check service is up and responding"""
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
u.log.debug('Skipping API checks as ceilometer api has been '
|
||||
'removed')
|
||||
return
|
||||
u.log.debug('Checking api functionality...')
|
||||
assert(self.ceil.samples.list() == [])
|
||||
assert(self.ceil.meters.list() == [])
|
||||
@ -537,7 +590,13 @@ class CeilometerBasicDeployment(OpenStackAmuletDeployment):
|
||||
# Services which are expected to restart upon config change,
|
||||
# and corresponding config files affected by the change
|
||||
conf_file = '/etc/ceilometer/ceilometer.conf'
|
||||
if self._get_openstack_release() >= self.xenial_ocata:
|
||||
if self._get_openstack_release() >= self.xenial_queens:
|
||||
services = {
|
||||
'ceilometer-polling: AgentManager worker(0)': conf_file,
|
||||
'ceilometer-agent-notification: NotificationService worker(0)':
|
||||
conf_file,
|
||||
}
|
||||
elif self._get_openstack_release() >= self.xenial_ocata:
|
||||
services = {
|
||||
'ceilometer-collector: CollectorService worker(0)': conf_file,
|
||||
'ceilometer-polling: AgentManager worker(0)': conf_file,
|
||||
|
@ -21,6 +21,9 @@ from collections import OrderedDict
|
||||
from charmhelpers.contrib.amulet.deployment import (
|
||||
AmuletDeployment
|
||||
)
|
||||
from charmhelpers.contrib.openstack.amulet.utils import (
|
||||
OPENSTACK_RELEASES_PAIRS
|
||||
)
|
||||
|
||||
DEBUG = logging.DEBUG
|
||||
ERROR = logging.ERROR
|
||||
@ -271,11 +274,8 @@ class OpenStackAmuletDeployment(AmuletDeployment):
|
||||
release.
|
||||
"""
|
||||
# Must be ordered by OpenStack release (not by Ubuntu release):
|
||||
(self.trusty_icehouse, self.trusty_kilo, self.trusty_liberty,
|
||||
self.trusty_mitaka, self.xenial_mitaka, self.xenial_newton,
|
||||
self.yakkety_newton, self.xenial_ocata, self.zesty_ocata,
|
||||
self.xenial_pike, self.artful_pike, self.xenial_queens,
|
||||
self.bionic_queens,) = range(13)
|
||||
for i, os_pair in enumerate(OPENSTACK_RELEASES_PAIRS):
|
||||
setattr(self, os_pair, i)
|
||||
|
||||
releases = {
|
||||
('trusty', None): self.trusty_icehouse,
|
||||
|
@ -50,6 +50,13 @@ ERROR = logging.ERROR
|
||||
|
||||
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):
|
||||
"""OpenStack amulet utilities.
|
||||
@ -63,6 +70,33 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||
super(OpenStackAmuletUtils, self).__init__(log_level)
|
||||
|
||||
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):
|
||||
"""Validate endpoint data.
|
||||
|
||||
@ -141,7 +175,86 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||
if len(found) != expected_num_eps:
|
||||
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 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):
|
||||
"""Authenticate with Keystone"""
|
||||
self.log.debug('Authenticating with keystone...')
|
||||
port = 5000
|
||||
if admin_port:
|
||||
port = 35357
|
||||
base_ep = "http://{}:{}".format(keystone_ip.strip().decode('utf-8'),
|
||||
port)
|
||||
if not api_version or api_version == 2:
|
||||
ep = base_ep + "/v2.0"
|
||||
if not api_version:
|
||||
api_version = 2
|
||||
sess, auth = self.get_keystone_session(
|
||||
keystone_ip=keystone_ip,
|
||||
username=username,
|
||||
password=password,
|
||||
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(
|
||||
username=username,
|
||||
password=password,
|
||||
@ -381,12 +517,7 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||
auth_url=ep
|
||||
)
|
||||
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:
|
||||
ep = base_ep + "/v3"
|
||||
auth = v3.Password(
|
||||
user_domain_name=user_domain_name,
|
||||
username=username,
|
||||
@ -397,10 +528,57 @@ class OpenStackAmuletUtils(AmuletUtils):
|
||||
auth_url=ep
|
||||
)
|
||||
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
|
||||
client.auth_ref = auth.get_access(sess)
|
||||
return client
|
||||
client.auth_ref = auth.get_access(session)
|
||||
return session, client
|
||||
|
||||
def authenticate_keystone_admin(self, keystone_sentry, user, password,
|
||||
tenant=None, api_version=None,
|
||||
|
Loading…
Reference in New Issue
Block a user