Skip to content

Commit 8717c5a

Browse files
committed
Force update script to download the image and calculate SHA512
Previously the precomputed SHA256 was used for most images. Since we want to check the hash against the openstack backend, we need to have the SHA512. Sadly, most images creators do not provide us with that hash pre-computed. The only solution is to download the images and computing the hash at runtime. Signed-off-by: Gondermann <[email protected]>
1 parent 1c3c523 commit 8717c5a

File tree

1 file changed

+41
-35
lines changed

1 file changed

+41
-35
lines changed

openstack_image_manager/update.py

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
import shutil
88
import sys
99
import time
10+
import hashlib
11+
import math
1012
from urllib.parse import urlparse
11-
from urllib.request import urlopen
1213

1314
from loguru import logger
1415
from minio import Minio
@@ -73,6 +74,11 @@ def mirror_image(image, latest_url, CONF):
7374
)
7475
os.remove(filename)
7576

77+
def size_clean(size):
78+
size_name = ("B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB")
79+
i = int(math.floor(math.log(size, 1024)))
80+
s = size / 1024 ** i
81+
return f"{s:.2f} {size_name[i]}"
7682

7783
def update_image(image, CONF):
7884
name = image["name"]
@@ -88,54 +94,54 @@ def update_image(image, CONF):
8894
logger.info(f"Getting checksums from {latest_checksum_url}")
8995

9096
result = requests.get(latest_checksum_url)
91-
checksums = {}
9297

93-
checksum_type = "sha256"
98+
hash_obj = hashlib.new("sha512")
99+
file_headers = None
100+
with requests.get(url=latest_url, stream=True, timeout=30) as response:
101+
if response.status_code != 200:
102+
logger.error(f"Downloading image '{name}' failed with error code {response.status_code}")
103+
return None
104+
105+
file_headers = response.headers
106+
file_size = int(file_headers["Content-Length"])
107+
logger.info(f"Image size {size_clean(file_size)}")
108+
109+
downloadedBytes = 0
110+
lastProgress = 0
111+
for chunk in response.iter_content(chunk_size=8192):
112+
downloadedBytes += 8192
113+
progressPercent = (downloadedBytes / file_size) * 100
114+
progress = round(min(max(progressPercent, 0), 100))
115+
if progress - lastProgress >= 5:
116+
logger.info(f"Downloading image: {progress}%")
117+
lastProgress = progress
118+
119+
hash_obj.update(chunk)
120+
121+
sha512_value = hash_obj.hexdigest()
122+
94123
filename_pattern = None
95124

96125
if image["shortname"] in ["centos-stream-8", "centos-stream-9", "centos-7"]:
97126
filename_pattern = latest_filename.replace("HEREBE", "")
98127
filename_pattern = filename_pattern.replace("DRAGONS", "")
99-
elif image["shortname"] in ["debian-10", "debian-11", "debian-12"]:
100-
checksum_type = "sha512"
128+
new_latest_filename_list = []
101129

102130
for line in result.text.split("\n"):
103-
if image["shortname"] in ["rocky-8", "rocky-9"]:
104-
splitted_line = re.split("\s+", line) # noqa W605
105-
if splitted_line[0] == "SHA256":
106-
checksums[latest_filename] = splitted_line[3]
107-
elif image["shortname"] in [
108-
"ubuntu-14.04",
109-
"ubuntu-16.04",
110-
"ubuntu-16.04-minimal",
111-
"ubuntu-18.04",
112-
"ubuntu-18.04-minimal",
113-
"ubuntu-20.04",
114-
"ubuntu-20.04-minimal",
115-
"ubuntu-22.04",
116-
"ubuntu-22.04-minimal",
117-
]:
118-
splitted_line = re.split("\s+", line) # noqa W605
119-
if len(splitted_line) == 2:
120-
checksums[splitted_line[1][1:]] = splitted_line[0]
121-
elif image["shortname"] in ["centos-7"]:
131+
if image["shortname"] in ["centos-7"]:
122132
splitted_line = re.split("\s+", line) # noqa W605
123133
if len(splitted_line) == 2:
124134
if re.search(filename_pattern, splitted_line[1]):
125-
checksums[splitted_line[1]] = splitted_line[0]
135+
new_latest_filename_list.append(splitted_line[1])
126136
elif image["shortname"] in ["centos-stream-8", "centos-stream-9"]:
127137
splitted_line = re.split("\s+", line) # noqa W605
128138
if splitted_line[0] == "SHA256" and re.search(
129139
filename_pattern, splitted_line[1][1:-1]
130140
):
131-
checksums[splitted_line[1][1:-1]] = splitted_line[3]
132-
else:
133-
splitted_line = re.split("\s+", line) # noqa W605
134-
if len(splitted_line) == 2:
135-
checksums[splitted_line[1]] = splitted_line[0]
141+
new_latest_filename_list.append(splitted_line[1][1:-1])
136142

137143
if filename_pattern:
138-
new_latest_filename = natsorted(checksums.keys())[-1]
144+
new_latest_filename = natsorted(new_latest_filename_list)[-1]
139145
new_latest_url = latest_url.replace(latest_filename, new_latest_filename)
140146

141147
logger.info(f"Latest URL is now {new_latest_url}")
@@ -144,7 +150,7 @@ def update_image(image, CONF):
144150
latest_filename = new_latest_filename
145151
latest_url = new_latest_url
146152

147-
current_checksum = f"{checksum_type}:{checksums[latest_filename]}"
153+
current_checksum = f"sha512:{sha512_value}"
148154
logger.info(f"Checksum of current {latest_filename} is {current_checksum}")
149155

150156
try:
@@ -166,9 +172,8 @@ def update_image(image, CONF):
166172
if latest_checksum != current_checksum:
167173
logger.info(f"Checking {latest_url}")
168174

169-
conn = urlopen(latest_url, timeout=30)
170175
struct = time.strptime(
171-
conn.headers["last-modified"], "%a, %d %b %Y %H:%M:%S %Z"
176+
file_headers["last-modified"], "%a, %d %b %Y %H:%M:%S %Z"
172177
)
173178
dt = datetime.fromtimestamp(time.mktime(struct))
174179

@@ -240,7 +245,8 @@ def main(
240245
for index, image in enumerate(data["images"]):
241246
if "latest_url" in image:
242247
updated_image = update_image(image, CONF)
243-
data["images"][index] = updated_image
248+
if updated_image:
249+
data["images"][index] = updated_image
244250

245251
with open(p, "w+") as fp:
246252
ryaml = ruamel.yaml.YAML()

0 commit comments

Comments
 (0)