Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement nydusd and nydus-snapshotter to deliver config through the socket API #1379

Closed
wants to merge 0 commits into from

Conversation

DarkMountain-wyz
Copy link

Relevant Issue (if applicable)

containerd/nydus-snapshotter#388

Details

  • The previous PR has been closed, so a new PR has been submitted
  • Command line parameter --config now represents the URL to request daemon config from nydus-snapshotter.
  • New command line parameter --config-source, representing the unix socket path for communication between nydus snapshot and nydusd.
  • Nydusd is now requesting config information from nydus-snapshotter instead of obtaining config by reading the config dump file.

Types of changes

What types of changes does your PullRequest introduce? Put an x in all the boxes that apply:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation Update (if none of the other choices apply)

Checklist

Go over all the following points, and put an x in all the boxes that apply.

  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.

@DarkMountain-wyz DarkMountain-wyz requested a review from a team as a code owner July 20, 2023 02:50
@DarkMountain-wyz DarkMountain-wyz requested review from liubogithub, imeoer and hsiangkao and removed request for a team July 20, 2023 02:50
@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , a new test job has been submitted. Please wait in patience. The test job url: https://tone.openanolis.cn/ws/nrh4nnio/test_result/85652

@codecov
Copy link

codecov bot commented Jul 20, 2023

Codecov Report

Merging #1379 (ba3357d) into master (9ab1ec1) will decrease coverage by 0.12%.
Report is 1 commits behind head on master.
The diff coverage is 1.98%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1379      +/-   ##
==========================================
- Coverage   46.29%   46.18%   -0.12%     
==========================================
  Files         123      123              
  Lines       38872    38960      +88     
  Branches    38872    38960      +88     
==========================================
- Hits        17997    17992       -5     
- Misses      19906    19994      +88     
- Partials      969      974       +5     
Files Coverage Δ
src/bin/nydusd/main.rs 0.18% <0.00%> (-0.01%) ⬇️
api/src/config.rs 69.37% <0.00%> (-2.07%) ⬇️
storage/src/backend/registry.rs 31.38% <4.00%> (-1.56%) ⬇️

... and 2 files with indirect coverage changes

@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , The CI test is completed, please check result:

Test CaseTest Result
build rust golang image✅ SUCCESS
compile nydusd✅ SUCCESS
compile ctr remote✅ SUCCESS
compile nydus snapshotter✅ SUCCESS
run container with rafs✅ SUCCESS
run container with zran✅ SUCCESS
run container with rafs and compile linux✅ SUCCESS

Congratulations, your test job passed!

@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , the code has been updated, so a new test job has been submitted. Please wait in patience. The test job url: https://tone.openanolis.cn/ws/nrh4nnio/test_result/87020

@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , The CI test is completed, please check result:

Test CaseTest Result
build rust golang image✅ SUCCESS
compile nydusd✅ SUCCESS
compile ctr remote✅ SUCCESS
compile nydus snapshotter✅ SUCCESS
run container with rafs✅ SUCCESS
run container with zran✅ SUCCESS
run container with rafs and compile linux✅ SUCCESS

Congratulations, your test job passed!

