コード例 #1
0
ファイル: images.py プロジェクト: B-Rich/productmd
class Images(productmd.common.MetadataBase):
    def __init__(self):
        super(Images, self).__init__()
        self.header = Header(self)
        self.compose = Compose(self)
        self.images = {}

    def __getitem__(self, variant):
        return self.images[variant]

    def __delitem__(self, variant):
        del self.images[variant]

    def serialize(self, parser):
        data = parser
        self.header.serialize(data)
        data["payload"] = {}
        data["payload"]["images"] = {}
        self.compose.serialize(data["payload"])
        for variant in self.images:
            for arch in self.images[variant]:
                for image_obj in self.images[variant][arch]:
                    images = data["payload"]["images"].setdefault(
                        variant, {}).setdefault(arch, [])
                    image_obj.serialize(images)
                    images.sort(key=lambda x: x["path"])
        return data

    def deserialize(self, data):
        self.header.deserialize(data)
        self.compose.deserialize(data["payload"])
        for variant in data["payload"]["images"]:
            for arch in data["payload"]["images"][variant]:
                for image in data["payload"]["images"][variant][arch]:
                    image_obj = Image(self)
                    image_obj.deserialize(image)
                    self.add(variant, arch, image_obj)
        self.header.set_current_version()

    def add(self, variant, arch, image):
        """
        Assign an :class:`.Image` object to variant and arch.

        :param variant: compose variant UID
        :type  variant: str
        :param arch:    compose architecture
        :type  arch:    str
        :param image:   image
        :type  image:   :class:`.Image`
        """

        if arch not in productmd.common.RPM_ARCHES:
            raise ValueError("Arch not found in RPM_ARCHES: %s" % arch)
        self.images.setdefault(variant, {}).setdefault(arch, set()).add(image)
コード例 #2
0
ファイル: images.py プロジェクト: AdamWill/productmd
class Images(productmd.common.MetadataBase):
    def __init__(self):
        super(Images, self).__init__()
        self.header = Header(self)
        self.compose = Compose(self)
        self.images = {}

    def __getitem__(self, variant):
        return self.images[variant]

    def __delitem__(self, variant):
        del self.images[variant]

    def serialize(self, parser):
        data = parser
        self.header.serialize(data)
        data["payload"] = {}
        data["payload"]["images"] = {}
        self.compose.serialize(data["payload"])
        for variant in self.images:
            for arch in self.images[variant]:
                for image_obj in self.images[variant][arch]:
                    images = data["payload"]["images"].setdefault(variant, {}).setdefault(arch, [])
                    image_obj.serialize(images)
                    images.sort(key=lambda x: x["path"])
        return data

    def deserialize(self, data):
        self.header.deserialize(data)
        self.compose.deserialize(data["payload"])
        for variant in data["payload"]["images"]:
            for arch in data["payload"]["images"][variant]:
                for image in data["payload"]["images"][variant][arch]:
                    image_obj = Image(self)
                    image_obj.deserialize(image)
                    self.add(variant, arch, image_obj)
        self.header.set_current_version()

    def add(self, variant, arch, image):
        """
        Assign an :class:`.Image` object to variant and arch.

        :param variant: compose variant UID
        :type  variant: str
        :param arch:    compose architecture
        :type  arch:    str
        :param image:   image
        :type  image:   :class:`.Image`
        """

        if arch not in productmd.common.RPM_ARCHES:
            raise ValueError("Arch not found in RPM_ARCHES: %s" % arch)
        self.images.setdefault(variant, {}).setdefault(arch, set()).add(image)
