Add Antelope support

* sync charm-helpers to classic charms
* change openstack-origin/source default to antelope
* align testing with antelope
* add new antelope bundles
* add antelope bundles to tests.yaml
* add antelope tests to osci.yaml and .zuul.yaml
* update build-on and run-on bases

Change-Id: I59238c9a3933756755903d0e6718699e6960cc5c
This commit is contained in:
Corey Bryant 2023-02-14 21:26:00 +00:00
parent 065e1509a3
commit 9af7effd2b
21 changed files with 505 additions and 58 deletions

View File

@ -1,3 +1,3 @@
- project: - project:
templates: templates:
- openstack-python3-charm-zed-jobs - openstack-python3-charm-jobs

View File

@ -32,3 +32,6 @@ bases:
- name: ubuntu - name: ubuntu
channel: "22.10" channel: "22.10"
architectures: [amd64, s390x, ppc64el, arm64] architectures: [amd64, s390x, ppc64el, arm64]
- name: ubuntu
channel: "23.04"
architectures: [amd64, s390x, ppc64el, arm64]

View File

@ -324,7 +324,7 @@ def valid_hacluster_config():
''' '''
vip = config_get('vip') vip = config_get('vip')
dns = config_get('dns-ha') dns = config_get('dns-ha')
if not(bool(vip) ^ bool(dns)): if not (bool(vip) ^ bool(dns)):
msg = ('HA: Either vip or dns-ha must be set but not both in order to ' msg = ('HA: Either vip or dns-ha must be set but not both in order to '
'use high availability') 'use high availability')
status_set('blocked', msg) status_set('blocked', msg)

View File

@ -539,7 +539,7 @@ def port_has_listener(address, port):
""" """
cmd = ['nc', '-z', address, str(port)] cmd = ['nc', '-z', address, str(port)]
result = subprocess.call(cmd) result = subprocess.call(cmd)
return not(bool(result)) return not (bool(result))
def assert_charm_supports_ipv6(): def assert_charm_supports_ipv6():

View File

