From 0fe1882475871b3fddde3889b514bf7dab0bf8a0 Mon Sep 17 00:00:00 2001 From: Kyr Shatskyy Date: Wed, 5 Feb 2025 14:43:31 +0100 Subject: [PATCH] discover: add opensuse distro handler Signed-off-by: Kyr Shatskyy --- downburst/discover.py | 80 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/downburst/discover.py b/downburst/discover.py index 0be5f4f..71b05c1 100644 --- a/downburst/discover.py +++ b/downburst/discover.py @@ -33,6 +33,17 @@ def handle_starttag(self, tag, attrs): if key == 'href' and val.endswith('.qcow2') and 'GenericCloud' in val: self.urls.append(val) +class LeapImageParser(HTMLParser): + def __init__(self): + self.urls = [] + HTMLParser.__init__(self) + + def handle_starttag(self, tag, attrs): + if tag == 'a': + for key, val in attrs: + if key == 'href' and val.endswith('.qcow2') and 'Cloud' in val: + self.urls.append(val) + class ReleaseParser(HTMLParser): def __init__(self): @@ -73,6 +84,20 @@ def handle_starttag(self, tag, attrs): if res: self.versions.append(val.rstrip('/')) +class OpenSUSEVersionParser(HTMLParser): + def __init__(self): + self.versions = [] + HTMLParser.__init__(self) + + def handle_starttag(self, tag, attrs): + if tag == 'a': + r = re.compile(r'^\./([0-9]{2}\.[0-9])/') + for key, val in attrs: + if key == 'href': + res = r.search(val) + if res: + self.versions.append(res.group(1)) + class DistroHandler: def get_releases(self) -> dict[str, str]: log.error(f"Method 'get_releases' is undefined for class {self.__class__.__name__}") @@ -296,9 +321,64 @@ def __call__(self, release, arch): 'hash_function': 'sha256' } +class OpenSUSEHandler(DistroHandler): + URL="https://download.opensuse.org" + + def get_releases(self) -> dict[str, str]: + url = f"{self.URL}/distribution/leap/" + log.debug(f"Lookup for openSUSE Leap releases by url {url}") + r = requests.get(url) + r.raise_for_status() + parser = OpenSUSEVersionParser() + parser.feed(r.content.decode()) + parser.close() + log.debug(f"openSUSE versions: {parser.versions}") + return {v:None for v in parser.versions} + + def get_sha256(self, base_url, filename): + url = f"{base_url}/{filename}.sha256" + r = requests.get(url) + for line in r.content.decode().strip().split("\n"): + if filename in line: + sha256, f = re.split(r"\s+", line) + return sha256 + raise fNameError('SHA-256 checksums not found for file ' + filename + + ' at ' + url) + + def get_latest_release_image(self, url, arch): + r = requests.get(url) + r.raise_for_status() + parser = LeapImageParser() + parser.feed(r.content.decode()) + parser.close() + r = re.compile(r"[0-9]+\.[0-9]+\.[0-9]-Cloud-(Build[0-9]+\.[0-9]+)\.qcow2$") + for href in parser.urls: + res = r.search(href) + if res and arch in href: + serial=res.group(1) + return href.lstrip('./'), serial + + raise NameError('Image not found on server at ' + url) + + def __call__(self, release, arch): + if arch == "amd64": + arch = "x86_64" + base_url = self.URL + f"/distribution/leap/{release}/appliances" + filename, serial = self.get_latest_release_image(base_url, arch) + log.debug(f"Found image for release '{release}': {filename} ({serial})") + sha256 = self.get_sha256(base_url, filename) + url = base_url + '/' + filename + return { + 'url': url, + 'serial': serial.lstrip('Build'), + 'checksum': sha256, + 'hash_function': 'sha256' + } + HANDLERS = { 'ubuntu': UbuntuHandler(), + 'opensuse': OpenSUSEHandler(), 'rocky': RockyHandler(), }