Skip to content

Commit

Permalink
Merge pull request #37 from ceph/wip-ubuntu-24.04
Browse files Browse the repository at this point in the history
Support latest ubuntu image for UbuntuHandler discovery
  • Loading branch information
kshtsk authored Jan 31, 2025
2 parents 9e0da3d + 56ad819 commit 5255751
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 25 deletions.
6 changes: 3 additions & 3 deletions downburst/destroy.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def looks_like_downburst_volume(name, vol_name):
return True

# additional disks for the vm
if re.match(name + '-(\d+).img', vol_name):
if re.match(name + r'-(\d+).img', vol_name):
return True

# cloud-init.{name}.iso: cloud-init meta-data CD-ROM
Expand All @@ -33,7 +33,7 @@ def looks_like_downburst_volume(name, vol_name):
return True

# additional RBD backed objects
if re.match(name + '-(\d+)', vol_name):
if re.match(name + r'-(\d+)', vol_name):
return True

return False
Expand Down Expand Up @@ -106,7 +106,7 @@ def destroy(args):
pool = conn.storagePoolLookupByName(poolentry)

for vol_name in pool.listVolumes():
log.debug('Checking Volumel: {volume}'.format(volume=vol_name))
log.debug('Checking Volume: {volume}'.format(volume=vol_name))
if looks_like_downburst_volume(
name=args.name,
vol_name=vol_name,
Expand Down
50 changes: 35 additions & 15 deletions downburst/discover.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import os
import requests
import re
import csv
import json
import logging
import os
import re
import requests

from html.parser import HTMLParser

log = logging.getLogger(__name__)

URL=os.environ.get("DOWNBURST_DISCOVER_URL", "http://download.ceph.com/cloudinit/")

class Parser(HTMLParser):
Expand All @@ -19,6 +22,17 @@ def handle_starttag(self, tag, attrs):
if key == 'href' and (val.endswith('.img') or val.endswith('.raw')):
self.filenames.append(val)

class ReleaseParser(HTMLParser):
def __init__(self):
self.dirs = []
HTMLParser.__init__(self)

def handle_starttag(self, tag, attrs):
if tag == 'a':
for key, val in attrs:
if key == 'href' and val.startswith('release-'):
self.dirs.append(val.rstrip('/'))

class UbuntuHandler:
URL = 'http://cloud-images.ubuntu.com'

Expand Down Expand Up @@ -49,6 +63,8 @@ class UbuntuHandler:
'16.04': 'xenial',
'18.04': 'bionic',
'20.04': 'focal',
'22.04': 'jammy',
'24.04': 'noble',
}

RELEASE_TO_VERSION = {v:k for k, v in VERSION_TO_RELEASE.items()}
Expand All @@ -70,26 +86,29 @@ def get_version(self, distroversion):
pass
return distroversion

def get_serial(self, release):
url = self.URL + '/query/released.latest.txt'
def get_latest_release_serial(self, release):
url = self.URL + f"/releases/{release}"
r = requests.get(url)
r.raise_for_status()
serial = None
for row in csv.DictReader(r.content.decode().strip().split("\n"),
delimiter="\t",
fieldnames=('release', 'flavour', 'stability',
'serial')):

if row['release'] == release and row['flavour'] == 'server':
return row['serial'], row['stability']
parser = ReleaseParser()
parser.feed(r.content.decode())
parser.close()
latest_release_directory = sorted(parser.dirs)[-1]
if latest_release_directory:
serial = latest_release_directory.split('-')[1]
return serial, 'release'

raise NameError('Image not found on server at ' + url)

def get_filename(self, arch, version, state):
if state == 'release':
state = ''
else:
state = '-' + state
if version == '20.04':
major, minor = version.split('.')
if int(major) >= 23 and int(minor) >= 10:
return 'ubuntu-' + version + state + '-server-cloudimg-'+ arch + '.img'
elif int(major) >= 20:
return 'ubuntu-' + version + state + '-server-cloudimg-'+ arch + '-disk-kvm.img'
else:
return 'ubuntu-' + version + state + '-server-cloudimg-'+ arch + '-disk1.img'
Expand Down Expand Up @@ -130,8 +149,9 @@ def __call__(self, distroversion, arch):
if arch == "x86_64":
arch = "amd64"
release = self.get_release(distroversion)
log.debug(f"Found release: {release}")
version = self.get_version(distroversion)
serial, state = self.get_serial(release)
serial, state = self.get_latest_release_serial(release)
filename = self.get_filename(arch, version, state)
base_url = self.get_base_url(release, serial, state)
sha256 = self.get_sha256(base_url, filename)
Expand Down
5 changes: 4 additions & 1 deletion downburst/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ def find_cloud_image(pool, distro, distroversion, arch):
log.debug('No cloud images found.')
return None

log.debug(names)
# the build serial is zero-padded, hence alphabetically sortable;
# max is the latest image
return max(names)
latest=max(names)
log.debug(f"Found latest image {latest}")
return latest


def upload_volume(vol, fp, hash_function, checksum):
Expand Down
17 changes: 11 additions & 6 deletions downburst/test/test_discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ def test_ubuntu_handler(m_requests_get):
assert '18.04' == h.get_version('bionic')
m_request = Mock()
m_request.content = (
b"focal server release 20230302\n"
b"jammy server release 20230303\n")
b"<html>\n<body>\n<div>\n<div>\n<pre><hr>\n"
b'<a href="/releases/">Parent Directory</a>\n'
b'<a href="release-20241216/">release-20241216/</a>\n'
b'<a href="release-20250109/">release-20250109/</a>\n'
b'<a href="release/">release/</a>\n'
b"<hr></pre>\n"
b"</div></div></body></html>\n")
m_requests_get.return_value = m_request
assert ('20230302','release') == h.get_serial('focal')
assert ('20250109','release') == h.get_latest_release_serial('focal')

@patch('downburst.discover.UbuntuHandler.get_serial')
def test_get(m_get_serial):
m_get_serial.return_value = ('20230420', 'release')
@patch('downburst.discover.UbuntuHandler.get_latest_release_serial')
def test_get(m_get_latest_release_serial):
m_get_latest_release_serial.return_value = ('20230420', 'release')
checksum = 'cd824b19795e8a6b9ae993b0b5157de0275e952a7a9e8b9717ca07acec22f51b'
res = discover.get('ubuntu', '20.04', 'x86_64')
assert checksum == res['checksum']
Expand Down

0 comments on commit 5255751

Please sign in to comment.