Merge "Add Kinetic and Zed support"

This commit is contained in:
Zuul 2022-08-30 03:37:09 +00:00 committed by Gerrit Code Review
commit 7c65a33ea8
23 changed files with 271 additions and 128 deletions

View File

@ -1,4 +1,4 @@
- project: - project:
templates: templates:
- openstack-python3-charm-yoga-jobs - openstack-python3-charm-zed-jobs
- openstack-cover-jobs - openstack-cover-jobs

3
bindep.txt Normal file
View File

@ -0,0 +1,3 @@
libffi-dev [platform:dpkg]
libxml2-dev [platform:dpkg]
libxslt1-dev [platform:dpkg]

View File

@ -24,13 +24,10 @@ parts:
bases: bases:
- build-on: - build-on:
- name: ubuntu - name: ubuntu
channel: "20.04" channel: "22.04"
architectures: architectures:
- amd64 - amd64
run-on: run-on:
- name: ubuntu
channel: "20.04"
architectures: [amd64, s390x, ppc64el, arm64]
- name: ubuntu - name: ubuntu
channel: "22.04" channel: "22.04"
architectures: [amd64, s390x, ppc64el, arm64] architectures: [amd64, s390x, ppc64el, arm64]

View File

@ -467,7 +467,7 @@ def ns_query(address):
try: try:
answers = dns.resolver.query(address, rtype) answers = dns.resolver.query(address, rtype)
except dns.resolver.NXDOMAIN: except (dns.resolver.NXDOMAIN, dns.resolver.NoNameservers):
return None return None
if answers: if answers:

View File