コード例 #3
0
class Images(productmd.common.MetadataBase):
    def __init__(self):
        super(Images, self).__init__()
        self.header = Header(self, "productmd.images")
        self.compose = Compose(self)
        self.images = {}

    def __getitem__(self, variant):
        return self.images[variant]

    def __delitem__(self, variant):
        del self.images[variant]

    def serialize(self, parser):
        data = parser
        self.header.serialize(data)
        data["payload"] = {}
        data["payload"]["images"] = {}
        self.compose.serialize(data["payload"])
        for variant in self.images:
            for arch in self.images[variant]:
                for image_obj in self.images[variant][arch]:
                    images = data["payload"]["images"].setdefault(
                        variant, {}).setdefault(arch, [])
                    image_obj.serialize(images)
                    images.sort(key=lambda x: x["path"])
        return data

    def deserialize(self, data):
        self.header.deserialize(data)
        self.compose.deserialize(data["payload"])
        for variant in data["payload"]["images"]:
            for arch in data["payload"]["images"][variant]:
                for image in data["payload"]["images"][variant][arch]:
                    image_obj = Image(self)
                    image_obj.deserialize(image)
                    if self.header.version_tuple <= (1, 1):
                        self._add_1_1(data, variant, arch, image_obj)
                    else:
                        self.add(variant, arch, image_obj)
        self.header.set_current_version()

    def _add_1_1(self, data, variant, arch, image):
        if arch == "src":
            # move src under binary arches
            for variant_arch in data["payload"]["images"][variant]:
                if variant_arch == "src":
                    continue
                self.add(variant, variant_arch, image)
        else:
            self.add(variant, arch, image)

    def add(self, variant, arch, image):
        """
        Assign an :class:`.Image` object to variant and arch.

        :param variant: compose variant UID
        :type  variant: str
        :param arch:    compose architecture
        :type  arch:    str
        :param image:   image
        :type  image:   :class:`.Image`
        """

        if arch not in productmd.common.RPM_ARCHES:
            raise ValueError("Arch not found in RPM_ARCHES: %s" % arch)
        if arch in ["src", "nosrc"]:
            raise ValueError(
                "Source arch is not allowed. Map source files under binary arches."
            )
        if self.header.version_tuple >= (1, 1):
            # disallow adding a different image with same 'unique'
            # attributes. can't do this pre-1.1 as we couldn't truly
            # identify images before subvariant
            for checkvar in self.images:
                for checkarch in self.images[checkvar]:
                    for curimg in self.images[checkvar][checkarch]:
                        if identify_image(curimg) == identify_image(
                                image) and curimg.checksums != image.checksums:
                            raise ValueError(
                                "Image {0} shares all UNIQUE_IMAGE_ATTRIBUTES with "
                                "image {1}! This is forbidden.".format(
                                    image, curimg))
        self.images.setdefault(variant, {}).setdefault(arch, set()).add(image)
コード例 #4
0
ファイル: composeinfo.py プロジェクト: jkonecny12/productmd
class ComposeInfo(productmd.common.MetadataBase):
    """
    This class only encapsulates other classes with actual data.
    """
    def __init__(self):
        super(ComposeInfo, self).__init__()

        self.header = Header(
            self,
            "productmd.composeinfo")  #: (:class:`.Header`) -- Metadata header
        self.compose = Compose(self)  #: (:class:`.Compose`) -- Compose details
        self.release = Release(self)  #: (:class:`.Release`) -- Release details
        self.base_product = BaseProduct(
            self
        )  #: (:class:`.BaseProduct`) -- Base product details (optional)
        self.variants = Variants(
            self)  #: (:class:`.Variants`) -- release variants
        self.validate()
        self.header.set_current_version()

    def __str__(self):
        result = self.release_id
        if self.compose.label:
            result += " (%s)" % self.compose.label
        return result

    def __cmp__(self, other):
        result = cmp(self.release, other.release)
        if result != 0:
            return result

        result = cmp(self.base_product, other.base_product)
        if result != 0:
            return result

        result = cmp(self.compose, other.compose)
        if result != 0:
            return result

        return 0

    def get_release_id(self, major_version=False):
        if major_version:
            result = "%s-%s" % (self.release.short, self.release.major_version)
        else:
            result = "%s-%s" % (self.release.short, self.release.version)
        if self.release.is_layered:
            result += "-%s-%s" % (self.base_product.short,
                                  self.base_product.version)
        return result

    @property
    def release_id(self):
        return self.get_release_id()

    def create_compose_id(self):
        result = "%s-%s%s" % (self.release.short, self.release.version,
                              self.release.type_suffix)
        if self.release.is_layered:
            result += "-%s-%s%s" % (self.base_product.short,
                                    self.base_product.version,
                                    self.base_product.type_suffix)

        rhel5 = (self.release.short == "RHEL"
                 and self.release.major_version == "5")
        rhel5 &= (self.base_product.short == "RHEL"
                  and self.base_product.major_version == "5")
        if rhel5:
            # HACK: there are 2 RHEL 5 composes -> need to add Server or Client variant to compose ID
            if self.variants.variants:
                variant = sorted(self.variants.variants)[0]
                if variant in ("Client", "Server"):
                    result += "-%s" % variant
        result += "-%s%s.%s" % (self.compose.date, self.compose.type_suffix,
                                self.compose.respin)
        return result

    def serialize(self, parser):
        data = parser
        self.header.serialize(data)
        data["payload"] = {}
        self.compose.serialize(data["payload"])
        self.release.serialize(data["payload"])
        if self.release.is_layered:
            self.base_product.serialize(data["payload"])
        self.variants.serialize(data["payload"])
        return data

    def deserialize(self, data):
        self.header.deserialize(data)
        self.compose.deserialize(data["payload"])
        self.release.deserialize(data["payload"])
        if self.release.is_layered:
            self.base_product.deserialize(data["payload"])
        self.variants.deserialize(data["payload"])
        self.header.set_current_version()

    def __getitem__(self, name):
        return self.variants[name]

    def get_variants(self, *args, **kwargs):
        return self.variants.get_variants(*args, **kwargs)
