Caracal-Squid enablement

contains:
  - Bundle updates
  - charmhelpers sync
  - drop lunar/mantic

Change-Id: I6ca31ca3b0cc8aedabaeaf2a2e64dede1248e388
Signed-off-by: Utkarsh Bhatt <utkarsh.bhatt@canonical.com>
This commit is contained in:
Utkarsh Bhatt 2024-05-02 16:15:29 +05:30
parent 8ca8dc7cd8
commit 1f66d4ae6a
27 changed files with 513 additions and 204 deletions

View File

@ -33,9 +33,3 @@ bases:
- name: ubuntu - name: ubuntu
channel: "22.04" channel: "22.04"
architectures: [amd64, s390x, ppc64el, arm64] 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]

View File

@ -16,6 +16,7 @@ import glob
import re import re
import subprocess import subprocess
import socket import socket
import ssl
from functools import partial from functools import partial
@ -527,20 +528,57 @@ def get_hostname(address, fqdn=True):
return result.split('.')[0] 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, 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 address: an IP address or hostname
@param port: integer port @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 Note calls 'zc' via a subprocess shell
""" """
if not sslinfo:
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))
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(): def assert_charm_supports_ipv6():
"""Check whether we are able to support charms ipv6.""" """Check whether we are able to support charms ipv6."""

View File

@ -202,6 +202,21 @@ class OSContextGenerator(object):
return self.related 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): class SharedDBContext(OSContextGenerator):
interfaces = ['shared-db'] interfaces = ['shared-db']
@ -545,7 +560,7 @@ class IdentityServiceContext(OSContextGenerator):
'internal_auth_url': internal_auth_url, '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 # add nested dictionary for keystone_authtoken generic
# templating # templating
if keystonemiddleware_os_release: if keystonemiddleware_os_release:
@ -557,6 +572,7 @@ 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_user_id'] = _resolve('service_user_id')
ctxt['admin_tenant_id'] = _resolve('service_tenant_id') ctxt['admin_tenant_id'] = _resolve('service_tenant_id')
ctxt['admin_domain_id'] = _resolve('service_domain_id') ctxt['admin_domain_id'] = _resolve('service_domain_id')
return ctxt return ctxt

View File

@ -0,0 +1,4 @@
{% if audit_middleware -%}
[audit_middleware_notifications]
driver = log
{% endif -%}

View File

@ -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 -%}

View File

