From 57a4d071b4bda1ad15dd08ffc200d23cd02c6928 Mon Sep 17 00:00:00 2001 From: Charles Short Date: Wed, 11 Oct 2023 13:17:46 -0400 Subject: [PATCH] Add "export/import" support Add the ability to export and import ostree branches into an ostree repository. The way that this works is that apt-ostree uses "the ostree pull-local" command to import or export an ostree branch into a repository. This allows the user to easily import a branch from an extermal source, like an ISO. The methods that are called "backup" and "restore" so the CLI library wont get traceback when trying to run them. Story: 2010867 Task: 48556 Change-Id: Ic1791089118a64ab491673abcaec1559c725eaa9 Signed-off-by: Charles Short --- apt_ostree/cmd/compose/__init__.py | 4 ++++ apt_ostree/cmd/compose/backup.py | 38 ++++++++++++++++++++++++++++++ apt_ostree/cmd/compose/restore.py | 38 ++++++++++++++++++++++++++++++ apt_ostree/compose.py | 27 +++++++++++++++++++++ apt_ostree/ostree.py | 8 +++++++ 5 files changed, 115 insertions(+) create mode 100644 apt_ostree/cmd/compose/backup.py create mode 100644 apt_ostree/cmd/compose/restore.py diff --git a/apt_ostree/cmd/compose/__init__.py b/apt_ostree/cmd/compose/__init__.py index 58f2d6d..70aaca0 100644 --- a/apt_ostree/cmd/compose/__init__.py +++ b/apt_ostree/cmd/compose/__init__.py @@ -7,12 +7,14 @@ SPDX-License-Identifier: Apache-2.0 import click +from apt_ostree.cmd.compose.backup import backup from apt_ostree.cmd.compose.commit import commit from apt_ostree.cmd.compose.create import create from apt_ostree.cmd.compose.image import image from apt_ostree.cmd.compose.init import init from apt_ostree.cmd.compose.install import install from apt_ostree.cmd.compose.repo import repo +from apt_ostree.cmd.compose.restore import restore from apt_ostree.cmd.compose.uninstall import uninstall from apt_ostree.cmd.compose.upgrade import upgrade @@ -23,6 +25,7 @@ def compose(ctxt): pass +compose.add_command(backup) compose.add_command(commit) compose.add_command(create) compose.add_command(image) @@ -30,4 +33,5 @@ compose.add_command(init) compose.add_command(install) compose.add_command(upgrade) compose.add_command(repo) +compose.add_command(restore) compose.add_command(uninstall) diff --git a/apt_ostree/cmd/compose/backup.py b/apt_ostree/cmd/compose/backup.py new file mode 100644 index 0000000..dc6ece0 --- /dev/null +++ b/apt_ostree/cmd/compose/backup.py @@ -0,0 +1,38 @@ +""" +Copyright (c) 2023 Wind River Systems, Inc. + +SPDX-License-Identifier: Apache-2.0 + +""" + +import errno +import sys + +import click + +from apt_ostree.cmd.options import branch_option +from apt_ostree.cmd.options import repo_option +from apt_ostree.cmd import pass_state_context +from apt_ostree.compose import Compose + + +@click.command( + name="export", + help="Export a branch from an ostree repository.") +@pass_state_context +@repo_option +@branch_option +@click.argument( + "export_dir" +) +def backup(state, repo, branch, export_dir): + try: + Compose(state).backup(export_dir) + except KeyboardInterrupt: + click.secho("\n" + ("Exiting at your request.")) + sys.exit(130) + except BrokenPipeError: + sys.exit() + except OSError as error: + if error.errno == errno.ENOSPC: + sys.exit("error - No space left on device.") diff --git a/apt_ostree/cmd/compose/restore.py b/apt_ostree/cmd/compose/restore.py new file mode 100644 index 0000000..527e566 --- /dev/null +++ b/apt_ostree/cmd/compose/restore.py @@ -0,0 +1,38 @@ +""" +Copyright (c) 2023 Wind River Systems, Inc. + +SPDX-License-Identifier: Apache-2.0 + +""" + +import errno +import sys + +import click + +from apt_ostree.cmd.options import branch_option +from apt_ostree.cmd.options import repo_option +from apt_ostree.cmd import pass_state_context +from apt_ostree.compose import Compose + + +@click.command( + name="import", + help="Import a branch from an ostree repository.") +@pass_state_context +@repo_option +@branch_option +@click.argument( + "export_dir" +) +def restore(state, repo, branch, export_dir): + try: + Compose(state).restore(export_dir) + except KeyboardInterrupt: + click.secho("\n" + ("Exiting at your request.")) + sys.exit(130) + except BrokenPipeError: + sys.exit() + except OSError as error: + if error.errno == errno.ENOSPC: + sys.exit("error - No space left on device.") diff --git a/apt_ostree/compose.py b/apt_ostree/compose.py index d0d497a..034333c 100644 --- a/apt_ostree/compose.py +++ b/apt_ostree/compose.py @@ -5,6 +5,7 @@ SPDX-License-Identifier: Apache-2.0 """ import logging +import pathlib import shutil import sys @@ -38,6 +39,32 @@ class Compose: self.logging.info(f"Found ostree repository: {self.state.repo}") self.ostree.init() + 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.console.print( + f"Pulling from {self.state.branch} to {export_dir}.", + highlight=False) + self.ostree.ostree_pull(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.console.print( + f"Pulling from {self.state.branch} to {import_dir}.", + highlight=False) + self.ostree.ostree_pull(import_dir) + def enablerepo(self): """Enable Debian package feed.""" try: diff --git a/apt_ostree/ostree.py b/apt_ostree/ostree.py index 14f09e0..a536fab 100644 --- a/apt_ostree/ostree.py +++ b/apt_ostree/ostree.py @@ -42,6 +42,14 @@ class Ostree: self.logging.error(f"Failed to create repo: {e}") sys.exit(1) + def ostree_pull(self, repo_dir): + """Copy a branch from an existing repo into a new repo.""" + return run_command( + ["ostree", "pull-local", f"--repo={repo_dir}", + str(self.state.repo), str(self.state.branch)], + check=True + ) + def ostree_commit(self, root=None, repo=None,