コード例 #5
0
ファイル: composeinfo.py プロジェクト: AdamWill/productmd
class ComposeInfo(productmd.common.MetadataBase):
    """
    This class only encapsulates other classes with actual data.
    """

    def __init__(self):
        super(ComposeInfo, self).__init__()

        self.header = Header(self)              #: (:class:`.Header`) -- Metadata header
        self.compose = Compose(self)            #: (:class:`.Compose`) -- Compose details
        self.release = Release(self)            #: (:class:`.Release`) -- Release details
        self.base_product = BaseProduct(self)   #: (:class:`.BaseProduct`) -- Base product details (optional)
        self.variants = Variants(self)          #: (:class:`.Variants`) -- release variants
        self.validate()
        self.header.set_current_version()

    def __str__(self):
        result = self.release_id
        if self.compose.label:
            result += " (%s)" % self.compose.label
        return result

    def __cmp__(self, other):
        result = cmp(self.release, other.product)
        if result != 0:
            return result

        result = cmp(self.base_product, other.base_product)
        if result != 0:
            return result

        result = cmp(self.compose, other.compose)
        if result != 0:
            return result

        return 0

    def get_release_id(self, major_version=False):
        if major_version:
            result = "%s-%s" % (self.release.short, self.release.major_version)
        else:
            result = "%s-%s" % (self.release.short, self.release.version)
        if self.release.is_layered:
            result += "-%s-%s" % (self.base_product.short, self.base_product.version)
        return result

    @property
    def release_id(self):
        return self.get_release_id()

    def create_compose_id(self):
        result = "%s-%s" % (self.release.short, self.release.version)
        if self.release.is_layered:
            result += "-%s-%s" % (self.base_product.short, self.base_product.version)

        rhel5 = (self.release.short == "RHEL" and self.release.major_version == "5")
        rhel5 &= (self.base_product.short == "RHEL" and self.base_product.major_version == "5")
        if rhel5:
            # HACK: there are 2 RHEL 5 composes -> need to add Server or Client variant to compose ID
            if self.variants.variants:
                variant = sorted(self.variants.variants)[0]
                if variant in ("Client", "Server"):
                    result += "-%s" % variant
        result += "-%s%s.%s" % (self.compose.date, self.compose.type_suffix, self.compose.respin)
        return result

    def serialize(self, parser):
        data = parser
        self.header.serialize(data)
        data["payload"] = {}
        self.compose.serialize(data["payload"])
        self.release.serialize(data["payload"])
        if self.release.is_layered:
            self.base_product.serialize(data["payload"])
        self.variants.serialize(data["payload"])
        return data

    def deserialize(self, data):
        self.header.deserialize(data)
        self.compose.deserialize(data["payload"])
        self.release.deserialize(data["payload"])
        if self.release.is_layered:
            self.base_product.deserialize(data["payload"])
        self.variants.deserialize(data["payload"])
        self.header.set_current_version()

    def __getitem__(self, name):
        return self.variants[name]

    def get_variants(self, *args, **kwargs):
        return self.variants.get_variants(*args, **kwargs)