@ -118,12 +118,7 @@ from charmhelpers.contrib.openstack.utils import (
) )
from charmhelpers.core.unitdata import kv from charmhelpers.core.unitdata import kv
try: from charmhelpers.contrib.hardware import pci
from sriov_netplan_shim import pci
except ImportError:
# The use of the function and contexts that require the pci module is
# optional.
pass
try: try:
import psutil import psutil
@ -426,6 +421,9 @@ class IdentityServiceContext(OSContextGenerator):
('password', ctxt.get('admin_password', '')), ('password', ctxt.get('admin_password', '')),
('signing_dir', ctxt.get('signing_dir', '')),)) ('signing_dir', ctxt.get('signing_dir', '')),))
if ctxt.get('service_type'):
c.update((('service_type', ctxt.get('service_type')),))
return c return c
def __call__(self): def __call__(self):
@ -468,6 +466,9 @@ class IdentityServiceContext(OSContextGenerator):
'internal_protocol': int_protocol, 'internal_protocol': int_protocol,
'api_version': api_version}) 'api_version': api_version})
if rdata.get('service_type'):
ctxt['service_type'] = rdata.get('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': rdata.get('service_domain'),
@ -539,6 +540,9 @@ class IdentityCredentialsContext(IdentityServiceContext):
'api_version': api_version 'api_version': api_version
}) })
if rdata.get('service_type'):
ctxt['service_type'] = rdata.get('service_type')
if float(api_version) > 2: if float(api_version) > 2:
ctxt.update({'admin_domain_name': ctxt.update({'admin_domain_name':
rdata.get('domain')}) rdata.get('domain')})
@ -2556,14 +2560,18 @@ class OVSDPDKDeviceContext(OSContextGenerator):
:rtype: List[int] :rtype: List[int]
""" """
cores = [] cores = []
ranges = cpulist.split(',') if cpulist and re.match(r"^[0-9,\-^]*$", cpulist):
for cpu_range in ranges: ranges = cpulist.split(',')
if "-" in cpu_range: for cpu_range in ranges:
cpu_min_max = cpu_range.split('-') if "-" in cpu_range:
cores += range(int(cpu_min_max[0]), cpu_min_max = cpu_range.split('-')
int(cpu_min_max[1]) + 1) cores += range(int(cpu_min_max[0]),
else: int(cpu_min_max[1]) + 1)
cores.append(int(cpu_range)) elif "^" in cpu_range:
cpu_rm = cpu_range.split('^')
cores.remove(int(cpu_rm[1]))
else:
cores.append(int(cpu_range))
return cores return cores
def _numa_node_cores(self): def _numa_node_cores(self):
@ -2582,36 +2590,32 @@ class OVSDPDKDeviceContext(OSContextGenerator):
def cpu_mask(self): def cpu_mask(self):
"""Get hex formatted CPU mask """Get hex formatted CPU mask
The mask is based on using the first config:dpdk-socket-cores The mask is based on using the first config:dpdk-socket-cores
cores of each NUMA node in the unit. cores of each NUMA node in the unit.
:returns: hex formatted CPU mask :returns: hex formatted CPU mask
:rtype: str :rtype: str
""" """
return self.cpu_masks()['dpdk_lcore_mask'] num_cores = config('dpdk-socket-cores')
mask = 0
def cpu_masks(self):
"""Get hex formatted CPU masks
The mask is based on using the first config:dpdk-socket-cores
cores of each NUMA node in the unit, followed by the
next config:pmd-socket-cores
:returns: Dict of hex formatted CPU masks
:rtype: Dict[str, str]
"""
num_lcores = config('dpdk-socket-cores')
pmd_cores = config('pmd-socket-cores')
lcore_mask = 0
pmd_mask = 0
for cores in self._numa_node_cores().values(): for cores in self._numa_node_cores().values():
for core in cores[:num_lcores]: for core in cores[:num_cores]:
lcore_mask = lcore_mask | 1 << core mask = mask | 1 << core
for core in cores[num_lcores:][:pmd_cores]: return format(mask, '#04x')
pmd_mask = pmd_mask | 1 << core
return { @classmethod
'pmd_cpu_mask': format(pmd_mask, '#04x'), def pmd_cpu_mask(cls):
'dpdk_lcore_mask': format(lcore_mask, '#04x')} """Get hex formatted pmd CPU mask
The mask is based on config:pmd-cpu-set.
:returns: hex formatted CPU mask
:rtype: str
"""
mask = 0
cpu_list = cls._parse_cpu_list(config('pmd-cpu-set'))
if cpu_list:
for core in cpu_list:
mask = mask | 1 << core
return format(mask, '#x')
def socket_memory(self): def socket_memory(self):
"""Formatted list of socket memory configuration per socket. """Formatted list of socket memory configuration per socket.
@ -2690,6 +2694,7 @@ class OVSDPDKDeviceContext(OSContextGenerator):
ctxt['device_whitelist'] = self.device_whitelist() ctxt['device_whitelist'] = self.device_whitelist()
ctxt['socket_memory'] = self.socket_memory() ctxt['socket_memory'] = self.socket_memory()
ctxt['cpu_mask'] = self.cpu_mask() ctxt['cpu_mask'] = self.cpu_mask()
ctxt['pmd_cpu_mask'] = self.pmd_cpu_mask()
return ctxt return ctxt
@ -3120,7 +3125,7 @@ class SRIOVContext(OSContextGenerator):
"""Determine number of Virtual Functions (VFs) configured for device. """Determine number of Virtual Functions (VFs) configured for device.
:param device: Object describing a PCI Network interface card (NIC)/ :param device: Object describing a PCI Network interface card (NIC)/
:type device: sriov_netplan_shim.pci.PCINetDevice :type device: contrib.hardware.pci.PCINetDevice
:param sriov_numvfs: Number of VFs requested for blanket configuration. :param sriov_numvfs: Number of VFs requested for blanket configuration.
:type sriov_numvfs: int :type sriov_numvfs: int
:returns: Number of VFs to configure for device :returns: Number of VFs to configure for device

View File

@ -9,4 +9,7 @@ project_name = {{ admin_tenant_name }}
username = {{ admin_user }} username = {{ admin_user }}
password = {{ admin_password }} password = {{ admin_password }}
signing_dir = {{ signing_dir }} signing_dir = {{ signing_dir }}
{% if service_type -%}
service_type = {{ service_type }}
{% endif -%}
{% endif -%} {% endif -%}