@ -61,6 +61,7 @@ from charmhelpers.core.hookenv import (
network_get_primary_address, network_get_primary_address,
WARNING, WARNING,
service_name, service_name,
remote_service_name,
) )
from charmhelpers.core.sysctl import create as sysctl_create from charmhelpers.core.sysctl import create as sysctl_create
@ -348,6 +349,14 @@ def db_ssl(rdata, ctxt, ssl_dir):
class IdentityServiceContext(OSContextGenerator): class IdentityServiceContext(OSContextGenerator):
_forward_compat_remaps = {
'admin_user': 'admin-user-name',
'service_username': 'service-user-name',
'service_tenant': 'service-project-name',
'service_tenant_id': 'service-project-id',
'service_domain': 'service-domain-name',
}
def __init__(self, def __init__(self,
service=None, service=None,
service_user=None, service_user=None,
@ -400,11 +409,16 @@ class IdentityServiceContext(OSContextGenerator):
# 'www_authenticate_uri' replaced 'auth_uri' since Stein, # 'www_authenticate_uri' replaced 'auth_uri' since Stein,
# see keystonemiddleware upstream sources for more info # see keystonemiddleware upstream sources for more info
if CompareOpenStackReleases(keystonemiddleware_os_rel) >= 'stein': if CompareOpenStackReleases(keystonemiddleware_os_rel) >= 'stein':
c.update(( if 'public_auth_url' in ctxt:
('www_authenticate_uri', "{}://{}:{}/v3".format( c.update((
ctxt.get('service_protocol', ''), ('www_authenticate_uri', '{}/v3'.format(
ctxt.get('service_host', ''), ctxt.get('public_auth_url'))),))
ctxt.get('service_port', ''))),)) else:
c.update((
('www_authenticate_uri', "{}://{}:{}/v3".format(
ctxt.get('service_protocol', ''),
ctxt.get('service_host', ''),
ctxt.get('service_port', ''))),))
else: else:
c.update(( c.update((
('auth_uri', "{}://{}:{}/v3".format( ('auth_uri', "{}://{}:{}/v3".format(
@ -412,11 +426,17 @@ class IdentityServiceContext(OSContextGenerator):
ctxt.get('service_host', ''), ctxt.get('service_host', ''),
ctxt.get('service_port', ''))),)) ctxt.get('service_port', ''))),))
if 'internal_auth_url' in ctxt:
c.update((
('auth_url', ctxt.get('internal_auth_url')),))
else:
c.update((
('auth_url', "{}://{}:{}/v3".format(
ctxt.get('auth_protocol', ''),
ctxt.get('auth_host', ''),
ctxt.get('auth_port', ''))),))
c.update(( c.update((
('auth_url', "{}://{}:{}/v3".format(
ctxt.get('auth_protocol', ''),
ctxt.get('auth_host', ''),
ctxt.get('auth_port', ''))),
('project_domain_name', ctxt.get('admin_domain_name', '')), ('project_domain_name', ctxt.get('admin_domain_name', '')),
('user_domain_name', ctxt.get('admin_domain_name', '')), ('user_domain_name', ctxt.get('admin_domain_name', '')),
('project_name', ctxt.get('admin_tenant_name', '')), ('project_name', ctxt.get('admin_tenant_name', '')),
@ -444,39 +464,86 @@ class IdentityServiceContext(OSContextGenerator):
for rid in relation_ids(self.rel_name): for rid in relation_ids(self.rel_name):
self.related = True self.related = True
for unit in related_units(rid): for unit in related_units(rid):
rdata = {}
# NOTE(jamespage):
# forwards compat with application data
# bag driven approach to relation.
_adata = relation_get(rid=rid, app=remote_service_name(rid))
adata = {}
# if no app data bag presented - fallback
# to legacy unit based relation data
rdata = relation_get(rid=rid, unit=unit) rdata = relation_get(rid=rid, unit=unit)
serv_host = rdata.get('service_host') if _adata:
# New app data bag uses - instead of _
# in key names - remap for compat with
# existing relation data keys
for key, value in _adata.items():
if key == 'api-version':
adata[key.replace('-', '_')] = value.strip('v')
else:
adata[key.replace('-', '_')] = value
# Re-map some keys for backwards compatibility
for target, source in self._forward_compat_remaps.items():
adata[target] = _adata.get(source)
# Now preferentially get data from the app data bag, but if
# it's not available, get it from the legacy based relation
# data.
def _resolve(key):
return adata.get(key) or rdata.get(key)
serv_host = _resolve('service_host')
serv_host = format_ipv6_addr(serv_host) or serv_host serv_host = format_ipv6_addr(serv_host) or serv_host
auth_host = rdata.get('auth_host') auth_host = _resolve('auth_host')
auth_host = format_ipv6_addr(auth_host) or auth_host auth_host = format_ipv6_addr(auth_host) or auth_host
int_host = rdata.get('internal_host') int_host = _resolve('internal_host',)
int_host = format_ipv6_addr(int_host) or int_host int_host = format_ipv6_addr(int_host) or int_host
svc_protocol = rdata.get('service_protocol') or 'http' svc_protocol = _resolve('service_protocol') or 'http'
auth_protocol = rdata.get('auth_protocol') or 'http' auth_protocol = _resolve('auth_protocol') or 'http'
int_protocol = rdata.get('internal_protocol') or 'http' admin_role = _resolve('admin_role') or 'Admin'
api_version = rdata.get('api_version') or '2.0' int_protocol = _resolve('internal_protocol') or 'http'
ctxt.update({'service_port': rdata.get('service_port'), api_version = _resolve('api_version') or '2.0'
ctxt.update({'service_port': _resolve('service_port'),
'service_host': serv_host, 'service_host': serv_host,
'auth_host': auth_host, 'auth_host': auth_host,
'auth_port': rdata.get('auth_port'), 'auth_port': _resolve('auth_port'),
'internal_host': int_host, 'internal_host': int_host,
'internal_port': rdata.get('internal_port'), 'internal_port': _resolve('internal_port'),
'admin_tenant_name': rdata.get('service_tenant'), 'admin_tenant_name': _resolve('service_tenant'),
'admin_user': rdata.get('service_username'), 'admin_user': _resolve('service_username'),
'admin_password': rdata.get('service_password'), 'admin_password': _resolve('service_password'),
'admin_role': admin_role,
'service_protocol': svc_protocol, 'service_protocol': svc_protocol,
'auth_protocol': auth_protocol, 'auth_protocol': auth_protocol,
'internal_protocol': int_protocol, 'internal_protocol': int_protocol,
'api_version': api_version}) 'api_version': api_version})
if rdata.get('service_type'): service_type = _resolve('service_type')
ctxt['service_type'] = rdata.get('service_type') if service_type:
ctxt['service_type'] = service_type
if float(api_version) > 2: if float(api_version) > 2:
ctxt.update({ ctxt.update({
'admin_domain_name': rdata.get('service_domain'), 'admin_domain_name': _resolve('service_domain'),
'service_project_id': rdata.get('service_tenant_id'), 'service_project_id': _resolve('service_tenant_id'),
'service_domain_id': rdata.get('service_domain_id')}) 'service_domain_id': _resolve('service_domain_id')})
# NOTE:
# keystone-k8s operator presents full URLS
# for all three endpoints - public and internal are
# externally addressable for machine based charm
public_auth_url = _resolve('public_auth_url')
# if 'public_auth_url' in rdata:
if public_auth_url:
ctxt.update({
'public_auth_url': public_auth_url,
})
internal_auth_url = _resolve('internal_auth_url')
# if 'internal_auth_url' in rdata:
if internal_auth_url:
ctxt.update({
'internal_auth_url': internal_auth_url,
})
# we keep all veriables in ctxt for compatibility and # we keep all veriables in ctxt for compatibility and
# add nested dictionary for keystone_authtoken generic # add nested dictionary for keystone_authtoken generic
@ -490,8 +557,8 @@ class IdentityServiceContext(OSContextGenerator):
# NOTE(jamespage) this is required for >= icehouse # NOTE(jamespage) this is required for >= icehouse
# so a missing value just indicates keystone needs # so a missing value just indicates keystone needs
# upgrading # upgrading
ctxt['admin_tenant_id'] = rdata.get('service_tenant_id') ctxt['admin_tenant_id'] = _resolve('service_tenant_id')
ctxt['admin_domain_id'] = rdata.get('service_domain_id') ctxt['admin_domain_id'] = _resolve('service_domain_id')
return ctxt return ctxt
return {} return {}

View File

@ -310,7 +310,7 @@ def ssh_known_hosts_lines(application_name, user=None):
for hosts_line in hosts: for hosts_line in hosts:
if hosts_line.rstrip(): if hosts_line.rstrip():
known_hosts_list.append(hosts_line.rstrip()) known_hosts_list.append(hosts_line.rstrip())
return(known_hosts_list) return known_hosts_list
def ssh_authorized_keys_lines(application_name, user=None): def ssh_authorized_keys_lines(application_name, user=None):
@ -327,7 +327,7 @@ def ssh_authorized_keys_lines(application_name, user=None):
for authkey_line in keys: for authkey_line in keys:
if authkey_line.rstrip(): if authkey_line.rstrip():
authorized_keys_list.append(authkey_line.rstrip()) authorized_keys_list.append(authkey_line.rstrip())
return(authorized_keys_list) return authorized_keys_list
def ssh_compute_remove(public_key, application_name, user=None): def ssh_compute_remove(public_key, application_name, user=None):

View File

@ -12,4 +12,6 @@ signing_dir = {{ signing_dir }}
{% if service_type -%} {% if service_type -%}
service_type = {{ service_type }} service_type = {{ service_type }}
{% endif -%} {% endif -%}
service_token_roles = {{ admin_role }}
service_token_roles_required = True
{% endif -%} {% endif -%}

View File

@ -0,0 +1,11 @@
{% if auth_host -%}
[service_user]
send_service_user_token = true
auth_type = password
auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}
project_domain_id = default
user_domain_id = default
project_name = {{ admin_tenant_name }}
username = {{ admin_user }}
password = {{ admin_password }}
{% endif -%}

View File

@ -159,6 +159,7 @@ OPENSTACK_CODENAMES = OrderedDict([
('2021.2', 'xena'), ('2021.2', 'xena'),
('2022.1', 'yoga'), ('2022.1', 'yoga'),
('2022.2', 'zed'), ('2022.2', 'zed'),
('2023.1', 'antelope'),
]) ])
# The ugly duckling - must list releases oldest to newest # The ugly duckling - must list releases oldest to newest
@ -1327,7 +1328,7 @@ def _check_listening_on_services_ports(services, test=False):
@param test: default=False, if False, test for closed, otherwise open. @param test: default=False, if False, test for closed, otherwise open.
@returns OrderedDict(service: [port-not-open, ...]...), [boolean] @returns OrderedDict(service: [port-not-open, ...]...), [boolean]
""" """
test = not(not(test)) # ensure test is True or False test = not (not (test)) # ensure test is True or False
all_ports = list(itertools.chain(*services.values())) all_ports = list(itertools.chain(*services.values()))
ports_states = [port_has_listener('0.0.0.0', p) for p in all_ports] ports_states = [port_has_listener('0.0.0.0', p) for p in all_ports]
map_ports = OrderedDict() map_ports = OrderedDict()
@ -1583,7 +1584,7 @@ def is_unit_paused_set():
with unitdata.HookData()() as t: with unitdata.HookData()() as t:
kv = t[0] kv = t[0]
# transform something truth-y into a Boolean. # transform something truth-y into a Boolean.
return not(not(kv.get('unit-paused'))) return not (not (kv.get('unit-paused')))
except Exception: except Exception:
return False return False
@ -2181,7 +2182,7 @@ def is_unit_upgrading_set():
with unitdata.HookData()() as t: with unitdata.HookData()() as t:
kv = t[0] kv = t[0]
# transform something truth-y into a Boolean. # transform something truth-y into a Boolean.
return not(not(kv.get('unit-upgrading'))) return not (not (kv.get('unit-upgrading')))
except Exception: except Exception:
return False return False

View File

@ -173,7 +173,12 @@ def retrieve_secret_id(url, token):
# hvac < 0.9.2 assumes adapter is an instance, so doesn't instantiate # hvac < 0.9.2 assumes adapter is an instance, so doesn't instantiate
if not isinstance(client.adapter, hvac.adapters.Request): if not isinstance(client.adapter, hvac.adapters.Request):
client.adapter = hvac.adapters.Request(base_uri=url, token=token) client.adapter = hvac.adapters.Request(base_uri=url, token=token)
response = client._post('/v1/sys/wrapping/unwrap') try:
# hvac == 1.0.0 has an API to unwrap with the user token
response = client.sys.unwrap()
except AttributeError:
# fallback to hvac < 1.0.0
response = client._post('/v1/sys/wrapping/unwrap')
if response.status_code == 200: if response.status_code == 200:
data = response.json() data = response.json()
return data['data']['secret_id'] return data['data']['secret_id']

View File

@ -954,7 +954,7 @@ def pwgen(length=None):
random_generator = random.SystemRandom() random_generator = random.SystemRandom()
random_chars = [ random_chars = [
random_generator.choice(alphanumeric_chars) for _ in range(length)] random_generator.choice(alphanumeric_chars) for _ in range(length)]
return(''.join(random_chars)) return ''.join(random_chars)
def is_phy_iface(interface): def is_phy_iface(interface):

View File

@ -31,6 +31,7 @@ UBUNTU_RELEASES = (
'impish', 'impish',
'jammy', 'jammy',
'kinetic', 'kinetic',
'lunar',
) )

View File

@ -171,8 +171,9 @@ class Storage(object):
path parameter which causes sqlite3 to only build the db in memory. path parameter which causes sqlite3 to only build the db in memory.
This should only be used for testing purposes. This should only be used for testing purposes.
""" """
def __init__(self, path=None): def __init__(self, path=None, keep_revisions=False):
self.db_path = path self.db_path = path
self.keep_revisions = keep_revisions
if path is None: if path is None:
if 'UNIT_STATE_DB' in os.environ: if 'UNIT_STATE_DB' in os.environ:
self.db_path = os.environ['UNIT_STATE_DB'] self.db_path = os.environ['UNIT_STATE_DB']
@ -242,7 +243,7 @@ class Storage(object):
Remove a key from the database entirely. Remove a key from the database entirely.
""" """
self.cursor.execute('delete from kv where key=?', [key]) self.cursor.execute('delete from kv where key=?', [key])
if self.revision and self.cursor.rowcount: if self.keep_revisions and self.revision and self.cursor.rowcount:
self.cursor.execute( self.cursor.execute(
'insert into kv_revisions values (?, ?, ?)', 'insert into kv_revisions values (?, ?, ?)',
[key, self.revision, json.dumps('DELETED')]) [key, self.revision, json.dumps('DELETED')])
@ -259,14 +260,14 @@ class Storage(object):
if keys is not None: if keys is not None:
keys = ['%s%s' % (prefix, key) for key in keys] keys = ['%s%s' % (prefix, key) for key in keys]
self.cursor.execute('delete from kv where key in (%s)' % ','.join(['?'] * len(keys)), keys) self.cursor.execute('delete from kv where key in (%s)' % ','.join(['?'] * len(keys)), keys)
if self.revision and self.cursor.rowcount: if self.keep_revisions and self.revision and self.cursor.rowcount:
self.cursor.execute( self.cursor.execute(
'insert into kv_revisions values %s' % ','.join(['(?, ?, ?)'] * len(keys)), 'insert into kv_revisions values %s' % ','.join(['(?, ?, ?)'] * len(keys)),
list(itertools.chain.from_iterable((key, self.revision, json.dumps('DELETED')) for key in keys))) list(itertools.chain.from_iterable((key, self.revision, json.dumps('DELETED')) for key in keys)))
else: else:
self.cursor.execute('delete from kv where key like ?', self.cursor.execute('delete from kv where key like ?',
['%s%%' % prefix]) ['%s%%' % prefix])
if self.revision and self.cursor.rowcount: if self.keep_revisions and self.revision and self.cursor.rowcount:
self.cursor.execute( self.cursor.execute(
'insert into kv_revisions values (?, ?, ?)', 'insert into kv_revisions values (?, ?, ?)',
['%s%%' % prefix, self.revision, json.dumps('DELETED')]) ['%s%%' % prefix, self.revision, json.dumps('DELETED')])
@ -299,7 +300,7 @@ class Storage(object):
where key = ?''', [serialized, key]) where key = ?''', [serialized, key])
# Save # Save
if not self.revision: if (not self.keep_revisions) or (not self.revision):
return value return value
self.cursor.execute( self.cursor.execute(

View File

@ -230,6 +230,18 @@ CLOUD_ARCHIVE_POCKETS = {
'zed/proposed': 'jammy-proposed/zed', 'zed/proposed': 'jammy-proposed/zed',
'jammy-zed/proposed': 'jammy-proposed/zed', 'jammy-zed/proposed': 'jammy-proposed/zed',
'jammy-proposed/zed': 'jammy-proposed/zed', 'jammy-proposed/zed': 'jammy-proposed/zed',
# antelope
'antelope': 'jammy-updates/antelope',
'jammy-antelope': 'jammy-updates/antelope',
'jammy-antelope/updates': 'jammy-updates/antelope',
'jammy-updates/antelope': 'jammy-updates/antelope',
'antelope/proposed': 'jammy-proposed/antelope',
'jammy-antelope/proposed': 'jammy-proposed/antelope',
'jammy-proposed/antelope': 'jammy-proposed/antelope',
# OVN
'focal-ovn-22.03': 'focal-updates/ovn-22.03',
'focal-ovn-22.03/proposed': 'focal-proposed/ovn-22.03',
} }
@ -257,6 +269,7 @@ OPENSTACK_RELEASES = (
'xena', 'xena',
'yoga', 'yoga',
'zed', 'zed',
'antelope',
) )
@ -284,6 +297,7 @@ UBUNTU_OPENSTACK_RELEASE = OrderedDict([
('impish', 'xena'), ('impish', 'xena'),
('jammy', 'yoga'), ('jammy', 'yoga'),
('kinetic', 'zed'), ('kinetic', 'zed'),
('lunar', 'antelope'),
]) ])
@ -363,6 +377,9 @@ def apt_install(packages, options=None, fatal=False, quiet=False):
:type quiet: bool :type quiet: bool
:raises: subprocess.CalledProcessError :raises: subprocess.CalledProcessError
""" """
if not packages:
log("Nothing to install", level=DEBUG)
return
if options is None: if options is None:
options = ['--option=Dpkg::Options::=--force-confold'] options = ['--option=Dpkg::Options::=--force-confold']
@ -687,6 +704,7 @@ def add_source(source, key=None, fail_invalid=False):
(r"^cloud-archive:(.*)$", _add_apt_repository), (r"^cloud-archive:(.*)$", _add_apt_repository),
(r"^((?:deb |http:|https:|ppa:).*)$", _add_apt_repository), (r"^((?:deb |http:|https:|ppa:).*)$", _add_apt_repository),
(r"^cloud:(.*)-(.*)\/staging$", _add_cloud_staging), (r"^cloud:(.*)-(.*)\/staging$", _add_cloud_staging),
(r"^cloud:(.*)-(ovn-.*)$", _add_cloud_distro_check),
(r"^cloud:(.*)-(.*)$", _add_cloud_distro_check), (r"^cloud:(.*)-(.*)$", _add_cloud_distro_check),
(r"^cloud:(.*)$", _add_cloud_pocket), (r"^cloud:(.*)$", _add_cloud_pocket),
(r"^snap:.*-(.*)-(.*)$", _add_cloud_distro_check), (r"^snap:.*-(.*)-(.*)$", _add_cloud_distro_check),
@ -750,6 +768,11 @@ def _add_apt_repository(spec):
) )
def __write_sources_list_d_actual_pocket(file, actual_pocket):
with open('/etc/apt/sources.list.d/{}'.format(file), 'w') as apt:
apt.write(CLOUD_ARCHIVE.format(actual_pocket))
def _add_cloud_pocket(pocket): def _add_cloud_pocket(pocket):
"""Add a cloud pocket as /etc/apt/sources.d/cloud-archive.list """Add a cloud pocket as /etc/apt/sources.d/cloud-archive.list
@ -769,8 +792,9 @@ def _add_cloud_pocket(pocket):
'Unsupported cloud: source option %s' % 'Unsupported cloud: source option %s' %
pocket) pocket)
actual_pocket = CLOUD_ARCHIVE_POCKETS[pocket] actual_pocket = CLOUD_ARCHIVE_POCKETS[pocket]
with open('/etc/apt/sources.list.d/cloud-archive.list', 'w') as apt: __write_sources_list_d_actual_pocket(
apt.write(CLOUD_ARCHIVE.format(actual_pocket)) 'cloud-archive{}.list'.format('' if 'ovn' not in pocket else '-ovn'),
actual_pocket)
def _add_cloud_staging(cloud_archive_release, openstack_release): def _add_cloud_staging(cloud_archive_release, openstack_release):
@ -931,10 +955,14 @@ def _run_with_retries(cmd, max_retries=CMD_RETRY_COUNT, retry_exitcodes=(1,),
try: try:
result = subprocess.check_call(cmd, env=env, **kwargs) result = subprocess.check_call(cmd, env=env, **kwargs)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
retry_count = retry_count + 1
if retry_count > max_retries:
raise
result = e.returncode result = e.returncode
if result not in retry_results:
# a non-retriable exitcode was produced
raise
retry_count += 1
if retry_count > max_retries:
# a retriable exitcode was produced more than {max_retries} times
raise
log(retry_message) log(retry_message)
time.sleep(CMD_RETRY_DELAY) time.sleep(CMD_RETRY_DELAY)

View File

@ -19,6 +19,7 @@ tags:
series: series:
- jammy - jammy
- kinetic - kinetic
- lunar
provides: provides:
nrpe-external-master: nrpe-external-master:
interface: nrpe-external-master interface: nrpe-external-master

View File

@ -1,7 +1,7 @@
- project: - project:
templates: templates:
- charm-unit-jobs-py310 - charm-unit-jobs-py310
- charm-zed-functional-jobs - charm-functional-jobs
vars: vars:
needs_charm_build: true needs_charm_build: true
charm_build_name: ceilometer-agent charm_build_name: ceilometer-agent

View File

@ -26,3 +26,4 @@ git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.open
git+https://opendev.org/openstack/tempest.git#egg=tempest git+https://opendev.org/openstack/tempest.git#egg=tempest
croniter # needed for charm-rabbitmq-server unit tests croniter # needed for charm-rabbitmq-server unit tests
psutil

View File

@ -0,0 +1,325 @@
variables:
openstack-origin: &openstack-origin cloud:jammy-antelope
series: jammy
comment:
- 'machines section to decide order of deployment. database sooner = faster'
machines:
'0':
constraints: mem=3072M
'1':
constraints: mem=3072M
'2':
constraints: mem=3072M
'3':
'4':
# Note that holding memcached at focal as it's not available at jammy yet.
series: focal
'5':
'6':
'7':
'8':
'9':
'10':
'11':
'12':
'13':
constraints: mem=4096M
'14':
constraints: mem=4096M cores=4
'15':
'16':
'17':
'18':
'19':
applications:
keystone-mysql-router:
charm: ch:mysql-router
channel: latest/edge
placement-mysql-router:
charm: ch:mysql-router
channel: latest/edge
glance-mysql-router:
charm: ch:mysql-router
channel: latest/edge
nova-cloud-controller-mysql-router:
charm: ch:mysql-router
channel: latest/edge
gnocchi-mysql-router:
charm: ch:mysql-router
channel: latest/edge
neutron-api-mysql-router:
charm: ch:mysql-router
channel: latest/edge
mysql-innodb-cluster:
charm: ch:mysql-innodb-cluster
num_units: 3
options:
source: *openstack-origin
to:
- '0'
- '1'
- '2'
channel: latest/edge
rabbitmq-server:
charm: ch:rabbitmq-server
num_units: 1
to:
- '3'
channel: latest/edge
memcached:
charm: ch:memcached
num_units: 1
# Note that holding memcached at focal as it's not available at jammy yet.
series: focal
to:
- '4'
ceph-osd:
charm: ch:ceph-osd
num_units: 3
options:
source: *openstack-origin
storage:
osd-devices: 'cinder,10G'
to:
- '5'
- '6'
- '7'
channel: latest/edge
ceph-mon:
charm: ch:ceph-mon
num_units: 3
options:
source: *openstack-origin
to:
- '8'
- '9'
- '10'
channel: latest/edge
keystone:
charm: ch:keystone
num_units: 1
options:
openstack-origin: *openstack-origin
to:
- '11'
channel: latest/edge
glance:
charm: ch:glance
num_units: 1
options:
openstack-origin: *openstack-origin
to:
- '12'
channel: latest/edge
nova-cloud-controller:
charm: ch:nova-cloud-controller
num_units: 1
options:
openstack-origin: *openstack-origin
network-manager: Neutron
to:
- '13'
channel: latest/edge
nova-compute:
charm: ch:nova-compute
num_units: 1
options:
openstack-origin: *openstack-origin
to:
- '14'
channel: latest/edge
neutron-api:
charm: ch:neutron-api
num_units: 1
options:
manage-neutron-plugin-legacy-mode: true
openstack-origin: *openstack-origin
flat-network-providers: physnet1
neutron-security-groups: true
to:
- '15'
channel: latest/edge
neutron-gateway:
charm: ch:neutron-gateway
num_units: 1
options:
openstack-origin: *openstack-origin
bridge-mappings: physnet1:br-ex
to:
- '16'
channel: latest/edge
neutron-openvswitch:
charm: ch:neutron-openvswitch
channel: latest/edge
ceilometer:
charm: ch:ceilometer
num_units: 1
options:
openstack-origin: *openstack-origin
debug: true
polling-interval: 10
polling-batch-size: 0
to:
- '17'
channel: latest/edge
gnocchi:
charm: ch:gnocchi
num_units: 1
options:
openstack-origin: *openstack-origin
to:
- '18'
channel: latest/edge
placement:
charm: ch:placement
num_units: 1
constraints: mem=1G
options:
openstack-origin: *openstack-origin
to:
- '19'
channel: latest/edge
ceilometer-agent:
charm: ../../ceilometer-agent.charm
options:
polling-interval: 10
# NOTE(lourot): we normally set this to `true` in other bundles in order
# to validate more metrics but this is broken on Wallaby. See lp:1938884
enable-all-pollsters: false
relations:
- - 'ceilometer:amqp'
- 'rabbitmq-server:amqp'
- - 'ceilometer:identity-notifications'
- 'keystone:identity-notifications'
- - 'ceilometer:ceilometer-service'
- 'ceilometer-agent:ceilometer-service'
- - 'ceilometer:metric-service'
- 'gnocchi:metric-service'
- - 'ceilometer:identity-credentials'
- 'keystone:identity-credentials'
- - 'keystone:shared-db'
- 'keystone-mysql-router:shared-db'
- - 'keystone-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'ceilometer-agent:amqp'
- 'rabbitmq-server:amqp'
- - 'nova-compute:nova-ceilometer'
- 'ceilometer-agent:nova-ceilometer'
- - 'nova-compute:amqp'
- 'rabbitmq-server:amqp'
- - 'placement:shared-db'
- 'placement-mysql-router:shared-db'
- - 'placement-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'placement:identity-service'
- 'keystone:identity-service'
- - 'placement:placement'
- 'nova-cloud-controller:placement'
- - 'glance:identity-service'
- 'keystone:identity-service'
- - 'glance:shared-db'
- 'glance-mysql-router:shared-db'
- - 'glance-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'glance:amqp'
- 'rabbitmq-server:amqp'
- - 'nova-compute:image-service'
- 'glance:image-service'
- - 'nova-cloud-controller:shared-db'
- 'nova-cloud-controller-mysql-router:shared-db'
- - 'nova-cloud-controller-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'nova-cloud-controller:amqp'
- 'rabbitmq-server:amqp'
- - 'nova-cloud-controller:identity-service'
- 'keystone:identity-service'
- - 'nova-cloud-controller:cloud-compute'
- 'nova-compute:cloud-compute'
- - 'nova-cloud-controller:image-service'
- 'glance:image-service'
- - 'ceph-mon:osd'
- 'ceph-osd:mon'
- - 'gnocchi:shared-db'
- 'gnocchi-mysql-router:shared-db'
- - 'gnocchi-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'gnocchi:storage-ceph'
- 'ceph-mon:client'
- - 'gnocchi:coordinator-memcached'
- 'memcached:cache'
- - 'gnocchi:identity-service'
- 'keystone:identity-service'
- - 'neutron-gateway:amqp'
- 'rabbitmq-server:amqp'
- - 'nova-cloud-controller:quantum-network-service'
- 'neutron-gateway:quantum-network-service'
- - 'neutron-api:shared-db'
- 'neutron-api-mysql-router:shared-db'
- - 'neutron-api-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'neutron-api:amqp'
- 'rabbitmq-server:amqp'
- - 'neutron-api:neutron-api'
- 'nova-cloud-controller:neutron-api'
- - 'neutron-api:identity-service'
- 'keystone:identity-service'
- - 'nova-compute:neutron-plugin'
- 'neutron-openvswitch:neutron-plugin'
- - 'rabbitmq-server:amqp'
- 'neutron-openvswitch:amqp'

View File

@ -1,7 +1,7 @@
variables: variables:
openstack-origin: &openstack-origin distro openstack-origin: &openstack-origin distro
series: jammy series: lunar
comment: comment:
- 'machines section to decide order of deployment. database sooner = faster' - 'machines section to decide order of deployment. database sooner = faster'
@ -14,7 +14,7 @@ machines:
constraints: mem=3072M constraints: mem=3072M
'3': '3':
'4': '4':
# Note that holding memcached at focal as it's not available at jammy yet. # Note that holding memcached at focal as it's not available at lunar yet.
series: focal series: focal
'5': '5':
'6': '6':
@ -76,7 +76,7 @@ applications:
memcached: memcached:
charm: ch:memcached charm: ch:memcached
num_units: 1 num_units: 1
# Note that holding memcached at focal as it's not available at jammy yet. # Note that holding memcached at focal as it's not available at lunar yet.
series: focal series: focal
to: to:
- '4' - '4'

View File

@ -9,15 +9,15 @@ configure:
- zaza.openstack.charm_tests.nova.setup.manage_ssh_key - zaza.openstack.charm_tests.nova.setup.manage_ssh_key
gate_bundles: gate_bundles:
- jammy-yoga - jammy-zed
dev_bundles: dev_bundles:
- jammy-yoga - jammy-antelope
- jammy-zed
- kinetic-zed - kinetic-zed
- lunar-antelope
smoke_bundles: smoke_bundles:
- jammy-yoga - jammy-zed
tests: tests:
- zaza.openstack.charm_tests.ceilometer.tests.CeilometerTest - zaza.openstack.charm_tests.ceilometer.tests.CeilometerTest
@ -31,3 +31,4 @@ target_deploy_status:
tests_options: tests_options:
force_deploy: force_deploy:
- kinetic-zed - kinetic-zed
- lunar-antelope

View File

@ -25,7 +25,7 @@ setenv = VIRTUAL_ENV={envdir}
commands = stestr run --slowest {posargs} commands = stestr run --slowest {posargs}
allowlist_externals = allowlist_externals =
charmcraft charmcraft
rename.sh {toxinidir}/rename.sh
passenv = passenv =
HOME HOME
TERM TERM