Skip to content

Commit dec2e4b

Browse files
author
maxing.lan
committed
feat: builder: add backend configure support for optimize subcommand
With backend configure supoorted, we can read chunk on demand by specifying backend such as registry without downloadling whole image during image building. Signed-off-by: maxing.lan <[email protected]>
1 parent ce62847 commit dec2e4b

File tree

2 files changed

+60
-16
lines changed

2 files changed

+60
-16
lines changed

builder/src/optimize_prefetch.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,13 @@ use nydus_api::ConfigV2;
2020
use nydus_rafs::metadata::layout::RafsBlobTable;
2121
use nydus_rafs::metadata::RafsSuper;
2222
use nydus_rafs::metadata::RafsVersion;
23+
use nydus_storage::backend::BlobBackend;
2324
use nydus_storage::device::BlobInfo;
2425
use nydus_storage::meta::BatchContextGenerator;
2526
use nydus_storage::meta::BlobChunkInfoV2Ondisk;
2627
use nydus_utils::compress;
2728
use sha2::Digest;
2829
use std::cmp::{max, min};
29-
use std::fs::File;
30-
use std::io::{Read, Seek, Write};
3130
use std::mem::size_of;
3231
use std::sync::Arc;
3332
pub struct OptimizePrefetch {}
@@ -94,7 +93,7 @@ impl PrefetchFileInfo {
9493
}
9594

9695
impl PrefetchBlobState {
97-
fn new(ctx: &BuildContext, blob_layer_num: u32, blobs_dir_path: &Path) -> Result<Self> {
96+
fn new(ctx: &BuildContext, blob_layer_num: u32, output_blob_dir_path: &Path) -> Result<Self> {
9897
let mut blob_info = BlobInfo::new(
9998
blob_layer_num,
10099
String::from("prefetch-blob"),
@@ -109,7 +108,7 @@ impl PrefetchBlobState {
109108
let mut blob_ctx = BlobContext::from(ctx, &blob_info, ChunkSource::Build)?;
110109
blob_ctx.blob_meta_info_enabled = true;
111110
let blob_writer = ArtifactWriter::new(crate::ArtifactStorage::FileDir(
112-
blobs_dir_path.to_path_buf(),
111+
output_blob_dir_path.to_path_buf(),
113112
))
114113
.map(|writer| Box::new(writer) as Box<dyn Artifact>)?;
115114
Ok(Self {
@@ -127,16 +126,18 @@ impl OptimizePrefetch {
127126
ctx: &mut BuildContext,
128127
bootstrap_mgr: &mut BootstrapManager,
129128
blob_table: &mut RafsBlobTable,
130-
blobs_dir_path: PathBuf,
129+
output_blob_dir_path: PathBuf,
131130
prefetch_files: Vec<PrefetchFileInfo>,
131+
backend: Arc<dyn BlobBackend + Send + Sync>,
132132
) -> Result<BuildOutput> {
133133
// create a new blob for prefetch layer
134134

135135
let blob_layer_num = match blob_table {
136136
RafsBlobTable::V5(table) => table.get_all().len(),
137137
RafsBlobTable::V6(table) => table.get_all().len(),
138138
};
139-
let mut blob_state = PrefetchBlobState::new(&ctx, blob_layer_num as u32, &blobs_dir_path)?;
139+
let mut blob_state =
140+
PrefetchBlobState::new(&ctx, blob_layer_num as u32, &output_blob_dir_path)?;
140141
let mut batch = BatchContextGenerator::new(0)?;
141142
for node in prefetch_files.clone() {
142143
Self::process_prefetch_node(
@@ -145,7 +146,7 @@ impl OptimizePrefetch {
145146
&mut blob_state,
146147
&mut batch,
147148
blob_table,
148-
&blobs_dir_path,
149+
backend.clone(),
149150
)?;
150151
}
151152

@@ -286,7 +287,7 @@ impl OptimizePrefetch {
286287
prefetch_state: &mut PrefetchBlobState,
287288
batch: &mut BatchContextGenerator,
288289
blob_table: &RafsBlobTable,
289-
blobs_dir_path: &Path,
290+
backend: Arc<dyn BlobBackend + Send + Sync>,
290291
) -> Result<()> {
291292
let file = prefetch_file_info.file.clone();
292293
if tree.get_node_mut(&file).is_none() {
@@ -329,13 +330,17 @@ impl OptimizePrefetch {
329330
.get(chunk.inner.blob_index() as usize)
330331
.map(|entry| entry.blob_id())
331332
.ok_or(anyhow!("failed to get blob id"))?;
332-
let mut blob_file = Arc::new(File::open(blobs_dir_path.join(blob_id))?);
333333

334334
let inner = Arc::make_mut(&mut chunk.inner);
335335

336+
let reader = backend
337+
.clone()
338+
.get_reader(&blob_id.clone())
339+
.expect("get blob err");
336340
let mut buf = vec![0u8; inner.compressed_size() as usize];
337-
blob_file.seek(std::io::SeekFrom::Start(inner.compressed_offset()))?;
338-
blob_file.read_exact(&mut buf)?;
341+
reader
342+
.read(&mut buf, inner.compressed_offset())
343+
.expect("read blob err");
339344
prefetch_state.blob_writer.write_all(&buf)?;
340345
inner.set_blob_index(blob_info.blob_index());
341346
if blob_ctx.chunk_count == u32::MAX {

src/bin/nydus-image/main.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,32 @@ fn prepare_cmd_args(bti_string: &'static str) -> App {
555555
.num_args(1),
556556
)
557557
.arg(arg_config.clone())
558+
.arg(
559+
Arg::new("backend-type")
560+
.long("backend-type")
561+
.help(format!(
562+
"Type of backend [possible values: {}]",
563+
BlobFactory::supported_backends()
564+
.into_iter()
565+
.filter(|x| x != "localfs")
566+
.collect::<Vec<_>>()
567+
.join(", ")
568+
))
569+
.required(false)
570+
)
571+
.arg(
572+
Arg::new("backend-config")
573+
.long("backend-config")
574+
.help("Config string of backend")
575+
.required(false),
576+
)
577+
.arg(
578+
Arg::new("backend-config-file")
579+
.long("backend-config-file")
580+
.help("Config file of backend")
581+
.conflicts_with("backend-config")
582+
.required(false),
583+
)
558584
.arg(
559585
Arg::new("blob-dir")
560586
.long("blob-dir")
@@ -570,6 +596,11 @@ fn prepare_cmd_args(bti_string: &'static str) -> App {
570596
.short('O')
571597
.help("Output path of optimized bootstrap"),
572598
)
599+
.arg(
600+
Arg::new("output-blob-dir")
601+
.long("output-blob-dir")
602+
.help("Directroy path for storing optimized blob"),
603+
)
573604
.arg(
574605
arg_output_json.clone(),
575606
)
@@ -1683,7 +1714,7 @@ impl Command {
16831714
}
16841715

16851716
fn optimize(matches: &ArgMatches, build_info: &BuildTimeInfo) -> Result<()> {
1686-
let blobs_dir_path = Self::get_blobs_dir(matches)?;
1717+
let output_blob_dir_path = Self::get_output_blob_dir(matches)?;
16871718
let prefetch_file = Self::get_prefetch_files(matches)?;
16881719
let bootstrap_path = Self::get_bootstrap(matches)?;
16891720
let dst_bootstrap = match matches.get_one::<String>("output-bootstrap") {
@@ -1699,6 +1730,13 @@ impl Command {
16991730
..Default::default()
17001731
};
17011732

1733+
let (_c, backend) = match Self::get_backend(matches, "optimizer") {
1734+
Ok((c, b)) => (c, b),
1735+
Err(e) => {
1736+
bail!("{}, --blob-dir or --backend-type must be specified", e);
1737+
}
1738+
};
1739+
17021740
let sb = update_ctx_from_bootstrap(&mut build_ctx, config, bootstrap_path)?;
17031741
let mut tree = Tree::from_bootstrap(&sb, &mut ())?;
17041742
let mut bootstrap_mgr = BootstrapManager::new(Some(dst_bootstrap), None);
@@ -1718,8 +1756,9 @@ impl Command {
17181756
&mut build_ctx,
17191757
&mut bootstrap_mgr,
17201758
&mut blob_table,
1721-
blobs_dir_path.to_path_buf(),
1759+
output_blob_dir_path.to_path_buf(),
17221760
prefetch_nodes,
1761+
backend,
17231762
)
17241763
.with_context(|| "Failed to generate prefetch bootstrap")?;
17251764

@@ -1832,10 +1871,10 @@ impl Command {
18321871
}
18331872
}
18341873

1835-
fn get_blobs_dir(matches: &ArgMatches) -> Result<&Path> {
1836-
match matches.get_one::<String>("blob-dir") {
1874+
fn get_output_blob_dir(matches: &ArgMatches) -> Result<&Path> {
1875+
match matches.get_one::<String>("output-blob-dir") {
18371876
Some(s) => Ok(Path::new(s)),
1838-
None => bail!("missing parameter `blob-dir`"),
1877+
None => bail!("missing parameter `output-blob-dir`"),
18391878
}
18401879
}
18411880

0 commit comments

Comments
 (0)