View File

@ -6,6 +6,9 @@ auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/v3
auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v3 auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v3
project_domain_name = {{ admin_domain_name }} project_domain_name = {{ admin_domain_name }}
user_domain_name = {{ admin_domain_name }} user_domain_name = {{ admin_domain_name }}
{% if service_type -%}
service_type = {{ service_type }}
{% endif -%}
{% else -%} {% else -%}
auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }} auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}
auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}

View File

@ -158,6 +158,7 @@ OPENSTACK_CODENAMES = OrderedDict([
('2021.1', 'wallaby'), ('2021.1', 'wallaby'),
('2021.2', 'xena'), ('2021.2', 'xena'),
('2022.1', 'yoga'), ('2022.1', 'yoga'),
('2022.2', 'zed'),
]) ])
# The ugly duckling - must list releases oldest to newest # The ugly duckling - must list releases oldest to newest
@ -400,13 +401,16 @@ def get_os_codename_version(vers):
error_out(e) error_out(e)
def get_os_version_codename(codename, version_map=OPENSTACK_CODENAMES): def get_os_version_codename(codename, version_map=OPENSTACK_CODENAMES,
raise_exception=False):
'''Determine OpenStack version number from codename.''' '''Determine OpenStack version number from codename.'''
for k, v in version_map.items(): for k, v in version_map.items():
if v == codename: if v == codename:
return k return k
e = 'Could not derive OpenStack version for '\ e = 'Could not derive OpenStack version for '\
'codename: %s' % codename 'codename: %s' % codename
if raise_exception:
raise ValueError(str(e))
error_out(e) error_out(e)

View File