コード例 #6
0
class Rpms(productmd.common.MetadataBase):
    def __init__(self):
        super(Rpms, self).__init__()
        self.header = Header(self, "productmd.rpms")
        self.compose = Compose(self)
        self.rpms = {}

    def __getitem__(self, variant):
        return self.rpms[variant]

    def __delitem__(self, variant):
        del self.rpms[variant]

    def _check_nevra(self, nevra):
        if ":" not in nevra:
            raise ValueError("Missing epoch in N-E:V-R.A: %s" % nevra)

        try:
            nevra_dict = productmd.common.parse_nvra(nevra)
        except ValueError:
            raise ValueError("Invalid N-E:V-R.A: %s" % nevra)

        nevra_dict["epoch"] = nevra_dict["epoch"] or 0
        nevra = "%(name)s-%(epoch)s:%(version)s-%(release)s.%(arch)s" % nevra_dict
        return nevra, nevra_dict

    def serialize(self, parser):
        data = parser
        self.header.serialize(data)
        data["payload"] = {}
        data["payload"]["rpms"] = {}
        self.compose.serialize(data["payload"])
        data["payload"]["rpms"] = self.rpms
        return data

    def deserialize(self, data):
        self.header.deserialize(data)
        if self.header.version_tuple <= (0, 3):
            self.deserialize_0_3(data)
        else:
            self.deserialize_1_0(data)
        self.validate()

        self.header.set_current_version()

    def deserialize_0_3(self, data):
        self.compose.deserialize(data["payload"])
        payload = data["payload"]["manifest"]
        self.rpms = {}
        for variant in payload:
            for arch in payload[variant]:
                if arch == "src":
                    continue
                for srpm_nevra, rpms in payload[variant][arch].items():
                    srpm_data = payload[variant].get("src",
                                                     {}).get(srpm_nevra, None)
                    for rpm_nevra, rpm_data in rpms.items():
                        category = rpm_data["type"]
                        if category == "package":
                            category = "binary"
                        self.add(variant, arch, rpm_nevra, rpm_data["path"],
                                 rpm_data["sigkey"], category, srpm_nevra)
                        if srpm_data is not None:
                            self.add(variant, arch, srpm_nevra,
                                     srpm_data["path"], srpm_data["sigkey"],
                                     "source")

    def deserialize_1_0(self, data):
        self.compose.deserialize(data["payload"])
        self.rpms = data["payload"]["rpms"]

    def add(self,
            variant,
            arch,
            nevra,
            path,
            sigkey,
            category,
            srpm_nevra=None):
        """
        Map RPM to to variant and arch.

        :param variant: compose variant UID
        :type  variant: str
        :param arch:    compose architecture
        :type  arch:    str
        :param nevra:   name-epoch:version-release.arch
        :type  nevra:   str
        :param sigkey:  sigkey hash
        :type  sigkey:  str or None
        :param category:    RPM category, one of binary, debug, source
        :type  category:    str
        :param srpm_nevra:  name-epoch:version-release.arch of RPM's SRPM
        :type  srpm_nevra:  str
        """

        if arch not in productmd.common.RPM_ARCHES:
            raise ValueError("Arch not found in RPM_ARCHES: %s" % arch)

        if arch in ["src", "nosrc"]:
            raise ValueError(
                "Source arch is not allowed. Map source files under binary arches."
            )

        if category not in SUPPORTED_CATEGORIES:
            raise ValueError("Invalid category value: %s" % category)

        if path.startswith("/"):
            raise ValueError("Relative path expected: %s" % path)

        nevra, nevra_dict = self._check_nevra(nevra)

        if category == "source" and srpm_nevra is not None:
            raise ValueError(
                "Expected blank srpm_nevra for source package: %s" % nevra)

        if category != "source" and srpm_nevra is None:
            raise ValueError("Missing srpm_nevra for package: %s" % nevra)

        if (category == "source") != (nevra_dict["arch"] in ("src", "nosrc")):
            raise ValueError("Invalid category/arch combination: %s/%s" %
                             (category, nevra))

        if sigkey is not None:
            sigkey = sigkey.lower()

        if srpm_nevra:
            srpm_nevra, _ = self._check_nevra(srpm_nevra)
        else:
            srpm_nevra = nevra

        arches = self.rpms.setdefault(variant, {})
        srpms = arches.setdefault(arch, {})
        rpms = srpms.setdefault(srpm_nevra, {})
        rpms[nevra] = {"sigkey": sigkey, "path": path, "category": category}
