Skip to content

Commit bba1e4b

Browse files
committed
Add mirror support for registry fs
1 parent 6afbbf0 commit bba1e4b

6 files changed

Lines changed: 61 additions & 15 deletions

File tree

README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,16 @@ Default configure file `overlaybd.json` is installed to `/etc/overlaybd/`.
191191
| credentialFilePath(legacy) | The credential used for fetching images on registry. `/opt/overlaybd/cred.json` is the default value. |
192192
| credentialConfig.mode | Authentication mode for lazy-loading. <br> - `file` means reading credential from `credentialConfig.path`. <br> - `http` means sending an http request to `credentialConfig.path` |
193193
| credentialConfig.path | credential file path or url which is determined by `mode` |
194-
| download.enable | Whether background downloading is enabled or not. |
195-
| download.delay | The seconds waiting to start downloading task after the overlaybd device launched. |
196-
| download.delayExtra | A random extra delay is attached to delay, avoiding too many tasks started at the same time. |
197-
| download.maxMBps | The speed limit in MB/s for a downloading task. |
198-
| download.blockSize | The download block size from source, in byte. `262144` is default (256 KB). |
199-
| p2pConfig.enable | Whether p2p proxy is enabled or not. |
200-
| p2pConfig.address | The proxy for p2p download, the format is `localhost:<P2PConfig.Port>/<P2PConfig.APIKey>`, depending on dadip2p.yaml |
194+
| download.enable | Whether background downloading is enabled or not. |
195+
| download.delay | The seconds waiting to start downloading task after the overlaybd device launched. |
196+
| download.delayExtra | A random extra delay is attached to delay, avoiding too many tasks started at the same time. |
197+
| download.maxMBps | The speed limit in MB/s for a downloading task. |
198+
| download.blockSize | The download block size from source, in byte. `262144` is default (256 KB). |
199+
| p2pConfig.enable | Whether p2p proxy is enabled or not. |
200+
| p2pConfig.address | The proxy for p2p download, the format is `localhost:<P2PConfig.Port>/<P2PConfig.APIKey>`, depending on dadip2p.yaml |
201+
| mirrors.[].host | The host name of the registry to mirror. Mirrors are only supported for `registryFsVersion` 'v2'. |
202+
| mirrors.[].mirror | The mirror URL to use to download a blob inplace of the given host. Includes the scheme (e.g http://localhost:8080) |
203+
| mirrors.[].timeoutMs | The timeout to get a response from the mirror, in milliseconds. |
201204
| exporterConfig.enable | whether or not create a server to show Prometheus metrics. |
202205
| exporterConfig.uriPrefix | URI prefix for export metrics. |
203206
| exporterConfig.port | port for http server to show metrics. |

src/config.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ struct P2PConfig : public ConfigUtils::Config {
7474
APPCFG_PARA(address, std::string, "http://localhost:9731/accelerator");
7575
};
7676

77+
struct MirrorConfig : public ConfigUtils::Config {
78+
APPCFG_CLASS
79+
80+
APPCFG_PARA(host, std::string);
81+
APPCFG_PARA(mirror, std::string);
82+
APPCFG_PARA(timeoutMs, uint64_t, 200);
83+
};
84+
7785
struct GzipCacheConfig : public ConfigUtils::Config {
7886
APPCFG_CLASS
7987

@@ -146,6 +154,7 @@ struct GlobalConfig : public ConfigUtils::Config {
146154
APPCFG_PARA(enableAudit, bool, true);
147155
APPCFG_PARA(enableThread, bool, false);
148156
APPCFG_PARA(p2pConfig, P2PConfig);
157+
APPCFG_PARA(mirrors, std::vector<MirrorConfig>);
149158
APPCFG_PARA(exporterConfig, ExporterConfig);
150159
APPCFG_PARA(auditPath, std::string, "/var/log/overlaybd-audit.log");
151160
APPCFG_PARA(registryFsVersion, std::string, "v2");

src/image_service.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ int ImageService::init() {
348348
registryfs_creator = new_registryfs_v2;
349349

350350
global_fs.underlay_registryfs = registryfs_creator(
351-
{this, &ImageService::reload_auth}, cafile, 30UL * 1000000,
351+
{this, &ImageService::reload_auth}, global_conf.mirrors(), cafile, 30UL * 1000000,
352352
global_conf.certConfig().certFile().c_str(), global_conf.certConfig().keyFile().c_str(), global_conf.userAgent().c_str());
353353
if (global_fs.underlay_registryfs == nullptr) {
354354
LOG_ERROR_RETURN(0, -1, "create registryfs failed.");

src/overlaybd/registryfs/registryfs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ inline IFile *RegistryFSImpl::open(const char *pathname, int) {
527527
return file;
528528
}
529529

530-
IFileSystem *new_registryfs_v1(PasswordCB callback, const char *caFile, uint64_t timeout,
530+
IFileSystem *new_registryfs_v1(PasswordCB callback, std::vector<ImageConfigNS::MirrorConfig> /*mirrors*/, const char *caFile, uint64_t timeout,
531531
const char *cert_file, const char *key_file, const char *__) {
532532
if (!callback)
533533
LOG_ERROR_RETURN(EINVAL, nullptr, "password callback not set");

src/overlaybd/registryfs/registryfs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616

1717
#pragma once
18+
19+
#include "../../config.h"
20+
1821
#include <stdint.h>
1922
#include <string>
2023
#include <photon/common/callback.h>
@@ -29,13 +32,15 @@ using PasswordCB = Delegate<std::pair<std::string, std::string>, const char *>;
2932

3033
extern "C" {
3134
photon::fs::IFileSystem *new_registryfs_v1(PasswordCB callback,
35+
std::vector<ImageConfigNS::MirrorConfig> mirrors,
3236
const char *caFile = nullptr,
3337
uint64_t timeout = -1,
3438
const char *cert_file = nullptr,
3539
const char *key_file = nullptr,
3640
const char *__ = nullptr);
3741

3842
photon::fs::IFileSystem *new_registryfs_v2(PasswordCB callback,
43+
std::vector<ImageConfigNS::MirrorConfig> mirrors,
3944
const char *caFile = nullptr,
4045
uint64_t timeout = -1,
4146
const char *cert_file = nullptr,

src/overlaybd/registryfs/registryfs_v2.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <photon/fs/virtual-file.h>
4040
#include <photon/fs/localfs.h>
4141
#include <photon/net/http/client.h>
42+
#include <photon/net/http/url.h>
4243
#include <photon/net/utils.h>
4344
#include <photon/net/security-context/tls-stream.h>
4445
#include <rapidjson/document.h>
@@ -126,9 +127,9 @@ class RegistryFSImpl_v2 : public RegistryFS {
126127
return open(pathname, flags); // ignore mode
127128
}
128129

129-
RegistryFSImpl_v2(PasswordCB callback, const char *caFile, uint64_t timeout,
130+
RegistryFSImpl_v2(PasswordCB callback, std::vector<ImageConfigNS::MirrorConfig> mirrors, const char *caFile, uint64_t timeout,
130131
photon::net::TLSContext *ctx, const char *ua)
131-
: m_callback(callback), m_caFile(caFile), m_timeout(timeout), m_tls_ctx(ctx),
132+
: m_callback(callback), m_mirrors(std::move(mirrors)), m_caFile(caFile), m_timeout(timeout), m_tls_ctx(ctx),
132133
m_meta_size(kMinimalMetaLife), m_scope_token(kMinimalTokenLife),
133134
m_url_info(kMinimalAUrlLife) {
134135

@@ -209,8 +210,35 @@ class RegistryFSImpl_v2 : public RegistryFS {
209210
}
210211

211212
UrlInfo* get_actual_url(const estring &url, uint64_t timeout, long &code) {
212-
213213
Timeout tmo(timeout);
214+
if (m_accelerate.empty() && !m_mirrors.empty()) {
215+
// If p2p acceleration is not enabled, and mirrors are configured,
216+
// check each mirror whose host matches, in order, until one of them succeeds.
217+
URL parsed(url);
218+
if (!parsed.empty()) {
219+
// The URL was parsed successfully.
220+
for (ImageConfigNS::MirrorConfig& mirror : m_mirrors) {
221+
if (mirror.host() == parsed.host_port()) {
222+
long mirror_code = 0;
223+
estring mirror_url = mirror.mirror() + std::string(parsed.path());
224+
Timeout mirrorTimeout(std::min(tmo.timeout(), mirror.timeoutMs() * 1000));
225+
LOG_INFO("trying mirror `", mirror_url, "` for original url `", url, "` with timeout=", mirrorTimeout.timeout_ms(), "ms");
226+
UrlInfo* info = get_actual_url_impl(mirror_url, mirrorTimeout, mirror_code);
227+
if (info != nullptr) {
228+
code = mirror_code;
229+
return info;
230+
}
231+
}
232+
}
233+
LOG_INFO("falling back to original url `", url, "`");
234+
} else {
235+
LOG_WARN("failed to parse url `", url, "`");
236+
}
237+
}
238+
return get_actual_url_impl(url, tmo.timeout(), code);
239+
}
240+
241+
UrlInfo* get_actual_url_impl(const estring &url, Timeout tmo, long &code) {
214242
estring authurl, scope;
215243
estring *token = nullptr;
216244

@@ -317,6 +345,7 @@ class RegistryFSImpl_v2 : public RegistryFS {
317345

318346
protected:
319347
PasswordCB m_callback;
348+
std::vector<ImageConfigNS::MirrorConfig> m_mirrors;
320349
estring m_accelerate;
321350
estring m_caFile;
322351
estring m_useragent;
@@ -533,15 +562,15 @@ inline IFile *RegistryFSImpl_v2::open(const char *pathname, int) {
533562
return file;
534563
}
535564

536-
IFileSystem *new_registryfs_v2(PasswordCB callback, const char *caFile, uint64_t timeout,
565+
IFileSystem *new_registryfs_v2(PasswordCB callback, std::vector<ImageConfigNS::MirrorConfig> mirrors, const char *caFile, uint64_t timeout,
537566
const char *cert_file, const char *key_file, const char *customized_ua) {
538567
if (!callback)
539568
LOG_ERROR_RETURN(EINVAL, nullptr, "password callback not set");
540569
auto ctx = new_tls_context_from_file(cert_file, key_file);
541570
if (!ctx) {
542571
LOG_ERRNO_RETURN(0, nullptr, "failed to new tls context");
543572
}
544-
return new RegistryFSImpl_v2(callback, caFile ? caFile : "", timeout, ctx, customized_ua);
573+
return new RegistryFSImpl_v2(callback, std::move(mirrors), caFile ? caFile : "", timeout, ctx, customized_ua);
545574
}
546575

547576
class RegistryUploader : public VirtualFile {
@@ -738,7 +767,7 @@ class RegistryUploader : public VirtualFile {
738767
photon::init(photon::INIT_EVENT_DEFAULT, photon::INIT_IO_NONE);
739768
DEFER(photon::fini());
740769
m_upload_fs = new RegistryFSImpl_v2({this, &RegistryUploader::load_auth},
741-
"", m_timeout, m_tls_ctx, nullptr);
770+
{}, "", m_timeout, m_tls_ctx, nullptr);
742771
DEFER({ delete m_upload_fs; });
743772
m_http_client_ts = photon::now;
744773
::posix_memalign(&m_upload_buf, 4096, 1024 * 1024);

0 commit comments

Comments
 (0)