|
1 | 1 | // SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors |
2 | 2 | // SPDX-License-Identifier: Apache-2.0 |
3 | 3 |
|
4 | | -use crate::{FileCommand, PulledImageData, IMAGE_DIR}; |
5 | | -use feos_proto::image_service::{ImageInfo, ImageState}; |
| 4 | +use crate::{FileCommand, ImageInfo, PulledImageData, IMAGE_DIR}; |
| 5 | +use feos_proto::image_service::ImageState; |
6 | 6 | use flate2::read::GzDecoder; |
7 | 7 | use log::{error, info, warn}; |
| 8 | +use oci_distribution::manifest; |
8 | 9 | use serde::{Deserialize, Serialize}; |
9 | 10 | use std::collections::HashMap; |
10 | 11 | use std::io::Cursor; |
11 | 12 | use std::path::Path; |
12 | 13 | use tar::Archive; |
13 | 14 | use tokio::{fs, sync::mpsc}; |
14 | 15 |
|
| 16 | +const INITRAMFS_MEDIA_TYPE: &str = "application/vnd.ironcore.image.initramfs.v1alpha1.initramfs"; |
| 17 | +const VMLINUZ_MEDIA_TYPE: &str = "application/vnd.ironcore.image.vmlinuz.v1alpha1.vmlinuz"; |
| 18 | +const ROOTFS_MEDIA_TYPE: &str = "application/vnd.ironcore.image.rootfs.v1alpha1.rootfs"; |
| 19 | + |
15 | 20 | #[derive(Serialize, Deserialize)] |
16 | 21 | struct ImageMetadata { |
17 | 22 | image_ref: String, |
@@ -86,27 +91,42 @@ impl FileStore { |
86 | 91 | ) -> Result<(), std::io::Error> { |
87 | 92 | fs::create_dir_all(final_dir).await?; |
88 | 93 |
|
89 | | - // Handle both single-blob rootfs (for VMs) and layered rootfs (for containers) |
90 | | - if image_data.layers.len() == 1 && image_ref.contains("cloud-hypervisor") { |
91 | | - // Assuming this is a single rootfs blob for a VM |
92 | | - let final_disk_path = final_dir.join("disk.image"); |
93 | | - fs::write(final_disk_path, &image_data.layers[0]).await?; |
94 | | - } else { |
95 | | - // Unpack layers for a container |
96 | | - let rootfs_path = final_dir.join("rootfs"); |
97 | | - fs::create_dir_all(&rootfs_path).await?; |
98 | | - for layer_data in image_data.layers { |
99 | | - let cursor = Cursor::new(layer_data); |
100 | | - let decoder = GzDecoder::new(cursor); |
101 | | - let mut archive = Archive::new(decoder); |
102 | | - archive.unpack(&rootfs_path)?; |
| 94 | + for layer in image_data.layers { |
| 95 | + match layer.media_type.as_str() { |
| 96 | + manifest::IMAGE_LAYER_GZIP_MEDIA_TYPE |
| 97 | + | manifest::IMAGE_DOCKER_LAYER_GZIP_MEDIA_TYPE => { |
| 98 | + let rootfs_path = final_dir.join("rootfs"); |
| 99 | + if !rootfs_path.exists() { |
| 100 | + fs::create_dir_all(&rootfs_path).await?; |
| 101 | + } |
| 102 | + let cursor = Cursor::new(layer.data); |
| 103 | + let decoder = GzDecoder::new(cursor); |
| 104 | + let mut archive = Archive::new(decoder); |
| 105 | + tokio::task::block_in_place(move || archive.unpack(&rootfs_path))?; |
| 106 | + } |
| 107 | + ROOTFS_MEDIA_TYPE => { |
| 108 | + let path = final_dir.join("disk.image"); |
| 109 | + fs::write(path, layer.data).await?; |
| 110 | + } |
| 111 | + INITRAMFS_MEDIA_TYPE => { |
| 112 | + let path = final_dir.join("initramfs"); |
| 113 | + fs::write(path, layer.data).await?; |
| 114 | + } |
| 115 | + VMLINUZ_MEDIA_TYPE => { |
| 116 | + let path = final_dir.join("vmlinuz"); |
| 117 | + fs::write(path, layer.data).await?; |
| 118 | + } |
| 119 | + _ => { |
| 120 | + warn!( |
| 121 | + "FileStore: Skipping layer with unsupported media type: {}", |
| 122 | + layer.media_type |
| 123 | + ); |
| 124 | + } |
103 | 125 | } |
104 | 126 | } |
105 | 127 |
|
106 | | - // Save OCI config.json |
107 | 128 | fs::write(final_dir.join("config.json"), image_data.config).await?; |
108 | 129 |
|
109 | | - // Save internal metadata |
110 | 130 | let metadata = ImageMetadata { |
111 | 131 | image_ref: image_ref.to_string(), |
112 | 132 | }; |
|
0 commit comments