コード例 #7
0
ファイル: images.py プロジェクト: nphilipp/productmd
class Images(productmd.common.MetadataBase):
    def __init__(self):
        super(Images, self).__init__()
        self.header = Header(self, "productmd.images")
        self.compose = Compose(self)
        self.images = {}

    def __getitem__(self, variant):
        return self.images[variant]

    def __delitem__(self, variant):
        del self.images[variant]

    def serialize(self, parser):
        data = parser
        self.header.serialize(data)
        data["payload"] = {}
        data["payload"]["images"] = {}
        self.compose.serialize(data["payload"])
        for variant in self.images:
            for arch in self.images[variant]:
                for image_obj in self.images[variant][arch]:
                    images = data["payload"]["images"].setdefault(variant, {}).setdefault(arch, [])
                    image_obj.serialize(images)
                    images.sort(key=lambda x: x["path"])
        return data

    def deserialize(self, data):
        self.header.deserialize(data)
        self.compose.deserialize(data["payload"])
        for variant in data["payload"]["images"]:
            for arch in data["payload"]["images"][variant]:
                for image in data["payload"]["images"][variant][arch]:
                    image_obj = Image(self)
                    image_obj.deserialize(image)
                    if self.header.version_tuple <= (1, 1):
                        self._add_1_1(data, variant, arch, image_obj)
                    else:
                        self.add(variant, arch, image_obj)
        self.header.set_current_version()

    def _add_1_1(self, data, variant, arch, image):
        if arch == "src":
            # move src under binary arches
            for variant_arch in data["payload"]["images"][variant]:
                if variant_arch == "src":
                    continue
                self.add(variant, variant_arch, image)
        else:
            self.add(variant, arch, image)

    def add(self, variant, arch, image):
        """
        Assign an :class:`.Image` object to variant and arch.

        :param variant: compose variant UID
        :type  variant: str
        :param arch:    compose architecture
        :type  arch:    str
        :param image:   image
        :type  image:   :class:`.Image`
        """

        if arch not in productmd.common.RPM_ARCHES:
            raise ValueError("Arch not found in RPM_ARCHES: %s" % arch)
        if arch in ["src", "nosrc"]:
            raise ValueError("Source arch is not allowed. Map source files under binary arches.")
        self.images.setdefault(variant, {}).setdefault(arch, set()).add(image)
