7.8 KiB
SAL RFS (Remote File System) Module (sal::virt::rfs
)
Overview
The sal::virt::rfs
module provides a Rust interface for interacting with an underlying rfs
command-line tool. This tool facilitates mounting various types of remote and local filesystems and managing packed filesystem layers.
The module allows Rust applications and herodo
Rhai scripts to:
- Mount and unmount filesystems from different sources (e.g., local paths, SSH, S3, WebDAV).
- List currently mounted filesystems and retrieve information about specific mounts.
- Pack directories into filesystem layers, potentially using specified storage backends.
- Unpack, list contents of, and verify these filesystem layers.
All operations are performed by invoking the rfs
CLI tool and parsing its output.
Key Design Points
- CLI Wrapper: This module acts as a wrapper around an external
rfs
command-line utility. The actual filesystem operations and layer management are delegated to this tool. - Asynchronous Operations (Implicit): While the Rust functions themselves might be synchronous, the underlying
execute_rfs_command
(presumably fromsuper::cmd
) likely handles command execution, which could be asynchronous or blocking depending on its implementation. - Filesystem Abstraction: Supports mounting diverse filesystem types such as
local
,ssh
,s3
, andwebdav
through therfs
tool's capabilities. - Layer Management: Provides functionalities to
pack
directories into portable layers,unpack
them,list_contents
, andverify
their integrity. This is useful for creating and managing reproducible filesystem snapshots or components. - Store Specifications (
StoreSpec
): The packing functionality allows specifyingStoreSpec
types, suggesting that packed layers can be stored or referenced using different backend mechanisms (e.g., local files, S3 buckets). This enables flexible storage and retrieval of filesystem layers. - Builder Pattern: Uses
RfsBuilder
for constructing mount commands with various options andPackBuilder
for packing operations, providing a fluent interface for complex configurations. - Rhai Scriptability: Most functionalities are exposed to Rhai scripts via
herodo
through thesal::rhai::rfs
bridge, enabling automation of filesystem and layer management tasks. - Structured Error Handling: Defines
RfsError
for specific error conditions encountered duringrfs
command execution or output parsing.
Rhai Scripting with herodo
The sal::virt::rfs
module is scriptable via herodo
. The following functions are available in Rhai, prefixed with rfs_
:
Mount Operations
-
rfs_mount(source: String, target: String, mount_type: String, options: Map) -> Map
- Mounts a filesystem.
source
: The source path or URL (e.g.,/path/to/local_dir
,ssh://user@host:/remote/path
,s3://bucket/key
).target
: The local path where the filesystem will be mounted.mount_type
: A string specifying the type of filesystem (e.g., "local", "ssh", "s3", "webdav").options
: A Rhai map of additional mount options (e.g.,#{ "read_only": true, "uid": 1000 }
).- Returns a map containing details of the mount (id, source, target, fs_type, options) on success.
-
rfs_unmount(target: String) -> ()
- Unmounts the filesystem at the specified target path.
-
rfs_list_mounts() -> Array
- Lists all currently mounted filesystems managed by
rfs
. - Returns an array of maps, each representing a mount with its details.
- Lists all currently mounted filesystems managed by
-
rfs_unmount_all() -> ()
- Unmounts all filesystems currently managed by
rfs
.
- Unmounts all filesystems currently managed by
-
rfs_get_mount_info(target: String) -> Map
- Retrieves information about a specific mounted filesystem.
- Returns a map with mount details if found.
Pack/Layer Operations
-
rfs_pack(directory: String, output: String, store_specs: String) -> ()
- Packs the contents of a
directory
into anoutput
file (layer). store_specs
: A comma-separated string defining storage specifications for the layer (e.g.,"file:path=/path/to/local_store,s3:bucket=my-archive,region=us-west-1"
). Each spec istype:key=value,key2=value2
.
- Packs the contents of a
-
rfs_unpack(input: String, directory: String) -> ()
- Unpacks an
input
layer file into the specifieddirectory
.
- Unpacks an
-
rfs_list_contents(input: String) -> String
- Lists the contents of an
input
layer file. - Returns a string containing the file listing (raw output from the
rfs
tool).
- Lists the contents of an
-
rfs_verify(input: String) -> bool
- Verifies the integrity of an
input
layer file. - Returns
true
if the layer is valid,false
otherwise.
- Verifies the integrity of an
Rhai Example
// Example: Mounting a local directory (ensure /mnt/my_local_mount exists)
let source_dir = "/tmp/my_data_source"; // Create this directory first
let target_mount = "/mnt/my_local_mount";
// Create source_dir if it doesn't exist for the example to run
// In a real script, you might use sal::os::dir_create or ensure it exists.
// For this example, assume it's manually created or use: os_run_command(`mkdir -p ${source_dir}`);
print(`Mounting ${source_dir} to ${target_mount}...`);
let mount_result = rfs_mount(source_dir, target_mount, "local", #{});
if mount_result.is_ok() {
print(`Mount successful: ${mount_result}`);
} else {
print(`Mount failed: ${mount_result}`);
}
// List mounts
print("\nCurrent mounts:");
let mounts = rfs_list_mounts();
if mounts.is_ok() {
for m in mounts {
print(` Target: ${m.target}, Source: ${m.source}, Type: ${m.fs_type}`);
}
} else {
print(`Error listing mounts: ${mounts}`);
}
// Example: Packing a directory
let dir_to_pack = "/tmp/pack_this_dir"; // Create and populate this directory
let packed_file = "/tmp/my_layer.pack";
// os_run_command(`mkdir -p ${dir_to_pack}`);
// os_run_command(`echo 'hello' > ${dir_to_pack}/file1.txt`);
print(`\nPacking ${dir_to_pack} to ${packed_file}...`);
// Using a file-based store spec for simplicity
let pack_store_specs = "file:path=/tmp/rfs_store";
// os_run_command(`mkdir -p /tmp/rfs_store`);
let pack_result = rfs_pack(dir_to_pack, packed_file, pack_store_specs);
if pack_result.is_ok() {
print("Packing successful.");
// List contents of the packed file
print(`\nContents of ${packed_file}:`);
let contents = rfs_list_contents(packed_file);
if contents.is_ok() {
print(contents);
} else {
print(`Error listing contents: ${contents}`);
}
// Verify the packed file
print(`\nVerifying ${packed_file}...`);
let verify_result = rfs_verify(packed_file);
if verify_result.is_ok() && verify_result {
print("Verification successful: Layer is valid.");
} else {
print(`Verification failed or error: ${verify_result}`);
}
// Example: Unpacking
let unpack_dir = "/tmp/unpacked_layer_here";
// os_run_command(`mkdir -p ${unpack_dir}`);
print(`\nUnpacking ${packed_file} to ${unpack_dir}...`);
let unpack_result = rfs_unpack(packed_file, unpack_dir);
if unpack_result.is_ok() {
print("Unpacking successful.");
// You would typically check contents of unpack_dir here
// os_run_command(`ls -la ${unpack_dir}`);
} else {
print(`Error unpacking: ${unpack_result}`);
}
} else {
print(`Error packing: ${pack_result}`);
}
// Cleanup: Unmount the local mount
if mount_result.is_ok() {
print(`\nUnmounting ${target_mount}...`);
rfs_unmount(target_mount);
}
// To run this example, ensure the 'rfs' command-line tool is installed and configured,
// and that the necessary directories (/tmp/my_data_source, /mnt/my_local_mount, etc.)
// exist and have correct permissions.
// You might need to run herodo with sudo for mount/unmount operations.
print("\nRFS Rhai script finished.");
This module provides a flexible way to manage diverse filesystems and filesystem layers, making it a powerful tool for system automation and deployment tasks within the SAL ecosystem.