Example #1
0
 def test_maps_boot_resource_by_content_id_product_name_and_version(self):
     image = make_image_spec()
     resource = make_boot_resource()
     boot_dict = set_resource(resource=resource.copy(), image_spec=image)
     self.assertEqual(
         {
             (
                 resource['content_id'],
                 resource['product_name'],
                 resource['version_name'],
             ): [image.subarch],
         },
         map_products(boot_dict).mapping)
Example #2
0
    def test_concatenates_similar_resources(self):
        image1 = make_image_spec()
        image2 = make_image_spec()
        resource = make_boot_resource()
        boot_dict = BootImageMapping()
        # Create two images in boot_dict, both containing the same resource.
        for image in [image1, image2]:
            set_resource(
                boot_dict=boot_dict, resource=resource.copy(), image_spec=image
            )

        products_mapping = map_products(boot_dict)
        key = (
            resource["content_id"],
            resource["product_name"],
            resource["version_name"],
        )
        self.assertEqual([key], list(products_mapping.mapping))
        self.assertItemsEqual(
            [image1.subarch, image2.subarch], products_mapping.get(resource)
        )
Example #3
0
 def test_maps_empty_dict_to_empty_dict(self):
     empty_boot_image_dict = BootImageMapping()
     self.assertEqual({}, map_products(empty_boot_image_dict).mapping)
Example #4
0
def import_images(sources):
    """Import images.  Callable from the command line.

    :param config: An iterable of dicts representing the sources from
        which boot images will be downloaded.
    """
    if len(sources) == 0:
        msg = "Can't import: region did not provide a source."
        try_send_rack_event(EVENT_TYPES.RACK_IMPORT_WARNING, msg)
        maaslog.warning(msg)
        return False

    msg = "Starting rack boot image import"
    maaslog.info(msg)
    try_send_rack_event(EVENT_TYPES.RACK_IMPORT_INFO, msg)

    with ClusterConfiguration.open() as config:
        storage = FilePath(config.tftp_root).parent().path

    with tempdir("keyrings") as keyrings_path:
        # XXX: Band-aid to ensure that the keyring_data is bytes. Future task:
        # try to figure out why this sometimes happens.
        for source in sources:
            if "keyring_data" in source and not isinstance(
                    source["keyring_data"], bytes):
                source["keyring_data"] = source["keyring_data"].encode("utf-8")

        # We download the keyrings now  because we need them for both
        # download_all_image_descriptions() and
        # download_all_boot_resources() later.
        sources = write_all_keyrings(keyrings_path, sources)

        # The region produces a SimpleStream which is similar, but not
        # identical to the actual SimpleStream. These differences cause
        # validation to fail. So grab everything from the region and trust it
        # did proper filtering before the rack.
        image_descriptions = download_all_image_descriptions(
            sources, validate_products=False)
        if image_descriptions.is_empty():
            msg = ("Finished importing boot images, the region does not have "
                   "any boot images available.")
            try_send_rack_event(EVENT_TYPES.RACK_IMPORT_WARNING, msg)
            maaslog.warning(msg)
            return False

        meta_file_content = image_descriptions.dump_json()
        if meta_contains(storage, meta_file_content):
            maaslog.info("Finished importing boot images, the region does not "
                         "have any new images.")
            try_send_rack_event(EVENT_TYPES.RACK_IMPORT_INFO, msg)
            maaslog.info(msg)
            return False

        product_mapping = map_products(image_descriptions)

        try:
            snapshot_path = download_all_boot_resources(
                sources, storage, product_mapping)
        except Exception as e:
            try_send_rack_event(
                EVENT_TYPES.RACK_IMPORT_ERROR,
                "Unable to import boot images: %s" % e,
            )
            maaslog.error(
                "Unable to import boot images; cleaning up failed snapshot "
                "and cache.")
            # Cleanup snapshots and cache since download failed.
            cleanup_snapshots_and_cache(storage)
            raise

    maaslog.info("Writing boot image metadata.")
    write_snapshot_metadata(snapshot_path, meta_file_content)

    maaslog.info("Linking boot images snapshot %s" % snapshot_path)
    link_bootloaders(snapshot_path)

    # If we got here, all went well.  This is now truly the "current" snapshot.
    update_current_symlink(storage, snapshot_path)

    # Now cleanup the old snapshots and cache.
    maaslog.info("Cleaning up old snapshots and cache.")
    cleanup_snapshots_and_cache(storage)

    # Import is now finished.
    msg = "Finished importing boot images."
    maaslog.info(msg)
    try_send_rack_event(EVENT_TYPES.RACK_IMPORT_INFO, msg)
    return True