From 7e63c211d340fb1fb87a0a227b02c2ba9401bde8 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 22 Nov 2025 23:16:50 +0000 Subject: [PATCH] Add cluster demo script for easy cluster management This script provides a convenient way to spawn and manage a ToastyFS cluster for demo and testing purposes. Features include: - Start a cluster with configurable number of chunk servers - Automatic building if binary is not present - Process management with PID tracking - Status checking for all cluster nodes - Easy cleanup of all cluster processes - Separate log files for each server component - Colorized output for better readability Usage: ./scripts/cluster_demo.sh start [num_servers] - Start cluster ./scripts/cluster_demo.sh stop - Stop cluster ./scripts/cluster_demo.sh status - Show status ./scripts/cluster_demo.sh clean - Clean data/logs --- .gitignore | 6 + scripts/README.md | 43 ++++++- scripts/cluster_demo.sh | 269 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+), 3 deletions(-) create mode 100755 scripts/cluster_demo.sh diff --git a/.gitignore b/.gitignore index d841367..9a15687 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.o *.a chunk_server_data_* + # Coverage reports coverage_report/ *.gcov @@ -10,3 +11,8 @@ coverage_report/ *.gcno *.wal *.tmp + +# Cluster demo artifacts +.cluster_demo.pids +cluster_logs/ +cluster_data/ diff --git a/scripts/README.md b/scripts/README.md index bcaac89..5387a44 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,8 +1,45 @@ -# Branch Coverage Measurement +# Scripts -This directory contains scripts for measuring branch coverage of the random simulation. +This directory contains utility scripts for ToastyFS development and testing. -## Prerequisites +## Cluster Demo Script + +The `cluster_demo.sh` script allows you to easily spawn and manage a ToastyFS cluster for demo and testing purposes. + +### Usage + +```bash +# Start a cluster with 3 chunk servers (default) +./scripts/cluster_demo.sh start + +# Start a cluster with a custom number of chunk servers +./scripts/cluster_demo.sh start 5 + +# Check cluster status +./scripts/cluster_demo.sh status + +# Stop the cluster +./scripts/cluster_demo.sh stop + +# Clean all cluster data and logs +./scripts/cluster_demo.sh clean +``` + +### What it does + +The script: +- Builds ToastyFS if needed +- Starts one metadata server (leader) on port 8080 +- Starts the specified number of chunk servers on ports 8081, 8082, etc. +- Stores all process IDs for easy management +- Captures logs to `cluster_logs/` directory +- Stores data in `cluster_data/` directory + +All servers run in the background, making it easy to test the cluster with client applications. + +## Branch Coverage Measurement + +### Prerequisites The HTML report generation requires `lcov`: diff --git a/scripts/cluster_demo.sh b/scripts/cluster_demo.sh new file mode 100755 index 0000000..8087f4c --- /dev/null +++ b/scripts/cluster_demo.sh @@ -0,0 +1,269 @@ +#!/bin/bash +# +# ToastyFS Cluster Demo Script +# =========================== +# This script allows you to easily spawn and manage a ToastyFS cluster for demo purposes. +# +# Usage: +# ./scripts/cluster_demo.sh start [num_chunk_servers] - Start a cluster +# ./scripts/cluster_demo.sh stop - Stop the cluster +# ./scripts/cluster_demo.sh status - Show cluster status +# ./scripts/cluster_demo.sh clean - Clean data and log files +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +PID_FILE="$PROJECT_DIR/.cluster_demo.pids" +LOG_DIR="$PROJECT_DIR/cluster_logs" +DATA_DIR="$PROJECT_DIR/cluster_data" + +METADATA_PORT=8080 +CHUNK_SERVER_BASE_PORT=8081 + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +build_if_needed() { + if [ ! -f "$PROJECT_DIR/toastyfs.out" ] && [ ! -f "$PROJECT_DIR/toastyfs.exe" ]; then + print_info "Binary not found. Building ToastyFS..." + cd "$PROJECT_DIR" + make + print_success "Build complete" + fi +} + +get_binary() { + if [ -f "$PROJECT_DIR/toastyfs.out" ]; then + echo "$PROJECT_DIR/toastyfs.out" + elif [ -f "$PROJECT_DIR/toastyfs.exe" ]; then + echo "$PROJECT_DIR/toastyfs.exe" + else + print_error "ToastyFS binary not found" + exit 1 + fi +} + +start_cluster() { + local num_chunk_servers=${1:-3} + + if [ -f "$PID_FILE" ]; then + print_error "Cluster already running (PID file exists)" + print_info "Run '$0 stop' first or remove $PID_FILE if the cluster is not running" + exit 1 + fi + + build_if_needed + local binary=$(get_binary) + + # Create directories + mkdir -p "$LOG_DIR" + mkdir -p "$DATA_DIR" + + print_info "Starting ToastyFS cluster..." + print_info " Metadata server: 127.0.0.1:$METADATA_PORT" + print_info " Chunk servers: $num_chunk_servers" + echo + + # Start metadata server + print_info "Starting metadata server on port $METADATA_PORT..." + local metadata_wal="$DATA_DIR/metadata.wal" + "$binary" --leader \ + --addr 127.0.0.1 \ + --port $METADATA_PORT \ + --wal-file "$metadata_wal" \ + > "$LOG_DIR/metadata.log" 2>&1 & + + local metadata_pid=$! + echo "$metadata_pid" > "$PID_FILE" + print_success "Metadata server started (PID: $metadata_pid)" + + # Wait a bit for metadata server to start + sleep 1 + + # Start chunk servers + for i in $(seq 1 $num_chunk_servers); do + local port=$((CHUNK_SERVER_BASE_PORT + i - 1)) + local data_path="$DATA_DIR/chunk_server_$i/" + + print_info "Starting chunk server $i on port $port..." + mkdir -p "$data_path" + + "$binary" \ + --addr 127.0.0.1 \ + --port $port \ + --path "$data_path" \ + --remote-addr 127.0.0.1 \ + --remote-port $METADATA_PORT \ + > "$LOG_DIR/chunk_server_$i.log" 2>&1 & + + local chunk_pid=$! + echo "$chunk_pid" >> "$PID_FILE" + print_success "Chunk server $i started (PID: $chunk_pid)" + + # Small delay between starting servers + sleep 0.5 + done + + echo + print_success "Cluster started successfully!" + echo + print_info "Connect to the cluster using:" + print_info " Address: 127.0.0.1" + print_info " Port: $METADATA_PORT" + echo + print_info "View logs at: $LOG_DIR/" + print_info "Data stored at: $DATA_DIR/" + echo + print_info "To stop the cluster, run: $0 stop" +} + +stop_cluster() { + if [ ! -f "$PID_FILE" ]; then + print_warning "No PID file found. Cluster may not be running." + exit 0 + fi + + print_info "Stopping ToastyFS cluster..." + + local stopped=0 + local failed=0 + + while IFS= read -r pid; do + if [ -n "$pid" ]; then + if kill -0 "$pid" 2>/dev/null; then + kill "$pid" 2>/dev/null && { + print_success "Stopped process $pid" + stopped=$((stopped + 1)) + } || { + print_error "Failed to stop process $pid" + failed=$((failed + 1)) + } + else + print_warning "Process $pid not running" + fi + fi + done < "$PID_FILE" + + rm -f "$PID_FILE" + + echo + print_success "Cluster stopped (Stopped: $stopped, Failed: $failed)" +} + +show_status() { + if [ ! -f "$PID_FILE" ]; then + print_info "Cluster is NOT running" + exit 0 + fi + + print_info "Cluster status:" + echo + + local running=0 + local not_running=0 + local line_num=0 + + while IFS= read -r pid; do + if [ -n "$pid" ]; then + line_num=$((line_num + 1)) + local server_type="Chunk server $((line_num - 1))" + [ $line_num -eq 1 ] && server_type="Metadata server" + + if kill -0 "$pid" 2>/dev/null; then + echo -e " ${GREEN}●${NC} $server_type (PID: $pid) - ${GREEN}running${NC}" + running=$((running + 1)) + else + echo -e " ${RED}●${NC} $server_type (PID: $pid) - ${RED}not running${NC}" + not_running=$((not_running + 1)) + fi + fi + done < "$PID_FILE" + + echo + if [ $not_running -eq 0 ]; then + print_success "All $running servers are running" + else + print_warning "$running running, $not_running not running" + fi + + if [ -d "$LOG_DIR" ]; then + echo + print_info "Log directory: $LOG_DIR" + print_info "Recent log files:" + ls -lht "$LOG_DIR" | head -n 6 | tail -n 5 | awk '{print " " $9 " (" $5 ")"}' + fi +} + +clean_data() { + if [ -f "$PID_FILE" ]; then + print_error "Cluster is running. Stop it first with: $0 stop" + exit 1 + fi + + print_warning "This will delete all cluster data and logs!" + read -p "Are you sure? (y/N) " -n 1 -r + echo + + if [[ $REPLY =~ ^[Yy]$ ]]; then + print_info "Cleaning data and logs..." + rm -rf "$DATA_DIR" + rm -rf "$LOG_DIR" + print_success "Cleaned successfully" + else + print_info "Cancelled" + fi +} + +# Main command dispatcher +case "${1:-}" in + start) + start_cluster "${2:-3}" + ;; + stop) + stop_cluster + ;; + status) + show_status + ;; + clean) + clean_data + ;; + *) + echo "ToastyFS Cluster Demo Script" + echo + echo "Usage:" + echo " $0 start [num_chunk_servers] - Start a cluster (default: 3 chunk servers)" + echo " $0 stop - Stop the cluster" + echo " $0 status - Show cluster status" + echo " $0 clean - Clean data and log files" + echo + echo "Examples:" + echo " $0 start # Start with 3 chunk servers" + echo " $0 start 5 # Start with 5 chunk servers" + echo " $0 status # Check if cluster is running" + echo " $0 stop # Stop all servers" + exit 1 + ;; +esac