diff --git a/modules/nixos/redis-cluster.nix b/modules/nixos/redis-cluster.nix index 5b6da21..3d50413 100644 --- a/modules/nixos/redis-cluster.nix +++ b/modules/nixos/redis-cluster.nix @@ -283,7 +283,12 @@ in }; # Cluster management utilities - environment.systemPackages = [ pkgs.redis ]; + environment.systemPackages = [ + pkgs.redis + (pkgs.writeShellScriptBin "redis-cluster-rebuild" '' + exec /etc/redis-cluster-rebuild.sh "$@" + '') + ]; # Create helper scripts environment.etc."redis-cluster-info.sh" = { @@ -306,5 +311,221 @@ in ''; mode = "0755"; }; + + environment.etc."redis-cluster-rebuild.sh" = { + text = '' + #!/bin/bash + set -e + + # Configuration from NixOS + MASTERS=${toString cfg.masters} + REPLICAS_PER_MASTER=${toString cfg.replicasPerMaster} + BASE_PORT=${toString cfg.basePort} + ANNOUNCE_IP="${cfg.announceIp}" + + echo "Redis Cluster Rebuild Script" + echo "============================" + echo "Masters: $MASTERS" + echo "Replicas per master: $REPLICAS_PER_MASTER" + echo "Base port: $BASE_PORT" + echo "Announce IP: $ANNOUNCE_IP" + echo "" + + # Function to stop all Redis services + stop_redis_services() { + echo "Stopping Redis services..." + + # Stop cluster init service first + systemctl stop redis-cluster-init.service 2>/dev/null || true + + # Stop all master services + for i in $(seq 0 $((MASTERS - 1))); do + echo " Stopping redis-master-$i..." + systemctl stop redis-master-$i.service 2>/dev/null || true + done + + # Stop all replica services + for master_idx in $(seq 0 $((MASTERS - 1))); do + for replica_idx in $(seq 0 $((REPLICAS_PER_MASTER - 1))); do + echo " Stopping redis-replica-$master_idx-$replica_idx..." + systemctl stop redis-replica-$master_idx-$replica_idx.service 2>/dev/null || true + done + done + + echo "All Redis services stopped." + } + + # Function to clean Redis data directories + clean_redis_data() { + echo "Cleaning Redis data directories..." + + # Remove main Redis data directory + if [ -d "/var/lib/redis" ]; then + echo " Removing /var/lib/redis..." + rm -rf /var/lib/redis + fi + + # Remove any cluster configuration files from working directories + for i in $(seq 0 $((MASTERS - 1))); do + local port=$((BASE_PORT + i)) + rm -f /var/lib/redis*/nodes-$port.conf 2>/dev/null || true + rm -f /tmp/nodes-$port.conf 2>/dev/null || true + rm -f ./nodes-$port.conf 2>/dev/null || true + done + + # Remove replica cluster config files + for master_idx in $(seq 0 $((MASTERS - 1))); do + for replica_idx in $(seq 0 $((REPLICAS_PER_MASTER - 1))); do + local port=$((BASE_PORT + MASTERS + master_idx * REPLICAS_PER_MASTER + replica_idx)) + rm -f /var/lib/redis*/nodes-$port.conf 2>/dev/null || true + rm -f /tmp/nodes-$port.conf 2>/dev/null || true + rm -f ./nodes-$port.conf 2>/dev/null || true + done + done + + echo "Redis data directories cleaned." + } + + # Function to start Redis services + start_redis_services() { + echo "Starting Redis services..." + + # Start all master services + for i in $(seq 0 $((MASTERS - 1))); do + echo " Starting redis-master-$i..." + systemctl start redis-master-$i.service + done + + # Start all replica services + for master_idx in $(seq 0 $((MASTERS - 1))); do + for replica_idx in $(seq 0 $((REPLICAS_PER_MASTER - 1))); do + echo " Starting redis-replica-$master_idx-$replica_idx..." + systemctl start redis-replica-$master_idx-$replica_idx.service + done + done + + echo "All Redis services started." + } + + # Function to wait for Redis services to be ready + wait_for_redis() { + echo "Waiting for Redis services to be ready..." + + # Wait for masters + for i in $(seq 0 $((MASTERS - 1))); do + local port=$((BASE_PORT + i)) + echo " Waiting for master on port $port..." + for attempt in $(seq 1 30); do + if ${pkgs.redis}/bin/redis-cli -p $port ping >/dev/null 2>&1; then + echo " Master on port $port is ready." + break + fi + if [ $attempt -eq 30 ]; then + echo " ERROR: Master on port $port failed to start!" + exit 1 + fi + sleep 1 + done + done + + # Wait for replicas + for master_idx in $(seq 0 $((MASTERS - 1))); do + for replica_idx in $(seq 0 $((REPLICAS_PER_MASTER - 1))); do + local port=$((BASE_PORT + MASTERS + master_idx * REPLICAS_PER_MASTER + replica_idx)) + echo " Waiting for replica on port $port..." + for attempt in $(seq 1 30); do + if ${pkgs.redis}/bin/redis-cli -p $port ping >/dev/null 2>&1; then + echo " Replica on port $port is ready." + break + fi + if [ $attempt -eq 30 ]; then + echo " ERROR: Replica on port $port failed to start!" + exit 1 + fi + sleep 1 + done + done + done + + echo "All Redis services are ready." + } + + # Function to create the cluster + create_cluster() { + echo "Creating Redis cluster..." + + # Build master nodes list + MASTER_NODES="" + for i in $(seq 0 $((MASTERS - 1))); do + local port=$((BASE_PORT + i)) + MASTER_NODES="$MASTER_NODES $ANNOUNCE_IP:$port" + done + + echo " Master nodes:$MASTER_NODES" + echo " Creating cluster with $REPLICAS_PER_MASTER replicas per master..." + + ${pkgs.redis}/bin/redis-cli --cluster create $MASTER_NODES --cluster-replicas $REPLICAS_PER_MASTER --cluster-yes + + echo "Redis cluster created successfully!" + } + + # Function to show cluster status + show_cluster_status() { + echo "" + echo "Cluster Status:" + echo "===============" + ${pkgs.redis}/bin/redis-cli -p $BASE_PORT cluster nodes + echo "" + ${pkgs.redis}/bin/redis-cli -p $BASE_PORT cluster info + } + + # Main execution + case "''${1:-rebuild}" in + "stop") + stop_redis_services + ;; + "clean") + clean_redis_data + ;; + "start") + start_redis_services + wait_for_redis + ;; + "create") + create_cluster + show_cluster_status + ;; + "rebuild"|"") + echo "Full rebuild process starting..." + stop_redis_services + sleep 2 + clean_redis_data + start_redis_services + wait_for_redis + sleep 3 + create_cluster + show_cluster_status + echo "" + echo "Redis cluster rebuild completed successfully!" + ;; + "status") + show_cluster_status + ;; + *) + echo "Usage: $0 [stop|clean|start|create|rebuild|status]" + echo "" + echo "Commands:" + echo " stop - Stop all Redis services" + echo " clean - Remove Redis data directories" + echo " start - Start all Redis services" + echo " create - Create the cluster (services must be running)" + echo " rebuild - Full rebuild (stop, clean, start, create) [default]" + echo " status - Show cluster status" + exit 1 + ;; + esac + ''; + mode = "0755"; + }; }; } \ No newline at end of file