nydus_api/http.rs
1// Copyright 2022 Alibaba Cloud. All rights reserved.
2// Copyright 2020 Ant Group. All rights reserved.
3// Copyright © 2019 Intel Corporation
4//
5// SPDX-License-Identifier: Apache-2.0
6
7use std::io;
8use std::sync::mpsc::{RecvError, SendError};
9
10use serde::Deserialize;
11use serde_json::Error as SerdeError;
12use thiserror::Error;
13
14use crate::BlobCacheEntry;
15
16/// Errors related to Metrics.
17#[derive(Error, Debug)]
18pub enum MetricsError {
19 #[error("no counter found for the metric")]
20 NoCounter,
21 #[error("failed to serialize metric: {0:?}")]
22 Serialize(#[source] SerdeError),
23}
24
25/// Mount a filesystem.
26#[derive(Clone, Deserialize, Debug)]
27pub struct ApiMountCmd {
28 /// Path to source of the filesystem.
29 pub source: String,
30 /// Type of filesystem.
31 #[serde(default)]
32 pub fs_type: String,
33 /// Configuration for the filesystem.
34 pub config: String,
35 /// List of files to prefetch.
36 #[serde(default)]
37 pub prefetch_files: Option<Vec<String>>,
38}
39
40/// Umount a mounted filesystem.
41#[derive(Clone, Deserialize, Debug)]
42pub struct ApiUmountCmd {
43 /// Path of mountpoint.
44 pub mountpoint: String,
45}
46
47/// Set/update daemon configuration.
48#[derive(Clone, Deserialize, Debug)]
49pub struct DaemonConf {
50 /// Logging level: Off, Error, Warn, Info, Debug, Trace.
51 pub log_level: String,
52}
53
54/// Identifier for cached blob objects.
55///
56/// Domains are used to control the blob sharing scope. All blobs associated with the same domain
57/// will be shared/reused, but blobs associated with different domains are isolated.
58#[derive(Clone, Debug, Default, Deserialize, Serialize)]
59pub struct BlobCacheObjectId {
60 /// Domain identifier for the object.
61 #[serde(default)]
62 pub domain_id: String,
63 /// Blob identifier for the object.
64 #[serde(default)]
65 pub blob_id: String,
66}
67
68#[derive(Debug)]
69pub enum ApiRequest {
70 /// Set daemon configuration.
71 ConfigureDaemon(DaemonConf),
72 /// Get daemon information.
73 GetDaemonInfo,
74 /// Get daemon global events.
75 GetEvents,
76 /// Stop the daemon.
77 Exit,
78 /// Start the daemon.
79 Start,
80 /// Send fuse fd to new daemon.
81 SendFuseFd,
82 /// Take over fuse fd from old daemon instance.
83 TakeoverFuseFd,
84
85 // Filesystem Related
86 /// Mount a filesystem.
87 Mount(String, ApiMountCmd),
88 /// Remount a filesystem.
89 Remount(String, ApiMountCmd),
90 /// Unmount a filesystem.
91 Umount(String),
92
93 /// Get storage backend metrics.
94 ExportBackendMetrics(Option<String>),
95 /// Get blob cache metrics.
96 ExportBlobcacheMetrics(Option<String>),
97
98 // Nydus API v1 requests
99 /// Get filesystem global metrics.
100 ExportFsGlobalMetrics(Option<String>),
101 /// Get filesystem access pattern log.
102 ExportFsAccessPatterns(Option<String>),
103 /// Get filesystem backend information.
104 ExportFsBackendInfo(String),
105 /// Get filesystem file metrics.
106 ExportFsFilesMetrics(Option<String>, bool),
107 /// Get information about filesystem inflight requests.
108 ExportFsInflightMetrics,
109
110 // Nydus API v2
111 /// Get daemon information excluding filesystem backends.
112 GetDaemonInfoV2,
113 /// Create a blob cache entry
114 CreateBlobObject(Box<BlobCacheEntry>),
115 /// Get information about blob cache entries
116 GetBlobObject(BlobCacheObjectId),
117 /// Delete a blob cache entry
118 DeleteBlobObject(BlobCacheObjectId),
119 /// Delete a blob cache file
120 DeleteBlobFile(String),
121}
122
123/// Kinds for daemon related error messages.
124#[derive(Debug)]
125pub enum DaemonErrorKind {
126 /// Service not ready yet.
127 NotReady,
128 /// Generic errors.
129 Other(String),
130 /// Message serialization/deserialization related errors.
131 Serde(SerdeError),
132 /// Unexpected event type.
133 UnexpectedEvent(String),
134 /// Can't upgrade the daemon.
135 UpgradeManager(String),
136 /// Unsupported requests.
137 Unsupported,
138}
139
140/// Kinds for metrics related error messages.
141#[derive(Debug)]
142pub enum MetricsErrorKind {
143 /// Generic daemon related errors.
144 Daemon(DaemonErrorKind),
145 /// Errors related to metrics implementation.
146 Stats(MetricsError),
147}
148
149#[derive(Error, Debug)]
150#[allow(clippy::large_enum_variant)]
151pub enum ApiError {
152 #[error("daemon internal error: {0:?}")]
153 DaemonAbnormal(DaemonErrorKind),
154 #[error("daemon events error: {0}")]
155 Events(String),
156 #[error("metrics error: {0:?}")]
157 Metrics(MetricsErrorKind),
158 #[error("failed to mount filesystem: {0:?}")]
159 MountFilesystem(DaemonErrorKind),
160 #[error("failed to send request to the API service: {0:?}")]
161 RequestSend(#[from] SendError<Option<ApiRequest>>),
162 #[error("failed to parse response payload type")]
163 ResponsePayloadType,
164 #[error("failed to receive response from the API service: {0:?}")]
165 ResponseRecv(#[from] RecvError),
166 #[error("failed to wake up the daemon: {0:?}")]
167 Wakeup(#[source] io::Error),
168}
169
170/// Specialized `std::result::Result` for API replies.
171pub type ApiResult<T> = std::result::Result<T, ApiError>;
172
173#[derive(Serialize)]
174pub enum ApiResponsePayload {
175 /// Filesystem backend metrics.
176 BackendMetrics(String),
177 /// Blobcache metrics.
178 BlobcacheMetrics(String),
179 /// Daemon version, configuration and status information in json.
180 DaemonInfo(String),
181 /// No data is sent on the channel.
182 Empty,
183 /// Global error events.
184 Events(String),
185
186 /// Filesystem global metrics, v1.
187 FsGlobalMetrics(String),
188 /// Filesystem per-file metrics, v1.
189 FsFilesMetrics(String),
190 /// Filesystem access pattern trace log, v1.
191 FsFilesPatterns(String),
192 // Filesystem Backend Information, v1.
193 FsBackendInfo(String),
194 // Filesystem Inflight Requests, v1.
195 FsInflightMetrics(String),
196
197 /// List of blob objects, v2
198 BlobObjectList(String),
199}
200
201/// Specialized version of [`std::result::Result`] for value returned by backend services.
202pub type ApiResponse = std::result::Result<ApiResponsePayload, ApiError>;
203
204/// HTTP error messages sent back to the clients.
205///
206/// The `HttpError` object will be sent back to client with `format!("{:?}", http_error)`.
207/// So unfortunately it implicitly becomes parts of the API, please keep it stable.
208#[derive(Debug)]
209pub enum HttpError {
210 // Daemon common related errors
211 /// Invalid HTTP request
212 BadRequest,
213 /// Failed to configure the daemon.
214 Configure(ApiError),
215 /// Failed to query information about daemon.
216 DaemonInfo(ApiError),
217 /// Failed to query global events.
218 Events(ApiError),
219 /// No handler registered for HTTP request URI
220 NoRoute,
221 /// Failed to parse HTTP request message body
222 ParseBody(SerdeError),
223 /// Query parameter is missed from the HTTP request.
224 QueryString(String),
225
226 /// Failed to mount filesystem.
227 Mount(ApiError),
228 /// Failed to remount filesystem.
229 Upgrade(ApiError),
230
231 // Metrics related errors
232 /// Failed to get backend metrics.
233 BackendMetrics(ApiError),
234 /// Failed to get blobcache metrics.
235 BlobcacheMetrics(ApiError),
236
237 // Filesystem related errors (v1)
238 /// Failed to get filesystem backend information
239 FsBackendInfo(ApiError),
240 /// Failed to get filesystem per-file metrics.
241 FsFilesMetrics(ApiError),
242 /// Failed to get global metrics.
243 GlobalMetrics(ApiError),
244 /// Failed to get information about inflight request
245 InflightMetrics(ApiError),
246 /// Failed to get filesystem file access trace.
247 Pattern(ApiError),
248
249 // Blob cache management related errors (v2)
250 /// Failed to create blob object
251 CreateBlobObject(ApiError),
252 /// Failed to delete blob object
253 DeleteBlobObject(ApiError),
254 /// Failed to delete blob file
255 DeleteBlobFile(ApiError),
256 /// Failed to list existing blob objects
257 GetBlobObjects(ApiError),
258}
259
260#[derive(Serialize, Debug)]
261pub(crate) struct ErrorMessage {
262 pub code: String,
263 pub message: String,
264}
265
266impl From<ErrorMessage> for Vec<u8> {
267 fn from(msg: ErrorMessage) -> Self {
268 // Safe to unwrap since `ErrorMessage` must succeed in serialization
269 serde_json::to_vec(&msg).unwrap()
270 }
271}