@ -614,7 +614,8 @@ class Pool(BasePool):
class ReplicatedPool(BasePool): class ReplicatedPool(BasePool):
def __init__(self, service, name=None, pg_num=None, replicas=None, def __init__(self, service, name=None, pg_num=None, replicas=None,
percent_data=None, app_name=None, op=None): percent_data=None, app_name=None, op=None,
profile_name='replicated_rule'):
"""Initialize ReplicatedPool object. """Initialize ReplicatedPool object.
Pool information is either initialized from individual keyword Pool information is either initialized from individual keyword
@ -631,6 +632,8 @@ class ReplicatedPool(BasePool):
to this replicated pool. to this replicated pool.
:type replicas: int :type replicas: int
:raises: KeyError :raises: KeyError
:param profile_name: Crush Profile to use
:type profile_name: Optional[str]
""" """
# NOTE: Do not perform initialization steps that require live data from # NOTE: Do not perform initialization steps that require live data from
# a running cluster here. The *Pool classes may be used for validation. # a running cluster here. The *Pool classes may be used for validation.
@ -645,11 +648,20 @@ class ReplicatedPool(BasePool):
# we will fail with KeyError if it is not provided. # we will fail with KeyError if it is not provided.
self.replicas = op['replicas'] self.replicas = op['replicas']
self.pg_num = op.get('pg_num') self.pg_num = op.get('pg_num')
self.profile_name = op.get('crush-profile') or profile_name
else: else:
self.replicas = replicas or 2 self.replicas = replicas or 2
self.pg_num = pg_num self.pg_num = pg_num
self.profile_name = profile_name or 'replicated_rule'
def _create(self): def _create(self):
# Validate if crush profile exists
if self.profile_name is None:
msg = ("Failed to discover crush profile named "
"{}".format(self.profile_name))
log(msg, level=ERROR)
raise PoolCreationError(msg)
# Do extra validation on pg_num with data from live cluster # Do extra validation on pg_num with data from live cluster
if self.pg_num: if self.pg_num:
# Since the number of placement groups were specified, ensure # Since the number of placement groups were specified, ensure
@ -667,12 +679,12 @@ class ReplicatedPool(BasePool):
'--pg-num-min={}'.format( '--pg-num-min={}'.format(
min(AUTOSCALER_DEFAULT_PGS, self.pg_num) min(AUTOSCALER_DEFAULT_PGS, self.pg_num)
), ),
self.name, str(self.pg_num) self.name, str(self.pg_num), self.profile_name
] ]
else: else:
cmd = [ cmd = [
'ceph', '--id', self.service, 'osd', 'pool', 'create', 'ceph', '--id', self.service, 'osd', 'pool', 'create',
self.name, str(self.pg_num) self.name, str(self.pg_num), self.profile_name
] ]
check_call(cmd) check_call(cmd)
@ -691,7 +703,7 @@ class ErasurePool(BasePool):
def __init__(self, service, name=None, erasure_code_profile=None, def __init__(self, service, name=None, erasure_code_profile=None,
percent_data=None, app_name=None, op=None, percent_data=None, app_name=None, op=None,
allow_ec_overwrites=False): allow_ec_overwrites=False):
"""Initialize ReplicatedPool object. """Initialize ErasurePool object.
Pool information is either initialized from individual keyword Pool information is either initialized from individual keyword
arguments or from a individual CephBrokerRq operation Dict. arguments or from a individual CephBrokerRq operation Dict.
@ -777,6 +789,9 @@ def enabled_manager_modules():
:rtype: List[str] :rtype: List[str]
""" """
cmd = ['ceph', 'mgr', 'module', 'ls'] cmd = ['ceph', 'mgr', 'module', 'ls']
quincy_or_later = cmp_pkgrevno('ceph-common', '17.1.0') >= 0
if quincy_or_later:
cmd.append('--format=json')
try: try:
modules = check_output(cmd).decode('utf-8') modules = check_output(cmd).decode('utf-8')
except CalledProcessError as e: except CalledProcessError as e:
@ -1842,7 +1857,7 @@ class CephBrokerRq(object):
} }
def add_op_create_replicated_pool(self, name, replica_count=3, pg_num=None, def add_op_create_replicated_pool(self, name, replica_count=3, pg_num=None,
**kwargs): crush_profile=None, **kwargs):
"""Adds an operation to create a replicated pool. """Adds an operation to create a replicated pool.
Refer to docstring for ``_partial_build_common_op_create`` for Refer to docstring for ``_partial_build_common_op_create`` for
@ -1856,6 +1871,10 @@ class CephBrokerRq(object):
for pool. for pool.
:type pg_num: int :type pg_num: int
:raises: AssertionError if provided data is of invalid type/range :raises: AssertionError if provided data is of invalid type/range
:param crush_profile: Name of crush profile to use. If not set the
ceph-mon unit handling the broker request will
set its default value.
:type crush_profile: Optional[str]
""" """
if pg_num and kwargs.get('weight'): if pg_num and kwargs.get('weight'):
raise ValueError('pg_num and weight are mutually exclusive') raise ValueError('pg_num and weight are mutually exclusive')
@ -1865,6 +1884,7 @@ class CephBrokerRq(object):
'name': name, 'name': name,
'replicas': replica_count, 'replicas': replica_count,
'pg_num': pg_num, 'pg_num': pg_num,
'crush-profile': crush_profile
} }
op.update(self._partial_build_common_op_create(**kwargs)) op.update(self._partial_build_common_op_create(**kwargs))

View File

