{ "cells": [ { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "view-in-github" }, "source": [ "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ContextLab/clustrix/blob/master/docs/source/notebooks/ssh_tutorial.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ๐Ÿš€ SSH Remote Execution Tutorial\n", "\n", "This tutorial demonstrates how to use Clustrix for **automated SSH-based remote execution** without a job scheduler. Perfect for executing functions on remote servers, workstations, or cloud instances.\n", "\n", "## โœจ **New: Automated SSH Key Setup**\n", "\n", "Clustrix now includes **15-second automated SSH key setup** that eliminates manual configuration! No more spending 15-30 minutes on SSH setup.\n", "\n", "## ๐Ÿ“‹ Prerequisites\n", "\n", "- Access to a remote server (cloud instance, workstation, or HPC login node)\n", "- Username and password for initial authentication\n", "- Python installed on the remote server\n", "- โœจ **That's it!** No manual SSH key setup required" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Install Clustrix (uncomment if needed)\n", "# !pip install clustrix\n", "\n", "import clustrix\n", "from clustrix import cluster, configure, setup_ssh_keys_with_fallback\n", "from clustrix.config import ClusterConfig\n", "import numpy as np\n", "\n", "print(\"โœ… Clustrix imported successfully!\")\n", "print(\"๐Ÿ“ฑ Look for the interactive widget that appeared above or below.\")\n", "print(\"๐Ÿ”‘ You can use the widget's SSH Key Setup section for easy configuration.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ๐Ÿ”‘ Step 1: Automated SSH Key Setup\n", "\n", "**This is the magic step!** Instead of manually setting up SSH keys, Clustrix does it automatically." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# ๐Ÿ”ง Configure your remote server details\n", "# Replace these with your actual server information\n", "\n", "config = ClusterConfig(\n", " cluster_type=\"ssh\",\n", " cluster_host=\"your-server.example.com\", # Your server hostname or IP\n", " username=\"your-username\", # Your username on the server\n", " port=22, # SSH port (usually 22)\n", " \n", " # Remote execution settings\n", " remote_work_dir=\"/tmp/clustrix\", # Directory for temporary files\n", " python_executable=\"python3\", # Python command on remote server\n", " cleanup_on_success=True, # Clean up after successful execution\n", " max_parallel_jobs=5, # Limit concurrent executions\n", ")\n", "\n", "print(\"โœ… Server configuration created!\")\n", "print(f\"๐ŸŽฏ Target: {config.cluster_host}\")\n", "print(f\"๐Ÿ‘ค User: {config.username}\")\n", "print(f\"๐Ÿ”Œ Port: {config.port}\")\n", "print(\"\\n๐Ÿ”‘ Ready for automated SSH key setup...\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# ๐Ÿš€ AUTOMATED SSH KEY SETUP\n", "# This replaces 15-30 minutes of manual work with 15 seconds of automation!\n", "\n", "print(\"๐Ÿ”„ Setting up SSH keys automatically...\")\n", "print(\"๐Ÿ’ก You'll be prompted for your password (this is normal and secure).\")\n", "print()\n", "\n", "ssh_result = setup_ssh_keys_with_fallback(\n", " config=config,\n", " cluster_alias=\"my_server\", # Creates SSH alias for easy access\n", " key_type=\"ed25519\", # Modern, secure key type\n", " force_refresh=False, # Set True to generate new keys\n", ")\n", "\n", "# ๐Ÿ“Š Display results\n", "print(\"\\n\" + \"=\"*60)\n", "print(\"๐Ÿ”‘ SSH KEY SETUP RESULTS\")\n", "print(\"=\"*60)\n", "\n", "if ssh_result[\"success\"]:\n", " print(\"๐ŸŽ‰ SUCCESS! SSH keys configured automatically!\")\n", " print(f\"๐Ÿ”‘ Key path: {ssh_result['key_path']}\")\n", " print(f\"๐Ÿ“ฆ Key already existed: {ssh_result['key_already_existed']}\")\n", " print(f\"๐Ÿš€ Key deployed: {ssh_result['key_deployed']}\")\n", " print(f\"๐Ÿ”— Connection tested: {ssh_result['connection_tested']}\")\n", " \n", " if \"ssh_config_updated\" in ssh_result.get(\"details\", {}):\n", " print(\"โš™๏ธ SSH config updated with alias\")\n", " print(\"\\n๐ŸŽฏ You can now connect with: ssh my_server\")\n", " \n", " print(\"\\nโœจ What just happened:\")\n", " print(\" ๐Ÿ” Generated Ed25519 SSH key pair\")\n", " print(\" ๐Ÿ“ค Deployed public key to remote server\")\n", " print(\" ๐Ÿงน Cleaned up any conflicting old keys\")\n", " print(\" โš™๏ธ Updated SSH configuration\")\n", " print(\" โœ… Tested connection to verify success\")\n", " \n", "else:\n", " print(\"โŒ SSH key setup failed\")\n", " print(f\"๐Ÿ” Error: {ssh_result.get('error', 'Unknown error')}\")\n", " \n", " if \"details\" in ssh_result:\n", " print(\"\\n๐Ÿ”ง Troubleshooting details:\")\n", " for key, value in ssh_result[\"details\"].items():\n", " print(f\" {key}: {value}\")\n", " \n", " print(\"\\n๐Ÿ’ก Try:\")\n", " print(\" - Check hostname and username are correct\")\n", " print(\" - Verify network connectivity to the server\")\n", " print(\" - Test manual SSH connection first\")\n", " \n", "print(\"\\n\" + \"=\"*60)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## โš™๏ธ Step 2: Configure Clustrix\n", "\n", "Now that SSH keys are set up, configure Clustrix for remote execution:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Configure Clustrix with the SSH setup\n", "configure(\n", " cluster_type=\"ssh\",\n", " cluster_host=config.cluster_host,\n", " username=config.username,\n", " port=config.port,\n", " \n", " # Remote environment\n", " remote_work_dir=config.remote_work_dir,\n", " python_executable=config.python_executable,\n", " \n", " # Execution settings\n", " cleanup_on_success=True,\n", " max_parallel_jobs=5,\n", " \n", " # Optional: Remote environment activation\n", " # conda_env_name=\"myenv\", # Activate conda environment\n", " # virtualenv_path=\"/path/to/venv\", # Activate virtual environment\n", ")\n", "\n", "print(\"โœ… Clustrix configured for SSH remote execution!\")\n", "print(f\"๐ŸŽฏ Target server: {config.cluster_host}\")\n", "print(f\"๐Ÿ“ Remote work directory: {config.remote_work_dir}\")\n", "print(f\"๐Ÿ Python executable: {config.python_executable}\")\n", "print(\"\\n๐Ÿš€ Ready to execute functions remotely!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ๐Ÿงฎ Example 1: Basic Remote Computation\n", "\n", "Execute a simple mathematical computation remotely:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@cluster\n", "def basic_remote_computation(n=1000000):\n", " \"\"\"\n", " Simple computation executed on remote server.\n", " \"\"\"\n", " import math\n", " import time\n", " import platform\n", " from datetime import datetime\n", " \n", " print(f\"๐Ÿ–ฅ๏ธ Executing on: {platform.node()}\")\n", " print(f\"๐Ÿ Python version: {platform.python_version()}\")\n", " print(f\"โšก Starting computation at {datetime.now()}\")\n", " print(f\"๐Ÿ”ข Computing sum of squares for {n:,} numbers\")\n", " \n", " start_time = time.time()\n", " \n", " # Compute sum of squares\n", " total = sum(i*i for i in range(n))\n", " \n", " # Compute some mathematical functions\n", " sqrt_total = math.sqrt(total)\n", " log_total = math.log(total)\n", " \n", " end_time = time.time()\n", " execution_time = end_time - start_time\n", " \n", " result = {\n", " 'n': n,\n", " 'sum_of_squares': total,\n", " 'sqrt_sum': sqrt_total,\n", " 'log_sum': log_total,\n", " 'execution_time_seconds': execution_time,\n", " 'hostname': platform.node(),\n", " 'python_version': platform.python_version(),\n", " 'completion_time': datetime.now().isoformat()\n", " }\n", " \n", " print(f\"โœ… Computation completed in {execution_time:.2f} seconds\")\n", " return result\n", "\n", "# Execute on remote server\n", "print(\"๐Ÿš€ Executing basic computation on remote server...\")\n", "result = basic_remote_computation(500000)\n", "\n", "print(f\"\\n๐ŸŽ‰ REMOTE COMPUTATION COMPLETE\")\n", "print(f\"๐Ÿ–ฅ๏ธ Executed on: {result['hostname']}\")\n", "print(f\"๐Ÿ Python version: {result['python_version']}\")\n", "print(f\"๐Ÿ”ข Numbers processed: {result['n']:,}\")\n", "print(f\"๐Ÿ“Š Sum of squares: {result['sum_of_squares']:,}\")\n", "print(f\"๐Ÿ“ Square root of sum: {result['sqrt_sum']:,.2f}\")\n", "print(f\"โฑ๏ธ Execution time: {result['execution_time_seconds']:.2f} seconds\")\n", "print(f\"๐Ÿ• Completed at: {result['completion_time']}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ๐Ÿ“Š Example 2: Remote Data Processing with NumPy\n", "\n", "Process numerical data on the remote server:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@cluster\n", "def remote_numpy_computation(matrix_size=1000, num_iterations=5):\n", " \"\"\"\n", " Perform numerical computations using NumPy on remote server.\n", " \"\"\"\n", " import numpy as np\n", " import time\n", " import platform\n", " from datetime import datetime\n", " \n", " print(f\"๐Ÿ–ฅ๏ธ Remote execution on: {platform.node()}\")\n", " print(f\"๐Ÿ“Š NumPy version: {np.__version__}\")\n", " print(f\"๐Ÿ”ข Matrix size: {matrix_size}x{matrix_size}\")\n", " print(f\"๐Ÿ”„ Iterations: {num_iterations}\")\n", " \n", " results = []\n", " total_start_time = time.time()\n", " \n", " for iteration in range(num_iterations):\n", " print(f\"\\n๐Ÿ”„ Iteration {iteration + 1}/{num_iterations}\")\n", " \n", " start_time = time.time()\n", " \n", " # Generate random matrices\n", " print(\" ๐Ÿ“‹ Generating random matrices...\")\n", " A = np.random.randn(matrix_size, matrix_size)\n", " B = np.random.randn(matrix_size, matrix_size)\n", " \n", " # Matrix multiplication\n", " print(\" โœ–๏ธ Performing matrix multiplication...\")\n", " C = np.dot(A, B)\n", " \n", " # Eigenvalue computation (smaller matrix for speed)\n", " small_size = min(100, matrix_size)\n", " print(f\" ๐Ÿงฎ Computing eigenvalues ({small_size}x{small_size})...\")\n", " eigenvalues = np.linalg.eigvals(A[:small_size, :small_size])\n", " \n", " # Statistical analysis\n", " print(\" ๐Ÿ“ˆ Computing statistics...\")\n", " stats = {\n", " 'matrix_mean': float(np.mean(C)),\n", " 'matrix_std': float(np.std(C)),\n", " 'matrix_max': float(np.max(C)),\n", " 'matrix_min': float(np.min(C)),\n", " 'eigenvalue_mean': float(np.mean(eigenvalues.real)),\n", " 'eigenvalue_max': float(np.max(eigenvalues.real)),\n", " 'frobenius_norm': float(np.linalg.norm(C, 'fro')),\n", " }\n", " \n", " end_time = time.time()\n", " iteration_time = end_time - start_time\n", " \n", " iteration_result = {\n", " 'iteration': iteration + 1,\n", " 'execution_time': iteration_time,\n", " 'statistics': stats\n", " }\n", " \n", " results.append(iteration_result)\n", " print(f\" โฑ๏ธ Iteration completed in {iteration_time:.2f} seconds\")\n", " \n", " total_end_time = time.time()\n", " total_time = total_end_time - total_start_time\n", " \n", " # Aggregate statistics\n", " execution_times = [r['execution_time'] for r in results]\n", " \n", " final_result = {\n", " 'computation_info': {\n", " 'matrix_size': matrix_size,\n", " 'num_iterations': num_iterations,\n", " 'hostname': platform.node(),\n", " 'numpy_version': np.__version__,\n", " 'completion_time': datetime.now().isoformat()\n", " },\n", " 'performance': {\n", " 'total_time': total_time,\n", " 'average_iteration_time': np.mean(execution_times),\n", " 'min_iteration_time': np.min(execution_times),\n", " 'max_iteration_time': np.max(execution_times),\n", " 'operations_per_second': (num_iterations * matrix_size * matrix_size) / total_time\n", " },\n", " 'iteration_results': results\n", " }\n", " \n", " print(f\"\\nโœ… All computations completed!\")\n", " print(f\"โฑ๏ธ Total execution time: {total_time:.2f} seconds\")\n", " print(f\"๐Ÿ“Š Average iteration time: {np.mean(execution_times):.2f} seconds\")\n", " \n", " return final_result\n", "\n", "# Execute numerical computation on remote server\n", "print(\"๐Ÿš€ Starting remote NumPy computation...\")\n", "numpy_result = remote_numpy_computation(matrix_size=500, num_iterations=3)\n", "\n", "print(f\"\\n๐ŸŽ‰ REMOTE NUMPY COMPUTATION COMPLETE\")\n", "info = numpy_result['computation_info']\n", "print(f\"๐Ÿ–ฅ๏ธ Executed on: {info['hostname']}\")\n", "print(f\"๐Ÿ“Š NumPy version: {info['numpy_version']}\")\n", "print(f\"๐Ÿ”ข Matrix size: {info['matrix_size']}x{info['matrix_size']}\")\n", "print(f\"๐Ÿ”„ Iterations: {info['num_iterations']}\")\n", "\n", "perf = numpy_result['performance']\n", "print(f\"\\n๐Ÿ“ˆ Performance Metrics:\")\n", "print(f\" โฑ๏ธ Total time: {perf['total_time']:.2f} seconds\")\n", "print(f\" ๐Ÿ“Š Average iteration: {perf['average_iteration_time']:.2f} seconds\")\n", "print(f\" โšก Operations/second: {perf['operations_per_second']:,.0f}\")\n", "print(f\" ๐Ÿƒ Fastest iteration: {perf['min_iteration_time']:.2f} seconds\")\n", "print(f\" ๐ŸŒ Slowest iteration: {perf['max_iteration_time']:.2f} seconds\")\n", "\n", "# Show statistics from the last iteration\n", "if numpy_result['iteration_results']:\n", " last_stats = numpy_result['iteration_results'][-1]['statistics']\n", " print(f\"\\n๐Ÿ“Š Final Matrix Statistics:\")\n", " print(f\" ๐Ÿ“ˆ Mean: {last_stats['matrix_mean']:.4f}\")\n", " print(f\" ๐Ÿ“Š Std Dev: {last_stats['matrix_std']:.4f}\")\n", " print(f\" ๐Ÿ”บ Max: {last_stats['matrix_max']:.4f}\")\n", " print(f\" ๐Ÿ”ป Min: {last_stats['matrix_min']:.4f}\")\n", " print(f\" ๐Ÿงฎ Eigenvalue Mean: {last_stats['eigenvalue_mean']:.4f}\")\n", " print(f\" ๐Ÿ“ Frobenius Norm: {last_stats['frobenius_norm']:.2f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ๐Ÿ—‚๏ธ Example 3: Remote File System Analysis\n", "\n", "Analyze the file system structure on the remote server:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@cluster\n", "def remote_system_analysis():\n", " \"\"\"\n", " Analyze system information and file system on remote server.\n", " \"\"\"\n", " import os\n", " import platform\n", " import shutil\n", " import subprocess\n", " import psutil # Common on many systems\n", " from datetime import datetime\n", " \n", " print(f\"๐Ÿ–ฅ๏ธ Analyzing system: {platform.node()}\")\n", " \n", " # Basic system information\n", " system_info = {\n", " 'hostname': platform.node(),\n", " 'system': platform.system(),\n", " 'release': platform.release(),\n", " 'version': platform.version(),\n", " 'machine': platform.machine(),\n", " 'processor': platform.processor(),\n", " 'python_version': platform.python_version(),\n", " 'architecture': platform.architecture(),\n", " }\n", " \n", " print(f\"๐Ÿ’ป System: {system_info['system']} {system_info['release']}\")\n", " print(f\"๐Ÿ—๏ธ Architecture: {system_info['machine']}\")\n", " print(f\"๐Ÿ Python: {system_info['python_version']}\")\n", " \n", " # Memory and CPU information\n", " try:\n", " memory = psutil.virtual_memory()\n", " cpu_info = {\n", " 'cpu_count': psutil.cpu_count(),\n", " 'cpu_percent': psutil.cpu_percent(interval=1),\n", " 'memory_total_gb': memory.total / (1024**3),\n", " 'memory_available_gb': memory.available / (1024**3),\n", " 'memory_percent': memory.percent,\n", " }\n", " print(f\"โšก CPUs: {cpu_info['cpu_count']}\")\n", " print(f\"๐Ÿง  Memory: {cpu_info['memory_total_gb']:.1f} GB total, {cpu_info['memory_available_gb']:.1f} GB available\")\n", " except ImportError:\n", " print(\"๐Ÿ“Š psutil not available, skipping detailed system metrics\")\n", " cpu_info = {'error': 'psutil not available'}\n", " \n", " # Disk usage analysis\n", " disk_info = {}\n", " important_paths = ['/', '/home', '/tmp', '/var', '/usr']\n", " \n", " print(\"\\n๐Ÿ’พ Disk Usage Analysis:\")\n", " for path in important_paths:\n", " if os.path.exists(path):\n", " try:\n", " usage = shutil.disk_usage(path)\n", " disk_info[path] = {\n", " 'total_gb': usage.total / (1024**3),\n", " 'used_gb': usage.used / (1024**3),\n", " 'free_gb': usage.free / (1024**3),\n", " 'used_percent': (usage.used / usage.total) * 100\n", " }\n", " print(f\" ๐Ÿ“ {path}: {disk_info[path]['used_gb']:.1f}GB used / {disk_info[path]['total_gb']:.1f}GB total ({disk_info[path]['used_percent']:.1f}%)\")\n", " except (OSError, PermissionError):\n", " disk_info[path] = {'error': 'Permission denied or path inaccessible'}\n", " \n", " # Environment analysis\n", " env_info = {\n", " 'user': os.environ.get('USER', 'unknown'),\n", " 'home': os.environ.get('HOME', 'unknown'),\n", " 'shell': os.environ.get('SHELL', 'unknown'),\n", " 'path_entries': len(os.environ.get('PATH', '').split(':')),\n", " 'working_directory': os.getcwd(),\n", " }\n", " \n", " print(f\"\\n๐Ÿ‘ค Environment Info:\")\n", " print(f\" User: {env_info['user']}\")\n", " print(f\" Home: {env_info['home']}\")\n", " print(f\" Shell: {env_info['shell']}\")\n", " print(f\" Working Dir: {env_info['working_directory']}\")\n", " \n", " # Available Python packages\n", " print(\"\\n๐Ÿ Checking Python Environment:\")\n", " common_packages = [\n", " 'numpy', 'pandas', 'scipy', 'matplotlib', 'sklearn', 'requests',\n", " 'psutil', 'jupyter', 'ipython', 'pytest', 'click', 'flask'\n", " ]\n", " \n", " package_status = {}\n", " for package in common_packages:\n", " try:\n", " __import__(package)\n", " # Try to get version\n", " try:\n", " mod = __import__(package)\n", " version = getattr(mod, '__version__', 'unknown')\n", " package_status[package] = {'available': True, 'version': version}\n", " except:\n", " package_status[package] = {'available': True, 'version': 'unknown'}\n", " except ImportError:\n", " package_status[package] = {'available': False}\n", " \n", " available_packages = [pkg for pkg, info in package_status.items() if info['available']]\n", " print(f\" โœ… Available packages ({len(available_packages)}/{len(common_packages)}): {', '.join(available_packages[:8])}\")\n", " \n", " # Network connectivity test\n", " network_info = {}\n", " try:\n", " import socket\n", " hostname = socket.gethostname()\n", " ip_address = socket.gethostbyname(hostname)\n", " network_info = {\n", " 'hostname': hostname,\n", " 'ip_address': ip_address,\n", " 'connectivity': 'basic_ok'\n", " }\n", " print(f\"\\n๐ŸŒ Network: {hostname} ({ip_address})\")\n", " except Exception as e:\n", " network_info = {'error': str(e)}\n", " print(f\"\\n๐ŸŒ Network: Error getting network info\")\n", " \n", " # Final analysis result\n", " analysis_result = {\n", " 'analysis_metadata': {\n", " 'timestamp': datetime.now().isoformat(),\n", " 'analysis_type': 'remote_system_analysis'\n", " },\n", " 'system_information': system_info,\n", " 'performance_info': cpu_info,\n", " 'disk_usage': disk_info,\n", " 'environment': env_info,\n", " 'python_packages': package_status,\n", " 'network_info': network_info\n", " }\n", " \n", " print(f\"\\nโœ… System analysis completed!\")\n", " return analysis_result\n", "\n", "# Analyze remote system\n", "print(\"๐Ÿš€ Starting remote system analysis...\")\n", "system_result = remote_system_analysis()\n", "\n", "print(f\"\\n๐ŸŽ‰ REMOTE SYSTEM ANALYSIS COMPLETE\")\n", "sys_info = system_result['system_information']\n", "print(f\"๐Ÿ–ฅ๏ธ System: {sys_info['hostname']} ({sys_info['system']} {sys_info['release']})\")\n", "print(f\"๐Ÿ—๏ธ Architecture: {sys_info['machine']}\")\n", "print(f\"๐Ÿ Python: {sys_info['python_version']}\")\n", "\n", "if 'error' not in system_result['performance_info']:\n", " perf = system_result['performance_info']\n", " print(f\"\\n๐Ÿ“Š Performance:\")\n", " print(f\" โšก CPUs: {perf['cpu_count']}\")\n", " print(f\" ๐Ÿง  Memory: {perf['memory_total_gb']:.1f} GB ({perf['memory_percent']:.1f}% used)\")\n", " print(f\" ๐Ÿ”ฅ CPU Usage: {perf['cpu_percent']:.1f}%\")\n", "\n", "env = system_result['environment']\n", "print(f\"\\n๐Ÿ‘ค Environment:\")\n", "print(f\" User: {env['user']}\")\n", "print(f\" Home: {env['home']}\")\n", "print(f\" Working Dir: {env['working_directory']}\")\n", "\n", "packages = system_result['python_packages']\n", "available = [pkg for pkg, info in packages.items() if info['available']]\n", "print(f\"\\n๐Ÿ Python Environment:\")\n", "print(f\" ๐Ÿ“ฆ Available packages: {len(available)}/{len(packages)}\")\n", "print(f\" โœ… Key packages: {', '.join(available[:6])}\")\n", "\n", "disk = system_result['disk_usage']\n", "print(f\"\\n๐Ÿ’พ Storage:\")\n", "for path, info in disk.items():\n", " if 'error' not in info:\n", " print(f\" ๐Ÿ“ {path}: {info['free_gb']:.1f} GB free\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ๐Ÿงช Example 4: Remote Environment Testing\n", "\n", "Test specific capabilities and benchmark performance:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@cluster\n", "def benchmark_remote_performance():\n", " \"\"\"\n", " Benchmark computational performance on remote server.\n", " \"\"\"\n", " import time\n", " import math\n", " import platform\n", " from datetime import datetime\n", " \n", " print(f\"๐Ÿ Starting performance benchmarks on {platform.node()}\")\n", " benchmarks = {}\n", " \n", " # CPU benchmark: Prime number calculation\n", " print(\"\\n๐Ÿ”ข CPU Benchmark: Prime number calculation\")\n", " start_time = time.time()\n", " \n", " def is_prime(n):\n", " if n < 2:\n", " return False\n", " for i in range(2, int(math.sqrt(n)) + 1):\n", " if n % i == 0:\n", " return False\n", " return True\n", " \n", " primes = [n for n in range(2, 10000) if is_prime(n)]\n", " cpu_time = time.time() - start_time\n", " \n", " benchmarks['cpu_benchmark'] = {\n", " 'test': 'prime_calculation',\n", " 'range': '2-10000',\n", " 'primes_found': len(primes),\n", " 'execution_time': cpu_time,\n", " 'primes_per_second': len(primes) / cpu_time\n", " }\n", " \n", " print(f\" โœ… Found {len(primes)} primes in {cpu_time:.3f} seconds\")\n", " print(f\" ๐Ÿ“Š Rate: {len(primes) / cpu_time:.1f} primes/second\")\n", " \n", " # Memory benchmark: List operations\n", " print(\"\\n๐Ÿง  Memory Benchmark: Large list operations\")\n", " start_time = time.time()\n", " \n", " # Create large list\n", " large_list = list(range(1000000))\n", " \n", " # Perform operations\n", " reversed_list = large_list[::-1]\n", " sorted_sample = sorted(large_list[::1000])\n", " list_sum = sum(large_list[::100])\n", " \n", " memory_time = time.time() - start_time\n", " \n", " benchmarks['memory_benchmark'] = {\n", " 'test': 'list_operations',\n", " 'list_size': len(large_list),\n", " 'operations': ['reverse', 'sort_sample', 'sum_subset'],\n", " 'execution_time': memory_time,\n", " 'sum_result': list_sum\n", " }\n", " \n", " print(f\" โœ… Processed {len(large_list):,} elements in {memory_time:.3f} seconds\")\n", " print(f\" ๐Ÿ“Š Rate: {len(large_list) / memory_time:,.0f} elements/second\")\n", " \n", " # I/O benchmark: File operations\n", " print(\"\\n๐Ÿ“ I/O Benchmark: File read/write operations\")\n", " import tempfile\n", " import os\n", " \n", " start_time = time.time()\n", " \n", " # Write test\n", " test_data = \"\\n\".join([f\"Line {i}: {i*i}\" for i in range(10000)])\n", " \n", " with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:\n", " temp_file = f.name\n", " f.write(test_data)\n", " \n", " # Read test\n", " with open(temp_file, 'r') as f:\n", " read_data = f.read()\n", " \n", " # Verify and cleanup\n", " lines_read = len(read_data.split('\\n'))\n", " file_size = os.path.getsize(temp_file)\n", " os.unlink(temp_file)\n", " \n", " io_time = time.time() - start_time\n", " \n", " benchmarks['io_benchmark'] = {\n", " 'test': 'file_read_write',\n", " 'lines_written': 10000,\n", " 'lines_read': lines_read,\n", " 'file_size_bytes': file_size,\n", " 'execution_time': io_time,\n", " 'throughput_mb_per_sec': (file_size / (1024*1024)) / io_time\n", " }\n", " \n", " print(f\" โœ… Wrote/read {file_size:,} bytes in {io_time:.3f} seconds\")\n", " print(f\" ๐Ÿ“Š Throughput: {(file_size / (1024*1024)) / io_time:.2f} MB/second\")\n", " \n", " # Mathematical benchmark: Floating point operations\n", " print(\"\\n๐Ÿงฎ Math Benchmark: Floating point operations\")\n", " start_time = time.time()\n", " \n", " total = 0.0\n", " for i in range(100000):\n", " total += math.sin(i) * math.cos(i) + math.sqrt(i + 1)\n", " \n", " math_time = time.time() - start_time\n", " \n", " benchmarks['math_benchmark'] = {\n", " 'test': 'trigonometric_operations',\n", " 'operations_count': 100000 * 3, # sin, cos, sqrt per iteration\n", " 'result': total,\n", " 'execution_time': math_time,\n", " 'operations_per_second': (100000 * 3) / math_time\n", " }\n", " \n", " print(f\" โœ… Performed {100000 * 3:,} operations in {math_time:.3f} seconds\")\n", " print(f\" ๐Ÿ“Š Rate: {(100000 * 3) / math_time:,.0f} operations/second\")\n", " \n", " # Summary\n", " total_benchmark_time = sum([b['execution_time'] for b in benchmarks.values()])\n", " \n", " result = {\n", " 'benchmark_metadata': {\n", " 'hostname': platform.node(),\n", " 'system': platform.system(),\n", " 'machine': platform.machine(),\n", " 'python_version': platform.python_version(),\n", " 'timestamp': datetime.now().isoformat(),\n", " 'total_benchmark_time': total_benchmark_time\n", " },\n", " 'benchmarks': benchmarks\n", " }\n", " \n", " print(f\"\\n๐Ÿ All benchmarks completed!\")\n", " print(f\"โฑ๏ธ Total benchmark time: {total_benchmark_time:.3f} seconds\")\n", " \n", " return result\n", "\n", "# Run performance benchmarks\n", "print(\"๐Ÿš€ Starting remote performance benchmarks...\")\n", "benchmark_result = benchmark_remote_performance()\n", "\n", "print(f\"\\n๐ŸŽ‰ REMOTE BENCHMARKS COMPLETE\")\n", "meta = benchmark_result['benchmark_metadata']\n", "print(f\"๐Ÿ–ฅ๏ธ System: {meta['hostname']} ({meta['system']} {meta['machine']})\")\n", "print(f\"๐Ÿ Python: {meta['python_version']}\")\n", "print(f\"โฑ๏ธ Total time: {meta['total_benchmark_time']:.3f} seconds\")\n", "\n", "benchmarks = benchmark_result['benchmarks']\n", "\n", "print(f\"\\n๐Ÿ“Š Benchmark Results:\")\n", "cpu = benchmarks['cpu_benchmark']\n", "print(f\" ๐Ÿ”ข CPU: {cpu['primes_per_second']:.1f} primes/sec\")\n", "\n", "memory = benchmarks['memory_benchmark']\n", "print(f\" ๐Ÿง  Memory: {len(memory['operations'])} ops on {memory['list_size']:,} elements in {memory['execution_time']:.3f}s\")\n", "\n", "io = benchmarks['io_benchmark']\n", "print(f\" ๐Ÿ“ I/O: {io['throughput_mb_per_sec']:.2f} MB/sec throughput\")\n", "\n", "math_bench = benchmarks['math_benchmark']\n", "print(f\" ๐Ÿงฎ Math: {math_bench['operations_per_second']:,.0f} ops/sec\")\n", "\n", "print(f\"\\n๐Ÿ† Remote server performance profile complete!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ๐Ÿ”ง SSH Connection Testing and Troubleshooting\n", "\n", "Test your SSH connection and get troubleshooting information:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def test_ssh_connection():\n", " \"\"\"\n", " Test SSH connection and provide troubleshooting information.\n", " \"\"\"\n", " from clustrix import get_config\n", " from clustrix.executor import ClusterExecutor\n", " \n", " try:\n", " print(\"๐Ÿ” Testing SSH connection...\")\n", " config = get_config()\n", " \n", " if config.cluster_type != 'ssh':\n", " print(\"โŒ Current configuration is not for SSH.\")\n", " print(\"๐Ÿ’ก Please run the SSH configuration cell above first.\")\n", " return False\n", " \n", " print(f\"๐ŸŽฏ Target: {config.cluster_host}:{getattr(config, 'port', 22)}\")\n", " print(f\"๐Ÿ‘ค User: {config.username}\")\n", " print(f\"๐Ÿ”‘ Key: {getattr(config, 'key_file', 'auto-detected')}\")\n", " \n", " # Test basic connection\n", " executor = ClusterExecutor(config)\n", " executor.connect()\n", " print(\"โœ… SSH connection successful!\")\n", " \n", " # Test basic commands\n", " print(\"\\n๐Ÿงช Testing basic commands...\")\n", " commands = [\n", " (\"hostname\", \"๐Ÿ–ฅ๏ธ Remote hostname\"),\n", " (\"whoami\", \"๐Ÿ‘ค Remote user\"),\n", " (\"pwd\", \"๐Ÿ“ Working directory\"),\n", " (\"python3 --version\", \"๐Ÿ Python version\"),\n", " (\"uname -a\", \"๐Ÿ’ป System info\")\n", " ]\n", " \n", " for cmd, description in commands:\n", " try:\n", " stdout, stderr = executor._execute_command(cmd)\n", " output = (stdout or stderr or \"no output\").strip()\n", " print(f\" โœ… {description}: {output}\")\n", " except Exception as e:\n", " print(f\" โŒ {description}: {str(e)}\")\n", " \n", " # Test work directory\n", " work_dir = getattr(config, 'remote_work_dir', '/tmp/clustrix')\n", " print(f\"\\n๐Ÿ“ Testing work directory: {work_dir}\")\n", " try:\n", " stdout, stderr = executor._execute_command(f\"mkdir -p {work_dir} && echo 'Directory OK'\")\n", " if \"Directory OK\" in stdout:\n", " print(f\" โœ… Work directory accessible and writable\")\n", " else:\n", " print(f\" โš ๏ธ Work directory test inconclusive\")\n", " except Exception as e:\n", " print(f\" โŒ Work directory error: {e}\")\n", " \n", " executor.disconnect()\n", " print(\"\\n๐ŸŽ‰ SSH connection test completed successfully!\")\n", " print(\"โœ… Your SSH configuration is working correctly.\")\n", " return True\n", " \n", " except Exception as e:\n", " print(f\"\\nโŒ SSH connection test failed: {e}\")\n", " print(\"\\n๐Ÿ”ง Troubleshooting suggestions:\")\n", " print(\" 1. Check hostname and port are correct\")\n", " print(\" 2. Verify username is correct\")\n", " print(\" 3. Test manual SSH: ssh user@hostname\")\n", " print(\" 4. Check firewall and network connectivity\")\n", " print(\" 5. Try force refresh: setup_ssh_keys_with_fallback(..., force_refresh=True)\")\n", " return False\n", "\n", "# Run connection test\n", "print(\"๐Ÿ” SSH CONNECTION TEST\")\n", "print(\"=\" * 30)\n", "test_success = test_ssh_connection()\n", "\n", "if test_success:\n", " print(\"\\n๐Ÿš€ Ready for remote execution!\")\n", "else:\n", " print(\"\\n๐Ÿ”ง Please fix SSH issues before proceeding.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ๐Ÿ“š Summary and Best Practices\n", "\n", "### ๐ŸŽ‰ What You've Learned\n", "\n", "1. **๐Ÿ”‘ Automated SSH Setup**: 15-second setup vs 15-30 minute manual process\n", "2. **โš™๏ธ Remote Configuration**: Easy Clustrix setup for SSH execution\n", "3. **๐Ÿงฎ Remote Computing**: Mathematical computations on remote servers\n", "4. **๐Ÿ“Š Data Processing**: NumPy operations and analysis remotely\n", "5. **๐Ÿ—‚๏ธ System Analysis**: File system and environment inspection\n", "6. **๐Ÿ Performance Testing**: Benchmarking remote server capabilities\n", "7. **๐Ÿ”ง Troubleshooting**: Connection testing and problem resolution\n", "\n", "### ๐Ÿ”’ Security Best Practices\n", "\n", "- **โœ… Use SSH keys**: Automated setup creates secure Ed25519 keys\n", "- **โœ… Unique keys**: Different keys for different servers\n", "- **โœ… Regular rotation**: Use `force_refresh=True` periodically\n", "- **โœ… Secure storage**: Keys stored with proper permissions (600/644)\n", "- **โœ… Clean up**: Enable `cleanup_on_success=True`\n", "- **โœ… Monitor access**: Check SSH logs on your servers\n", "\n", "### ๐Ÿ’ก Performance Tips\n", "\n", "- **Parallel execution**: Set `max_parallel_jobs` appropriately\n", "- **Work directory**: Use fast storage (e.g., `/tmp` or SSD)\n", "- **Environment setup**: Use conda/virtualenv for package management\n", "- **Data transfer**: Minimize large data transfers between local/remote\n", "- **Connection reuse**: Clustrix automatically reuses SSH connections\n", "\n", "### ๐ŸŽฏ When to Use SSH vs Other Cluster Types\n", "\n", "**Choose SSH when:**\n", "- Working with single servers or workstations\n", "- Need immediate execution (no queuing)\n", "- Prototyping and development\n", "- Cloud instances (AWS, GCP, Azure)\n", "- Personal computing resources\n", "\n", "**Choose SLURM/PBS/SGE when:**\n", "- Large HPC clusters with job schedulers\n", "- Need resource management and fair sharing\n", "- Production workloads with resource constraints\n", "- Long-running computations requiring scheduling\n", "\n", "**Choose Kubernetes when:**\n", "- Containerized execution environments\n", "- Auto-scaling and fault tolerance needed\n", "- Cloud-native applications\n", "- Microservices architecture\n", "\n", "### ๐Ÿš€ Next Steps\n", "\n", "1. **Try other tutorials**:\n", " - [SLURM Tutorial](slurm_tutorial.ipynb) for HPC clusters\n", " - [Kubernetes Tutorial](kubernetes_tutorial.ipynb) for container orchestration\n", " - [Cost Monitoring Tutorial](cost_monitoring_tutorial.ipynb) for cloud costs\n", "\n", "2. **Explore advanced features**:\n", " - Multiple cluster configurations\n", " - Custom environment setup\n", " - Filesystem utilities\n", " - Cloud provider integrations\n", "\n", "3. **Read documentation**:\n", " - [SSH Setup Guide](../ssh_setup.rst) for detailed configuration\n", " - [API Documentation](../api/decorator.rst) for advanced options\n", " - [Clustrix Documentation](https://clustrix.readthedocs.io) for comprehensive guides\n", "\n", "### ๐ŸŽŠ Congratulations!\n", "\n", "You've successfully learned how to use Clustrix's automated SSH setup and remote execution capabilities. You can now:\n", "\n", "- โšก Set up SSH access in 15 seconds instead of 15-30 minutes\n", "- ๐Ÿš€ Execute Python functions on any SSH-accessible server\n", "- ๐Ÿ“Š Perform complex computations remotely\n", "- ๐Ÿ”ง Troubleshoot and optimize your setup\n", "- ๐Ÿ”’ Maintain security best practices\n", "\n", "**Happy remote computing!** ๐ŸŽ‰" ] } ], "metadata": { "colab": { "provenance": [], "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }