
When ostree changes a repository it requires a summary update for the changes to be seen by clients of this remote repository. This commit adds summary update call after every change in the repo. Test Plan: PASS: Deploy a host after a deploy start to apply PASS: Undeploy a host after a deploy start to remove PASS: Undeploy a host after an abort Story: 2010676 Task: 51017 Change-Id: I276fd823b81db8c66cb0c83f8ab19f963d182bf0 Signed-off-by: Lindley Vieira <lindley.vieira@windriver.com>
146 lines
4.7 KiB
Python
146 lines
4.7 KiB
Python
"""
|
|
Copyright (c) 2023 Wind River Systems, Inc.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
|
|
"""
|
|
import logging
|
|
import pathlib
|
|
import shutil
|
|
import sys
|
|
|
|
|
|
from rich.console import Console
|
|
|
|
from apt_ostree.deploy import Deploy
|
|
from apt_ostree.ostree import Ostree
|
|
from apt_ostree.repo import Repo
|
|
|
|
|
|
class Compose:
|
|
def __init__(self, state):
|
|
self.logging = logging.getLogger(__name__)
|
|
self.state = state
|
|
self.ostree = Ostree(self.state)
|
|
self.repo = Repo(self.state)
|
|
self.deploy = Deploy(self.state)
|
|
self.console = Console()
|
|
|
|
self.workspace = self.state.workspace
|
|
self.workdir = self.state.workspace.joinpath("deployment")
|
|
self.workdir.mkdir(parents=True, exist_ok=True)
|
|
self.rootfs = None
|
|
|
|
def create(self):
|
|
"""Create an OSTree repository."""
|
|
if self.state.repo.exists():
|
|
self.logging.error(
|
|
f"Repository already exists: {self.state.repo}")
|
|
sys.exit(1)
|
|
|
|
self.logging.info(f"Found ostree repository: {self.state.repo}")
|
|
self.ostree.init()
|
|
|
|
def rollback(self, commit):
|
|
"""Rolling back to a previous commit."""
|
|
self.logging.info(f"Rollback back to {commit}.")
|
|
self.ostree.ostree_rollback(commit)
|
|
|
|
self.ostree.ostree_summary_update()
|
|
|
|
def backup(self, export_dir):
|
|
"""Export branch to a new ostree repo."""
|
|
export_dir = pathlib.Path(export_dir)
|
|
if not export_dir.exists():
|
|
self.logging.error("Ostree export repo does not exist")
|
|
sys.exit(1)
|
|
|
|
# Copy the existing branch from one repository to another.
|
|
self.logging.info(
|
|
f"Pulling from {self.state.branch} to {export_dir}.")
|
|
self.ostree.ostree_pull(export_dir)
|
|
|
|
self.ostree.ostree_summary_update(export_dir)
|
|
|
|
def restore(self, import_dir):
|
|
"""Import a branch into a repostiory."""
|
|
import_dir = pathlib.Path(import_dir)
|
|
if not import_dir.exists():
|
|
self.logging.error("Ostree import repo does not exist")
|
|
sys.exit(1)
|
|
|
|
# Copy the existing branch from one repository to another.
|
|
self.logging.info(
|
|
f"Pulling from {self.state.branch} to {import_dir}.")
|
|
self.ostree.ostree_pull(import_dir)
|
|
|
|
self.ostree.ostree_summary_update(import_dir)
|
|
|
|
def enablerepo(self):
|
|
"""Enable Debian package feed."""
|
|
try:
|
|
self.repo.add_repo()
|
|
except Exception as e:
|
|
self.logging.error(f"Failed to add repo: {e}")
|
|
sys.exit(1)
|
|
|
|
def disablerepo(self):
|
|
self.repo.disable_repo()
|
|
|
|
def checkout(self, rootfs):
|
|
rootfs = pathlib.Path(rootfs)
|
|
if rootfs.exists():
|
|
self.logging.error(f"Directory already exists: {rootfs}")
|
|
sys.exit(1)
|
|
|
|
self._checkout(rootfs, self.state.branch)
|
|
self.deploy.prestaging(rootfs)
|
|
|
|
def commit(self, parent):
|
|
"""Commit changes to an ostree repo."""
|
|
self.logging.info(f"Cloning {self.state.branch} from {parent}.")
|
|
rev = self._checkout(parent)
|
|
if not rev:
|
|
self.logging.error("Failed to fetch commit")
|
|
sys.exit(1)
|
|
with self.console.status(f"Commiting {rev[:10]}."):
|
|
r = self.ostree.ostree_commit(
|
|
root=self.rootfs,
|
|
branch=self.state.branch,
|
|
parent=rev,
|
|
repo=self.state.repo,
|
|
subject="Forked from parent",
|
|
msg=f"Forked from {parent} ({rev[:10]})."
|
|
)
|
|
if r.returncode != 0:
|
|
self.logging.error("Failed to commit.")
|
|
sys.exit(1)
|
|
|
|
self.logging.info(f"Successfully commited {self.state.branch}"
|
|
f"({rev[:10]}) from {parent}.")
|
|
self.ostree.ostree_summary_update(self.state.repo)
|
|
self.logging.info("Cleaning up.")
|
|
try:
|
|
shutil.rmtree(self.rootfs)
|
|
except OSError as e:
|
|
self.logging.error(f"Failed to remove rootfs {self.rootfs}: {e}")
|
|
|
|
def _checkout(self, rootfs=None, branch=None):
|
|
"""Checkout a commit from an ostree branch."""
|
|
if branch is not None:
|
|
rev = self.ostree.ostree_ref(branch)
|
|
|
|
with self.console.status(f"Checking out {rev[:10]}..."):
|
|
self.workdir = self.workdir.joinpath(branch)
|
|
if rootfs:
|
|
if rootfs.exists():
|
|
shutil.rmtree(rootfs)
|
|
self.rootfs = rootfs
|
|
else:
|
|
self.workdir.mkdir(parents=True, exist_ok=True)
|
|
self.rootfs = self.workdir.joinpath(rev)
|
|
if self.rootfs.exists():
|
|
shutil.rmtree(self.rootfs)
|
|
self.ostree.ostree_checkout(branch, self.rootfs)
|
|
return rev
|