openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

100 lines
2.6 KiB

import abc
import os
from pathlib import Path
import subprocess
from typing import List
from markdown_it import MarkdownIt
from openpilot.common.params import Params
from openpilot.common.swaglog import cloudlog
LOCK_FILE = os.getenv("UPDATER_LOCK_FILE", "/tmp/safe_staging_overlay.lock")
STAGING_ROOT = os.getenv("UPDATER_STAGING_ROOT", "/data/safe_staging")
FINALIZED = os.path.join(STAGING_ROOT, "finalized")
def run(cmd: list[str], cwd: str = None) -> str:
return subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT, encoding='utf8')
class UpdateStrategy(abc.ABC):
def __init__(self):
self.params = Params()
@abc.abstractmethod
def init(self) -> None:
pass
@abc.abstractmethod
def cleanup(self) -> None:
pass
@abc.abstractmethod
def get_available_channels(self) -> List[str]:
"""List of available channels to install, (branches, releases, etc)"""
@abc.abstractmethod
def current_channel(self) -> str:
"""Current channel installed"""
@abc.abstractmethod
def fetched_path(self) -> str:
"""Path to the fetched update"""
@property
def target_channel(self) -> str:
"""Target Channel"""
b: str | None = self.params.get("UpdaterTargetBranch", encoding='utf-8')
if b is None:
b = self.current_channel()
return b
@abc.abstractmethod
def update_ready(self) -> bool:
"""Check if an update is ready to be installed"""
@abc.abstractmethod
def update_available(self) -> bool:
"""Check if an update is available for the current channel"""
@abc.abstractmethod
def describe_current_channel(self) -> tuple[str, str]:
"""Describe the current channel installed, (description, release_notes)"""
@abc.abstractmethod
def describe_ready_channel(self) -> tuple[str, str]:
"""Describe the channel that is ready to be installed, (description, release_notes)"""
@abc.abstractmethod
def fetch_update(self) -> None:
pass
@abc.abstractmethod
def finalize_update(self) -> None:
pass
def set_consistent_flag(consistent: bool) -> None:
os.sync()
consistent_file = Path(os.path.join(FINALIZED, ".overlay_consistent"))
if consistent:
consistent_file.touch()
elif not consistent:
consistent_file.unlink(missing_ok=True)
os.sync()
def parse_release_notes(releases_md: str) -> str:
try:
r = releases_md.split('\n\n', 1)[0] # Slice latest release notes
try:
return str(MarkdownIt().render(r))
except Exception:
return r + "\n"
except FileNotFoundError:
pass
except Exception:
cloudlog.exception("failed to parse release notes")
return ""