@ -114,6 +114,33 @@ def service_stop(service_name, **kwargs):
return service('stop', service_name, **kwargs) return service('stop', service_name, **kwargs)
def service_enable(service_name, **kwargs):
"""Enable a system service.
The specified service name is managed via the system level init system.
Some init systems (e.g. upstart) require that additional arguments be
provided in order to directly control service instances whereas other init
systems allow for addressing instances of a service directly by name (e.g.
systemd).
The kwargs allow for the additional parameters to be passed to underlying
init systems for those systems which require/allow for them. For example,
the ceph-osd upstart script requires the id parameter to be passed along
in order to identify which running daemon should be restarted. The follow-
ing example restarts the ceph-osd service for instance id=4:
service_enable('ceph-osd', id=4)
:param service_name: the name of the service to enable
:param **kwargs: additional parameters to pass to the init system when
managing services. These will be passed as key=value
parameters to the init system's commandline. kwargs
are ignored for init systems not allowing additional
parameters via the commandline (systemd).
"""
return service('enable', service_name, **kwargs)
def service_restart(service_name, **kwargs): def service_restart(service_name, **kwargs):
"""Restart a system service. """Restart a system service.
@ -134,7 +161,7 @@ def service_restart(service_name, **kwargs):
:param service_name: the name of the service to restart :param service_name: the name of the service to restart
:param **kwargs: additional parameters to pass to the init system when :param **kwargs: additional parameters to pass to the init system when
managing services. These will be passed as key=value managing services. These will be passed as key=value
parameters to the init system's commandline. kwargs parameters to the init system's commandline. kwargs
are ignored for init systems not allowing additional are ignored for init systems not allowing additional
parameters via the commandline (systemd). parameters via the commandline (systemd).
""" """
@ -250,7 +277,7 @@ def service_resume(service_name, init_dir="/etc/init",
return started return started
def service(action, service_name, **kwargs): def service(action, service_name=None, **kwargs):
"""Control a system service. """Control a system service.
:param action: the action to take on the service :param action: the action to take on the service
@ -259,7 +286,9 @@ def service(action, service_name, **kwargs):
the form of key=value. the form of key=value.
""" """
if init_is_systemd(service_name=service_name): if init_is_systemd(service_name=service_name):
cmd = ['systemctl', action, service_name] cmd = ['systemctl', action]
if service_name is not None:
cmd.append(service_name)
else: else:
cmd = ['service', service_name, action] cmd = ['service', service_name, action]
for key, value in kwargs.items(): for key, value in kwargs.items():

View File

@ -30,6 +30,7 @@ UBUNTU_RELEASES = (
'hirsute', 'hirsute',
'impish', 'impish',
'jammy', 'jammy',
'kinetic',
) )

View File

@ -15,7 +15,8 @@
import os import os
import json import json
import inspect import inspect
from collections import Iterable, OrderedDict from collections import OrderedDict
from collections.abc import Iterable
from charmhelpers.core import host from charmhelpers.core import host
from charmhelpers.core import hookenv from charmhelpers.core import hookenv

View File

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import contextlib
import os import os
import hashlib import hashlib
import re import re
@ -24,11 +25,15 @@ from charmhelpers.payload.archive import (
get_archive_handler, get_archive_handler,
extract, extract,
) )
from charmhelpers.core.hookenv import (
env_proxy_settings,
)
from charmhelpers.core.host import mkdir, check_hash from charmhelpers.core.host import mkdir, check_hash
from urllib.request import ( from urllib.request import (
build_opener, install_opener, urlopen, urlretrieve, build_opener, install_opener, urlopen, urlretrieve,
HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler,
ProxyHandler
) )
from urllib.parse import urlparse, urlunparse, parse_qs from urllib.parse import urlparse, urlunparse, parse_qs
from urllib.error import URLError from urllib.error import URLError
@ -50,6 +55,20 @@ def splitpasswd(user):
return user, None return user, None
@contextlib.contextmanager
def proxy_env():
"""
Creates a context which temporarily modifies the proxy settings in os.environ.
"""
restore = {**os.environ} # Copy the current os.environ
juju_proxies = env_proxy_settings() or {}
os.environ.update(**juju_proxies) # Insert or Update the os.environ
yield os.environ
for key in juju_proxies:
del os.environ[key] # remove any keys which were added or updated
os.environ.update(**restore) # restore any original values
class ArchiveUrlFetchHandler(BaseFetchHandler): class ArchiveUrlFetchHandler(BaseFetchHandler):
""" """
Handler to download archive files from arbitrary URLs. Handler to download archive files from arbitrary URLs.
@ -80,6 +99,7 @@ class ArchiveUrlFetchHandler(BaseFetchHandler):
# propagate all exceptions # propagate all exceptions
# URLError, OSError, etc # URLError, OSError, etc
proto, netloc, path, params, query, fragment = urlparse(source) proto, netloc, path, params, query, fragment = urlparse(source)
handlers = []
if proto in ('http', 'https'): if proto in ('http', 'https'):
auth, barehost = splituser(netloc) auth, barehost = splituser(netloc)
if auth is not None: if auth is not None:
@ -89,10 +109,13 @@ class ArchiveUrlFetchHandler(BaseFetchHandler):
# Realm is set to None in add_password to force the username and password # Realm is set to None in add_password to force the username and password
# to be used whatever the realm # to be used whatever the realm
passman.add_password(None, source, username, password) passman.add_password(None, source, username, password)
authhandler = HTTPBasicAuthHandler(passman) handlers.append(HTTPBasicAuthHandler(passman))
opener = build_opener(authhandler)
install_opener(opener) with proxy_env():
response = urlopen(source) handlers.append(ProxyHandler())
opener = build_opener(*handlers)
install_opener(opener)
response = urlopen(source)
try: try:
with open(dest, 'wb') as dest_file: with open(dest, 'wb') as dest_file:
dest_file.write(response.read()) dest_file.write(response.read())

