1+ use std:: collections:: HashMap ;
12use std:: fs;
2- use std:: sync:: { Arc , Mutex , Weak } ;
3+ use std:: sync:: { Arc , Mutex , RwLock , Weak } ;
34
45use anyhow:: { anyhow, Result } ;
5- use cloudlet:: driver;
6- use cloudlet:: driver:: http:: { Header , Method , Response } ;
7- use cloudlet:: driver:: log:: Level ;
8- use cloudlet_impl:: WasmCloudlet ;
9- use exports:: cloudlet:: driver:: bridge;
10- use simplelog:: { debug, error, info, warn} ;
11- use tonic:: async_trait;
12- use wasmtime:: component:: { bindgen, Component , Linker , ResourceAny } ;
6+ use cloudlet:: WasmCloudlet ;
7+ use common:: config:: LoadFromTomlFile ;
8+ use config:: WasmConfig ;
9+ use generated:: exports:: cloudlet:: driver:: bridge;
10+ use generated:: Driver ;
11+ use simplelog:: { error, info, warn} ;
12+ use wasmtime:: component:: { Component , Linker , ResourceAny } ;
1313use wasmtime:: { Config , Engine , Store } ;
1414use wasmtime_wasi:: { DirPerms , FilePerms , ResourceTable , WasiCtx , WasiCtxBuilder , WasiView } ;
1515
@@ -18,23 +18,45 @@ use super::{DriverCloudletHandle, GenericDriver, Information};
1818use crate :: application:: cloudlet:: { Capabilities , Cloudlet , HostAndPort , RemoteController } ;
1919use crate :: storage:: Storage ;
2020
21- mod cloudlet_impl ;
21+ mod config ;
2222
23- bindgen ! ( {
24- world: "driver" ,
25- path: "../protocol/wit/" ,
26- } ) ;
23+ mod cloudlet;
24+ mod http;
25+ mod log;
26+ mod process;
27+
28+ pub mod generated {
29+ use wasmtime:: component:: bindgen;
30+
31+ bindgen ! ( {
32+ world: "driver" ,
33+ path: "../protocol/wit/" ,
34+ } ) ;
35+ }
2736
2837const WASM_DIRECTORY : & str = "wasm" ;
2938
30- /* Caching of compiled wasm artifacts */
31- const CACHE_CONFIG_FILE : & str = "wasm.toml" ;
32- const DEFAULT_CACHE_CONFIG : & str = r#"# Comment out certain settings to use default values.
33- # For more settings, please refer to the documentation:
39+ /* Caching of compiled wasm artifacts and other configuration */
40+ const CONFIG_FILE : & str = "wasm.toml" ;
41+ const DEFAULT_CONFIG : & str = r#"# For more settings, please refer to the documentation:
3442# https://bytecodealliance.github.io/wasmtime/cli-cache.html
3543
3644[cache]
37- enabled = true"# ;
45+ enabled = true
46+
47+ # This section is crucial for granting the drivers their required permissions
48+ # https://httprafa.github.io/atomic-cloud/controller/drivers/wasm/permissions/
49+
50+ [[drivers]]
51+ name = "pterodactyl"
52+ inherit_stdio = false
53+ inherit_args = false
54+ inherit_env = false
55+ inherit_network = true
56+ allow_ip_name_lookup = true
57+ allow_http = true
58+ allow_process = false
59+ mounts = []"# ;
3860
3961struct WasmDriverState {
4062 handle : Weak < WasmDriver > ,
@@ -51,90 +73,12 @@ impl WasiView for WasmDriverState {
5173 }
5274}
5375
54- #[ async_trait]
55- impl driver:: api:: Host for WasmDriverState {
76+ impl generated:: cloudlet:: driver:: api:: Host for WasmDriverState {
5677 fn get_name ( & mut self ) -> String {
5778 self . handle . upgrade ( ) . unwrap ( ) . name . clone ( )
5879 }
5980}
6081
61- #[ async_trait]
62- impl driver:: log:: Host for WasmDriverState {
63- fn log_string ( & mut self , level : Level , message : String ) {
64- match level {
65- Level :: Info => info ! (
66- "<blue>[{}]</> {}" ,
67- & self . handle. upgrade( ) . unwrap( ) . name. to_uppercase( ) ,
68- message
69- ) ,
70- Level :: Warn => warn ! (
71- "<blue>[{}]</> {}" ,
72- & self . handle. upgrade( ) . unwrap( ) . name. to_uppercase( ) ,
73- message
74- ) ,
75- Level :: Error => error ! (
76- "<blue>[{}] {}" ,
77- & self . handle. upgrade( ) . unwrap( ) . name. to_uppercase( ) ,
78- message
79- ) ,
80- Level :: Debug => debug ! (
81- "[{}] {}" ,
82- & self . handle. upgrade( ) . unwrap( ) . name. to_uppercase( ) ,
83- message
84- ) ,
85- }
86- }
87- }
88-
89- #[ async_trait]
90- impl driver:: http:: Host for WasmDriverState {
91- fn send_http_request (
92- & mut self ,
93- method : Method ,
94- url : String ,
95- headers : Vec < Header > ,
96- body : Option < Vec < u8 > > ,
97- ) -> Option < Response > {
98- let driver = self . handle . upgrade ( ) . unwrap ( ) ;
99- let mut request = match method {
100- Method :: Get => minreq:: get ( url) ,
101- Method :: Patch => minreq:: patch ( url) ,
102- Method :: Post => minreq:: post ( url) ,
103- Method :: Put => minreq:: put ( url) ,
104- Method :: Delete => minreq:: delete ( url) ,
105- } ;
106- if let Some ( body) = body {
107- request = request. with_body ( body) ;
108- }
109- for header in headers {
110- request = request. with_header ( & header. key , & header. value ) ;
111- }
112- let response = match request. send ( ) {
113- Ok ( response) => response,
114- Err ( error) => {
115- warn ! (
116- "<red>Failed</> to send HTTP request for driver <blue>{}</>: <red>{}</>" ,
117- & driver. name, error
118- ) ;
119- return None ;
120- }
121- } ;
122- Some ( Response {
123- status_code : response. status_code as u32 ,
124- reason_phrase : response. reason_phrase . clone ( ) ,
125- headers : response
126- . headers
127- . iter ( )
128- . map ( |header| Header {
129- key : header. 0 . clone ( ) ,
130- value : header. 1 . clone ( ) ,
131- } )
132- . collect ( ) ,
133- bytes : response. into_bytes ( ) ,
134- } )
135- }
136- }
137-
13882struct WasmDriverHandle {
13983 store : Store < WasmDriverState > ,
14084 resource : ResourceAny , // This is delete when the store is dropped
@@ -150,12 +94,18 @@ impl WasmDriverHandle {
15094 }
15195}
15296
97+ pub struct WasmDriverData {
98+ child_processes : RwLock < HashMap < u32 , std:: process:: Child > > ,
99+ }
100+
153101pub struct WasmDriver {
154102 own : Weak < WasmDriver > ,
155103
156104 name : String ,
157105 bindings : Driver ,
158106 handle : Mutex < Option < WasmDriverHandle > > ,
107+
108+ data : WasmDriverData ,
159109}
160110
161111impl WasmDriver {
@@ -166,7 +116,6 @@ impl WasmDriver {
166116 }
167117}
168118
169- #[ async_trait]
170119impl GenericDriver for WasmDriver {
171120 fn name ( & self ) -> & String {
172121 & self . name
@@ -210,7 +159,12 @@ impl GenericDriver for WasmDriver {
210159}
211160
212161impl WasmDriver {
213- fn new ( cloud_identifier : & str , name : & str , source : & Source ) -> Result < Arc < Self > > {
162+ fn new (
163+ config : & WasmConfig ,
164+ cloud_identifier : & str ,
165+ name : & str ,
166+ source : & Source ,
167+ ) -> Result < Arc < Self > > {
214168 let config_directory = Storage :: get_config_folder_for_driver ( name) ;
215169 let data_directory = Storage :: get_data_folder_for_driver ( name) ;
216170 if !config_directory. exists ( ) {
@@ -230,26 +184,46 @@ impl WasmDriver {
230184 } ) ;
231185 }
232186
233- let mut config = Config :: new ( ) ;
234- config . wasm_component_model ( true ) ;
187+ let mut engine_config = Config :: new ( ) ;
188+ engine_config . wasm_component_model ( true ) ;
235189 if let Err ( error) =
236- config . cache_config_load ( Storage :: get_configs_folder ( ) . join ( CACHE_CONFIG_FILE ) )
190+ engine_config . cache_config_load ( Storage :: get_configs_folder ( ) . join ( CONFIG_FILE ) )
237191 {
238192 warn ! (
239193 "<red>Failed</> to enable caching for wasmtime engine: <red>{}</>" ,
240194 & error
241195 ) ;
242196 }
243197
244- let engine = Engine :: new ( & config ) ?;
198+ let engine = Engine :: new ( & engine_config ) ?;
245199 let component = Component :: from_binary ( & engine, & source. code ) ?;
246200
247201 let mut linker = Linker :: new ( & engine) ;
248202 wasmtime_wasi:: add_to_linker_sync ( & mut linker) ?;
249203 Driver :: add_to_linker ( & mut linker, |state : & mut WasmDriverState | state) ?;
250204
251- let wasi = WasiCtxBuilder :: new ( )
252- . inherit_stdio ( )
205+ let mut wasi = WasiCtxBuilder :: new ( ) ;
206+ if let Some ( config) = config. get_config ( name) {
207+ if config. inherit_stdio {
208+ wasi. inherit_stdio ( ) ;
209+ }
210+ if config. inherit_args {
211+ wasi. inherit_args ( ) ;
212+ }
213+ if config. inherit_env {
214+ wasi. inherit_env ( ) ;
215+ }
216+ if config. inherit_network {
217+ wasi. inherit_network ( ) ;
218+ }
219+ if config. allow_ip_name_lookup {
220+ wasi. allow_ip_name_lookup ( true ) ;
221+ }
222+ for mount in & config. mounts {
223+ wasi. preopened_dir ( & mount. host , & mount. guest , DirPerms :: all ( ) , FilePerms :: all ( ) ) ?;
224+ }
225+ }
226+ let wasi = wasi
253227 . preopened_dir (
254228 & config_directory,
255229 "/configs/" ,
@@ -258,6 +232,7 @@ impl WasmDriver {
258232 ) ?
259233 . preopened_dir ( & data_directory, "/data/" , DirPerms :: all ( ) , FilePerms :: all ( ) ) ?
260234 . build ( ) ;
235+
261236 let table = ResourceTable :: new ( ) ;
262237
263238 let mut store = Store :: new (
@@ -276,6 +251,9 @@ impl WasmDriver {
276251 name : name. to_string ( ) ,
277252 bindings,
278253 handle : Mutex :: new ( None ) ,
254+ data : WasmDriverData {
255+ child_processes : RwLock :: new ( HashMap :: new ( ) ) ,
256+ } ,
279257 }
280258 } ) ;
281259 let driver_resource = driver
@@ -291,17 +269,27 @@ impl WasmDriver {
291269 Ok ( driver)
292270 }
293271
294- pub fn load_all ( cloud_identifier : & str , drivers : & mut Vec < Arc < dyn GenericDriver > > ) {
272+ pub fn load_all (
273+ cloud_identifier : & str ,
274+ drivers : & mut Vec < Arc < dyn GenericDriver > > ,
275+ ) -> WasmConfig {
295276 // Check if cache configuration exists
296- let cache_config = Storage :: get_configs_folder ( ) . join ( CACHE_CONFIG_FILE ) ;
297- if !cache_config . exists ( ) {
298- fs:: write ( & cache_config , DEFAULT_CACHE_CONFIG ) . unwrap_or_else ( |error| {
277+ let config_file = Storage :: get_configs_folder ( ) . join ( CONFIG_FILE ) ;
278+ if !config_file . exists ( ) {
279+ fs:: write ( & config_file , DEFAULT_CONFIG ) . unwrap_or_else ( |error| {
299280 warn ! (
300- "<red>Failed</> to create default cache configuration file: <red>{}</>" ,
281+ "<red>Failed</> to create default wasm configuration file: <red>{}</>" ,
301282 & error
302283 )
303284 } ) ;
304285 }
286+ let config = WasmConfig :: load_from_file ( & config_file) . unwrap_or_else ( |error| {
287+ warn ! (
288+ "<red>Failed</> to load wasm configuration file: <red>{}</>" ,
289+ & error
290+ ) ;
291+ WasmConfig :: default ( )
292+ } ) ;
305293
306294 let old_loaded = drivers. len ( ) ;
307295
@@ -322,7 +310,7 @@ impl WasmDriver {
322310 "<red>Failed</> to read driver directory: <red>{}</>" ,
323311 & error
324312 ) ;
325- return ;
313+ return config ;
326314 }
327315 } ;
328316
@@ -365,7 +353,7 @@ impl WasmDriver {
365353 } ;
366354
367355 info ! ( "Compiling driver <blue>{}</>..." , & name) ;
368- let driver = WasmDriver :: new ( cloud_identifier, & name, & source) ;
356+ let driver = WasmDriver :: new ( & config , cloud_identifier, & name, & source) ;
369357 match driver {
370358 Ok ( driver) => match driver. init ( ) {
371359 Ok ( info) => {
@@ -399,6 +387,7 @@ impl WasmDriver {
399387 "The Wasm driver feature is <yellow>enabled</>, but no Wasm drivers were loaded."
400388 ) ;
401389 }
390+ config
402391 }
403392}
404393
0 commit comments