Skip to content

Commit f914b91

Browse files
committed
storage: support external config merge
Signed-off-by: Yan Song <[email protected]>
1 parent 8e4af88 commit f914b91

File tree

15 files changed

+173
-39
lines changed

15 files changed

+173
-39
lines changed

Cargo.lock

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ default = [
9393
"backend-s3",
9494
"backend-http-proxy",
9595
"backend-localdisk",
96+
"backend-external",
9697
"dedup",
9798
]
9899
virtiofs = [
@@ -114,6 +115,7 @@ backend-localdisk = [
114115
backend-oss = ["nydus-storage/backend-oss"]
115116
backend-registry = ["nydus-storage/backend-registry"]
116117
backend-s3 = ["nydus-storage/backend-s3"]
118+
backend-external = ["nydus-storage/backend-external"]
117119

118120
dedup = ["nydus-storage/dedup"]
119121

api/src/config.rs

+30
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ pub struct ConfigV2 {
2525
pub id: String,
2626
/// Configuration information for storage backend.
2727
pub backend: Option<BackendConfigV2>,
28+
/// Configuration for external storage backends, order insensitivity.
29+
#[serde(default)]
30+
pub external_backends: Vec<ExternalBackendConfig>,
2831
/// Configuration information for local cache system.
2932
pub cache: Option<CacheConfigV2>,
3033
/// Configuration information for RAFS filesystem.
@@ -42,6 +45,7 @@ impl Default for ConfigV2 {
4245
version: 2,
4346
id: String::new(),
4447
backend: None,
48+
external_backends: Vec::new(),
4549
cache: None,
4650
rafs: None,
4751
overlay: None,
@@ -57,6 +61,7 @@ impl ConfigV2 {
5761
version: 2,
5862
id: id.to_string(),
5963
backend: None,
64+
external_backends: Vec::new(),
6065
cache: None,
6166
rafs: None,
6267
overlay: None,
@@ -971,6 +976,9 @@ pub struct BlobCacheEntryConfigV2 {
971976
/// Configuration information for storage backend.
972977
#[serde(default)]
973978
pub backend: BackendConfigV2,
979+
/// Configuration for external storage backends, order insensitivity.
980+
#[serde(default)]
981+
pub external_backends: Vec<ExternalBackendConfig>,
974982
/// Configuration information for local cache system.
975983
#[serde(default)]
976984
pub cache: CacheConfigV2,
@@ -1034,6 +1042,7 @@ impl From<&BlobCacheEntryConfigV2> for ConfigV2 {
10341042
version: c.version,
10351043
id: c.id.clone(),
10361044
backend: Some(c.backend.clone()),
1045+
external_backends: c.external_backends.clone(),
10371046
cache: Some(c.cache.clone()),
10381047
rafs: None,
10391048
overlay: None,
@@ -1309,6 +1318,19 @@ struct CacheConfig {
13091318
pub prefetch_config: BlobPrefetchConfig,
13101319
}
13111320

1321+
/// Additional configuration information for external backend, its items
1322+
/// will be merged to the configuration from image.
1323+
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
1324+
pub struct ExternalBackendConfig {
1325+
/// External backend identifier to merge.
1326+
pub patch: HashMap<String, String>,
1327+
/// External backend type.
1328+
#[serde(rename = "type")]
1329+
pub kind: String,
1330+
/// External backend config items to merge.
1331+
pub config: HashMap<String, String>,
1332+
}
1333+
13121334
impl TryFrom<&CacheConfig> for CacheConfigV2 {
13131335
type Error = std::io::Error;
13141336

@@ -1350,6 +1372,9 @@ struct FactoryConfig {
13501372
pub id: String,
13511373
/// Configuration for storage backend.
13521374
pub backend: BackendConfig,
1375+
/// Configuration for external storage backends, order insensitivity.
1376+
#[serde(default)]
1377+
pub external_backends: Vec<ExternalBackendConfig>,
13531378
/// Configuration for blob cache manager.
13541379
#[serde(default)]
13551380
pub cache: CacheConfig,
@@ -1410,6 +1435,7 @@ impl TryFrom<RafsConfig> for ConfigV2 {
14101435
version: 2,
14111436
id: v.device.id,
14121437
backend: Some(backend),
1438+
external_backends: v.device.external_backends,
14131439
cache: Some(cache),
14141440
rafs: Some(rafs),
14151441
overlay: None,
@@ -1500,6 +1526,9 @@ pub(crate) struct BlobCacheEntryConfig {
15001526
///
15011527
/// Possible value: `LocalFsConfig`, `RegistryConfig`, `OssConfig`, `LocalDiskConfig`.
15021528
backend_config: Value,
1529+
/// Configuration for external storage backends, order insensitivity.
1530+
#[serde(default)]
1531+
external_backends: Vec<ExternalBackendConfig>,
15031532
/// Type of blob cache, corresponding to `FactoryConfig::CacheConfig::cache_type`.
15041533
///
15051534
/// Possible value: "fscache", "filecache".
@@ -1535,6 +1564,7 @@ impl TryFrom<&BlobCacheEntryConfig> for BlobCacheEntryConfigV2 {
15351564
version: 2,
15361565
id: v.id.clone(),
15371566
backend: (&backend_config).try_into()?,
1567+
external_backends: v.external_backends.clone(),
15381568
cache: (&cache_config).try_into()?,
15391569
metadata_path: v.metadata_path.clone(),
15401570
})

builder/src/core/context.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,7 @@ mod tests {
16261626
registry: None,
16271627
http_proxy: None,
16281628
}),
1629+
external_backends: Vec::new(),
16291630
id: "id".to_owned(),
16301631
cache: None,
16311632
rafs: None,

clib/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ backend-oss = ["nydus-storage/backend-oss"]
2626
backend-registry = ["nydus-storage/backend-registry"]
2727
backend-http-proxy = ["nydus-storage/backend-http-proxy"]
2828
backend-localdisk = ["nydus-storage/backend-localdisk"]
29+
backend-external = ["nydus-storage/backend-external"]

storage/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ url = { version = "2.1.1", optional = true }
4444
vm-memory = "0.14.1"
4545
fuse-backend-rs = "^0.12.0"
4646
gpt = { version = "3.1.0", optional = true }
47+
chrono = { version = "0.4", features = ["serde"] }
48+
serde_bytes = "0.11"
4749

4850
nydus-api = { version = "0.3", path = "../api" }
4951
nydus-utils = { version = "0.4", path = "../utils", features = [
@@ -66,6 +68,7 @@ backend-oss = ["base64", "httpdate", "hmac", "sha1", "reqwest", "url"]
6668
backend-registry = ["base64", "reqwest", "url"]
6769
backend-s3 = ["base64", "hmac", "http", "reqwest", "sha2", "time", "url"]
6870
backend-http-proxy = ["hyper", "hyperlocal", "http", "reqwest", "url"]
71+
backend-external = ["base64", "reqwest", "url"]
6972
dedup = ["rusqlite", "r2d2", "r2d2_sqlite"]
7073
prefetch-rate-limit = ["leaky-bucket"]
7174

storage/src/backend/connection.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ pub(crate) struct ConnectionConfig {
7474
pub timeout: u32,
7575
pub connect_timeout: u32,
7676
pub retry_limit: u8,
77+
pub redirect: bool,
7778
}
7879

7980
impl Default for ConnectionConfig {
@@ -85,6 +86,7 @@ impl Default for ConnectionConfig {
8586
timeout: 5,
8687
connect_timeout: 5,
8788
retry_limit: 0,
89+
redirect: false,
8890
}
8991
}
9092
}
@@ -98,6 +100,7 @@ impl From<OssConfig> for ConnectionConfig {
98100
timeout: c.timeout,
99101
connect_timeout: c.connect_timeout,
100102
retry_limit: c.retry_limit,
103+
redirect: false,
101104
}
102105
}
103106
}
@@ -111,6 +114,7 @@ impl From<S3Config> for ConnectionConfig {
111114
timeout: c.timeout,
112115
connect_timeout: c.connect_timeout,
113116
retry_limit: c.retry_limit,
117+
redirect: false,
114118
}
115119
}
116120
}
@@ -124,6 +128,7 @@ impl From<RegistryConfig> for ConnectionConfig {
124128
timeout: c.timeout,
125129
connect_timeout: c.connect_timeout,
126130
retry_limit: c.retry_limit,
131+
redirect: false,
127132
}
128133
}
129134
}
@@ -137,6 +142,7 @@ impl From<HttpProxyConfig> for ConnectionConfig {
137142
timeout: c.timeout,
138143
connect_timeout: c.connect_timeout,
139144
retry_limit: c.retry_limit,
145+
redirect: false,
140146
}
141147
}
142148
}
@@ -651,8 +657,12 @@ impl Connection {
651657

652658
let mut cb = Client::builder()
653659
.timeout(timeout)
654-
.connect_timeout(connect_timeout)
655-
.redirect(Policy::none());
660+
.connect_timeout(connect_timeout);
661+
if config.redirect {
662+
cb = cb.redirect(Policy::default());
663+
} else {
664+
cb = cb.redirect(Policy::none());
665+
}
656666

657667
if config.skip_verify {
658668
cb = cb.danger_accept_invalid_certs(true);

storage/src/backend/external/local.rs

+17-9
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
// SPDX-License-Identifier: Apache-2.0
44

55
use std::collections::HashMap;
6-
use std::io::Result;
76
use std::os::unix::fs::FileExt;
87
use std::path::PathBuf;
8+
use std::result::Result;
99

1010
use crate::backend::external::{meta::MetaMap, ExternalBlobReader};
1111
use crate::device::BlobChunkInfo;
@@ -24,25 +24,33 @@ pub struct LocalBackend {
2424
}
2525

2626
impl LocalBackend {
27-
pub fn new(meta_path: PathBuf, config: &HashMap<String, String>) -> Result<Self> {
28-
let meta_map = MetaMap::new(meta_path)?;
29-
let root = PathBuf::from(config.get("root").unwrap());
27+
pub fn new(meta_path: PathBuf, config: &HashMap<String, String>) -> Result<Self, String> {
28+
let meta_map = MetaMap::new(meta_path).map_err(|e| e.to_string())?;
29+
let root = PathBuf::from(
30+
config
31+
.get("root")
32+
.ok_or_else(|| format!("root is not specified in local backend config"))?,
33+
);
3034
Ok(Self { meta_map, root })
3135
}
3236
}
3337

3438
impl ExternalBlobReader for LocalBackend {
35-
fn read(&self, buf: &mut [u8], chunks: &[&dyn BlobChunkInfo]) -> Result<usize> {
39+
fn read(&self, buf: &mut [u8], chunks: &[&dyn BlobChunkInfo]) -> Result<usize, String> {
3640
let chunk_index = chunks[0].id();
37-
let (object_bytes, chunk) = self.meta_map.get_object(chunk_index)?;
41+
let (object_bytes, chunk) = self
42+
.meta_map
43+
.get_object(chunk_index)
44+
.map_err(|e| e.to_string())?;
3845

3946
let object: Object = rmp_serde::from_slice(&object_bytes)
40-
.map_err(|_e| einval!("failed to deserialize object"))?;
47+
.map_err(|e| format!("failed to deserialize object: {}", e.to_string()))?;
4148

4249
let path = self.root.join(&object.path);
4350

44-
let file = std::fs::File::open(path)?;
45-
file.read_exact_at(buf, chunk.object_offset)?;
51+
let file = std::fs::File::open(path).map_err(|e| e.to_string())?;
52+
file.read_exact_at(buf, chunk.object_offset)
53+
.map_err(|e| e.to_string())?;
4654

4755
Ok(buf.len())
4856
}

storage/src/backend/external/meta.rs

+17-12
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ use std::mem::size_of;
77
use std::path::Path;
88
use std::{fs::File, os::unix::fs::MetadataExt};
99

10+
use serde::{Serialize, Deserialize};
11+
1012
use nydus_utils::filemap::FileMapState;
11-
use serde::{Deserialize, Serialize};
1213

1314
// Layout
1415
//
@@ -92,7 +93,7 @@ impl MetaMap {
9293
let object_meta_offset = header.object_meta_offset;
9394

9495
let chunk_meta = self.map.get_ref::<ChunkMeta>(chunk_meta_offset as usize)?;
95-
let object_meta = self
96+
let _object_meta = self
9697
.map
9798
.get_ref::<ObjectMeta>(object_meta_offset as usize)?;
9899

@@ -102,16 +103,20 @@ impl MetaMap {
102103
+ chunk_index as usize * chunk_meta.entry_size as usize,
103104
)?;
104105
let object_index = chunk.object_index;
105-
let object_offset = if object_meta.entry_size == 0 {
106-
let object_offset_offset = object_meta_offset as usize
107-
+ size_of::<ObjectMeta>()
108-
+ object_index as usize * size_of::<ObjectOffset>();
109-
*self.map.get_ref::<ObjectOffset>(object_offset_offset)? as usize
110-
} else {
111-
object_meta_offset as usize
112-
+ size_of::<ObjectMeta>()
113-
+ object_index as usize * object_meta.entry_size as usize
114-
};
106+
// let object_offset_offset = if object_meta.entry_size == 0 {
107+
// object_meta_offset as usize
108+
// + size_of::<ObjectMeta>()
109+
// + object_index as usize * size_of::<ObjectOffset>()
110+
// } else {
111+
// object_meta_offset as usize
112+
// + size_of::<ObjectMeta>()
113+
// + object_index as usize
114+
// * (size_of::<u32>() as usize + object_meta.entry_size as usize) as usize
115+
// };
116+
let object_offset_offset = object_meta_offset as usize
117+
+ size_of::<ObjectMeta>()
118+
+ object_index as usize * size_of::<ObjectOffset>();
119+
let object_offset = *self.map.get_ref::<ObjectOffset>(object_offset_offset)? as usize;
115120

116121
let object_size = *self.map.get_ref::<u32>(object_offset)? as usize;
117122

0 commit comments

Comments
 (0)