View File

@ -222,6 +222,14 @@ CLOUD_ARCHIVE_POCKETS = {
'yoga/proposed': 'focal-proposed/yoga', 'yoga/proposed': 'focal-proposed/yoga',
'focal-yoga/proposed': 'focal-proposed/yoga', 'focal-yoga/proposed': 'focal-proposed/yoga',
'focal-proposed/yoga': 'focal-proposed/yoga', 'focal-proposed/yoga': 'focal-proposed/yoga',
# Zed
'zed': 'jammy-updates/zed',
'jammy-zed': 'jammy-updates/zed',
'jammy-zed/updates': 'jammy-updates/zed',
'jammy-updates/zed': 'jammy-updates/zed',
'zed/proposed': 'jammy-proposed/zed',
'jammy-zed/proposed': 'jammy-proposed/zed',
'jammy-proposed/zed': 'jammy-proposed/zed',
} }
@ -248,6 +256,7 @@ OPENSTACK_RELEASES = (
'wallaby', 'wallaby',
'xena', 'xena',
'yoga', 'yoga',
'zed',
) )
@ -274,6 +283,7 @@ UBUNTU_OPENSTACK_RELEASE = OrderedDict([
('hirsute', 'wallaby'), ('hirsute', 'wallaby'),
('impish', 'xena'), ('impish', 'xena'),
('jammy', 'yoga'), ('jammy', 'yoga'),
('kinetic', 'zed'),
]) ])

View File

@ -10,7 +10,6 @@ tags:
- amqp - amqp
- misc - misc
series: series:
- focal
- jammy - jammy
provides: provides:
amqp: amqp:

View File

@ -1,9 +1,9 @@
- project: - project:
templates: templates:
- charm-unit-jobs-py38
- charm-unit-jobs-py310 - charm-unit-jobs-py310
- charm-yoga-functional-jobs - charm-zed-functional-jobs
vars: vars:
needs_charm_build: true needs_charm_build: true
charm_build_name: rabbitmq-server charm_build_name: rabbitmq-server
build_type: charmcraft build_type: charmcraft
charmcraft_channel: 2.0/stable

View File

