Skip to content

Commit

Permalink
Add Sunbeam support to OpenStack plugin
Browse files Browse the repository at this point in the history
Also:
 * fixes Juju units summary to include charm revision
where charm has no repo-info file.
 * adds snap channel to summary output
 * shows pods and containers from microk8s

Resolves: #995
  • Loading branch information
dosaboy committed Jan 9, 2025
1 parent 1e51266 commit ad3c4e7
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 60 deletions.
18 changes: 9 additions & 9 deletions examples/hotsos-example-kubernetes.summary.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ kubernetes:
- kube-proxy (1)
- kube-scheduler (1)
snaps:
- cdk-addons 1.23.0
- core 16-2.54.2
- core18 20211215
- core20 20220114
- kube-apiserver 1.23.3
- kube-controller-manager 1.23.3
- kube-proxy 1.23.3
- kube-scheduler 1.23.3
- kubectl 1.23.3
- cdk-addons 1.23.0 (latest/stable)
- core 16-2.54.2 (latest/stable)
- core18 20211215 (latest/stable)
- core20 20220114 (latest/stable)
- kube-apiserver 1.23.3 (latest/stable)
- kube-controller-manager 1.23.3 (latest/stable)
- kube-proxy 1.23.3 (latest/stable)
- kube-scheduler 1.23.3 (latest/stable)
- kubectl 1.23.3 (latest/stable)
dpkg:
- vaultlocker 1.0.6-0ubuntu1
flannel:
Expand Down
2 changes: 1 addition & 1 deletion examples/hotsos-example-vault.summary.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ vault:
- vault-mysql-router
ps: []
snaps:
- vault 1.5.9
- vault 1.5.9 (1.5/stable)
3 changes: 2 additions & 1 deletion hotsos/core/host_helpers/packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,8 @@ def all_formatted(self):
if not _all:
return []

return [f"{name} {info['version']}" for name, info in _all.items()]
return [f"{name} {info['version']} ({info['channel']})"
for name, info in _all.items()]

@property
def core(self):
Expand Down
23 changes: 15 additions & 8 deletions hotsos/core/plugins/kubernetes.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
# Snap-only deps
K8S_PACKAGE_DEPS_SNAP = [r'core[0-9]*']
K8S_SNAP_DEPS = K8S_PACKAGE_DEPS + K8S_PACKAGE_DEPS_SNAP

MICROK8S_COMMON = 'var/snap/microk8s/common'

@dataclass
class KubernetesInstallInfo(InstallInfoBase):
Expand Down Expand Up @@ -88,9 +88,12 @@ def pods(self):
pods = []
pods_path = os.path.join(HotSOSConfig.data_root,
"var/log/pods")
if os.path.exists(pods_path):
for pod in os.listdir(pods_path):
pods.append(pod)
mk8s_pods_path = os.path.join(HotSOSConfig.data_root,
MICROK8S_COMMON, '/var/log/pods')
for path in [pods_path, mk8s_pods_path]:
if os.path.exists(path):
for pod in os.listdir(path):
pods.append(pod)

return sorted(pods)

Expand All @@ -99,10 +102,14 @@ def containers(self):
containers = []
containers_path = os.path.join(HotSOSConfig.data_root,
"var/log/containers")
if os.path.exists(containers_path):
for pod in os.listdir(containers_path):
pod = pod.partition('.log')[0]
containers.append(pod)
mk8s_containers_path = os.path.join(HotSOSConfig.data_root,
MICROK8S_COMMON,
'var/log/containers')
for path in [containers_path, mk8s_containers_path]:
if os.path.exists(path):
for ctr in os.listdir(path):
ctr = ctr.partition('.log')[0]
containers.append(ctr)

return sorted(containers)

Expand Down
43 changes: 31 additions & 12 deletions hotsos/core/plugins/openstack/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
DPKGVersion,
InstallInfoBase,
PebbleHelper,
SnapPackageHelper,
SystemdHelper,
SSLCertificate,
SSLCertificatesHelper,
Expand All @@ -22,6 +23,8 @@
OSTProjectCatalog,
OST_EOL_INFO,
OST_REL_INFO,
OST_SUNBEAM_REL_INFO,
OST_SUNBEAM_SNAP_NAMES,
)
from hotsos.core.plugins.openstack.neutron import NeutronBase
from hotsos.core.plugins.openstack.nova import NovaBase
Expand All @@ -47,26 +50,29 @@ class OpenStackInstallInfo(InstallInfoBase):

def __post_init__(self):
service_exprs = self.project_catalog.service_exprs
core_pkgs = self.project_catalog.packages_core_exprs
other_pkgs = self.project_catalog.packages_dep_exprs
snap_core_pkgs = self.project_catalog.snap_core_exprs
core_pkgs = self.project_catalog.apt_core_exprs
other_pkgs = self.project_catalog.apt_dep_exprs

self.apt = APTPackageHelper(core_pkgs=core_pkgs,
other_pkgs=other_pkgs)
self.docker = DockerImageHelper(core_pkgs=core_pkgs,
other_pkgs=other_pkgs)
self.snaps = SnapPackageHelper(core_snaps=snap_core_pkgs)
self.pebble = PebbleHelper(service_exprs=service_exprs)
self.systemd = SystemdHelper(service_exprs=service_exprs)

def mixin(self, _self):
_self.apt = self.apt
_self.docker = self.docker
_self.pebble = self.pebble
_self.snaps = self.snaps
_self.systemd = self.systemd


class OpenstackBase():
class OpenstackBase(): # pylint: disable=too-many-instance-attributes
"""
Base class for Openstack checks.
Base class for OpenStack checks.
Contains per-service information such as packages, versions, config etc.
"""
Expand All @@ -77,19 +83,14 @@ def __init__(self, *args, **kwargs):
OctaviaBase())
self.project_catalog = OSTProjectCatalog()
# Keep pylint happy
self.apt = self.pebble = self.docker = self.systemd = None
self.apt = self.pebble = self.docker = self.snaps = self.systemd = None
OpenStackInstallInfo(project_catalog=self.project_catalog).mixin(self)

@cached_property
def apt_source_path(self):
return os.path.join(HotSOSConfig.data_root, 'etc/apt/sources.list.d')

@cached_property
def installed_pkg_release_names(self):
"""
Get release name for each installed package that we are tracking and
return as a list of names. The list should normally have length 1.
"""
def _get_apt_relnames(self):
relnames = set()
for pkg, values in OST_REL_INFO.items():
if pkg in self.apt.core:
Expand All @@ -110,6 +111,23 @@ def installed_pkg_release_names(self):
if r_lt:
relnames.add(r_lt)

return relnames

@cached_property
def installed_pkg_release_names(self):
"""
Get release name for each installed package that we are tracking and
return as a list of names. The list should normally have length 1.
"""
if self.apt.core:
relnames = self._get_apt_relnames()
else:
relnames = set()
for pkg in OST_SUNBEAM_SNAP_NAMES:
if pkg in self.snaps.core:
ver = self.snaps.get_version(pkg)
relnames.add(OST_SUNBEAM_REL_INFO[ver])

log.debug("release name(s) found: %s", ','.join(relnames))
return list(relnames)

