From 1f66d4ae6a25b317af4e702eb77768e2438c7021 Mon Sep 17 00:00:00 2001 From: Utkarsh Bhatt Date: Thu, 2 May 2024 16:15:29 +0530 Subject: [PATCH] Caracal-Squid enablement contains: - Bundle updates - charmhelpers sync - drop lunar/mantic Change-Id: I6ca31ca3b0cc8aedabaeaf2a2e64dede1248e388 Signed-off-by: Utkarsh Bhatt --- charmcraft.yaml | 6 - hooks/charmhelpers/contrib/network/ip.py | 48 +++++- .../charmhelpers/contrib/openstack/context.py | 18 ++- .../section-audit-middleware-notifications | 4 + .../openstack/templates/section-filter-audit | 6 + hooks/charmhelpers/contrib/openstack/utils.py | 49 +++---- .../charmhelpers/contrib/storage/linux/lvm.py | 6 +- hooks/charmhelpers/core/host.py | 7 +- hooks/charmhelpers/fetch/ubuntu.py | 10 ++ hooks/charmhelpers/osplatform.py | 28 +++- lib/charms_ceph/broker.py | 70 +++++++++ lib/charms_ceph/utils.py | 138 +++++------------- metadata.yaml | 2 - tests/bundles/focal-yoga-multisite.yaml | 8 +- tests/bundles/focal-yoga-namespaced.yaml | 6 +- tests/bundles/focal-yoga.yaml | 6 +- tests/bundles/jammy-antelope-multisite.yaml | 8 +- tests/bundles/jammy-antelope-namespaced.yaml | 9 +- tests/bundles/jammy-antelope.yaml | 8 +- tests/bundles/jammy-bobcat-multisite.yaml | 8 +- tests/bundles/jammy-bobcat-namespaced.yaml | 9 +- tests/bundles/jammy-bobcat.yaml | 9 +- tests/bundles/jammy-caracal-multisite.yaml | 99 +++++++++++++ tests/bundles/jammy-caracal-namespaced.yaml | 125 ++++++++++++++++ ...{mantic-bobcat.yaml => jammy-caracal.yaml} | 15 +- tests/bundles/local-jammy-antelope.yaml | 6 +- tests/tests.yaml | 9 +- 27 files changed, 513 insertions(+), 204 deletions(-) create mode 100644 hooks/charmhelpers/contrib/openstack/templates/section-audit-middleware-notifications create mode 100644 hooks/charmhelpers/contrib/openstack/templates/section-filter-audit create mode 100644 tests/bundles/jammy-caracal-multisite.yaml create mode 100644 tests/bundles/jammy-caracal-namespaced.yaml rename tests/bundles/{mantic-bobcat.yaml => jammy-caracal.yaml} (91%) diff --git a/charmcraft.yaml b/charmcraft.yaml index d5329498..e54ca1af 100644 --- a/charmcraft.yaml +++ b/charmcraft.yaml @@ -33,9 +33,3 @@ bases: - name: ubuntu channel: "22.04" architectures: [amd64, s390x, ppc64el, arm64] - - name: ubuntu - channel: "23.04" - architectures: [amd64, s390x, ppc64el, arm64] - - name: ubuntu - channel: "23.10" - architectures: [amd64, s390x, ppc64el, arm64] diff --git a/hooks/charmhelpers/contrib/network/ip.py b/hooks/charmhelpers/contrib/network/ip.py index cf9926b9..f3b4864f 100644 --- a/hooks/charmhelpers/contrib/network/ip.py +++ b/hooks/charmhelpers/contrib/network/ip.py @@ -16,6 +16,7 @@ import glob import re import subprocess import socket +import ssl from functools import partial @@ -527,19 +528,56 @@ def get_hostname(address, fqdn=True): return result.split('.')[0] -def port_has_listener(address, port): +class SSLPortCheckInfo(object): + + def __init__(self, key, cert, ca_cert, check_hostname=False): + self.key = key + self.cert = cert + self.ca_cert = ca_cert + # NOTE: by default we do not check hostname since the port check is + # typically performed using 0.0.0.0 which will not match the + # certificate. Hence the default for this is False. + self.check_hostname = check_hostname + + @property + def ssl_context(self): + context = ssl.create_default_context() + context.check_hostname = self.check_hostname + context.load_cert_chain(self.cert, self.key) + context.load_verify_locations(self.ca_cert) + return context + + +def port_has_listener(address, port, sslinfo=None): """ Returns True if the address:port is open and being listened to, - else False. + else False. By default uses netcat to check ports but if sslinfo is + provided will use an SSL connection instead. @param address: an IP address or hostname @param port: integer port + @param sslinfo: optional SSLPortCheckInfo object. + If provided, the check is performed using an ssl + connection. Note calls 'zc' via a subprocess shell """ - cmd = ['nc', '-z', address, str(port)] - result = subprocess.call(cmd) - return not (bool(result)) + if not sslinfo: + cmd = ['nc', '-z', address, str(port)] + result = subprocess.call(cmd) + return not (bool(result)) + + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock: + ssock = sslinfo.ssl_context.wrap_socket(sock, + server_hostname=address) + ssock.connect((address, port)) + # this bit is crucial to ensure tls close_notify is sent + ssock.unwrap() + + return True + except ConnectionRefusedError: + return False def assert_charm_supports_ipv6(): diff --git a/hooks/charmhelpers/contrib/openstack/context.py b/hooks/charmhelpers/contrib/openstack/context.py index 42f15032..cd70b55c 100644 --- a/hooks/charmhelpers/contrib/openstack/context.py +++ b/hooks/charmhelpers/contrib/openstack/context.py @@ -202,6 +202,21 @@ class OSContextGenerator(object): return self.related +class KeystoneAuditMiddleware(OSContextGenerator): + def __init__(self, service: str) -> None: + self.service_name = service + + def __call__(self): + """Return context dictionary containing configuration status of + audit-middleware and the charm service name. + """ + ctxt = { + 'audit_middleware': config('audit-middleware') or False, + 'service_name': self.service_name + } + return ctxt + + class SharedDBContext(OSContextGenerator): interfaces = ['shared-db'] @@ -545,7 +560,7 @@ class IdentityServiceContext(OSContextGenerator): 'internal_auth_url': internal_auth_url, }) - # we keep all veriables in ctxt for compatibility and + # we keep all variables in ctxt for compatibility and # add nested dictionary for keystone_authtoken generic # templating if keystonemiddleware_os_release: @@ -557,6 +572,7 @@ class IdentityServiceContext(OSContextGenerator): # NOTE(jamespage) this is required for >= icehouse # so a missing value just indicates keystone needs # upgrading + ctxt['admin_user_id'] = _resolve('service_user_id') ctxt['admin_tenant_id'] = _resolve('service_tenant_id') ctxt['admin_domain_id'] = _resolve('service_domain_id') return ctxt diff --git a/hooks/charmhelpers/contrib/openstack/templates/section-audit-middleware-notifications b/hooks/charmhelpers/contrib/openstack/templates/section-audit-middleware-notifications new file mode 100644 index 00000000..1f88014f --- /dev/null +++ b/hooks/charmhelpers/contrib/openstack/templates/section-audit-middleware-notifications @@ -0,0 +1,4 @@ +{% if audit_middleware -%} +[audit_middleware_notifications] +driver = log +{% endif -%} \ No newline at end of file diff --git a/hooks/charmhelpers/contrib/openstack/templates/section-filter-audit b/hooks/charmhelpers/contrib/openstack/templates/section-filter-audit new file mode 100644 index 00000000..11512aee --- /dev/null +++ b/hooks/charmhelpers/contrib/openstack/templates/section-filter-audit @@ -0,0 +1,6 @@ +{% if audit_middleware and service_name -%} +[filter:audit] +paste.filter_factory = keystonemiddleware.audit:filter_factory +audit_map_file = /etc/{{ service_name }}/api_audit_map.conf +service_name = {{ service_name }} +{% endif -%} \ No newline at end of file diff --git a/hooks/charmhelpers/contrib/openstack/utils.py b/hooks/charmhelpers/contrib/openstack/utils.py index e98be2c5..82c28d8e 100644 --- a/hooks/charmhelpers/contrib/openstack/utils.py +++ b/hooks/charmhelpers/contrib/openstack/utils.py @@ -161,6 +161,7 @@ OPENSTACK_CODENAMES = OrderedDict([ ('2022.2', 'zed'), ('2023.1', 'antelope'), ('2023.2', 'bobcat'), + ('2024.1', 'caracal'), ]) # The ugly duckling - must list releases oldest to newest @@ -416,17 +417,6 @@ def get_os_version_codename(codename, version_map=OPENSTACK_CODENAMES, error_out(e) -def get_os_version_codename_swift(codename): - '''Determine OpenStack version number of swift from codename.''' - # for k, v in six.iteritems(SWIFT_CODENAMES): - for k, v in SWIFT_CODENAMES.items(): - if k == codename: - return v[-1] - e = 'Could not derive swift version for '\ - 'codename: %s' % codename - error_out(e) - - def get_swift_codename(version): '''Determine OpenStack codename that corresponds to swift version.''' codenames = [k for k, v in SWIFT_CODENAMES.items() if version in v] @@ -585,7 +575,6 @@ def get_installed_os_version(): return openstack_release().get('OPENSTACK_CODENAME') -@cached def openstack_release(): """Return /etc/os-release in a dict.""" d = {} @@ -847,14 +836,10 @@ def openstack_upgrade_available(package): if not cur_vers: # The package has not been installed yet do not attempt upgrade return False - if "swift" in package: - codename = get_os_codename_install_source(src) - avail_vers = get_os_version_codename_swift(codename) - else: - try: - avail_vers = get_os_version_install_source(src) - except Exception: - avail_vers = cur_vers + try: + avail_vers = get_os_version_install_source(src) + except Exception: + avail_vers = cur_vers apt.init() return apt.version_compare(avail_vers, cur_vers) >= 1 @@ -1222,12 +1207,14 @@ def _ows_check_services_running(services, ports): return ows_check_services_running(services, ports) -def ows_check_services_running(services, ports): +def ows_check_services_running(services, ports, ssl_check_info=None): """Check that the services that should be running are actually running and that any ports specified are being listened to. @param services: list of strings OR dictionary specifying services/ports @param ports: list of ports + @param ssl_check_info: SSLPortCheckInfo object. If provided, port checks + will be done using an SSL connection. @returns state, message: strings or None, None """ messages = [] @@ -1243,7 +1230,7 @@ def ows_check_services_running(services, ports): # also verify that the ports that should be open are open # NB, that ServiceManager objects only OPTIONALLY have ports map_not_open, ports_open = ( - _check_listening_on_services_ports(services)) + _check_listening_on_services_ports(services, ssl_check_info)) if not all(ports_open): # find which service has missing ports. They are in service # order which makes it a bit easier. @@ -1258,7 +1245,8 @@ def ows_check_services_running(services, ports): if ports is not None: # and we can also check ports which we don't know the service for - ports_open, ports_open_bools = _check_listening_on_ports_list(ports) + ports_open, ports_open_bools = \ + _check_listening_on_ports_list(ports, ssl_check_info) if not all(ports_open_bools): messages.append( "Ports which should be open, but are not: {}" @@ -1317,7 +1305,8 @@ def _check_running_services(services): return list(zip(services, services_running)), services_running -def _check_listening_on_services_ports(services, test=False): +def _check_listening_on_services_ports(services, test=False, + ssl_check_info=None): """Check that the unit is actually listening (has the port open) on the ports that the service specifies are open. If test is True then the function returns the services with ports that are open rather than @@ -1327,11 +1316,14 @@ def _check_listening_on_services_ports(services, test=False): @param services: OrderedDict(service: [port, ...], ...) @param test: default=False, if False, test for closed, otherwise open. + @param ssl_check_info: SSLPortCheckInfo object. If provided, port checks + will be done using an SSL connection. @returns OrderedDict(service: [port-not-open, ...]...), [boolean] """ test = not (not (test)) # ensure test is True or False 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, ssl_check_info) + for p in all_ports] map_ports = OrderedDict() matched_ports = [p for p, opened in zip(all_ports, ports_states) if opened == test] # essentially opened xor test @@ -1342,16 +1334,19 @@ def _check_listening_on_services_ports(services, test=False): return map_ports, ports_states -def _check_listening_on_ports_list(ports): +def _check_listening_on_ports_list(ports, ssl_check_info=None): """Check that the ports list given are being listened to Returns a list of ports being listened to and a list of the booleans. + @param ssl_check_info: SSLPortCheckInfo object. If provided, port checks + will be done using an SSL connection. @param ports: LIST of port numbers. @returns [(port_num, boolean), ...], [boolean] """ - ports_open = [port_has_listener('0.0.0.0', p) for p in ports] + ports_open = [port_has_listener('0.0.0.0', p, ssl_check_info) + for p in ports] return zip(ports, ports_open), ports_open diff --git a/hooks/charmhelpers/contrib/storage/linux/lvm.py b/hooks/charmhelpers/contrib/storage/linux/lvm.py index d0a57211..0d294c79 100644 --- a/hooks/charmhelpers/contrib/storage/linux/lvm.py +++ b/hooks/charmhelpers/contrib/storage/linux/lvm.py @@ -17,8 +17,6 @@ from subprocess import ( CalledProcessError, check_call, check_output, - Popen, - PIPE, ) @@ -58,9 +56,7 @@ def remove_lvm_physical_volume(block_device): :param block_device: str: Full path of block device to scrub. ''' - p = Popen(['pvremove', '-ff', block_device], - stdin=PIPE) - p.communicate(input='y\n') + check_call(['pvremove', '-ff', '--yes', block_device]) def list_lvm_volume_group(block_device): diff --git a/hooks/charmhelpers/core/host.py b/hooks/charmhelpers/core/host.py index 70dde6a5..def403c5 100644 --- a/hooks/charmhelpers/core/host.py +++ b/hooks/charmhelpers/core/host.py @@ -256,8 +256,11 @@ def service_resume(service_name, init_dir="/etc/init", upstart_file = os.path.join(init_dir, "{}.conf".format(service_name)) sysv_file = os.path.join(initd_dir, service_name) if init_is_systemd(service_name=service_name): - service('unmask', service_name) - service('enable', service_name) + if service('is-enabled', service_name): + log('service {} already enabled'.format(service_name), level=DEBUG) + else: + service('unmask', service_name) + service('enable', service_name) elif os.path.exists(upstart_file): override_path = os.path.join( init_dir, '{}.override'.format(service_name)) diff --git a/hooks/charmhelpers/fetch/ubuntu.py b/hooks/charmhelpers/fetch/ubuntu.py index 1be992c4..d0089eb7 100644 --- a/hooks/charmhelpers/fetch/ubuntu.py +++ b/hooks/charmhelpers/fetch/ubuntu.py @@ -246,6 +246,14 @@ CLOUD_ARCHIVE_POCKETS = { 'bobcat/proposed': 'jammy-proposed/bobcat', 'jammy-bobcat/proposed': 'jammy-proposed/bobcat', 'jammy-proposed/bobcat': 'jammy-proposed/bobcat', + # caracal + 'caracal': 'jammy-updates/caracal', + 'jammy-caracal': 'jammy-updates/caracal', + 'jammy-caracal/updates': 'jammy-updates/caracal', + 'jammy-updates/caracal': 'jammy-updates/caracal', + 'caracal/proposed': 'jammy-proposed/caracal', + 'jammy-caracal/proposed': 'jammy-proposed/caracal', + 'jammy-proposed/caracal': 'jammy-proposed/caracal', # OVN 'focal-ovn-22.03': 'focal-updates/ovn-22.03', @@ -279,6 +287,7 @@ OPENSTACK_RELEASES = ( 'zed', 'antelope', 'bobcat', + 'caracal', ) @@ -308,6 +317,7 @@ UBUNTU_OPENSTACK_RELEASE = OrderedDict([ ('kinetic', 'zed'), ('lunar', 'antelope'), ('mantic', 'bobcat'), + ('noble', 'caracal'), ]) diff --git a/hooks/charmhelpers/osplatform.py b/hooks/charmhelpers/osplatform.py index 1ace468f..5d121866 100644 --- a/hooks/charmhelpers/osplatform.py +++ b/hooks/charmhelpers/osplatform.py @@ -9,19 +9,13 @@ def get_platform(): will be returned (which is the name of the module). This string is used to decide which platform module should be imported. """ - # linux_distribution is deprecated and will be removed in Python 3.7 - # Warnings *not* disabled, as we certainly need to fix this. - if hasattr(platform, 'linux_distribution'): - tuple_platform = platform.linux_distribution() - current_platform = tuple_platform[0] - else: - current_platform = _get_platform_from_fs() + current_platform = _get_current_platform() if "Ubuntu" in current_platform: return "ubuntu" elif "CentOS" in current_platform: return "centos" - elif "debian" in current_platform: + elif "debian" in current_platform or "Debian" in current_platform: # Stock Python does not detect Ubuntu and instead returns debian. # Or at least it does in some build environments like Travis CI return "ubuntu" @@ -36,6 +30,24 @@ def get_platform(): .format(current_platform)) +def _get_current_platform(): + """Return the current platform information for the OS. + + Attempts to lookup linux distribution information from the platform + module for releases of python < 3.7. For newer versions of python, + the platform is determined from the /etc/os-release file. + """ + # linux_distribution is deprecated and will be removed in Python 3.7 + # Warnings *not* disabled, as we certainly need to fix this. + if hasattr(platform, 'linux_distribution'): + tuple_platform = platform.linux_distribution() + current_platform = tuple_platform[0] + else: + current_platform = _get_platform_from_fs() + + return current_platform + + def _get_platform_from_fs(): """Get Platform from /etc/os-release.""" with open(os.path.join(os.sep, 'etc', 'os-release')) as fin: diff --git a/lib/charms_ceph/broker.py b/lib/charms_ceph/broker.py index 71f85f45..7f453ec8 100644 --- a/lib/charms_ceph/broker.py +++ b/lib/charms_ceph/broker.py @@ -106,6 +106,8 @@ def decode_req_encode_rsp(f): """Decorator to decode incoming requests and encode responses.""" def decode_inner(req): + if isinstance(req, bytes): + req = req.decode('utf-8') return json.dumps(f(json.loads(req))) return decode_inner @@ -833,6 +835,72 @@ def handle_rgw_region_set(request, service): os.unlink(infile.name) +def handle_create_cephfs_client(request, service): + """Creates a new CephFS client for a filesystem. + + :param request: The broker request + :param service: The ceph client to run the command under. + :returns: dict. exit-code and reason if not 0. + """ + fs_name = request.get('fs_name') + client_id = request.get('client_id') + # TODO: fs allows setting write permissions for a list of paths. + path = request.get('path') + perms = request.get('perms') + # Need all parameters + if not fs_name or not client_id or not path or not perms: + msg = "Missing fs_name, client_id, path or perms params" + log(msg, level=ERROR) + return {'exit-code': 1, 'stderr': msg} + + # Check that the provided fs_name exists + if fs_name not in get_cephfs(service=service): + msg = ("Ceph filesystem {} does not exist." + + "Cannot authorize client").format( + fs_name) + log(msg, level=ERROR) + return {'exit-code': 1, 'stderr': msg} + + # Check that the provided client does NOT exist. + try: + cmd = ["ceph", "--id", service, "auth", "ls", "-f", "json"] + auth_ls = json.loads(check_output(cmd, encoding="utf-8")) + except CalledProcessError as err: + log(err.output, level=ERROR) + return {'exit-code': 1, 'stderr': err.output} + except ValueError as err: + log(str(err), level=ERROR) + return {'exit-code': 1, 'stderr': str(err)} + + client = "client.{}".format(client_id) + if client in (elem["entity"] for elem in auth_ls["auth_dump"]): + msg = "Client {} already exists".format(client) + log(msg, level=ERROR) + return {'exit-code': 1, 'stderr': msg} + + # Try to authorize the client + try: + cmd = [ + "ceph", + "--id", service, + "fs", "authorize", + fs_name, + client, + path, + perms, + "-f", "json" + ] + fs_auth = json.loads(check_output(cmd, encoding="utf-8")) + except CalledProcessError as err: + log(err.output, level=ERROR) + return {'exit-code': 1, 'stderr': err.output} + except ValueError as err: + log(str(err), level=ERROR) + return {'exit-code': 1, 'stderr': str(err)} + + return {'exit-code': 0, 'key': fs_auth[0]["key"]} + + def process_requests_v1(reqs): """Process v1 requests. @@ -902,6 +970,8 @@ def process_requests_v1(reqs): ret = handle_add_permissions_to_key(request=req, service=svc) elif op == 'set-key-permissions': ret = handle_set_key_permissions(request=req, service=svc) + elif op == "create-cephfs-client": + ret = handle_create_cephfs_client(request=req, service=svc) else: msg = "Unknown operation '{}'".format(op) log(msg, level=ERROR) diff --git a/lib/charms_ceph/utils.py b/lib/charms_ceph/utils.py index 94bfb9e4..57cb1d7b 100644 --- a/lib/charms_ceph/utils.py +++ b/lib/charms_ceph/utils.py @@ -1324,16 +1324,6 @@ def systemd(): return CompareHostReleases(lsb_release()['DISTRIB_CODENAME']) >= 'vivid' -def use_bluestore(): - """Determine whether bluestore should be used for OSD's - - :returns: whether bluestore disk format should be used - :rtype: bool""" - if cmp_pkgrevno('ceph', '12.2.0') < 0: - return False - return config('bluestore') - - def bootstrap_monitor_cluster(secret): """Bootstrap local Ceph mon into the Ceph cluster @@ -1551,21 +1541,21 @@ def get_devices(name): def osdize(dev, osd_format, osd_journal, ignore_errors=False, encrypt=False, - bluestore=False, key_manager=CEPH_KEY_MANAGER, osd_id=None): + key_manager=CEPH_KEY_MANAGER, osd_id=None): if dev.startswith('/dev'): osdize_dev(dev, osd_format, osd_journal, ignore_errors, encrypt, - bluestore, key_manager, osd_id) + key_manager, osd_id) else: if cmp_pkgrevno('ceph', '14.0.0') >= 0: log("Directory backed OSDs can not be created on Nautilus", level=WARNING) return - osdize_dir(dev, encrypt, bluestore) + osdize_dir(dev, encrypt) def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False, - encrypt=False, bluestore=False, key_manager=CEPH_KEY_MANAGER, + encrypt=False, key_manager=CEPH_KEY_MANAGER, osd_id=None): """ Prepare a block device for use as a Ceph OSD @@ -1579,7 +1569,6 @@ def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False, :param: ignore_errors: Don't fail in the event of any errors during processing :param: encrypt: Encrypt block devices using 'key_manager' - :param: bluestore: Use bluestore native Ceph block device format :param: key_manager: Key management approach for encryption keys :raises subprocess.CalledProcessError: in the event that any supporting subprocess operation failed @@ -1630,15 +1619,13 @@ def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False, cmd = _ceph_volume(dev, osd_journal, encrypt, - bluestore, key_manager, osd_id) else: cmd = _ceph_disk(dev, osd_format, osd_journal, - encrypt, - bluestore) + encrypt) try: status_set('maintenance', 'Initializing device {}'.format(dev)) @@ -1669,7 +1656,7 @@ def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False, db.flush() -def _ceph_disk(dev, osd_format, osd_journal, encrypt=False, bluestore=False): +def _ceph_disk(dev, osd_format, osd_journal, encrypt=False): """ Prepare a device for usage as a Ceph OSD using ceph-disk @@ -1677,7 +1664,6 @@ def _ceph_disk(dev, osd_format, osd_journal, encrypt=False, bluestore=False): The function looks up realpath of the device :param: osd_journal: List of block devices to use for OSD journals :param: encrypt: Use block device encryption (unsupported) - :param: bluestore: Use bluestore storage for OSD :returns: list. 'ceph-disk' command and required parameters for execution by check_call """ @@ -1686,25 +1672,17 @@ def _ceph_disk(dev, osd_format, osd_journal, encrypt=False, bluestore=False): if encrypt: cmd.append('--dmcrypt') - if osd_format and not bluestore: - cmd.append('--fs-type') - cmd.append(osd_format) - - # NOTE(jamespage): enable experimental bluestore support - if use_bluestore(): - cmd.append('--bluestore') - wal = get_devices('bluestore-wal') - if wal: - cmd.append('--block.wal') - least_used_wal = find_least_used_utility_device(wal) - cmd.append(least_used_wal) - db = get_devices('bluestore-db') - if db: - cmd.append('--block.db') - least_used_db = find_least_used_utility_device(db) - cmd.append(least_used_db) - elif cmp_pkgrevno('ceph', '12.1.0') >= 0 and not bluestore: - cmd.append('--filestore') + cmd.append('--bluestore') + wal = get_devices('bluestore-wal') + if wal: + cmd.append('--block.wal') + least_used_wal = find_least_used_utility_device(wal) + cmd.append(least_used_wal) + db = get_devices('bluestore-db') + if db: + cmd.append('--block.db') + least_used_db = find_least_used_utility_device(db) + cmd.append(least_used_db) cmd.append(os.path.realpath(dev)) @@ -1715,8 +1693,8 @@ def _ceph_disk(dev, osd_format, osd_journal, encrypt=False, bluestore=False): return cmd -def _ceph_volume(dev, osd_journal, encrypt=False, bluestore=False, - key_manager=CEPH_KEY_MANAGER, osd_id=None): +def _ceph_volume(dev, osd_journal, encrypt=False, key_manager=CEPH_KEY_MANAGER, + osd_id=None): """ Prepare and activate a device for usage as a Ceph OSD using ceph-volume. @@ -1726,7 +1704,6 @@ def _ceph_volume(dev, osd_journal, encrypt=False, bluestore=False, :param: dev: Full path to use for OSD block device setup :param: osd_journal: List of block devices to use for OSD journals :param: encrypt: Use block device encryption - :param: bluestore: Use bluestore storage for OSD :param: key_manager: dm-crypt Key Manager to use :param: osd_id: The OSD-id to recycle, or None to create a new one :raises subprocess.CalledProcessError: in the event that any supporting @@ -1739,13 +1716,8 @@ def _ceph_volume(dev, osd_journal, encrypt=False, bluestore=False, osd_fsid = str(uuid.uuid4()) cmd.append('--osd-fsid') cmd.append(osd_fsid) - - if bluestore: - cmd.append('--bluestore') - main_device_type = 'block' - else: - cmd.append('--filestore') - main_device_type = 'data' + cmd.append('--bluestore') + main_device_type = 'block' if encrypt and key_manager == CEPH_KEY_MANAGER: cmd.append('--dmcrypt') @@ -1753,19 +1725,6 @@ def _ceph_volume(dev, osd_journal, encrypt=False, bluestore=False, if osd_id is not None: cmd.extend(['--osd-id', str(osd_id)]) - # On-disk journal volume creation - if not osd_journal and not bluestore: - journal_lv_type = 'journal' - cmd.append('--journal') - cmd.append(_allocate_logical_volume( - dev=dev, - lv_type=journal_lv_type, - osd_fsid=osd_fsid, - size='{}M'.format(calculate_volume_size('journal')), - encrypt=encrypt, - key_manager=key_manager) - ) - cmd.append('--data') cmd.append(_allocate_logical_volume(dev=dev, lv_type=main_device_type, @@ -1773,36 +1732,21 @@ def _ceph_volume(dev, osd_journal, encrypt=False, bluestore=False, encrypt=encrypt, key_manager=key_manager)) - if bluestore: - for extra_volume in ('wal', 'db'): - devices = get_devices('bluestore-{}'.format(extra_volume)) - if devices: - cmd.append('--block.{}'.format(extra_volume)) - least_used = find_least_used_utility_device(devices, - lvs=True) - cmd.append(_allocate_logical_volume( - dev=least_used, - lv_type=extra_volume, - osd_fsid=osd_fsid, - size='{}M'.format(calculate_volume_size(extra_volume)), - shared=True, - encrypt=encrypt, - key_manager=key_manager) - ) - - elif osd_journal: - cmd.append('--journal') - least_used = find_least_used_utility_device(osd_journal, - lvs=True) - cmd.append(_allocate_logical_volume( - dev=least_used, - lv_type='journal', - osd_fsid=osd_fsid, - size='{}M'.format(calculate_volume_size('journal')), - shared=True, - encrypt=encrypt, - key_manager=key_manager) - ) + for extra_volume in ('wal', 'db'): + devices = get_devices('bluestore-{}'.format(extra_volume)) + if devices: + cmd.append('--block.{}'.format(extra_volume)) + least_used = find_least_used_utility_device(devices, + lvs=True) + cmd.append(_allocate_logical_volume( + dev=least_used, + lv_type=extra_volume, + osd_fsid=osd_fsid, + size='{}M'.format(calculate_volume_size(extra_volume)), + shared=True, + encrypt=encrypt, + key_manager=key_manager) + ) return cmd @@ -2040,7 +1984,7 @@ def _allocate_logical_volume(dev, lv_type, osd_fsid, return "{}/{}".format(vg_name, lv_name) -def osdize_dir(path, encrypt=False, bluestore=False): +def osdize_dir(path, encrypt=False): """Ask ceph-disk to prepare a directory to become an OSD. :param path: str. The directory to osdize @@ -2077,12 +2021,8 @@ def osdize_dir(path, encrypt=False, bluestore=False): if cmp_pkgrevno('ceph', '0.60') >= 0: if encrypt: cmd.append('--dmcrypt') + cmd.append('--bluestore') - # NOTE(icey): enable experimental bluestore support - if cmp_pkgrevno('ceph', '10.2.0') >= 0 and bluestore: - cmd.append('--bluestore') - elif cmp_pkgrevno('ceph', '12.1.0') >= 0 and not bluestore: - cmd.append('--filestore') log("osdize dir cmd: {}".format(cmd)) subprocess.check_call(cmd) @@ -3232,6 +3172,7 @@ UPGRADE_PATHS = collections.OrderedDict([ ('octopus', 'pacific'), ('pacific', 'quincy'), ('quincy', 'reef'), + ('reef', 'squid'), ]) # Map UCA codenames to Ceph codenames @@ -3256,6 +3197,7 @@ UCA_CODENAME_MAP = { 'zed': 'quincy', 'antelope': 'quincy', 'bobcat': 'reef', + 'caracal': 'squid', } diff --git a/metadata.yaml b/metadata.yaml index 40f0b25e..16fc00bb 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -16,8 +16,6 @@ tags: series: - focal - jammy -- lunar -- mantic extra-bindings: public: admin: diff --git a/tests/bundles/focal-yoga-multisite.yaml b/tests/bundles/focal-yoga-multisite.yaml index 8c1a1cfd..006ed1d0 100644 --- a/tests/bundles/focal-yoga-multisite.yaml +++ b/tests/bundles/focal-yoga-multisite.yaml @@ -47,7 +47,7 @@ applications: - '2' - '6' - '7' - channel: latest/edge + channel: quincy/edge secondary-ceph-osd: charm: ch:ceph-osd @@ -62,7 +62,7 @@ applications: - '3' - '8' - '9' - channel: latest/edge + channel: quincy/edge ceph-mon: charm: ch:ceph-mon @@ -72,7 +72,7 @@ applications: source: *source to: - '4' - channel: latest/edge + channel: quincy/edge secondary-ceph-mon: charm: ch:ceph-mon @@ -82,7 +82,7 @@ applications: source: *source to: - '5' - channel: latest/edge + channel: quincy/edge relations: - - 'ceph-osd:mon' diff --git a/tests/bundles/focal-yoga-namespaced.yaml b/tests/bundles/focal-yoga-namespaced.yaml index 7d05aa82..e7d6ebd2 100644 --- a/tests/bundles/focal-yoga-namespaced.yaml +++ b/tests/bundles/focal-yoga-namespaced.yaml @@ -61,7 +61,7 @@ applications: - '4' - '5' - '6' - channel: latest/edge + channel: quincy/edge ceph-mon: charm: ch:ceph-mon @@ -72,7 +72,7 @@ applications: - '7' - '8' - '9' - channel: latest/edge + channel: quincy/edge keystone: expose: True @@ -82,7 +82,7 @@ applications: openstack-origin: *source to: - '10' - channel: latest/edge + channel: yoga/edge vault-mysql-router: charm: ch:mysql-router diff --git a/tests/bundles/focal-yoga.yaml b/tests/bundles/focal-yoga.yaml index 697a9be8..eac9de1f 100644 --- a/tests/bundles/focal-yoga.yaml +++ b/tests/bundles/focal-yoga.yaml @@ -60,7 +60,7 @@ applications: - '4' - '5' - '6' - channel: latest/edge + channel: quincy/edge ceph-mon: charm: ch:ceph-mon @@ -71,7 +71,7 @@ applications: - '7' - '8' - '9' - channel: latest/edge + channel: quincy/edge keystone: expose: True @@ -81,7 +81,7 @@ applications: openstack-origin: *source to: - '10' - channel: latest/edge + channel: yoga/edge vault-mysql-router: charm: ch:mysql-router diff --git a/tests/bundles/jammy-antelope-multisite.yaml b/tests/bundles/jammy-antelope-multisite.yaml index bf9daa5b..27d2a8b3 100644 --- a/tests/bundles/jammy-antelope-multisite.yaml +++ b/tests/bundles/jammy-antelope-multisite.yaml @@ -47,7 +47,7 @@ applications: - '2' - '6' - '7' - channel: latest/edge + channel: quincy/edge secondary-ceph-osd: charm: ch:ceph-osd @@ -62,7 +62,7 @@ applications: - '3' - '8' - '9' - channel: latest/edge + channel: quincy/edge ceph-mon: charm: ch:ceph-mon @@ -72,7 +72,7 @@ applications: source: *source to: - '4' - channel: latest/edge + channel: quincy/edge secondary-ceph-mon: charm: ch:ceph-mon @@ -82,7 +82,7 @@ applications: source: *source to: - '5' - channel: latest/edge + channel: quincy/edge relations: - - 'ceph-osd:mon' diff --git a/tests/bundles/jammy-antelope-namespaced.yaml b/tests/bundles/jammy-antelope-namespaced.yaml index 41d9c1c1..3c5e57d8 100644 --- a/tests/bundles/jammy-antelope-namespaced.yaml +++ b/tests/bundles/jammy-antelope-namespaced.yaml @@ -40,7 +40,8 @@ applications: channel: latest/edge ceph-radosgw: - charm: ../../ceph-radosgw.charm + charm: ch:ceph-radosgw + channel: quincy/edge num_units: 1 options: source: *source @@ -61,7 +62,7 @@ applications: - '4' - '5' - '6' - channel: latest/edge + channel: quincy/edge ceph-mon: charm: ch:ceph-mon @@ -72,7 +73,7 @@ applications: - '7' - '8' - '9' - channel: latest/edge + channel: quincy/edge keystone: expose: True @@ -82,7 +83,7 @@ applications: openstack-origin: *source to: - '10' - channel: latest/edge + channel: 2023.1/edge vault-mysql-router: charm: ch:mysql-router diff --git a/tests/bundles/jammy-antelope.yaml b/tests/bundles/jammy-antelope.yaml index ad5c78e8..02979ee6 100644 --- a/tests/bundles/jammy-antelope.yaml +++ b/tests/bundles/jammy-antelope.yaml @@ -39,7 +39,7 @@ applications: ceph-radosgw: charm: ch:ceph-radosgw - channel: latest/edge + channel: quincy/edge num_units: 1 options: source: *source @@ -59,7 +59,7 @@ applications: - '4' - '5' - '6' - channel: latest/edge + channel: quincy/edge ceph-mon: charm: ch:ceph-mon @@ -70,7 +70,7 @@ applications: - '7' - '8' - '9' - channel: latest/edge + channel: quincy/edge keystone: expose: True @@ -80,7 +80,7 @@ applications: openstack-origin: *source to: - '10' - channel: latest/edge + channel: 2023.1/edge vault-mysql-router: charm: ch:mysql-router diff --git a/tests/bundles/jammy-bobcat-multisite.yaml b/tests/bundles/jammy-bobcat-multisite.yaml index 48f1b9c4..19b5b68a 100644 --- a/tests/bundles/jammy-bobcat-multisite.yaml +++ b/tests/bundles/jammy-bobcat-multisite.yaml @@ -47,7 +47,7 @@ applications: - '2' - '6' - '7' - channel: latest/edge + channel: reef/edge secondary-ceph-osd: charm: ch:ceph-osd @@ -62,7 +62,7 @@ applications: - '3' - '8' - '9' - channel: latest/edge + channel: reef/edge ceph-mon: charm: ch:ceph-mon @@ -72,7 +72,7 @@ applications: source: *source to: - '4' - channel: latest/edge + channel: reef/edge secondary-ceph-mon: charm: ch:ceph-mon @@ -82,7 +82,7 @@ applications: source: *source to: - '5' - channel: latest/edge + channel: reef/edge relations: - - 'ceph-osd:mon' diff --git a/tests/bundles/jammy-bobcat-namespaced.yaml b/tests/bundles/jammy-bobcat-namespaced.yaml index 0ebcf4b3..8c385280 100644 --- a/tests/bundles/jammy-bobcat-namespaced.yaml +++ b/tests/bundles/jammy-bobcat-namespaced.yaml @@ -40,7 +40,8 @@ applications: channel: latest/edge ceph-radosgw: - charm: ../../ceph-radosgw.charm + charm: ch:ceph-radosgw + channel: reef/edge num_units: 1 options: source: *source @@ -61,7 +62,7 @@ applications: - '4' - '5' - '6' - channel: latest/edge + channel: reef/edge ceph-mon: charm: ch:ceph-mon @@ -72,7 +73,7 @@ applications: - '7' - '8' - '9' - channel: latest/edge + channel: reef/edge keystone: expose: True @@ -82,7 +83,7 @@ applications: openstack-origin: *source to: - '10' - channel: latest/edge + channel: 2023.2/edge vault-mysql-router: charm: ch:mysql-router diff --git a/tests/bundles/jammy-bobcat.yaml b/tests/bundles/jammy-bobcat.yaml index bcef92af..0e6c26da 100644 --- a/tests/bundles/jammy-bobcat.yaml +++ b/tests/bundles/jammy-bobcat.yaml @@ -40,7 +40,8 @@ applications: channel: latest/edge ceph-radosgw: - charm: ../../ceph-radosgw.charm + charm: ch:ceph-radosgw + channel: reef/edge num_units: 1 options: source: *source @@ -60,7 +61,7 @@ applications: - '4' - '5' - '6' - channel: latest/edge + channel: reef/edge ceph-mon: charm: ch:ceph-mon @@ -71,7 +72,7 @@ applications: - '7' - '8' - '9' - channel: latest/edge + channel: reef/edge keystone: expose: True @@ -81,7 +82,7 @@ applications: openstack-origin: *source to: - '10' - channel: latest/edge + channel: 2023.2/edge vault-mysql-router: charm: ch:mysql-router diff --git a/tests/bundles/jammy-caracal-multisite.yaml b/tests/bundles/jammy-caracal-multisite.yaml new file mode 100644 index 00000000..116737b5 --- /dev/null +++ b/tests/bundles/jammy-caracal-multisite.yaml @@ -0,0 +1,99 @@ +options: + source: &source cloud:jammy-caracal + +series: jammy + +comment: +- 'machines section to decide order of deployment. database sooner = faster' +machines: + '0': + '1': + '2': + '3': + '4': + '5': + '6': + '7': + '8': + '9': + +applications: + ceph-radosgw: + charm: ../../ceph-radosgw.charm + num_units: 1 + options: + source: *source + to: + - '0' + + secondary-ceph-radosgw: + charm: ../../ceph-radosgw.charm + num_units: 1 + options: + source: *source + to: + - '1' + + ceph-osd: + charm: ch:ceph-osd + num_units: 3 + constraints: "mem=2048" + storage: + osd-devices: 'cinder,10G' + options: + source: *source + osd-devices: '/srv/ceph /dev/test-non-existent' + to: + - '2' + - '6' + - '7' + channel: latest/edge + + secondary-ceph-osd: + charm: ch:ceph-osd + num_units: 3 + constraints: "mem=2048" + storage: + osd-devices: 'cinder,10G' + options: + source: *source + osd-devices: '/srv/ceph /dev/test-non-existent' + to: + - '3' + - '8' + - '9' + channel: latest/edge + + ceph-mon: + charm: ch:ceph-mon + num_units: 1 + options: + monitor-count: 1 + source: *source + to: + - '4' + channel: latest/edge + + secondary-ceph-mon: + charm: ch:ceph-mon + num_units: 1 + options: + monitor-count: 1 + source: *source + to: + - '5' + channel: latest/edge + +relations: + - - 'ceph-osd:mon' + - 'ceph-mon:osd' + + - - 'ceph-radosgw:mon' + - 'ceph-mon:radosgw' + + - - 'secondary-ceph-osd:mon' + - 'secondary-ceph-mon:osd' + + - - 'secondary-ceph-radosgw:mon' + - 'secondary-ceph-mon:radosgw' + diff --git a/tests/bundles/jammy-caracal-namespaced.yaml b/tests/bundles/jammy-caracal-namespaced.yaml new file mode 100644 index 00000000..b65b26e1 --- /dev/null +++ b/tests/bundles/jammy-caracal-namespaced.yaml @@ -0,0 +1,125 @@ +options: + source: &source cloud:jammy-caracal + +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': + '5': + '6': + '7': + '8': + '9': + '10': + '11': + +applications: + + keystone-mysql-router: + charm: ch:mysql-router + channel: 8.0/edge + + mysql-innodb-cluster: + charm: ch:mysql-innodb-cluster + num_units: 3 + options: + source: *source + to: + - '0' + - '1' + - '2' + channel: 8.0/edge + + ceph-radosgw: + charm: ch:ceph-radosgw + channel: latest/edge + num_units: 1 + options: + source: *source + namespace-tenants: True + to: + - '3' + + ceph-osd: + charm: ch:ceph-osd + num_units: 3 + constraints: "mem=2048" + storage: + osd-devices: 'cinder,10G' + options: + source: *source + osd-devices: '/srv/ceph /dev/test-non-existent' + to: + - '4' + - '5' + - '6' + channel: latest/edge + + ceph-mon: + charm: ch:ceph-mon + num_units: 3 + options: + source: *source + to: + - '7' + - '8' + - '9' + channel: latest/edge + + keystone: + expose: True + charm: ch:keystone + num_units: 1 + options: + openstack-origin: *source + to: + - '10' + channel: latest/edge + + vault-mysql-router: + charm: ch:mysql-router + channel: 8.0/edge + + vault: + charm: ch:vault + num_units: 1 + to: + - '11' + channel: 1.8/edge + +relations: + + - - 'keystone:shared-db' + - 'keystone-mysql-router:shared-db' + - - 'keystone-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + + - - 'ceph-osd:mon' + - 'ceph-mon:osd' + + - - 'ceph-radosgw:mon' + - 'ceph-mon:radosgw' + + - - 'ceph-radosgw:identity-service' + - 'keystone:identity-service' + + - - 'vault-mysql-router:db-router' + - 'mysql-innodb-cluster:db-router' + + - - 'vault:shared-db' + - 'vault-mysql-router:shared-db' + + - - 'keystone:certificates' + - 'vault:certificates' + + - - 'ceph-radosgw:certificates' + - 'vault:certificates' diff --git a/tests/bundles/mantic-bobcat.yaml b/tests/bundles/jammy-caracal.yaml similarity index 91% rename from tests/bundles/mantic-bobcat.yaml rename to tests/bundles/jammy-caracal.yaml index 9e0b78e1..59d66de1 100644 --- a/tests/bundles/mantic-bobcat.yaml +++ b/tests/bundles/jammy-caracal.yaml @@ -1,7 +1,7 @@ options: - source: &source cloud:mantic-bobcat + source: &source cloud:jammy-caracal -series: mantic +series: jammy comment: - 'machines section to decide order of deployment. database sooner = faster' @@ -26,7 +26,7 @@ applications: keystone-mysql-router: charm: ch:mysql-router - channel: latest/edge + channel: 8.0/edge mysql-innodb-cluster: charm: ch:mysql-innodb-cluster @@ -37,10 +37,11 @@ applications: - '0' - '1' - '2' - channel: latest/edge + channel: 8.0/edge ceph-radosgw: - charm: ../../ceph-radosgw.charm + charm: ch:ceph-radosgw + channel: latest/edge num_units: 1 options: source: *source @@ -85,14 +86,14 @@ applications: vault-mysql-router: charm: ch:mysql-router - channel: latest/edge + channel: 8.0/edge vault: charm: ch:vault num_units: 1 to: - '11' - channel: latest/edge + channel: 1.8/edge relations: diff --git a/tests/bundles/local-jammy-antelope.yaml b/tests/bundles/local-jammy-antelope.yaml index 2029ec51..a9dbdbdb 100644 --- a/tests/bundles/local-jammy-antelope.yaml +++ b/tests/bundles/local-jammy-antelope.yaml @@ -58,7 +58,7 @@ applications: - '4' - '5' - '6' - channel: latest/edge + channel: quincy/edge ceph-mon: charm: ch:ceph-mon @@ -69,7 +69,7 @@ applications: - '7' - '8' - '9' - channel: latest/edge + channel: quincy/edge keystone: expose: True @@ -79,7 +79,7 @@ applications: openstack-origin: *source to: - '10' - channel: latest/edge + channel: 2023.1/edge vault-mysql-router: charm: ch:mysql-router diff --git a/tests/tests.yaml b/tests/tests.yaml index 6b2be35c..f0c59360 100644 --- a/tests/tests.yaml +++ b/tests/tests.yaml @@ -10,18 +10,15 @@ smoke_bundles: - vault: jammy-antelope dev_bundles: - - lunar-antelope-multisite - - mantic-bobcat-multisite - jammy-antelope-multisite - jammy-bobcat-multisite - - vault: lunar-antelope - - vault: mantic-bobcat - - vault: lunar-antelope-namespaced - - vault: mantic-bobcat-namespaced + - jammy-caracal-multisite - vault: jammy-antelope - vault: jammy-bobcat + - vault: jammy-caracal - vault: jammy-antelope-namespaced - vault: jammy-bobcat-namespaced + - vault: jammy-caracal-namespaced target_deploy_status: vault: