Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(kbuild): Implement file download retry #2731

Merged
merged 2 commits into from
Nov 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 49 additions & 6 deletions kernelci/kbuild.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1-or-later

Check warning on line 1 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

Too many lines in module (1033/1000)
#
# Copyright (C) 2023 Collabora Limited
# Author: Denys Fedoryshchenko <[email protected]>
Expand Down Expand Up @@ -30,6 +30,7 @@
import tarfile
import json
import requests
import time
import yaml
import kernelci.api
import kernelci.api.helper
Expand All @@ -39,14 +40,14 @@


CROS_CONFIG_URL = \
"https://chromium.googlesource.com/chromiumos/third_party/kernel/+archive/refs/heads/{branch}/chromeos/config.tar.gz" # noqa

Check warning on line 43 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

Line too long (129/100)
LEGACY_CONFIG = [
'config/core/build-configs.yaml',
'/etc/kernelci/core/build-configs.yaml',
]
FW_GIT = "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git" # noqa

# TODO: find a way to automatically fetch this information

Check warning on line 50 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

TODO: find a way to automatically fetch this information
LATEST_LTS_MAJOR = 6
LATEST_LTS_MINOR = 6

Expand Down Expand Up @@ -103,18 +104,40 @@
REDIR = ' > >(tee {}) 2> >(tee {} >&1)'


def _download_file_inner(url, file_path):
try:
r = requests.get(url, stream=True, timeout=60)
except requests.exceptions.RequestException as e:
print(f"[_download_file_inner] Error: {e}")
return False
except requests.exceptions.Timeout as e:

Check failure on line 113 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

Bad except clauses order (RequestException is an ancestor class of Timeout)
print(f"[_download_file_inner] Timeout: {e}")
return False
except requests.exceptions.ConnectionError as e:

Check failure on line 116 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

Bad except clauses order (RequestException is an ancestor class of ConnectionError)
print(f"[_download_file_inner] Connection error: {e}")
return False
except Exception as e:
print(f"[_download_file_inner] Exception: {e}")
return False
if r.status_code == 200:
with open(file_path, 'wb') as f:
for chunk in r:
f.write(chunk)
return True


def _download_file(url, file_path):
'''
Download file to file_path
TODO(nuclearcat): Do we have anything generic in KernelCI for this?
'''
print(f"[_download_file] Downloading {url} to {file_path}")
r = requests.get(url, stream=True, timeout=60)
if r.status_code == 200:
with open(file_path, 'wb') as f:
for chunk in r:
f.write(chunk)
return True
retries = 10
while retries > 0:
if _download_file_inner(url, file_path):
return True
time.sleep(5)
retries -= 1
return False


Expand Down Expand Up @@ -422,6 +445,25 @@

return (buffer, fragment)

def _verify_network(self):
""" Verify network connectivity """
# TBD: Different URL? pool of urls?
retries = 10
while retries > 0:
try:
r = requests.get("https://google.com")
except Exception as e:
print(f"[_verify_network] Error: {e}")
time.sleep(5)
retries -= 1
continue
if r.status_code == 200:
return
time.sleep(5)

print("[_verify_network] Network is not available")
sys.exit(1)

def extract_config(self, frag):
""" Extract config fragments from legacy config file """
txt = ''
Expand Down Expand Up @@ -452,8 +494,8 @@
sys.exit(1)

print(f"Searching for fragment {fragname} in {cfg_path}")
if 'fragments' in yml:

Check failure on line 497 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

Value 'yml' doesn't support membership test
frag = yml['fragments']

Check failure on line 498 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

Value 'yml' is unsubscriptable
else:
print("No fragments section in config file")
self.submit_failure("No fragments section in config file")
Expand All @@ -479,7 +521,7 @@
elif fragment.startswith("CONFIG_"):
content = fragment + '\n'
else:
# TODO: implement 'path' option properly

Check warning on line 524 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

TODO: implement 'path' option properly
content = self.add_legacy_fragment(fragment)

fragfile = os.path.join(self._fragments_dir, f"{num}.config")
Expand Down Expand Up @@ -528,8 +570,8 @@
for i in range(0, fragnum):
self.addcmd("./scripts/kconfig/merge_config.sh" +
f" -m .config {self._fragments_dir}/{i}.config")
# TODO: olddefconfig should be optional/configurable

Check warning on line 573 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

TODO: olddefconfig should be optional/configurable
# TODO: log all warnings/errors of olddefconfig to separate file

Check warning on line 574 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

TODO: log all warnings/errors of olddefconfig to separate file
self.addcmd("make olddefconfig")
self.addcmd(f"cp .config {self._af_dir}/")
self.addcmd("cd ..")
Expand All @@ -537,12 +579,12 @@

def _generate_script(self):
""" Generate shell script for complete build """
# TODO(nuclearcat): Fetch firmware only if needed

Check warning on line 582 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

TODO(nuclearcat): Fetch firmware only if needed
print("Generating shell script")
fragnum = self._parse_fragments(firmware=True)
self._merge_frags(fragnum)
if not self._dtbs_check:
# TODO: verify if CONFIG_EXTRA_FIRMWARE have any files

Check warning on line 587 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

TODO: verify if CONFIG_EXTRA_FIRMWARE have any files
# We can check that if fragments have CONFIG_EXTRA_FIRMWARE
self._fetch_firmware()
self._build_kernel()
Expand Down Expand Up @@ -570,6 +612,7 @@

def write_script(self, filename):
""" Write shell compile script to file """
self._verify_network()
self._generate_script()
with open(filename, 'w') as f:
for step in self._steps:
Expand Down Expand Up @@ -640,7 +683,7 @@
""" Add kernel image packaging steps """
self.startjob("package_kimage")
self.addcmd("cd " + self._srcdir)
# TODO(nuclearcat): Not all images might be present

Check warning on line 686 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

TODO(nuclearcat): Not all images might be present
for img in KERNEL_IMAGE_NAMES[self._arch]:
self.addcmd("cp arch/" + self._arch + "/boot/" + img + " ../artifacts", False)
# add image to artifacts relative to artifacts dir
Expand Down Expand Up @@ -709,7 +752,7 @@

def serialize(self, filename):
""" Serialize class to json """
# TODO(nuclearcat): Implement to_json method?

Check warning on line 755 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

TODO(nuclearcat): Implement to_json method?
data = json.dumps(self, default=lambda o: o.__dict__,
sort_keys=True, indent=4)
with open(filename, 'w') as f:
Expand Down Expand Up @@ -854,7 +897,7 @@
api.node.update(node)
except requests.exceptions.HTTPError as err:
err_msg = json.loads(err.response.content).get("detail", [])
self.log.error(err_msg)

Check failure on line 900 in kernelci/kbuild.py

View workflow job for this annotation

GitHub Actions / Lint

Instance of 'KBuild' has no 'log' member
return

def submit(self, retcode, dry_run=False):
Expand Down
Loading