Expand Down Expand Up @@ -277,7 +295,8 @@ def is_runnable(cls):
@return: True or False
"""
if OpenstackBase().apt.core:
ost_common = OpenstackBase()
if ost_common.apt.core or ost_common.snaps.core:
return True

return False
Expand Down
21 changes: 19 additions & 2 deletions hotsos/core/plugins/openstack/openstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,16 @@
'stein': '1.0.0'}
}

OST_SUNBEAM_SNAP_NAMES = ['openstack', 'openstack-hypervisor']

OST_SUNBEAM_REL_INFO = {
'2025.1': 'epoxy',
'2024.2': 'dalmation',
'2024.1': 'caracal',
'2023.2': 'bobcat',
'2023.1': 'antelope',
}

OST_EXCEPTIONS = {'barbican': BARBICAN_EXCEPTIONS + CASTELLAN_EXCEPTIONS +
OSLO_MESSAGING_EXCEPTIONS,
'cinder': CINDER_EXCEPTIONS + CASTELLAN_EXCEPTIONS +
Expand Down Expand Up @@ -496,6 +506,9 @@ class OSTProjectCatalog():
'radvd',
]

# ref: https://github.com/orgs/canonical/repositories?q=%22snap-open%22
SNAP_DEPS_SUNBEAM = [r'openstack\S*']

def __init__(self):
self._projects = {}
self.add('aodh', config={'main': 'aodh.conf'},
Expand Down Expand Up @@ -621,15 +634,19 @@ def add(self, name, *args, **kwargs):
self._projects[name] = OSTProject(params)

@cached_property
def packages_core_exprs(self):
def snap_core_exprs(self):
return self.SNAP_DEPS_SUNBEAM

@cached_property
def apt_core_exprs(self):
core = set()
for p in self.all.values():
core.update(p.apt_params.core)

return list(core)

@cached_property
def packages_dep_exprs(self):
def apt_dep_exprs(self):
deps = set(self.APT_DEPS_COMMON)
for p in self.all.values():
deps.update(p.apt_params.deps)
Expand Down
18 changes: 10 additions & 8 deletions hotsos/plugin_extensions/juju/summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,17 @@ def summary_units(self):
name, _, ver = u.name.rpartition('-')
u_name = f"{name}/{ver}"
unit_info[u_name] = {}
if u.repo_info:
c_name = u.charm_name
if c_name:
unit_info[u_name]['charm'] = {'name': c_name}
c_name = u.charm_name
if c_name:
charm = {'name': c_name}
unit_info[u_name]['charm'] = charm
if u.repo_info:
sha1 = u.repo_info.get('commit')
unit_info[u_name]['charm']['repo-info'] = sha1
if c_name in self.charms:
unit_info[u_name]['charm']['version'] = \
self.charms[c_name].version
charm['repo-info'] = sha1

if c_name in self.charms:
charm['version'] = \
self.charms[c_name].version

if u.name in loginfo:
unit_info[u_name]['logs'] = loginfo[u.name]
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/host_helpers/test_packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def test_all(self):
self.assertEqual(obj.get_version("lxd"), "4.22")

def test_formatted(self):
expected = ['core20 20220114']
expected = ['core20 20220114 (latest/stable)']
obj = host_pack.SnapPackageHelper(["core20"])
self.assertEqual(obj.all_formatted, expected)

Expand Down
11 changes: 11 additions & 0 deletions tests/unit/test_juju.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ def test_get_unit_info(self):
self.assertEqual(self.part_output_to_actual(inst.output)['units'],
expected)

@utils.create_data_root(
{('var/lib/juju/agents/unit-sunbeam-machine-1/'
'state/deployer/manifests/'
'ch_3a_amd64_2f_jammy_2f_sunbeam-machine-32'): ''})
def test_get_unit_info_no_repo_info(self):
expected = {'sunbeam-machine/1':
{'charm': {'name': 'sunbeam-machine', 'version': 32}}}
inst = summary.JujuSummary()
self.assertEqual(self.part_output_to_actual(inst.output)['units'],
expected)


@utils.load_templated_tests('scenarios/juju')
class TestJujuScenarios(JujuTestsBase):
Expand Down
26 changes: 13 additions & 13 deletions tests/unit/test_kubernetes.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ def test_services(self):
expected)

def test_snaps(self):
result = ['cdk-addons 1.23.0',
'core 16-2.54.2',
'core18 20211215',
'core20 20220114',
'kube-apiserver 1.23.3',
'kube-controller-manager 1.23.3',
'kube-proxy 1.23.3',
'kube-scheduler 1.23.3',
'kubectl 1.23.3']
result = ['cdk-addons 1.23.0 (latest/stable)',
'core 16-2.54.2 (latest/stable)',
'core18 20211215 (latest/stable)',
'core20 20220114 (latest/stable)',
'kube-apiserver 1.23.3 (latest/stable)',
'kube-controller-manager 1.23.3 (latest/stable)',
'kube-proxy 1.23.3 (latest/stable)',
'kube-scheduler 1.23.3 (latest/stable)',
'kubectl 1.23.3 (latest/stable)']
inst = summary.KubernetesSummary()
self.assertEqual(self.part_output_to_actual(inst.output)['snaps'],
result)
Expand All @@ -97,10 +97,10 @@ def test_snaps_microk8s(self, mock_helper):
mock_helper.return_value.snap_list_all.return_value = \
SNAP_LIST_ALL_MICROK8S.splitlines()
inst = summary.KubernetesSummary()
result = ['core18 20230320',
'core20 20230308',
'core22 20230404',
'microk8s v1.26.4']
result = ['core18 20230320 (latest/stable)',
'core20 20230308 (latest/stable)',
'core22 20230404 (latest/stable)',
'microk8s v1.26.4 (1.26/stable)']
self.assertTrue(inst.is_runnable())
self.assertEqual(self.part_output_to_actual(inst.output)['snaps'],
result)
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_lxd.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_summary_keys(self):
'snap.lxd.user-daemon'],
'transient': ['snap.lxd.workaround']}},

'snaps': ['lxd 4.22']}
'snaps': ['lxd 4.22 (latest/stable)']}
inst = summary.LXDSummary()
self.assertEqual(self.part_output_to_actual(inst.output), expected)

Expand Down
Loading

0 comments on commit ad3c4e7

Please sign in to comment.