コード例 #8
0
ファイル: rpms.py プロジェクト: AdamWill/productmd
class Rpms(productmd.common.MetadataBase):
    def __init__(self):
        super(Rpms, self).__init__()
        self.header = Header(self)
        self.compose = Compose(self)
        self.rpms = {}

    def __getitem__(self, variant):
        return self.rpms[variant]

    def __delitem__(self, variant):
        del self.rpms[variant]

    def _check_nevra(self, nevra):
        if ":" not in nevra:
            raise ValueError("Missing epoch in N-E:V-R.A: %s" % nevra)

        try:
            nevra_dict = productmd.common.parse_nvra(nevra)
        except ValueError:
            raise ValueError("Invalid N-E:V-R.A: %s" % nevra)

        nevra_dict["epoch"] = nevra_dict["epoch"] or 0
        nevra = "%(name)s-%(epoch)s:%(version)s-%(release)s.%(arch)s" % nevra_dict
        return nevra, nevra_dict

    def serialize(self, parser):
        data = parser
        self.header.serialize(data)
        data["payload"] = {}
        data["payload"]["rpms"] = {}
        self.compose.serialize(data["payload"])
        data["payload"]["rpms"] = self.rpms
        return data

    def deserialize(self, data):
        self.header.deserialize(data)
        if self.header.version_tuple <= (0, 3):
            self.deserialize_0_3(data)
        else:
            self.deserialize_1_0(data)
        self.validate()

        self.header.set_current_version()

    def deserialize_0_3(self, data):
        self.compose.deserialize(data["payload"])
        payload = data["payload"]["manifest"]
        self.rpms = {}
        for variant in payload:
            for arch in payload[variant]:
                if arch == "src":
                    continue
                for srpm_nevra, rpms in payload[variant][arch].items():
                    srpm_data = payload[variant].get("src", {}).get(srpm_nevra, None)
                    for rpm_nevra, rpm_data in rpms.items():
                        category = rpm_data["type"]
                        if category == "package":
                            category = "binary"
                        self.add(variant, arch, rpm_nevra, rpm_data["path"], rpm_data["sigkey"], category, srpm_nevra)
                        if srpm_data is not None:
                            self.add(variant, arch, srpm_nevra, srpm_data["path"], srpm_data["sigkey"], "source")

    def deserialize_1_0(self, data):
        self.compose.deserialize(data["payload"])
        self.rpms = data["payload"]["rpms"]

    def add(self, variant, arch, nevra, path, sigkey, category, srpm_nevra=None):
        """
        Map RPM to to variant and arch.

        :param variant: compose variant UID
        :type  variant: str
        :param arch:    compose architecture
        :type  arch:    str
        :param nevra:   name-epoch:version-release.arch
        :type  nevra:   str
        :param sigkey:  sigkey hash
        :type  sigkey:  str or None
        :param category:    RPM category, one of binary, debug, source
        :type  category:    str
        :param srpm_nevra:  name-epoch:version-release.arch of RPM's SRPM
        :type  srpm_nevra:  str
        """

        if arch not in productmd.common.RPM_ARCHES:
            raise ValueError("Arch not found in RPM_ARCHES: %s" % arch)

        if category not in SUPPORTED_CATEGORIES:
            raise ValueError("Invalid category value: %s" % category)

        if path.startswith("/"):
            raise ValueError("Relative path expected: %s" % path)

        nevra, nevra_dict = self._check_nevra(nevra)

        if category == "source" and srpm_nevra is not None:
            raise ValueError("Expected blank srpm_nevra for source package: %s" % nevra)

        if category != "source" and srpm_nevra is None:
            raise ValueError("Missing srpm_nevra for package: %s" % nevra)

        if (category == "source") != (nevra_dict["arch"] in ("src", "nosrc")):
            raise ValueError("Invalid category/arch combination: %s/%s" % (category, nevra))

        if sigkey is not None:
            sigkey = sigkey.lower()

        if srpm_nevra:
            srpm_nevra, _ = self._check_nevra(srpm_nevra)
        else:
            srpm_nevra = nevra

        arches = self.rpms.setdefault(variant, {})
        srpms = arches.setdefault(arch, {})
        rpms = srpms.setdefault(srpm_nevra, {})
        rpms[nevra] = {"sigkey": sigkey, "path": path, "category": category}
コード例 #9
0
ファイル: images.py プロジェクト: ausil/productmd
class Images(productmd.common.MetadataBase):
    def __init__(self):
        super(Images, self).__init__()
        self.header = Header(self, "productmd.images")
        self.compose = Compose(self)
        self.images = {}

    def __getitem__(self, variant):
        return self.images[variant]

    def __delitem__(self, variant):
        del self.images[variant]

    def serialize(self, parser):
        data = parser
        self.header.serialize(data)
        data["payload"] = {}
        data["payload"]["images"] = {}
        self.compose.serialize(data["payload"])
        for variant in self.images:
            for arch in self.images[variant]:
                for image_obj in self.images[variant][arch]:
                    images = data["payload"]["images"].setdefault(variant, {}).setdefault(arch, [])
                    image_obj.serialize(images)
                    images.sort(key=lambda x: x["path"])
        return data

    def deserialize(self, data):
        self.header.deserialize(data)
        self.compose.deserialize(data["payload"])
        for variant in data["payload"]["images"]:
            for arch in data["payload"]["images"][variant]:
                for image in data["payload"]["images"][variant][arch]:
                    image_obj = Image(self)
                    image_obj.deserialize(image)
                    if self.header.version_tuple <= (1, 1):
                        self._add_1_1(data, variant, arch, image_obj)
                    else:
                        self.add(variant, arch, image_obj)
        self.header.set_current_version()

    def _add_1_1(self, data, variant, arch, image):
        if arch == "src":
            # move src under binary arches
            for variant_arch in data["payload"]["images"][variant]:
                if variant_arch == "src":
                    continue
                self.add(variant, variant_arch, image)
        else:
            self.add(variant, arch, image)

    def add(self, variant, arch, image):
        """
        Assign an :class:`.Image` object to variant and arch.

        :param variant: compose variant UID
        :type  variant: str
        :param arch:    compose architecture
        :type  arch:    str
        :param image:   image
        :type  image:   :class:`.Image`
        """

        if arch not in productmd.common.RPM_ARCHES:
            raise ValueError("Arch not found in RPM_ARCHES: %s" % arch)
        if arch in ["src", "nosrc"]:
            raise ValueError("Source arch is not allowed. Map source files under binary arches.")
        if self.header.version_tuple >= (1, 1):
            # disallow adding a different image with same 'unique'
            # attributes. can't do this pre-1.1 as we couldn't truly
            # identify images before subvariant
            for checkvar in self.images:
                for checkarch in self.images[checkvar]:
                    for curimg in self.images[checkvar][checkarch]:
                        if identify_image(curimg) == identify_image(image) and curimg.checksums != image.checksums:
                            raise ValueError("Image {0} shares all UNIQUE_IMAGE_ATTRIBUTES with "
                                             "image {1}! This is forbidden.".format(image, curimg))
        self.images.setdefault(variant, {}).setdefault(arch, set()).add(image)
コード例 #10
0
ファイル: treeinfo.py プロジェクト: maxamillion/productmd
class TreeInfo(productmd.common.MetadataBase):
    def __init__(self):
        super(productmd.common.MetadataBase, self)
        self.header = Header(self)              #: (:class:`productmd.common.Header`) -- Metadata header
        self.release = Release(self)            #: (:class:`.Release`) -- Release details
        self.base_product = BaseProduct(self)   #: (:class:`.BaseProduct`) -- Base product details (optional)
        self.tree = Tree(self)                  #: (:class:`.Tree`) -- Tree details
        self.variants = Variants(self)          #: (:class:`.Variants`) -- Release variants
        self.checksums = Checksums(self)        #: (:class:`.Checksums`) -- Checksums of images included in a tree
        self.images = Images(self)              #: (:class:`.Images`) -- Paths to images included in a tree
        self.stage2 = Stage2(self)              #: (:class:`.Stage2`) -- Stage 2 image path (for Anaconda installer)
        self.media = Media(self)                #: (:class:`.Media`) -- Media set information (optional)

    def __str__(self):
        result = "%s-%s" % (self.release.short, self.release.version)
        if self.release.is_layered:
            result += "-%s-%s" % (self.base_product.short, self.base_product.version)
        variant = sorted(self.variants)[0]
        result += " %s.%s" % (variant, self.tree.arch)
        return result

    def __getitem__(self, name):
        return self.variants[name]

    def __delitem__(self, name):
        del self.variants[name]

    def _get_parser(self):
        return productmd.common.SortedConfigParser()

    def parse_file(self, f):
        # parse file, return parser or dict with data
        f.seek(0)
        parser = productmd.common.SortedConfigParser()
        parser.read_file(f)
        return parser

    def build_file(self, parser, f):
        # build file from parser or dict with data
        parser.write(f)

    def serialize(self, parser):
        self.validate()
        self.header.serialize(parser)
        self.release.serialize(parser)
        if self.release.is_layered:
            self.base_product.serialize(parser)
        self.tree.serialize(parser)
        self.variants.serialize(parser)
        self.checksums.serialize(parser)
        self.images.serialize(parser)
        self.stage2.serialize(parser)
        self.media.serialize(parser)
        # HACK: generate [general] section for compatibility
        general = General(self)
        general.serialize(parser)

    def deserialize(self, parser):
        self.header.deserialize(parser)
        self.release.deserialize(parser)
        if self.release.is_layered:
            self.base_product.deserialize(parser)
        self.tree.deserialize(parser)
        self.variants.deserialize(parser)
        self.checksums.deserialize(parser)
        self.images.deserialize(parser)
        self.stage2.deserialize(parser)
        self.media.deserialize(parser)
        self.validate()
        self.header.set_current_version()
        return parser