Exemplo n.º 1
0
def package_constraint_to_reference(constraint: PackageConstraint) -> PackageReference:
    package_name, version_constraint = constraint.name, constraint.constraint
    # Allow only specific version for now.
    # Later we can improve package manager to support
    # installing packages using expressions like 'package>1.0.0'
    if version_constraint == VersionRange():  # empty range means any version
        return PackageReference(package_name, None)
    if not isinstance(version_constraint, Version):
        raise PackageManagerError(f'Can only install specific version. '
                                  f'Use only following expression "{package_name}=<version>" '
                                  f'to install specific version')
    return PackageReference(package_name, version_to_tag(version_constraint))
Exemplo n.º 2
0
def package_constraint_to_reference(
        constraint: PackageConstraint) -> PackageReference:
    package_name, version_constraint = constraint.name, constraint.constraint
    # Allow only specific version for now.
    # Later we can improve package manager to support
    # installing packages using expressions like 'package>1.0.0'
    if version_constraint.expression == '*':
        return PackageReference(package_name, None)
    if not version_constraint.is_exact():
        raise PackageManagerError(
            f'Can only install specific version. '
            f'Use only following expression "{package_name}=<version>" '
            f'to install specific version')
    version = version_constraint.get_exact_version()
    return PackageReference(package_name, version_to_tag(version))
Exemplo n.º 3
0
    def reset(self,
              name: str,
              force: bool = False,
              skip_host_plugins: bool = False):
        """ Reset package to defaults version

        Args:
            name: SONiC Package name.
            force: Force the installation.
            skip_host_plugins: Skip host plugins installation.
        Raises:
            PackageManagerError
        """

        with failure_ignore(force):
            if not self.is_installed(name):
                raise PackageManagerError(f'{name} is not installed')

        package = self.get_installed_package(name)
        default_reference = package.entry.default_reference
        if default_reference is None:
            raise PackageManagerError(
                f'package {name} has no default reference')

        package_ref = PackageReference(name, default_reference)
        source = self.get_package_source(package_ref=package_ref)
        self.upgrade_from_source(source,
                                 force=force,
                                 allow_downgrade=True,
                                 skip_host_plugins=skip_host_plugins)
Exemplo n.º 4
0
def parse_reference_expression(expression):
    try:
        return package_constraint_to_reference(PackageConstraint.parse(expression))
    except ValueError:
        # if we failed to parse the expression as constraint expression
        # we will try to parse it as reference
        return PackageReference.parse(expression)
Exemplo n.º 5
0
    def migrate_packages(self,
                         old_package_database: PackageDatabase,
                         dockerd_sock: Optional[str] = None):
        """
        Migrate packages from old database. This function can do a comparison between
        current database and the database passed in as argument. If the package is
        missing in the current database it will be added. If the package is installed
        in the passed database and in the current it is not installed it will be
        installed with a passed database package version. If the package is installed
        in the passed database and it is installed in the current database but with
        older version the package will be upgraded to the never version. If the package
        is installed in the passed database and in the current it is installed but with
        never version - no actions are taken. If dockerd_sock parameter is passed, the
        migration process will use loaded images from docker library of the currently
        installed image.

        Args:
            old_package_database: SONiC Package Database to migrate packages from.
            dockerd_sock: Path to dockerd socket.
        Raises:
            PackageManagerError
        """

        self._migrate_package_database(old_package_database)

        def migrate_package(old_package_entry, new_package_entry):
            """ Migrate package routine

            Args:
                old_package_entry: Entry in old package database.
                new_package_entry: Entry in new package database.
            """

            name = new_package_entry.name
            version = new_package_entry.version

            if dockerd_sock:
                # dockerd_sock is defined, so use docked_sock to connect to
                # dockerd and fetch package image from it.
                log.info(f'installing {name} from old docker library')
                docker_api = DockerApi(
                    docker.DockerClient(base_url=f'unix://{dockerd_sock}'))

                image = docker_api.get_image(old_package_entry.image_id)

                with tempfile.NamedTemporaryFile('wb') as file:
                    for chunk in image.save(named=True):
                        file.write(chunk)
                    file.flush()

                    self.install(tarball=file.name)
            else:
                log.info(f'installing {name} version {version}')

                self.install(f'{name}={version}')

        # TODO: Topological sort packages by their dependencies first.
        for old_package in old_package_database:
            if not old_package.installed or old_package.built_in:
                continue

            log.info(f'migrating package {old_package.name}')

            new_package = self.database.get_package(old_package.name)

            if new_package.installed:
                if old_package.version > new_package.version:
                    log.info(f'{old_package.name} package version is greater '
                             f'then installed in new image: '
                             f'{old_package.version} > {new_package.version}')
                    log.info(
                        f'upgrading {new_package.name} to {old_package.version}'
                    )
                    new_package.version = old_package.version
                    migrate_package(old_package, new_package)
                else:
                    log.info(
                        f'skipping {new_package.name} as installed version is newer'
                    )
            elif new_package.default_reference is not None:
                new_package_ref = PackageReference(
                    new_package.name, new_package.default_reference)
                package_source = self.get_package_source(
                    package_ref=new_package_ref)
                package = package_source.get_package()
                new_package_default_version = package.manifest['package'][
                    'version']
                if old_package.version > new_package_default_version:
                    log.info(
                        f'{old_package.name} package version is lower '
                        f'then the default in new image: '
                        f'{old_package.version} > {new_package_default_version}'
                    )
                    new_package.version = old_package.version
                    migrate_package(old_package, new_package)
                else:
                    self.install(
                        f'{new_package.name}={new_package_default_version}')
            else:
                # No default version and package is not installed.
                # Migrate old package same version.
                new_package.version = old_package.version
                migrate_package(old_package, new_package)

            self.database.commit()
def test_reference():
    package_constraint = PackageReference.parse(
        'swss@sha256:9780f6d83e45878749497a6297ed9906c19ee0cc48cc88dc63827564bb8768fd'
    )
    assert package_constraint.name == 'swss'
    assert package_constraint.reference == 'sha256:9780f6d83e45878749497a6297ed9906c19ee0cc48cc88dc63827564bb8768fd'
def test_reference_invalid():
    with pytest.raises(ValueError):
        PackageReference.parse('swssfdsf')