Complete markdown files cleanup and organization
- Organized 252 files across project - Root directory: 187 → 2 files (98.9% reduction) - Moved configuration guides to docs/04-configuration/ - Moved troubleshooting guides to docs/09-troubleshooting/ - Moved quick start guides to docs/01-getting-started/ - Moved reports to reports/ directory - Archived temporary files - Generated comprehensive reports and documentation - Created maintenance scripts and guides All files organized according to established standards.
This commit is contained in:
312
scripts/enable-lvm-thin-pve.sh
Executable file
312
scripts/enable-lvm-thin-pve.sh
Executable file
@@ -0,0 +1,312 @@
|
||||
#!/usr/bin/env bash
|
||||
# Enable LVM Thin Storage on pve for migrations
|
||||
# Creates volume group and thin pool from available disk
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Configuration
|
||||
PROXMOX_HOST_PVE="192.168.11.11"
|
||||
PVE_PASS="password"
|
||||
STORAGE_NAME="thin1"
|
||||
VG_NAME="pve"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
log_header() { echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; }
|
||||
|
||||
# SSH helper
|
||||
ssh_pve() {
|
||||
sshpass -p "$PVE_PASS" ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new root@"$PROXMOX_HOST_PVE" "$@" 2>&1
|
||||
}
|
||||
|
||||
# Find available disk
|
||||
find_available_disk() {
|
||||
# Check unpartitioned disks (sdc-sdh)
|
||||
for disk in sdc sdd sde sdf sdg sdh; do
|
||||
# Check if disk exists
|
||||
if ! ssh_pve "test -b /dev/$disk" 2>/dev/null; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if already a PV
|
||||
if ssh_pve "pvdisplay /dev/$disk 2>/dev/null | grep -q 'PV Name'"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if has partitions
|
||||
local has_partitions=$(ssh_pve "lsblk /dev/$disk 2>/dev/null | grep -q 'part' && echo 'yes' || echo 'no'")
|
||||
if [ "$has_partitions" == "yes" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "/dev/$disk"
|
||||
return 0
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Create physical volume
|
||||
create_physical_volume() {
|
||||
local disk=$1
|
||||
|
||||
log_info "Creating physical volume on $disk..."
|
||||
|
||||
# Check if already a PV
|
||||
if ssh_pve "pvdisplay $disk 2>/dev/null | grep -q 'PV Name'"; then
|
||||
log_warn "$disk is already a physical volume"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Wipe disk first (remove any existing signatures)
|
||||
log_info "Wiping disk $disk..."
|
||||
ssh_pve "wipefs -a $disk 2>/dev/null" || true
|
||||
|
||||
# Create PV (force if needed)
|
||||
if ssh_pve "pvcreate -f $disk 2>&1"; then
|
||||
log_success "Physical volume created on $disk"
|
||||
return 0
|
||||
else
|
||||
log_error "Failed to create physical volume"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Create volume group
|
||||
create_volume_group() {
|
||||
local vg_name=$1
|
||||
local disk=$2
|
||||
|
||||
log_info "Creating volume group '$vg_name'..."
|
||||
|
||||
# Check if VG already exists
|
||||
if ssh_pve "vgs $vg_name 2>/dev/null | grep -q $vg_name"; then
|
||||
log_warn "Volume group '$vg_name' already exists"
|
||||
|
||||
# Check if we can extend it
|
||||
if ssh_pve "vgextend $vg_name $disk 2>/dev/null"; then
|
||||
log_success "Extended volume group '$vg_name' with $disk"
|
||||
return 0
|
||||
else
|
||||
log_info "Volume group exists, using existing"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create VG
|
||||
if ssh_pve "vgcreate $vg_name $disk"; then
|
||||
log_success "Volume group '$vg_name' created"
|
||||
return 0
|
||||
else
|
||||
log_error "Failed to create volume group"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Create thin pool
|
||||
create_thin_pool() {
|
||||
local vg_name=$1
|
||||
local pool_name=$2
|
||||
|
||||
log_info "Creating thin pool '$pool_name' in volume group '$vg_name'..."
|
||||
|
||||
# Check if pool already exists
|
||||
if ssh_pve "lvs $vg_name/$pool_name 2>/dev/null | grep -q $pool_name"; then
|
||||
log_warn "Thin pool '$vg_name/$pool_name' already exists"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Get available space
|
||||
local vg_free=$(ssh_pve "vgs -o vg_free --noheadings --units g $vg_name 2>/dev/null | awk '{print int(\$1)}'" || echo "0")
|
||||
|
||||
if [ "$vg_free" -lt 10 ]; then
|
||||
log_error "Not enough free space in $vg_name (${vg_free}G available)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Use 90% of available space for thin pool
|
||||
local pool_size=$((vg_free * 90 / 100))
|
||||
log_info "Creating thin pool with ${pool_size}G (90% of ${vg_free}G free)"
|
||||
|
||||
# Create thin pool
|
||||
if ssh_pve <<EOF
|
||||
lvcreate -L ${pool_size}G -n ${pool_name} ${vg_name}
|
||||
lvconvert --type thin-pool -y ${vg_name}/${pool_name}
|
||||
EOF
|
||||
then
|
||||
log_success "Thin pool '$vg_name/$pool_name' created"
|
||||
return 0
|
||||
else
|
||||
log_error "Failed to create thin pool"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Add storage to Proxmox
|
||||
add_proxmox_storage() {
|
||||
local storage_name=$1
|
||||
local vg_name=$2
|
||||
local pool_name=$3
|
||||
|
||||
log_info "Adding '$storage_name' storage to Proxmox..."
|
||||
|
||||
# Check if storage already exists
|
||||
if ssh_pve "pvesm status 2>/dev/null | grep -q '^$storage_name'"; then
|
||||
local status=$(ssh_pve "pvesm status 2>/dev/null | grep '^$storage_name' | awk '{print \$3}'")
|
||||
|
||||
if [ "$status" == "active" ] || [ "$status" == "enabled" ]; then
|
||||
log_success "Storage '$storage_name' already exists and is active"
|
||||
return 0
|
||||
else
|
||||
log_info "Storage '$storage_name' exists but is inactive, removing..."
|
||||
ssh_pve "pvesm remove $storage_name 2>/dev/null" || true
|
||||
sleep 2
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add storage
|
||||
if ssh_pve <<EOF
|
||||
pvesm add lvmthin $storage_name \
|
||||
--thinpool ${pool_name} \
|
||||
--vgname ${vg_name} \
|
||||
--content images,rootdir \
|
||||
--nodes pve 2>&1
|
||||
EOF
|
||||
then
|
||||
log_success "Storage '$storage_name' added to Proxmox"
|
||||
return 0
|
||||
else
|
||||
log_warn "Storage add command had issues, checking if it was created..."
|
||||
sleep 2
|
||||
|
||||
if ssh_pve "pvesm status 2>/dev/null | grep -q '^$storage_name'"; then
|
||||
log_success "Storage '$storage_name' exists (may have been created)"
|
||||
return 0
|
||||
else
|
||||
log_error "Failed to add storage to Proxmox"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
echo ""
|
||||
log_header
|
||||
log_info "Enable LVM Thin Storage on pve"
|
||||
log_header
|
||||
echo ""
|
||||
|
||||
log_info "This script will:"
|
||||
log_info " 1. Find an available disk on pve"
|
||||
log_info " 2. Create a physical volume"
|
||||
log_info " 3. Create volume group '$VG_NAME'"
|
||||
log_info " 4. Create thin pool '$STORAGE_NAME'"
|
||||
log_info " 5. Add storage to Proxmox configuration"
|
||||
echo ""
|
||||
|
||||
# Check for non-interactive mode
|
||||
if [[ "${NON_INTERACTIVE:-}" != "1" ]] && [[ -t 0 ]]; then
|
||||
read -p "Continue? (y/N): " -n 1 -r
|
||||
echo ""
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_info "Operation cancelled"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Find available disk
|
||||
log_info "Finding available disk for LVM..."
|
||||
local disk=$(find_available_disk)
|
||||
if [ -z "$disk" ]; then
|
||||
log_error "Cannot proceed without an available disk"
|
||||
exit 1
|
||||
fi
|
||||
log_success "Found available disk: $disk"
|
||||
|
||||
log_warn "WARNING: This will use $disk for LVM storage"
|
||||
log_warn "Any existing data on $disk will be lost!"
|
||||
echo ""
|
||||
|
||||
if [[ "${NON_INTERACTIVE:-}" != "1" ]] && [[ -t 0 ]]; then
|
||||
read -p "Proceed with using $disk? (y/N): " -n 1 -r
|
||||
echo ""
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_info "Operation cancelled"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Create physical volume
|
||||
if ! create_physical_volume "$disk"; then
|
||||
log_error "Failed to create physical volume"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Create volume group
|
||||
if ! create_volume_group "$VG_NAME" "$disk"; then
|
||||
log_error "Failed to create volume group"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Create thin pool
|
||||
if ! create_thin_pool "$VG_NAME" "$STORAGE_NAME"; then
|
||||
log_error "Failed to create thin pool"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Add to Proxmox
|
||||
if ! add_proxmox_storage "$STORAGE_NAME" "$VG_NAME" "$STORAGE_NAME"; then
|
||||
log_error "Failed to add storage to Proxmox"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Final verification
|
||||
log_header
|
||||
log_info "Verification"
|
||||
log_header
|
||||
echo ""
|
||||
|
||||
log_info "Volume groups:"
|
||||
ssh_pve "vgs" || true
|
||||
echo ""
|
||||
|
||||
log_info "Thin pools:"
|
||||
ssh_pve "lvs $VG_NAME" || true
|
||||
echo ""
|
||||
|
||||
log_info "Storage status:"
|
||||
ssh_pve "pvesm status | grep -E '(thin1|local)'" || true
|
||||
echo ""
|
||||
|
||||
log_success "LVM thin storage enabled on pve!"
|
||||
log_info ""
|
||||
log_info "You can now migrate VMs to pve using '$STORAGE_NAME' storage:"
|
||||
log_info " pct migrate <VMID> pve --storage $STORAGE_NAME"
|
||||
echo ""
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
Reference in New Issue
Block a user