@ -11,14 +11,19 @@ pbr==5.6.0
simplejson>=2.2.0 simplejson>=2.2.0
netifaces>=0.10.4 netifaces>=0.10.4
# NOTE: newer versions of cryptography require a Rust compiler to build,
# see
# * https://github.com/openstack-charmers/zaza/issues/421
# * https://mail.python.org/pipermail/cryptography-dev/2021-January/001003.html
#
cryptography<3.4
# Strange import error with newer netaddr: # Strange import error with newer netaddr:
netaddr>0.7.16,<0.8.0 netaddr>0.7.16,<0.8.0
Jinja2>=2.6 # BSD License (3 clause) Jinja2>=2.6 # BSD License (3 clause)
six>=1.9.0 six>=1.9.0
# dnspython 2.0.0 dropped py3.5 support dnspython
dnspython<2.0.0; python_version < '3.6'
dnspython; python_version >= '3.6'
psutil>=1.1.1,<2.0.0 psutil>=1.1.1,<2.0.0

View File

@ -8,7 +8,6 @@
# all of its own requirements and if it doesn't, fix it there. # all of its own requirements and if it doesn't, fix it there.
# #
pyparsing<3.0.0 # aodhclient is pinned in zaza and needs pyparsing < 3.0.0, but cffi also needs it, so pin here. pyparsing<3.0.0 # aodhclient is pinned in zaza and needs pyparsing < 3.0.0, but cffi also needs it, so pin here.
cffi==1.14.6; python_version < '3.6' # cffi 1.15.0 drops support for py35.
setuptools<50.0.0 # https://github.com/pypa/setuptools/commit/04e3df22df840c6bb244e9b27bc56750c44b7c85 setuptools<50.0.0 # https://github.com/pypa/setuptools/commit/04e3df22df840c6bb244e9b27bc56750c44b7c85
requests>=2.18.4 requests>=2.18.4
@ -19,25 +18,12 @@ stestr>=2.2.0
# https://github.com/mtreinish/stestr/issues/145 # https://github.com/mtreinish/stestr/issues/145
cliff<3.0.0 cliff<3.0.0
# Dependencies of stestr. Newer versions use keywords that didn't exist in
# python 3.5 yet (e.g. "ModuleNotFoundError")
importlib-metadata<3.0.0; python_version < '3.6'
importlib-resources<3.0.0; python_version < '3.6'
# Some Zuul nodes sometimes pull newer versions of these dependencies which
# dropped support for python 3.5:
osprofiler<2.7.0;python_version<'3.6'
stevedore<1.31.0;python_version<'3.6'
debtcollector<1.22.0;python_version<'3.6'
oslo.utils<=3.41.0;python_version<'3.6'
coverage>=4.5.2 coverage>=4.5.2
pyudev # for ceph-* charm unit tests (need to fix the ceph-* charm unit tests/mocking) pyudev # for ceph-* charm unit tests (need to fix the ceph-* charm unit tests/mocking)
git+https://github.com/openstack-charmers/zaza.git#egg=zaza git+https://github.com/openstack-charmers/zaza.git#egg=zaza
git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.openstack git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.openstack
# Needed for charm-glance: # Needed for charm-glance:
git+https://opendev.org/openstack/tempest.git#egg=tempest;python_version>='3.6' git+https://opendev.org/openstack/tempest.git#egg=tempest
tempest<24.0.0;python_version<'3.6'
croniter # needed for charm-rabbitmq-server unit tests croniter # needed for charm-rabbitmq-server unit tests

View File

@ -17,8 +17,6 @@ machines:
'5': '5':
'6': '6':
'7': '7':
'8':
series: bionic # nagios not supported on focal+ yet
applications: applications:

View File

@ -1,7 +1,7 @@
variables: variables:
openstack-origin: &openstack-origin cloud:focal-yoga openstack-origin: &openstack-origin cloud:jammy-zed
series: focal series: jammy
comment: comment:
- 'machines section to decide order of deployment. database sooner = faster' - 'machines section to decide order of deployment. database sooner = faster'
@ -17,8 +17,6 @@ machines:
'5': '5':
'6': '6':
'7': '7':
'8':
series: bionic # nagios not supported on focal yet
applications: applications:
@ -77,16 +75,6 @@ applications:
- '7' - '7'
channel: latest/edge channel: latest/edge
nagios:
charm: cs:nagios
series: bionic # not supported on focal yet
num_units: 1
to:
- '8'
nrpe:
charm: cs:nrpe
relations: relations:
- - 'cinder:amqp' - - 'cinder:amqp'
@ -101,7 +89,3 @@ relations:
- 'keystone-mysql-router:shared-db' - 'keystone-mysql-router:shared-db'
- - 'keystone-mysql-router:db-router' - - 'keystone-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router' - 'mysql-innodb-cluster:db-router'
- - 'nrpe:nrpe-external-master'
- 'rabbitmq-server:nrpe-external-master'
- - 'nrpe:monitors'
- 'nagios:monitors'

