1- import os
2- import requests
3- import re
41import csv
52import json
3+ import logging
4+ import os
5+ import re
6+ import requests
67
78from html .parser import HTMLParser
89
10+ log = logging .getLogger (__name__ )
11+
912URL = os .environ .get ("DOWNBURST_DISCOVER_URL" , "http://download.ceph.com/cloudinit/" )
1013
1114class 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+
2236class 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 )
0 commit comments