@ -161,6 +161,7 @@ OPENSTACK_CODENAMES = OrderedDict([
('2022.2', 'zed'), ('2022.2', 'zed'),
('2023.1', 'antelope'), ('2023.1', 'antelope'),
('2023.2', 'bobcat'), ('2023.2', 'bobcat'),
('2024.1', 'caracal'),
]) ])
# The ugly duckling - must list releases oldest to newest # 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) 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): def get_swift_codename(version):
'''Determine OpenStack codename that corresponds to swift version.''' '''Determine OpenStack codename that corresponds to swift version.'''
codenames = [k for k, v in SWIFT_CODENAMES.items() if version in v] 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') return openstack_release().get('OPENSTACK_CODENAME')
@cached
def openstack_release(): def openstack_release():
"""Return /etc/os-release in a dict.""" """Return /etc/os-release in a dict."""
d = {} d = {}
@ -847,10 +836,6 @@ def openstack_upgrade_available(package):
if not cur_vers: if not cur_vers:
# The package has not been installed yet do not attempt upgrade # The package has not been installed yet do not attempt upgrade
return False return False
if "swift" in package:
codename = get_os_codename_install_source(src)
avail_vers = get_os_version_codename_swift(codename)
else:
try: try:
avail_vers = get_os_version_install_source(src) avail_vers = get_os_version_install_source(src)
except Exception: except Exception:
@ -1222,12 +1207,14 @@ def _ows_check_services_running(services, ports):
return 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 """Check that the services that should be running are actually running
and that any ports specified are being listened to. and that any ports specified are being listened to.
@param services: list of strings OR dictionary specifying services/ports @param services: list of strings OR dictionary specifying services/ports
@param ports: list of 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 @returns state, message: strings or None, None
""" """
messages = [] messages = []
@ -1243,7 +1230,7 @@ def ows_check_services_running(services, ports):
# also verify that the ports that should be open are open # also verify that the ports that should be open are open
# NB, that ServiceManager objects only OPTIONALLY have ports # NB, that ServiceManager objects only OPTIONALLY have ports
map_not_open, ports_open = ( 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): if not all(ports_open):
# find which service has missing ports. They are in service # find which service has missing ports. They are in service
# order which makes it a bit easier. # order which makes it a bit easier.
@ -1258,7 +1245,8 @@ def ows_check_services_running(services, ports):
if ports is not None: if ports is not None:
# and we can also check ports which we don't know the service for # 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): if not all(ports_open_bools):
messages.append( messages.append(
"Ports which should be open, but are not: {}" "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 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 """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 ports that the service specifies are open. If test is True then the
function returns the services with ports that are open rather than 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 services: OrderedDict(service: [port, ...], ...)
@param test: default=False, if False, test for closed, otherwise open. @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] @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, ssl_check_info)
for p in all_ports]
map_ports = OrderedDict() map_ports = OrderedDict()
matched_ports = [p for p, opened in zip(all_ports, ports_states) matched_ports = [p for p, opened in zip(all_ports, ports_states)
if opened == test] # essentially opened xor test 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 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 """Check that the ports list given are being listened to
Returns a list of ports being listened to and a list of the Returns a list of ports being listened to and a list of the
booleans. booleans.
@param ssl_check_info: SSLPortCheckInfo object. If provided, port checks
will be done using an SSL connection.
@param ports: LIST of port numbers. @param ports: LIST of port numbers.
@returns [(port_num, boolean), ...], [boolean] @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 return zip(ports, ports_open), ports_open

View File

@ -17,8 +17,6 @@ from subprocess import (
CalledProcessError, CalledProcessError,
check_call, check_call,
check_output, 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. :param block_device: str: Full path of block device to scrub.
''' '''
p = Popen(['pvremove', '-ff', block_device], check_call(['pvremove', '-ff', '--yes', block_device])
stdin=PIPE)
p.communicate(input='y\n')
def list_lvm_volume_group(block_device): def list_lvm_volume_group(block_device):

View File

@ -256,6 +256,9 @@ def service_resume(service_name, init_dir="/etc/init",
upstart_file = os.path.join(init_dir, "{}.conf".format(service_name)) upstart_file = os.path.join(init_dir, "{}.conf".format(service_name))
sysv_file = os.path.join(initd_dir, service_name) sysv_file = os.path.join(initd_dir, service_name)
if init_is_systemd(service_name=service_name): if init_is_systemd(service_name=service_name):
if service('is-enabled', service_name):
log('service {} already enabled'.format(service_name), level=DEBUG)
else:
service('unmask', service_name) service('unmask', service_name)
service('enable', service_name) service('enable', service_name)
elif os.path.exists(upstart_file): elif os.path.exists(upstart_file):

View File

@ -246,6 +246,14 @@ CLOUD_ARCHIVE_POCKETS = {
'bobcat/proposed': 'jammy-proposed/bobcat', 'bobcat/proposed': 'jammy-proposed/bobcat',
'jammy-bobcat/proposed': 'jammy-proposed/bobcat', 'jammy-bobcat/proposed': 'jammy-proposed/bobcat',
'jammy-proposed/bobcat': '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 # OVN
'focal-ovn-22.03': 'focal-updates/ovn-22.03', 'focal-ovn-22.03': 'focal-updates/ovn-22.03',
@ -279,6 +287,7 @@ OPENSTACK_RELEASES = (
'zed', 'zed',
'antelope', 'antelope',
'bobcat', 'bobcat',
'caracal',
) )
@ -308,6 +317,7 @@ UBUNTU_OPENSTACK_RELEASE = OrderedDict([
('kinetic', 'zed'), ('kinetic', 'zed'),
('lunar', 'antelope'), ('lunar', 'antelope'),
('mantic', 'bobcat'), ('mantic', 'bobcat'),
('noble', 'caracal'),
]) ])

View File

@ -9,19 +9,13 @@ def get_platform():
will be returned (which is the name of the module). will be returned (which is the name of the module).
This string is used to decide which platform module should be imported. This string is used to decide which platform module should be imported.
""" """
# linux_distribution is deprecated and will be removed in Python 3.7 current_platform = _get_current_platform()
# 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()
if "Ubuntu" in current_platform: if "Ubuntu" in current_platform:
return "ubuntu" return "ubuntu"
elif "CentOS" in current_platform: elif "CentOS" in current_platform:
return "centos" 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. # Stock Python does not detect Ubuntu and instead returns debian.
# Or at least it does in some build environments like Travis CI # Or at least it does in some build environments like Travis CI
return "ubuntu" return "ubuntu"
@ -36,6 +30,24 @@ def get_platform():
.format(current_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(): def _get_platform_from_fs():
"""Get Platform from /etc/os-release.""" """Get Platform from /etc/os-release."""
with open(os.path.join(os.sep, 'etc', 'os-release')) as fin: with open(os.path.join(os.sep, 'etc', 'os-release')) as fin:

View File

@ -106,6 +106,8 @@ def decode_req_encode_rsp(f):
"""Decorator to decode incoming requests and encode responses.""" """Decorator to decode incoming requests and encode responses."""
def decode_inner(req): def decode_inner(req):
if isinstance(req, bytes):
req = req.decode('utf-8')
return json.dumps(f(json.loads(req))) return json.dumps(f(json.loads(req)))
return decode_inner return decode_inner
@ -833,6 +835,72 @@ def handle_rgw_region_set(request, service):
os.unlink(infile.name) 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): def process_requests_v1(reqs):
"""Process v1 requests. """Process v1 requests.
@ -902,6 +970,8 @@ def process_requests_v1(reqs):
ret = handle_add_permissions_to_key(request=req, service=svc) ret = handle_add_permissions_to_key(request=req, service=svc)
elif op == 'set-key-permissions': elif op == 'set-key-permissions':
ret = handle_set_key_permissions(request=req, service=svc) ret = handle_set_key_permissions(request=req, service=svc)
elif op == "create-cephfs-client":
ret = handle_create_cephfs_client(request=req, service=svc)
else: else:
msg = "Unknown operation '{}'".format(op) msg = "Unknown operation '{}'".format(op)
log(msg, level=ERROR) log(msg, level=ERROR)

View File

@ -1324,16 +1324,6 @@ def systemd():
return CompareHostReleases(lsb_release()['DISTRIB_CODENAME']) >= 'vivid' 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): def bootstrap_monitor_cluster(secret):
"""Bootstrap local Ceph mon into the Ceph cluster """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, 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'): if dev.startswith('/dev'):
osdize_dev(dev, osd_format, osd_journal, osdize_dev(dev, osd_format, osd_journal,
ignore_errors, encrypt, ignore_errors, encrypt,
bluestore, key_manager, osd_id) key_manager, osd_id)
else: else:
if cmp_pkgrevno('ceph', '14.0.0') >= 0: if cmp_pkgrevno('ceph', '14.0.0') >= 0:
log("Directory backed OSDs can not be created on Nautilus", log("Directory backed OSDs can not be created on Nautilus",
level=WARNING) level=WARNING)
return return
osdize_dir(dev, encrypt, bluestore) osdize_dir(dev, encrypt)
def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False, 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): osd_id=None):
""" """
Prepare a block device for use as a Ceph OSD 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 :param: ignore_errors: Don't fail in the event of any errors during
processing processing
:param: encrypt: Encrypt block devices using 'key_manager' :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 :param: key_manager: Key management approach for encryption keys
:raises subprocess.CalledProcessError: in the event that any supporting :raises subprocess.CalledProcessError: in the event that any supporting
subprocess operation failed subprocess operation failed
@ -1630,15 +1619,13 @@ def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False,
cmd = _ceph_volume(dev, cmd = _ceph_volume(dev,
osd_journal, osd_journal,
encrypt, encrypt,
bluestore,
key_manager, key_manager,
osd_id) osd_id)
else: else:
cmd = _ceph_disk(dev, cmd = _ceph_disk(dev,
osd_format, osd_format,
osd_journal, osd_journal,
encrypt, encrypt)
bluestore)
try: try:
status_set('maintenance', 'Initializing device {}'.format(dev)) status_set('maintenance', 'Initializing device {}'.format(dev))
@ -1669,7 +1656,7 @@ def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False,
db.flush() 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 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 The function looks up realpath of the device
:param: osd_journal: List of block devices to use for OSD journals :param: osd_journal: List of block devices to use for OSD journals
:param: encrypt: Use block device encryption (unsupported) :param: encrypt: Use block device encryption (unsupported)
:param: bluestore: Use bluestore storage for OSD
:returns: list. 'ceph-disk' command and required parameters for :returns: list. 'ceph-disk' command and required parameters for
execution by check_call execution by check_call
""" """
@ -1686,12 +1672,6 @@ def _ceph_disk(dev, osd_format, osd_journal, encrypt=False, bluestore=False):
if encrypt: if encrypt:
cmd.append('--dmcrypt') 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') cmd.append('--bluestore')
wal = get_devices('bluestore-wal') wal = get_devices('bluestore-wal')
if wal: if wal:
@ -1703,8 +1683,6 @@ def _ceph_disk(dev, osd_format, osd_journal, encrypt=False, bluestore=False):
cmd.append('--block.db') cmd.append('--block.db')
least_used_db = find_least_used_utility_device(db) least_used_db = find_least_used_utility_device(db)
cmd.append(least_used_db) cmd.append(least_used_db)
elif cmp_pkgrevno('ceph', '12.1.0') >= 0 and not bluestore:
cmd.append('--filestore')
cmd.append(os.path.realpath(dev)) cmd.append(os.path.realpath(dev))
@ -1715,8 +1693,8 @@ def _ceph_disk(dev, osd_format, osd_journal, encrypt=False, bluestore=False):
return cmd return cmd
def _ceph_volume(dev, osd_journal, encrypt=False, bluestore=False, def _ceph_volume(dev, osd_journal, encrypt=False, key_manager=CEPH_KEY_MANAGER,
key_manager=CEPH_KEY_MANAGER, osd_id=None): osd_id=None):
""" """
Prepare and activate a device for usage as a Ceph OSD using ceph-volume. 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: dev: Full path to use for OSD block device setup
:param: osd_journal: List of block devices to use for OSD journals :param: osd_journal: List of block devices to use for OSD journals
:param: encrypt: Use block device encryption :param: encrypt: Use block device encryption
:param: bluestore: Use bluestore storage for OSD
:param: key_manager: dm-crypt Key Manager to use :param: key_manager: dm-crypt Key Manager to use
:param: osd_id: The OSD-id to recycle, or None to create a new one :param: osd_id: The OSD-id to recycle, or None to create a new one
:raises subprocess.CalledProcessError: in the event that any supporting :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()) osd_fsid = str(uuid.uuid4())
cmd.append('--osd-fsid') cmd.append('--osd-fsid')
cmd.append(osd_fsid) cmd.append(osd_fsid)
if bluestore:
cmd.append('--bluestore') cmd.append('--bluestore')
main_device_type = 'block' main_device_type = 'block'
else:
cmd.append('--filestore')
main_device_type = 'data'
if encrypt and key_manager == CEPH_KEY_MANAGER: if encrypt and key_manager == CEPH_KEY_MANAGER:
cmd.append('--dmcrypt') cmd.append('--dmcrypt')
@ -1753,19 +1725,6 @@ def _ceph_volume(dev, osd_journal, encrypt=False, bluestore=False,
if osd_id is not None: if osd_id is not None:
cmd.extend(['--osd-id', str(osd_id)]) 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('--data')
cmd.append(_allocate_logical_volume(dev=dev, cmd.append(_allocate_logical_volume(dev=dev,
lv_type=main_device_type, lv_type=main_device_type,
@ -1773,7 +1732,6 @@ def _ceph_volume(dev, osd_journal, encrypt=False, bluestore=False,
encrypt=encrypt, encrypt=encrypt,
key_manager=key_manager)) key_manager=key_manager))
if bluestore:
for extra_volume in ('wal', 'db'): for extra_volume in ('wal', 'db'):
devices = get_devices('bluestore-{}'.format(extra_volume)) devices = get_devices('bluestore-{}'.format(extra_volume))
if devices: if devices:
@ -1790,20 +1748,6 @@ def _ceph_volume(dev, osd_journal, encrypt=False, bluestore=False,
key_manager=key_manager) 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)
)
return cmd return cmd
@ -2040,7 +1984,7 @@ def _allocate_logical_volume(dev, lv_type, osd_fsid,
return "{}/{}".format(vg_name, lv_name) 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. """Ask ceph-disk to prepare a directory to become an OSD.
:param path: str. The directory to osdize :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 cmp_pkgrevno('ceph', '0.60') >= 0:
if encrypt: if encrypt:
cmd.append('--dmcrypt') cmd.append('--dmcrypt')
# NOTE(icey): enable experimental bluestore support
if cmp_pkgrevno('ceph', '10.2.0') >= 0 and bluestore:
cmd.append('--bluestore') cmd.append('--bluestore')
elif cmp_pkgrevno('ceph', '12.1.0') >= 0 and not bluestore:
cmd.append('--filestore')
log("osdize dir cmd: {}".format(cmd)) log("osdize dir cmd: {}".format(cmd))
subprocess.check_call(cmd) subprocess.check_call(cmd)
@ -3232,6 +3172,7 @@ UPGRADE_PATHS = collections.OrderedDict([
('octopus', 'pacific'), ('octopus', 'pacific'),
('pacific', 'quincy'), ('pacific', 'quincy'),
('quincy', 'reef'), ('quincy', 'reef'),
('reef', 'squid'),
]) ])
# Map UCA codenames to Ceph codenames # Map UCA codenames to Ceph codenames
@ -3256,6 +3197,7 @@ UCA_CODENAME_MAP = {
'zed': 'quincy', 'zed': 'quincy',
'antelope': 'quincy', 'antelope': 'quincy',
'bobcat': 'reef', 'bobcat': 'reef',
'caracal': 'squid',
} }

View File

@ -16,8 +16,6 @@ tags:
series: series:
- focal - focal
- jammy - jammy
- lunar
- mantic
extra-bindings: extra-bindings:
public: public:
admin: admin:

View File

@ -47,7 +47,7 @@ applications:
- '2' - '2'
- '6' - '6'
- '7' - '7'
channel: latest/edge channel: quincy/edge
secondary-ceph-osd: secondary-ceph-osd:
charm: ch:ceph-osd charm: ch:ceph-osd
@ -62,7 +62,7 @@ applications:
- '3' - '3'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: quincy/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -72,7 +72,7 @@ applications:
source: *source source: *source
to: to:
- '4' - '4'
channel: latest/edge channel: quincy/edge
secondary-ceph-mon: secondary-ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -82,7 +82,7 @@ applications:
source: *source source: *source
to: to:
- '5' - '5'
channel: latest/edge channel: quincy/edge
relations: relations:
- - 'ceph-osd:mon' - - 'ceph-osd:mon'

View File

@ -61,7 +61,7 @@ applications:
- '4' - '4'
- '5' - '5'
- '6' - '6'
channel: latest/edge channel: quincy/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -72,7 +72,7 @@ applications:
- '7' - '7'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: quincy/edge
keystone: keystone:
expose: True expose: True
@ -82,7 +82,7 @@ applications:
openstack-origin: *source openstack-origin: *source
to: to:
- '10' - '10'
channel: latest/edge channel: yoga/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router

View File

@ -60,7 +60,7 @@ applications:
- '4' - '4'
- '5' - '5'
- '6' - '6'
channel: latest/edge channel: quincy/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -71,7 +71,7 @@ applications:
- '7' - '7'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: quincy/edge
keystone: keystone:
expose: True expose: True
@ -81,7 +81,7 @@ applications:
openstack-origin: *source openstack-origin: *source
to: to:
- '10' - '10'
channel: latest/edge channel: yoga/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router

View File

@ -47,7 +47,7 @@ applications:
- '2' - '2'
- '6' - '6'
- '7' - '7'
channel: latest/edge channel: quincy/edge
secondary-ceph-osd: secondary-ceph-osd:
charm: ch:ceph-osd charm: ch:ceph-osd
@ -62,7 +62,7 @@ applications:
- '3' - '3'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: quincy/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -72,7 +72,7 @@ applications:
source: *source source: *source
to: to:
- '4' - '4'
channel: latest/edge channel: quincy/edge
secondary-ceph-mon: secondary-ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -82,7 +82,7 @@ applications:
source: *source source: *source
to: to:
- '5' - '5'
channel: latest/edge channel: quincy/edge
relations: relations:
- - 'ceph-osd:mon' - - 'ceph-osd:mon'

View File

@ -40,7 +40,8 @@ applications:
channel: latest/edge channel: latest/edge
ceph-radosgw: ceph-radosgw:
charm: ../../ceph-radosgw.charm charm: ch:ceph-radosgw
channel: quincy/edge
num_units: 1 num_units: 1
options: options:
source: *source source: *source
@ -61,7 +62,7 @@ applications:
- '4' - '4'
- '5' - '5'
- '6' - '6'
channel: latest/edge channel: quincy/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -72,7 +73,7 @@ applications:
- '7' - '7'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: quincy/edge
keystone: keystone:
expose: True expose: True
@ -82,7 +83,7 @@ applications:
openstack-origin: *source openstack-origin: *source
to: to:
- '10' - '10'
channel: latest/edge channel: 2023.1/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router

View File

@ -39,7 +39,7 @@ applications:
ceph-radosgw: ceph-radosgw:
charm: ch:ceph-radosgw charm: ch:ceph-radosgw
channel: latest/edge channel: quincy/edge
num_units: 1 num_units: 1
options: options:
source: *source source: *source
@ -59,7 +59,7 @@ applications:
- '4' - '4'
- '5' - '5'
- '6' - '6'
channel: latest/edge channel: quincy/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -70,7 +70,7 @@ applications:
- '7' - '7'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: quincy/edge
keystone: keystone:
expose: True expose: True
@ -80,7 +80,7 @@ applications:
openstack-origin: *source openstack-origin: *source
to: to:
- '10' - '10'
channel: latest/edge channel: 2023.1/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router

View File

@ -47,7 +47,7 @@ applications:
- '2' - '2'
- '6' - '6'
- '7' - '7'
channel: latest/edge channel: reef/edge
secondary-ceph-osd: secondary-ceph-osd:
charm: ch:ceph-osd charm: ch:ceph-osd
@ -62,7 +62,7 @@ applications:
- '3' - '3'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: reef/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -72,7 +72,7 @@ applications:
source: *source source: *source
to: to:
- '4' - '4'
channel: latest/edge channel: reef/edge
secondary-ceph-mon: secondary-ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -82,7 +82,7 @@ applications:
source: *source source: *source
to: to:
- '5' - '5'
channel: latest/edge channel: reef/edge
relations: relations:
- - 'ceph-osd:mon' - - 'ceph-osd:mon'

View File

@ -40,7 +40,8 @@ applications:
channel: latest/edge channel: latest/edge
ceph-radosgw: ceph-radosgw:
charm: ../../ceph-radosgw.charm charm: ch:ceph-radosgw
channel: reef/edge
num_units: 1 num_units: 1
options: options:
source: *source source: *source
@ -61,7 +62,7 @@ applications:
- '4' - '4'
- '5' - '5'
- '6' - '6'
channel: latest/edge channel: reef/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -72,7 +73,7 @@ applications:
- '7' - '7'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: reef/edge
keystone: keystone:
expose: True expose: True
@ -82,7 +83,7 @@ applications:
openstack-origin: *source openstack-origin: *source
to: to:
- '10' - '10'
channel: latest/edge channel: 2023.2/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router

View File

@ -40,7 +40,8 @@ applications:
channel: latest/edge channel: latest/edge
ceph-radosgw: ceph-radosgw:
charm: ../../ceph-radosgw.charm charm: ch:ceph-radosgw
channel: reef/edge
num_units: 1 num_units: 1
options: options:
source: *source source: *source
@ -60,7 +61,7 @@ applications:
- '4' - '4'
- '5' - '5'
- '6' - '6'
channel: latest/edge channel: reef/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -71,7 +72,7 @@ applications:
- '7' - '7'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: reef/edge
keystone: keystone:
expose: True expose: True
@ -81,7 +82,7 @@ applications:
openstack-origin: *source openstack-origin: *source
to: to:
- '10' - '10'
channel: latest/edge channel: 2023.2/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router

View File

@ -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'

View File

@ -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'

View File

@ -1,7 +1,7 @@
options: options:
source: &source cloud:mantic-bobcat source: &source cloud:jammy-caracal
series: mantic series: jammy
comment: comment:
- 'machines section to decide order of deployment. database sooner = faster' - 'machines section to decide order of deployment. database sooner = faster'
@ -26,7 +26,7 @@ applications:
keystone-mysql-router: keystone-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: latest/edge channel: 8.0/edge
mysql-innodb-cluster: mysql-innodb-cluster:
charm: ch:mysql-innodb-cluster charm: ch:mysql-innodb-cluster
@ -37,10 +37,11 @@ applications:
- '0' - '0'
- '1' - '1'
- '2' - '2'
channel: latest/edge channel: 8.0/edge
ceph-radosgw: ceph-radosgw:
charm: ../../ceph-radosgw.charm charm: ch:ceph-radosgw
channel: latest/edge
num_units: 1 num_units: 1
options: options:
source: *source source: *source
@ -85,14 +86,14 @@ applications:
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: latest/edge channel: 8.0/edge
vault: vault:
charm: ch:vault charm: ch:vault
num_units: 1 num_units: 1
to: to:
- '11' - '11'
channel: latest/edge channel: 1.8/edge
relations: relations:

View File

@ -58,7 +58,7 @@ applications:
- '4' - '4'
- '5' - '5'
- '6' - '6'
channel: latest/edge channel: quincy/edge
ceph-mon: ceph-mon:
charm: ch:ceph-mon charm: ch:ceph-mon
@ -69,7 +69,7 @@ applications:
- '7' - '7'
- '8' - '8'
- '9' - '9'
channel: latest/edge channel: quincy/edge
keystone: keystone:
expose: True expose: True
@ -79,7 +79,7 @@ applications:
openstack-origin: *source openstack-origin: *source
to: to:
- '10' - '10'
channel: latest/edge channel: 2023.1/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router

View File

@ -10,18 +10,15 @@ smoke_bundles:
- vault: jammy-antelope - vault: jammy-antelope
dev_bundles: dev_bundles:
- lunar-antelope-multisite
- mantic-bobcat-multisite
- jammy-antelope-multisite - jammy-antelope-multisite
- jammy-bobcat-multisite - jammy-bobcat-multisite
- vault: lunar-antelope - jammy-caracal-multisite
- vault: mantic-bobcat
- vault: lunar-antelope-namespaced
- vault: mantic-bobcat-namespaced
- vault: jammy-antelope - vault: jammy-antelope
- vault: jammy-bobcat - vault: jammy-bobcat
- vault: jammy-caracal
- vault: jammy-antelope-namespaced - vault: jammy-antelope-namespaced
- vault: jammy-bobcat-namespaced - vault: jammy-bobcat-namespaced
- vault: jammy-caracal-namespaced
target_deploy_status: target_deploy_status:
vault: vault: