diff --git a/Standards/scs-0102-v2-image-metadata.md b/Standards/scs-0102-v2-image-metadata.md index c9c47dbe7..bb1c4906e 100644 --- a/Standards/scs-0102-v2-image-metadata.md +++ b/Standards/scs-0102-v2-image-metadata.md @@ -73,9 +73,10 @@ require an additional field: The usage of standardized `os_distro`, `os_version`, `architecture`, and `os_purpose` help cloud users to create automation that works across clouds without requiring image names to be standardized. - _Uniqueness requirement_: whenever there are two images that have `os_hidden=False`, `visibility=public`, - and that coincide in all three fields `os_distro`, `os_version`, and `architecture`, then only one of them may - have `os_purpose=generic`. In other words, users who search visible public images for a generic OS + _Uniqueness requirement_: For every assignment of values for `os_distro`, `os_version`, + and `architecture`, there MUST be at most one public (`visibility=public`), + non-hidden (`os_hidden=False`) image with this assignment and `os_purpose=generic`. + In other words, users who search visible public images for a generic OS of a certain distro, version, and architecture will not get more than one result. The following property is recommended: diff --git a/Standards/scs-0102-w1-image-metadata-implementation-testing.md b/Standards/scs-0102-w1-image-metadata-implementation-testing.md index e56bb0d89..e82e1b223 100644 --- a/Standards/scs-0102-w1-image-metadata-implementation-testing.md +++ b/Standards/scs-0102-w1-image-metadata-implementation-testing.md @@ -45,6 +45,11 @@ The following testcase ensures that each image is as recent as claimed by its `r - `scs-0102-image-recency` +The following testcase ensures that generic OS images are uniquely identified via the triple +(architecture, os\_distro, os\_version): + +- `scs-0102-os_purpose-uniqueness` + ## Manual tests None. diff --git a/Tests/iaas/openstack_test.py b/Tests/iaas/openstack_test.py index 4afeaf138..62f8b8ae7 100755 --- a/Tests/iaas/openstack_test.py +++ b/Tests/iaas/openstack_test.py @@ -30,7 +30,7 @@ compute_scs_0102_prop_image_source, compute_scs_0102_prop_image_description, \ compute_scs_0102_prop_replace_frequency, compute_scs_0102_prop_provided_until, \ compute_scs_0102_prop_uuid_validity, compute_scs_0102_prop_hotfix_hours, \ - compute_scs_0102_image_recency + compute_scs_0102_image_recency, compute_scs_0102_os_purpose_uniqueness from scs_0103_standard_flavors.standard_flavors import \ SCS_0103_CANONICAL_NAMES, compute_flavor_lookup, compute_scs_0103_flavor from scs_0104_standard_images.standard_images import \ @@ -98,6 +98,7 @@ def make_container(cloud): c.add_function('scs_0102_prop_uuid_validity', lambda c: compute_scs_0102_prop_uuid_validity(c.images)) c.add_function('scs_0102_prop_hotfix_hours', lambda c: compute_scs_0102_prop_hotfix_hours(c.images)) c.add_function('scs_0102_image_recency', lambda c: compute_scs_0102_image_recency(c.images)) + c.add_function('scs_0102_os_purpose_uniqueness', lambda c: compute_scs_0102_os_purpose_uniqueness(c.images)) # scs_0103_standard_flavors c.add_function('flavor_lookup', lambda c: compute_flavor_lookup(c.flavors)) for canonical_name in SCS_0103_CANONICAL_NAMES: diff --git a/Tests/iaas/scs_0102_image_metadata/image_metadata.py b/Tests/iaas/scs_0102_image_metadata/image_metadata.py index a22501241..efe3d1bb9 100644 --- a/Tests/iaas/scs_0102_image_metadata/image_metadata.py +++ b/Tests/iaas/scs_0102_image_metadata/image_metadata.py @@ -1,5 +1,5 @@ import calendar -from collections import Counter +from collections import Counter, defaultdict import logging import sys import time @@ -332,3 +332,28 @@ def compute_scs_0102_image_recency(images): else: logger.info(f'Image "{replacement.name}" is a valid replacement for outdated "{img.name}"') return not errors + + +def compute_scs_0102_os_purpose_uniqueness(images): + """ + This test ensures that, for each combination of architecture, os_distro and os_version, + there is a most one public image with os_purpose=generic. + """ + # group images by (architecture, os_distro, os_version) + buckets = defaultdict(list) + for image in images: + if image.visibility != 'public' or image.is_hidden: + continue + if not image.os_distro or not image.os_version: + continue + if image.properties.get('os_purpose', '') != 'generic': + continue + key = (image.architecture or '', image.os_distro, image.os_version) + buckets[key].append(image) + num_faulty = 0 + for key, bucket in buckets.items(): + if len(bucket) < 2: + continue + num_faulty += 1 + _log_error(f'os_purpose=generic not unique {key!r}', bucket) + return num_faulty == 0 diff --git a/Tests/scs-compatible-iaas.yaml b/Tests/scs-compatible-iaas.yaml index 7d025c5fd..5d857af20 100644 --- a/Tests/scs-compatible-iaas.yaml +++ b/Tests/scs-compatible-iaas.yaml @@ -89,6 +89,9 @@ scripts: - id: scs-0102-image-recency description: Each image is as recent as properties (if set) suggest. url: https://docs.scs.community/standards/scs-0102-w1-image-metadata-implementation-testing#automated-tests + - id: scs-0102-os_purpose-uniqueness + description: Generic OS images are uniquely identified via triple (architecture, os\_distro, os\_version). + url: https://docs.scs.community/standards/scs-0102-w1-image-metadata-implementation-testing#automated-tests - id: scs-0103-flavor-1v-4 description: Check presence of flavor `SCS-1V-4`. url: https://docs.scs.community/standards/scs-0103-w1-standard-flavors-implementation#automated-tests @@ -330,6 +333,33 @@ modules: recommended: - scs-0102-prop-hash_algo - scs-0102-prop-os_purpose + - scs-0102-os_purpose-uniqueness + - scs-0102-prop-hypervisor_type + - scs-0102-prop-hw_rng_model + - scs-0102-prop-hotfix_hours + - id: scs-0102-v2 + name: Image metadata v2 + url: https://docs.scs.community/standards/scs-0102-v2-image-metadata + targets: + main: + - scs-0102-prop-architecture + - scs-0102-prop-min_disk + - scs-0102-prop-min_ram + - scs-0102-prop-os_version + - scs-0102-prop-os_distro + - scs-0102-prop-os_purpose + - scs-0102-prop-hw_disk_bus + - scs-0102-prop-image_build_date + - scs-0102-prop-image_original_user + - scs-0102-prop-image_source + - scs-0102-prop-image_description + - scs-0102-prop-replace_frequency + - scs-0102-prop-provided_until + - scs-0102-prop-uuid_validity + - scs-0102-image-recency + - scs-0102-os_purpose-uniqueness + recommended: + - scs-0102-prop-hash_algo - scs-0102-prop-hypervisor_type - scs-0102-prop-hw_rng_model - scs-0102-prop-hotfix_hours @@ -487,7 +517,7 @@ versions: - opc-v2022.11 - scs-0100-v3.1 - scs-0101-v1 - - scs-0102-v1 + - scs-0102-v2 # instead of scs-0102-v1 - scs-0103-v1 - ref: scs-0104-v1-2 parameters: