Skip to content

ThirdPartyContainerManagement(TPCM)_in_SonicPackageManager #2815

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

Merged
merged 4 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@
'xmltodict==0.12.0',
'lazy-object-proxy',
'six==1.16.0',
'scp==0.14.5',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the version number as per suggestion

] + sonic_dependencies,
setup_requires= [
'pytest-runner',
Expand Down
4 changes: 4 additions & 0 deletions sonic_installer/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,8 @@ def migrate_sonic_packages(bootloader, binary_image_version):
new_image_docker_mount = os.path.join(new_image_mount, "var", "lib", "docker")
docker_default_config = os.path.join(new_image_mount, "etc", "default", "docker")
docker_default_config_backup = os.path.join(new_image_mount, TMP_DIR, "docker_config_backup")
custom_manifests_path = os.path.join(PACKAGE_MANAGER_DIR, "manifests")
new_image_package_directory_path = os.path.join(new_image_mount, "var", "lib", "sonic-package-manager")

if not os.path.isdir(new_image_docker_dir):
# NOTE: This codepath can be reached if the installation process did not
Expand Down Expand Up @@ -372,6 +374,8 @@ def migrate_sonic_packages(bootloader, binary_image_version):
run_command_or_raise(["chroot", new_image_mount, DOCKER_CTL_SCRIPT, "start"])
docker_started = True
run_command_or_raise(["cp", packages_path, os.path.join(new_image_mount, TMP_DIR, packages_file)])
run_command_or_raise(["mkdir", "-p", custom_manifests_path])
run_command_or_raise(["cp", "-arf", custom_manifests_path, new_image_package_directory_path])
run_command_or_raise(["touch", os.path.join(new_image_mount, "tmp", DOCKERD_SOCK)])
run_command_or_raise(["mount", "--bind",
os.path.join(VAR_RUN_PATH, DOCKERD_SOCK),
Expand Down
129 changes: 128 additions & 1 deletion sonic_package_manager/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from sonic_package_manager.errors import PackageManagerError
from sonic_package_manager.logger import log
from sonic_package_manager.manager import PackageManager
from sonic_package_manager.manifest import MANIFESTS_LOCATION

BULLET_UC = '\u2022'

Expand Down Expand Up @@ -157,6 +158,13 @@ def repository(ctx):
pass


@cli.group()
@click.pass_context
def manifests(ctx):
""" Custom local Manifest management commands. """

pass

@cli.group()
@click.pass_context
def show(ctx):
Expand Down Expand Up @@ -280,6 +288,73 @@ def changelog(ctx,
exit_cli(f'Failed to print package changelog: {err}', fg='red')


@manifests.command('create')
@click.pass_context
@click.argument('name', type=click.Path())
@click.option('--from-json', type=str, help='specify manifest json file')
@root_privileges_required
def create_manifest(ctx, name, from_json):
"""Create a new custom local manifest file."""

manager: PackageManager = ctx.obj
try:
manager.create_package_manifest(name, from_json)
except Exception as e:
click.echo("Error: Manifest {} creation failed - {}".format(name, str(e)))
return


@manifests.command('update')
@click.pass_context
@click.argument('name', type=click.Path())
@click.option('--from-json', type=str, required=True)
@root_privileges_required
def update_manifest(ctx, name, from_json):
"""Update an existing custom local manifest file with new one."""

manager: PackageManager = ctx.obj
try:
manager.update_package_manifest(name, from_json)
except Exception as e:
click.echo(f"Error occurred while updating manifest '{name}': {e}")
return


@manifests.command('delete')
@click.pass_context
@click.argument('name', type=click.Path())
@root_privileges_required
def delete_manifest(ctx, name):
"""Delete a custom local manifest file."""
manager: PackageManager = ctx.obj
try:
manager.delete_package_manifest(name)
except Exception as e:
click.echo("Error: Failed to delete manifest file '{}'. {}".format(name, e))


@manifests.command('show')
@click.pass_context
@click.argument('name', type=click.Path())
@root_privileges_required
def show_manifest(ctx, name):
"""Show the contents of custom local manifest file."""
manager: PackageManager = ctx.obj
try:
manager.show_package_manifest(name)
except FileNotFoundError:
click.echo("Manifest file '{}' not found.".format(name))


@manifests.command('list')
@click.pass_context
@root_privileges_required
def list_manifests(ctx):
"""List all custom local manifest files."""
manager: PackageManager = ctx.obj
manager.list_package_manifest()


@repository.command()
@click.argument('name', type=str)
@click.argument('repository', type=str)
Expand Down Expand Up @@ -334,6 +409,14 @@ def remove(ctx, name):
help='Allow package downgrade. By default an attempt to downgrade the package '
'will result in a failure since downgrade might not be supported by the package, '
'thus requires explicit request from the user.')
@click.option('--use-local-manifest',
is_flag=True,
default=None,
help='Use locally created custom manifest file. ',
hidden=True)
@click.option('--name',
type=str,
help='custom name for the package')
@add_options(PACKAGE_SOURCE_OPTIONS)
@add_options(PACKAGE_COMMON_OPERATION_OPTIONS)
@add_options(PACKAGE_COMMON_INSTALL_OPTIONS)
Expand All @@ -348,7 +431,9 @@ def install(ctx,
enable,
set_owner,
skip_host_plugins,
allow_downgrade):
allow_downgrade,
use_local_manifest,
name):
""" Install/Upgrade package using [PACKAGE_EXPR] in format "<name>[=<version>|@<reference>]".

The repository to pull the package from is resolved by lookup in package database,
Expand Down Expand Up @@ -378,16 +463,58 @@ def install(ctx,
if allow_downgrade is not None:
install_opts['allow_downgrade'] = allow_downgrade

if use_local_manifest:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please disallow the use of custom user manifest on dockers that provide their own. This might create a lot of irrelevant complains from customers trying to do that and breaking the package functionality. Only allow to use custom manifest on dockers that don't have them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, I have made this option(use_local_manifest) to be hidden. Have kept this code as such in case if there is a requirement in future to override the built-in manifest.

if not name:
click.echo('name argument is not provided to use local manifest')
return
original_file = os.path.join(MANIFESTS_LOCATION, name)
if not os.path.exists(original_file):
click.echo(f'Local Manifest file for {name} does not exists to install')
return

try:
manager.install(package_expr,
from_repository,
from_tarball,
use_local_manifest,
name,
**install_opts)
except Exception as err:
exit_cli(f'Failed to install {package_source}: {err}', fg='red')
except KeyboardInterrupt:
exit_cli('Operation canceled by user', fg='red')

# At the end of sonic-package-manager install, a new manifest file is created with the name.
# At the end of sonic-package-manager uninstall name,
# this manifest file name and name.edit will be deleted.
# At the end of sonic-package-manager update,
# we need to mv maniests name.edit to name in case of success, else keep it as such.
# So during sonic-package-manager update,
# we could take old package from name and new package from edit and at the end, follow 3rd point


@cli.command()
@add_options(PACKAGE_COMMON_OPERATION_OPTIONS)
@add_options(PACKAGE_COMMON_INSTALL_OPTIONS)
@click.argument('name')
@click.pass_context
@root_privileges_required
def update(ctx, name, force, yes, skip_host_plugins):
""" Update package to the updated manifest file. """

manager: PackageManager = ctx.obj

update_opts = {
'force': force,
'skip_host_plugins': skip_host_plugins,
'update_only': True,
}
try:
manager.update(name, **update_opts)
except Exception as err:
exit_cli(f'Failed to update package {name}: {err}', fg='red')
except KeyboardInterrupt:
exit_cli('Operation canceled by user', fg='red')

@cli.command()
@add_options(PACKAGE_COMMON_OPERATION_OPTIONS)
Expand Down
Loading
Loading