166 lines
7.8 KiB
Markdown
166 lines
7.8 KiB
Markdown
# 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 from `super::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`, and `webdav` through the `rfs` tool's capabilities.
|
|
- **Layer Management**: Provides functionalities to `pack` directories into portable layers, `unpack` them, `list_contents`, and `verify` their integrity. This is useful for creating and managing reproducible filesystem snapshots or components.
|
|
- **Store Specifications (`StoreSpec`)**: The packing functionality allows specifying `StoreSpec` 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 and `PackBuilder` for packing operations, providing a fluent interface for complex configurations.
|
|
- **Rhai Scriptability**: Most functionalities are exposed to Rhai scripts via `herodo` through the `sal::rhai::rfs` bridge, enabling automation of filesystem and layer management tasks.
|
|
- **Structured Error Handling**: Defines `RfsError` for specific error conditions encountered during `rfs` 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.
|
|
|
|
- `rfs_unmount_all() -> ()`
|
|
- Unmounts all filesystems currently managed by `rfs`.
|
|
|
|
- `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 an `output` 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 is `type:key=value,key2=value2`.
|
|
|
|
- `rfs_unpack(input: String, directory: String) -> ()`
|
|
- Unpacks an `input` layer file into the specified `directory`.
|
|
|
|
- `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).
|
|
|
|
- `rfs_verify(input: String) -> bool`
|
|
- Verifies the integrity of an `input` layer file.
|
|
- Returns `true` if the layer is valid, `false` otherwise.
|
|
|
|
### Rhai Example
|
|
|
|
```rhai
|
|
// 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.
|