View File

@ -0,0 +1,91 @@
variables:
openstack-origin: &openstack-origin distro
series: kinetic
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':
'5':
'6':
'7':
applications:
keystone-mysql-router:
charm: ch:mysql-router
channel: latest/edge
cinder-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: ../../rabbitmq-server.charm
num_units: 3
constraints:
cpu-cores=2
options:
min-cluster-size: 3
max-cluster-tries: 6
ssl: "off"
management_plugin: "False"
stats_cron_schedule: "*/1 * * * *"
source: *openstack-origin
to:
- '3'
- '4'
- '5'
cinder:
charm: ch:cinder
num_units: 1
options:
openstack-origin: *openstack-origin
to:
- '6'
channel: latest/edge
keystone:
charm: ch:keystone
num_units: 1
options:
openstack-origin: *openstack-origin
admin-password: openstack
to:
- '7'
channel: latest/edge
relations:
- - 'cinder:amqp'
- 'rabbitmq-server:amqp'
- - 'cinder:shared-db'
- 'cinder-mysql-router:shared-db'
- - 'cinder-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'
- - 'cinder:identity-service'
- 'keystone:identity-service'
- - 'keystone:shared-db'
- 'keystone-mysql-router:shared-db'
- - 'keystone-mysql-router:db-router'
- 'mysql-innodb-cluster:db-router'

View File

@ -1,13 +1,15 @@
charm_name: rabbitmq-server charm_name: rabbitmq-server
smoke_bundles: smoke_bundles:
- focal-yoga - jammy-yoga
gate_bundles: gate_bundles:
- focal-yoga - jammy-yoga
dev_bundles: dev_bundles:
- jammy-yoga - jammy-yoga
- jammy-zed
- kinetic-zed
tests: tests:
- zaza.openstack.charm_tests.rabbitmq_server.tests.RabbitMQDeferredRestartTest - zaza.openstack.charm_tests.rabbitmq_server.tests.RabbitMQDeferredRestartTest
@ -15,5 +17,4 @@ tests:
tests_options: tests_options:
force_deploy: force_deploy:
# nrpe charm doesn't support hirsute->jammy and needs to be force installed - kinetic-zed
- jammy-yoga

28
tox.ini
View File

@ -48,26 +48,11 @@ basepython = python3
deps = -r{toxinidir}/build-requirements.txt deps = -r{toxinidir}/build-requirements.txt
commands = commands =
charmcraft clean charmcraft clean
charmcraft -v build charmcraft -v pack
{toxinidir}/rename.sh {toxinidir}/rename.sh
[testenv:py36] [testenv:py310]
basepython = python3.6 basepython = python3.10
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
[testenv:py37]
basepython = python3.7
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
[testenv:py38]
basepython = python3.8
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
[testenv:py39]
basepython = python3.9
deps = -r{toxinidir}/requirements.txt deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
@ -76,15 +61,10 @@ basepython = python3
deps = -r{toxinidir}/requirements.txt deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
[testenv:py310]
basepython = python3.10
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
[testenv:pep8] [testenv:pep8]
basepython = python3 basepython = python3
deps = flake8==3.9.2 deps = flake8==3.9.2
charm-tools==2.8.3 git+https://github.com/juju/charm-tools.git
commands = flake8 {posargs} hooks unit_tests tests actions lib files commands = flake8 {posargs} hooks unit_tests tests actions lib files
charm-proof charm-proof