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

Add upgrading of linux kernel #76

Merged
merged 7 commits into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
15 changes: 13 additions & 2 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from ops.main import main
from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus

from errors import MissingConfigurationError, RunnerError, SubprocessError
from errors import MissingConfigurationError, RunnerBinaryError, RunnerError, SubprocessError
from event_timer import EventTimer, TimerDisableError, TimerEnableError
from github_type import GitHubRunnerStatus
from runner import LXD_PROFILE_YAML
Expand Down Expand Up @@ -271,12 +271,16 @@ def _on_install(self, _event: InstallEvent) -> None:
self._stored.runner_bin_url = runner_info.download_url
runner_manager.update_runner_bin(runner_info)
# Safe guard against transient unexpected error.
except Exception as err: # pylint: disable=broad-exception-caught
except RunnerBinaryError as err:
logger.exception("Failed to update runner binary")
# Failure to download runner binary is a transient error.
# The charm automatically update runner binary on a schedule.
self.unit.status = MaintenanceStatus(f"Failed to update runner binary: {err}")
return

# Temporary solution: Upgrade the kernel due to a kernel bug in 5.15.
self._upgrade_kernel()

self.unit.status = MaintenanceStatus("Starting runners")
try:
self._reconcile_runners(runner_manager)
Expand All @@ -287,6 +291,12 @@ def _on_install(self, _event: InstallEvent) -> None:
else:
self.unit.status = BlockedStatus("Missing token or org/repo path config")

def _upgrade_kernel(self) -> None:
"""Upgrade the Linux kernel."""
execute_command(["/usr/bin/apt-get", "update"])
execute_command(["/usr/bin/apt-get", "install", "-qy", "linux-generic-hwe-22.04"])
execute_command(["reboot"])

@catch_charm_errors
def _on_upgrade_charm(self, _event: UpgradeCharmEvent) -> None:
"""Handle the update of charm.
Expand Down Expand Up @@ -549,6 +559,7 @@ def _install_deps(self) -> None:
env["NO_PROXY"] = self.proxies["no_proxy"]
env["no_proxy"] = self.proxies["no_proxy"]

execute_command(["/usr/bin/apt-get", "update"])
execute_command(["/usr/bin/apt-get", "install", "-qy", "gunicorn", "python3-pip"])
execute_command(
[
Expand Down
48 changes: 28 additions & 20 deletions src/runner_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,30 +190,40 @@ def update_runner_bin(self, binary: RunnerApplication) -> None:
"""
logger.info("Downloading runner binary from: %s", binary["download_url"])

# Delete old version of runner binary.
RunnerManager.runner_bin_path.unlink(missing_ok=True)
try:
# Delete old version of runner binary.
RunnerManager.runner_bin_path.unlink(missing_ok=True)
except OSError as err:
logger.exception("Unable to perform file operation on the runner binary path")
raise RunnerBinaryError("File operation failed on the runner binary path") from err

# Download the new file
response = self.session.get(binary["download_url"], stream=True)
try:
# Download the new file
response = self.session.get(binary["download_url"], stream=True)

logger.info(
"Download of runner binary from %s return status code: %i",
binary["download_url"],
response.status_code,
)
logger.info(
"Download of runner binary from %s return status code: %i",
binary["download_url"],
response.status_code,
)

if not binary["sha256_checksum"]:
logger.error("Checksum for runner binary is not found, unable to verify download.")
raise RunnerBinaryError("Checksum for runner binary is not found in GitHub response.")
if not binary["sha256_checksum"]:
logger.error("Checksum for runner binary is not found, unable to verify download.")
raise RunnerBinaryError(
"Checksum for runner binary is not found in GitHub response."
)

sha256 = hashlib.sha256()
sha256 = hashlib.sha256()

with RunnerManager.runner_bin_path.open(mode="wb") as file:
# Process with chunk_size of 128 KiB.
for chunk in response.iter_content(chunk_size=128 * 1024, decode_unicode=False):
file.write(chunk)
with RunnerManager.runner_bin_path.open(mode="wb") as file:
# Process with chunk_size of 128 KiB.
for chunk in response.iter_content(chunk_size=128 * 1024, decode_unicode=False):
file.write(chunk)

sha256.update(chunk)
sha256.update(chunk)
except requests.RequestException as err:
logger.exception("Failed to download of runner binary")
raise RunnerBinaryError("Failed to download runner binary") from err

logger.info("Finished download of runner binary.")

Expand All @@ -224,13 +234,11 @@ def update_runner_bin(self, binary: RunnerApplication) -> None:
binary["sha256_checksum"],
sha256,
)
RunnerManager.runner_bin_path.unlink(missing_ok=True)
raise RunnerBinaryError("Checksum mismatch for downloaded runner binary")

# Verify the file integrity.
if not tarfile.is_tarfile(file.name):
logger.error("Failed to decompress downloaded GitHub runner binary.")
RunnerManager.runner_bin_path.unlink(missing_ok=True)
raise RunnerBinaryError("Downloaded runner binary cannot be decompressed.")

logger.info("Validated newly downloaded runner binary and enabled it.")
Expand Down