@@ -418,7 +505,28 @@ fn process_fs_service(
)
}
None => match args.value_of("config") {
Some(v) => std::fs::read_to_string(v)?,
Some(v) => {
let socket_path = match args.value_of("config-source") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the option --config-source should be conflict with --config, right?

@@ -363,6 +373,83 @@ fn handle_rlimit_nofile_option(args: &ArgMatches, option_name: &str) -> Result<(
Ok(())
}

fn send_unix_socket_request(socket_path: &str, method: &str, url: &str) -> Option<String> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about putting this into api/src/config.rs, and naming it fn from_source(...).

fn send_unix_socket_request(socket_path: &str, method: &str, url: &str) -> Option<String> {
let mut stream = match UnixStream::connect(socket_path).ok() {
Some(stream) => stream,
None => return None,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd better return a Result instead of an Option, and handle the Result outside.

None => return None,
};

let request = format!("{} {} HTTP/1.1\r\nHost: localhost\r\n\r\n", method, url);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using the hyper::Client crate directly, instead of implementing the HTTP over the unix domain socket client by self?

let mut total_read = 0;

loop {
match stream.read(&mut buffer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it strange to actively read configuration from nydus-snapshotter. This means nydus daemon depends on nydus-snapshoter. But nydus-snapshotter is the manager of nydus daemon. So, I think nydus-snapshotter should update the configuration as needed instead of providing an API for the daemon.

@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , the code has been updated, so a new test job has been submitted. Please wait in patience. The test job url: https://tone.openanolis.cn/ws/nrh4nnio/test_result/89250

@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , The CI test is completed, please check result:

Test CaseTest Result
build rust golang image✅ SUCCESS
compile nydusd✅ SUCCESS
compile ctr remote✅ SUCCESS
compile nydus snapshotter✅ SUCCESS
run container with rafs✅ SUCCESS
run container with zran✅ SUCCESS
run container with rafs and compile linux✅ SUCCESS

Congratulations, your test job passed!

@@ -218,6 +220,32 @@ impl ConfigV2 {
}
}
}

/// Fill backend config from nydus-snapshotter
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not only for nydus snapshotter in the future.

let uri = Uri::new(sock, endpoint).into();
let response = client.get(uri).await?;
let status_code = response.status().as_u16();
let buf = hyper::body::to_bytes(response).await?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should read the response body after the status code check.

let buf = hyper::body::to_bytes(response).await?;
if status_code != 200 {
return Err(anyhow::anyhow!(
"Request failed with status code: {}",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

failed to request backend config from source, status code: {}

@@ -245,6 +273,7 @@ impl FromStr for ConfigV2 {
}
}
}
info!("你到这了吗");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this.

.global(true),
)
.arg(
Arg::new("credential-source")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about renaming it to backend-source, and combining the url with systemsock?

@imeoer
Copy link
Collaborator

imeoer commented Aug 8, 2023

@DarkMountain-wyz Please refine the commits and add some commit messages to explain why & how to do this.

@DarkMountain-wyz
Copy link
Author

DarkMountain-wyz commented Aug 8, 2023

@DarkMountain-wyz Please refine the commits and add some commit messages to explain why & how to do this.
I will do it

@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , the code has been updated, so a new test job has been submitted. Please wait in patience. The test job url: https://tone.openanolis.cn/ws/nrh4nnio/test_result/89600

@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , The CI test is completed, please check result:

Test CaseTest Result
build rust golang image✅ SUCCESS
compile nydusd✅ SUCCESS
compile ctr remote✅ SUCCESS
compile nydus snapshotter✅ SUCCESS
run container with rafs✅ SUCCESS
run container with zran✅ SUCCESS
run container with rafs and compile linux✅ SUCCESS

Congratulations, your test job passed!

@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , the code has been updated, so a new test job has been submitted. Please wait in patience. The test job url: https://tone.openanolis.cn/ws/nrh4nnio/test_result/89652

@anolis-bot
Copy link
Collaborator

@DarkMountain-wyz , The CI test is completed, please check result:

Test CaseTest Result
build rust golang image✅ SUCCESS
compile nydusd✅ SUCCESS
compile ctr remote✅ SUCCESS
compile nydus snapshotter✅ SUCCESS
run container with rafs✅ SUCCESS
run container with zran✅ SUCCESS
run container with rafs and compile linux✅ SUCCESS

Congratulations, your test job passed!

@imeoer
Copy link
Collaborator

imeoer commented Sep 25, 2023

@DarkMountain-wyz We'd better refresh the backend config when the registry auth expires.

api/Cargo.toml Outdated
@@ -13,6 +13,9 @@ libc = "0.2"
log = "0.4.8"
serde_json = "1.0.53"
toml = "0.5"
hyper = "0.14.11"
hyperlocal = "0.8.0"
anyhow = "1"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use the exact version 1.0 here?

api/Cargo.toml Outdated
@@ -21,9 +24,11 @@ lazy_static = { version = "1.4.0", optional = true }
mio = { version = "0.8", features = ["os-poll", "os-ext"], optional = true }
serde = { version = "1.0.110", features = ["rc", "serde_derive"] }
url = { version = "2.1.1", optional = true }
tokio = { version = "1.24", features = ["full"] }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the using of full feature will import a large number of dependencies, can we only use the necessary feature?

@@ -37,6 +39,7 @@ const REDIRECTED_STATUS_CODE: [StatusCode; 2] = [
];

const REGISTRY_DEFAULT_TOKEN_EXPIRATION: u64 = 10 * 60; // in seconds
const MAX_RETRIES: u32 = 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unnecessary to add the retry mechanism because the upper caller will retry if any error happens.


use serde::Deserialize;
use serde_json::Value;

lazy_static! {
pub static ref BACKEND_SOURCE_PATH: Mutex<Option<String>> = Mutex::new(None);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about putting this into BackendConfigV2 struct like this (as a private field, do not participate in Deserialize/Serialize):

pub struct BackendConfigV2 {
    /// Type of storage backend.
    #[serde(rename = "type")]
    pub backend_type: String,
    /// Source of storage backend configuration.
    #[serde(skip_serializing, skip_deserializing)]
    backend_source: Option<String>,
}


if token_resp.status() == StatusCode::OK {
return Ok(token_resp);
} else if token_resp.status() == StatusCode::FORBIDDEN && retries < MAX_RETRIES {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be vec![StatusCode::UNAUTHORIZED, StatusCode::FORBIDDEN].contains(&token_resp.status()).

let registry_auth = trim(registry_config.auth.clone());
let (new_username, new_password) =
Registry::get_authorization_info(&registry_auth)?;
username = new_username;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.username & self.password should be updated.

@@ -276,6 +276,13 @@ fn prepare_commandline_options() -> Command {
.required(false)
.global(true),
)
.arg(
Arg::new("backend-source")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smoke test is required. Please also update doc.

Copy link
Member

@bergwolf bergwolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title mentions config delivery but it actually is only about auth right? We already support configurating nydusd backend (which including auth info) via API. It is just that we need to amend nydus-snapshotter to stopping passing config via local file but via API instead. @DarkMountain-wyz Are you planning to look at the nydus-snapshotter part as well?

@@ -425,7 +432,11 @@ fn process_fs_service(
config.update_registry_auth_info(&auth);
serde_json::to_string(&config)?
} else {
std::fs::read_to_string(v)?
let mut config = ConfigV2::from_file(v)?;
if let Some(source) = args.value_of("backend-source") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it a backend-source or an auth-source? It looks like that we only use it to get auth info.

})
.ok()?;
let backend_config_v2 = BackendConfigV2::try_from(&backend_config).ok()?;
let mut backend_source = BACKEND_SOURCE_PATH.lock().unwrap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would deadlock as we call update_auth_from_source after taking the BACKEND_SOURCE_PATH mutex when dealing with backend auth failures, which also indicates that the code path has not been tested.

BACKEND_SOURCE_PATH should actually be only set when starting nydusd. There is no need to update it from time to time.

@bergwolf
Copy link
Member

bergwolf commented Nov 1, 2023

And where is the corresponding nydus-snapshotter part of the change? I assume we need a new API from snapshotter as well, no?

@DarkMountain-wyz
Copy link
Author

And where is the corresponding nydus-snapshotter part of the change? I assume we need a new API from snapshotter as well, no?

The corresponding modification for the nydus-snapshotter can be found in the pull request here. The approach taken involves providing a domain socket API for nydusd to request and retrieve backend information. The decision to pass all backend information rather than just authentication details is to ensure flexibility in case new types of backends are added in the future, without needing to modify this interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants