Skip to content

Commit 56ad819

Browse files
author
Kyr Shatskyy
committed
discover: add ReleaseParser for up-to-date Ubuntu releases
Though the url http://cloud-images.ubuntu.com/query/released.latest.txt still exists, it is not up-to-date and does not contain recent data about ubuntu releases and as a result no recent ubuntu images can be found. Instead we should look try and find the images by the directory: https://cloud-images.ubuntu.com/releases/ Signed-off-by: Kyr Shatskyy <kyrylo.shatskyy@gmail.com>
1 parent 498cc5a commit 56ad819

File tree

2 files changed

+46
-21
lines changed

2 files changed

+46
-21
lines changed

downburst/discover.py

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
import os
2-
import requests
3-
import re
41
import csv
52
import json
3+
import logging
4+
import os
5+
import re
6+
import requests
67

78
from html.parser import HTMLParser
89

10+
log = logging.getLogger(__name__)
11+
912
URL=os.environ.get("DOWNBURST_DISCOVER_URL", "http://download.ceph.com/cloudinit/")
1013

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

25+
class ReleaseParser(HTMLParser):
26+
def __init__(self):
27+
self.dirs = []
28+
HTMLParser.__init__(self)
29+
30+
def handle_starttag(self, tag, attrs):
31+
if tag == 'a':
32+
for key, val in attrs:
33+
if key == 'href' and val.startswith('release-'):
34+
self.dirs.append(val.rstrip('/'))
35+
2236
class UbuntuHandler:
2337
URL = 'http://cloud-images.ubuntu.com'
2438

@@ -49,6 +63,8 @@ class UbuntuHandler:
4963
'16.04': 'xenial',
5064
'18.04': 'bionic',
5165
'20.04': 'focal',
66+
'22.04': 'jammy',
67+
'24.04': 'noble',
5268
}
5369

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

73-
def get_serial(self, release):
74-
url = self.URL + '/query/released.latest.txt'
89+
def get_latest_release_serial(self, release):
90+
url = self.URL + f"/releases/{release}"
7591
r = requests.get(url)
7692
r.raise_for_status()
77-
serial = None
78-
for row in csv.DictReader(r.content.decode().strip().split("\n"),
79-
delimiter="\t",
80-
fieldnames=('release', 'flavour', 'stability',
81-
'serial')):
82-
83-
if row['release'] == release and row['flavour'] == 'server':
84-
return row['serial'], row['stability']
93+
parser = ReleaseParser()
94+
parser.feed(r.content.decode())
95+
parser.close()
96+
latest_release_directory = sorted(parser.dirs)[-1]
97+
if latest_release_directory:
98+
serial = latest_release_directory.split('-')[1]
99+
return serial, 'release'
100+
85101
raise NameError('Image not found on server at ' + url)
86102

87103
def get_filename(self, arch, version, state):
88104
if state == 'release':
89105
state = ''
90106
else:
91107
state = '-' + state
92-
if version == '20.04':
108+
major, minor = version.split('.')
109+
if int(major) >= 23 and int(minor) >= 10:
110+
return 'ubuntu-' + version + state + '-server-cloudimg-'+ arch + '.img'
111+
elif int(major) >= 20:
93112
return 'ubuntu-' + version + state + '-server-cloudimg-'+ arch + '-disk-kvm.img'
94113
else:
95114
return 'ubuntu-' + version + state + '-server-cloudimg-'+ arch + '-disk1.img'
@@ -130,8 +149,9 @@ def __call__(self, distroversion, arch):
130149
if arch == "x86_64":
131150
arch = "amd64"
132151
release = self.get_release(distroversion)
152+
log.debug(f"Found release: {release}")
133153
version = self.get_version(distroversion)
134-
serial, state = self.get_serial(release)
154+
serial, state = self.get_latest_release_serial(release)
135155
filename = self.get_filename(arch, version, state)
136156
base_url = self.get_base_url(release, serial, state)
137157
sha256 = self.get_sha256(base_url, filename)

downburst/test/test_discover.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@ def test_ubuntu_handler(m_requests_get):
88
assert '18.04' == h.get_version('bionic')
99
m_request = Mock()
1010
m_request.content = (
11-
b"focal server release 20230302\n"
12-
b"jammy server release 20230303\n")
11+
b"<html>\n<body>\n<div>\n<div>\n<pre><hr>\n"
12+
b'<a href="/releases/">Parent Directory</a>\n'
13+
b'<a href="release-20241216/">release-20241216/</a>\n'
14+
b'<a href="release-20250109/">release-20250109/</a>\n'
15+
b'<a href="release/">release/</a>\n'
16+
b"<hr></pre>\n"
17+
b"</div></div></body></html>\n")
1318
m_requests_get.return_value = m_request
14-
assert ('20230302','release') == h.get_serial('focal')
19+
assert ('20250109','release') == h.get_latest_release_serial('focal')
1520

16-
@patch('downburst.discover.UbuntuHandler.get_serial')
17-
def test_get(m_get_serial):
18-
m_get_serial.return_value = ('20230420', 'release')
21+
@patch('downburst.discover.UbuntuHandler.get_latest_release_serial')
22+
def test_get(m_get_latest_release_serial):
23+
m_get_latest_release_serial.return_value = ('20230420', 'release')
1924
checksum = 'cd824b19795e8a6b9ae993b0b5157de0275e952a7a9e8b9717ca07acec22f51b'
2025
res = discover.get('ubuntu', '20.04', 'x86_64')
2126
assert checksum == res['checksum']

0 commit comments

Comments
 (0)