mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 07:20:12 +01:00
Add Snap automatic upgrades.
Thanks to xet7 !
This commit is contained in:
parent
c2a3e11324
commit
0549bc0b0c
6 changed files with 1165 additions and 0 deletions
|
|
@ -9,6 +9,73 @@ if [ "true" == "${DISABLE_MONGODB}" ]; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
# Check if MongoDB migration is needed and handle it
|
||||
MIGRATION_STATUS="${SNAP_COMMON}/mongodb-migration-status.json"
|
||||
MIGRATION_LOG="${SNAP_COMMON}/mongodb-migration-log.txt"
|
||||
REVERT_FILE="${SNAP_COMMON}/revert-mongodb-migration.txt"
|
||||
|
||||
# Check if migration is needed
|
||||
check_migration_needed() {
|
||||
if [ -f "$MIGRATION_STATUS" ]; then
|
||||
local status=$(jq -r '.status' "$MIGRATION_STATUS" 2>/dev/null || echo "unknown")
|
||||
if [ "$status" = "completed" ]; then
|
||||
return 1
|
||||
elif [ "$status" = "running" ]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if we have MongoDB 3 data
|
||||
if [ -d "${SNAP_COMMON}/wekan" ] && [ ! -f "${SNAP_COMMON}/mongodb-version-7" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Handle migration
|
||||
handle_migration() {
|
||||
echo "MongoDB migration needed, starting migration process..."
|
||||
|
||||
# Start migration web interface in background
|
||||
$SNAP/bin/mongodb-migration-web &
|
||||
local web_pid=$!
|
||||
echo "$web_pid" > "${SNAP_COMMON}/migration-web.pid"
|
||||
|
||||
# Run migration
|
||||
if $SNAP/bin/mongodb-migrate; then
|
||||
echo "MongoDB migration completed successfully"
|
||||
# Kill migration web interface
|
||||
if [ -f "${SNAP_COMMON}/migration-web.pid" ]; then
|
||||
local web_pid=$(cat "${SNAP_COMMON}/migration-web.pid")
|
||||
kill "$web_pid" 2>/dev/null || true
|
||||
rm -f "${SNAP_COMMON}/migration-web.pid"
|
||||
fi
|
||||
else
|
||||
echo "MongoDB migration failed"
|
||||
# Kill migration web interface
|
||||
if [ -f "${SNAP_COMMON}/migration-web.pid" ]; then
|
||||
local web_pid=$(cat "${SNAP_COMMON}/migration-web.pid")
|
||||
kill "$web_pid" 2>/dev/null || true
|
||||
rm -f "${SNAP_COMMON}/migration-web.pid"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if revert is requested
|
||||
if [ -f "$REVERT_FILE" ]; then
|
||||
echo "Revert requested, stopping MongoDB and reverting migration..."
|
||||
snapctl stop --disable ${SNAP_NAME}.mongodb
|
||||
$SNAP/bin/mongodb-migrate
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Check if migration is needed
|
||||
if check_migration_needed; then
|
||||
handle_migration
|
||||
fi
|
||||
|
||||
# make sure we have set minimum env variables for locale
|
||||
if [ -z "${LANG}" ]; then
|
||||
export LANG=en_US.UTF-8
|
||||
|
|
|
|||
625
snap-src/bin/mongodb-migrate
Executable file
625
snap-src/bin/mongodb-migrate
Executable file
|
|
@ -0,0 +1,625 @@
|
|||
#!/bin/bash
|
||||
|
||||
# MongoDB Migration Script from version 3 to 7
|
||||
# This script handles migration with disk space checks, progress tracking, and error handling
|
||||
|
||||
set -e
|
||||
|
||||
# Source settings
|
||||
source $SNAP/bin/wekan-read-settings
|
||||
|
||||
# Migration configuration
|
||||
MIGRATION_LOG="${SNAP_COMMON}/mongodb-migration-log.txt"
|
||||
MIGRATION_STATUS="${SNAP_COMMON}/mongodb-migration-status.json"
|
||||
MIGRATION_PROGRESS="${SNAP_COMMON}/mongodb-migration-progress.html"
|
||||
REVERT_FILE="${SNAP_COMMON}/revert-mongodb-migration.txt"
|
||||
TEMP_DIR="${SNAP_COMMON}/mongodb-migration-temp"
|
||||
BACKUP_DIR="${SNAP_COMMON}/mongodb-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
|
||||
# MongoDB paths
|
||||
MONGO3_BIN="/snap/${SNAP_NAME}/current/bin"
|
||||
MONGO7_BIN="/snap/${SNAP_NAME}/current/usr/bin"
|
||||
MONGO3_LIB="/snap/${SNAP_NAME}/current/lib"
|
||||
MONGO7_LIB="/snap/${SNAP_NAME}/current/lib"
|
||||
|
||||
# Set up environment for MongoDB 3 tools
|
||||
export LD_LIBRARY_PATH="${MONGO3_LIB}:${MONGO3_LIB}/x86_64-linux-gnu:${LD_LIBRARY_PATH}"
|
||||
export PATH="${MONGO3_BIN}:${MONGO7_BIN}:${PATH}"
|
||||
|
||||
# Logging functions
|
||||
log_message() {
|
||||
local message="$1"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "[$timestamp] $message" | tee -a "$MIGRATION_LOG"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
local message="$1"
|
||||
log_message "ERROR: $message"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
local message="$1"
|
||||
log_message "SUCCESS: $message"
|
||||
}
|
||||
|
||||
# Disk space checking functions
|
||||
check_disk_space() {
|
||||
local required_space_gb="$1"
|
||||
local available_space_gb=$(df "$SNAP_COMMON" | awk 'NR==2 {print int($4/1024/1024)}')
|
||||
|
||||
if [ "$available_space_gb" -lt "$required_space_gb" ]; then
|
||||
log_error "Insufficient disk space. Required: ${required_space_gb}GB, Available: ${available_space_gb}GB"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_message "Disk space check passed. Available: ${available_space_gb}GB, Required: ${required_space_gb}GB"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Progress tracking functions
|
||||
update_progress() {
|
||||
local step="$1"
|
||||
local total_steps="$2"
|
||||
local description="$3"
|
||||
local percentage=$((step * 100 / total_steps))
|
||||
|
||||
# Update JSON status file
|
||||
cat > "$MIGRATION_STATUS" << EOF
|
||||
{
|
||||
"step": $step,
|
||||
"total_steps": $total_steps,
|
||||
"percentage": $percentage,
|
||||
"description": "$description",
|
||||
"timestamp": "$(date -Iseconds)",
|
||||
"status": "running"
|
||||
}
|
||||
EOF
|
||||
|
||||
# Update HTML progress page
|
||||
cat > "$MIGRATION_PROGRESS" << EOF
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>MongoDB Migration Progress</title>
|
||||
<meta http-equiv="refresh" content="5">
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 40px; }
|
||||
.progress-bar { width: 100%; background-color: #f0f0f0; border-radius: 5px; }
|
||||
.progress-fill { height: 30px; background-color: #4CAF50; border-radius: 5px; width: ${percentage}%; }
|
||||
.status { margin: 20px 0; }
|
||||
.error { color: red; }
|
||||
.success { color: green; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>MongoDB Migration Progress</h1>
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill"></div>
|
||||
</div>
|
||||
<div class="status">
|
||||
<p><strong>Progress:</strong> $step of $total_steps steps ($percentage%)</p>
|
||||
<p><strong>Current Step:</strong> $description</p>
|
||||
<p><strong>Last Updated:</strong> $(date)</p>
|
||||
</div>
|
||||
<p><em>This page will refresh automatically every 5 seconds.</em></p>
|
||||
</body>
|
||||
</html>
|
||||
EOF
|
||||
|
||||
log_message "Progress: $step/$total_steps ($percentage%) - $description"
|
||||
}
|
||||
|
||||
# Estimate completion time
|
||||
estimate_completion_time() {
|
||||
local start_time="$1"
|
||||
local current_step="$2"
|
||||
local total_steps="$3"
|
||||
|
||||
if [ "$current_step" -gt 0 ]; then
|
||||
local elapsed=$(($(date +%s) - start_time))
|
||||
local avg_time_per_step=$((elapsed / current_step))
|
||||
local remaining_steps=$((total_steps - current_step))
|
||||
local estimated_remaining=$((remaining_steps * avg_time_per_step))
|
||||
|
||||
local hours=$((estimated_remaining / 3600))
|
||||
local minutes=$(((estimated_remaining % 3600) / 60))
|
||||
local seconds=$((estimated_remaining % 60))
|
||||
|
||||
echo "${hours}h ${minutes}m ${seconds}s"
|
||||
else
|
||||
echo "Calculating..."
|
||||
fi
|
||||
}
|
||||
|
||||
# Create backup before migration
|
||||
create_backup() {
|
||||
log_message "Creating backup of MongoDB 3 database"
|
||||
|
||||
# Check disk space for backup (estimate 2x current database size)
|
||||
local db_size=$(du -s "${SNAP_COMMON}/wekan" 2>/dev/null | awk '{print $1}' || echo "0")
|
||||
local required_space=$((db_size * 2 / 1024 / 1024 + 1)) # Convert to GB and add 1GB buffer
|
||||
|
||||
if ! check_disk_space "$required_space"; then
|
||||
log_error "Insufficient disk space for backup"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Create backup directory
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Copy database files
|
||||
if [ -d "${SNAP_COMMON}/wekan" ]; then
|
||||
cp -r "${SNAP_COMMON}/wekan" "$BACKUP_DIR/"
|
||||
log_success "Database backup created at $BACKUP_DIR"
|
||||
return 0
|
||||
else
|
||||
log_error "No database found to backup"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if migration is needed
|
||||
check_migration_needed() {
|
||||
if [ -f "$MIGRATION_STATUS" ]; then
|
||||
local status=$(jq -r '.status' "$MIGRATION_STATUS" 2>/dev/null || echo "unknown")
|
||||
if [ "$status" = "completed" ]; then
|
||||
log_message "Migration already completed"
|
||||
return 1
|
||||
elif [ "$status" = "running" ]; then
|
||||
log_message "Migration already in progress"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if we have MongoDB 3 data (either in wekan directory or raw database files)
|
||||
if [ -d "${SNAP_COMMON}/wekan" ] && [ ! -f "${SNAP_COMMON}/mongodb-version-7" ]; then
|
||||
log_message "MongoDB 3 data detected in wekan directory"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check for MongoDB 3 raw database files
|
||||
if detect_mongodb3_raw_files; then
|
||||
log_message "MongoDB 3 raw database files detected"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_message "No migration needed"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Detect MongoDB 3 raw database files
|
||||
detect_mongodb3_raw_files() {
|
||||
# Look for MongoDB 3 specific files and directories
|
||||
local mongodb3_indicators=(
|
||||
"${SNAP_COMMON}/local.0"
|
||||
"${SNAP_COMMON}/local.ns"
|
||||
"${SNAP_COMMON}/local.1"
|
||||
"${SNAP_COMMON}/wekan.0"
|
||||
"${SNAP_COMMON}/wekan.ns"
|
||||
"${SNAP_COMMON}/wekan.1"
|
||||
"${SNAP_COMMON}/storage.bson"
|
||||
"${SNAP_COMMON}/_tmp"
|
||||
)
|
||||
|
||||
# Check for MongoDB 3 journal files
|
||||
local journal_files=(
|
||||
"${SNAP_COMMON}/journal"
|
||||
"${SNAP_COMMON}/j._0"
|
||||
)
|
||||
|
||||
# Check for MongoDB 3 lock file
|
||||
if [ -f "${SNAP_COMMON}/mongod.lock" ]; then
|
||||
log_message "MongoDB lock file found, checking for MongoDB 3 data"
|
||||
|
||||
# Check if any MongoDB 3 indicators exist
|
||||
for indicator in "${mongodb3_indicators[@]}"; do
|
||||
if [ -e "$indicator" ]; then
|
||||
log_message "MongoDB 3 indicator found: $indicator"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for journal files
|
||||
for journal in "${journal_files[@]}"; do
|
||||
if [ -e "$journal" ]; then
|
||||
log_message "MongoDB journal file found: $journal"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for any .0, .1, .ns files (MongoDB 3 data files)
|
||||
if find "${SNAP_COMMON}" -maxdepth 1 -name "*.0" -o -name "*.1" -o -name "*.ns" | grep -q .; then
|
||||
log_message "MongoDB 3 data files found"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Migrate raw MongoDB 3 database files
|
||||
migrate_raw_database_files() {
|
||||
log_message "Starting raw MongoDB 3 database files migration"
|
||||
|
||||
# Stop any running MongoDB processes
|
||||
log_message "Stopping any running MongoDB processes"
|
||||
pkill -f mongod || true
|
||||
sleep 3
|
||||
|
||||
# Start MongoDB 3 with raw files
|
||||
log_message "Starting MongoDB 3 with raw database files"
|
||||
local mongo3_pid
|
||||
mongod --dbpath "${SNAP_COMMON}" --port "${MONGODB_PORT:-27019}" --quiet &
|
||||
mongo3_pid=$!
|
||||
|
||||
# Wait for MongoDB 3 to start
|
||||
local retry_count=0
|
||||
while [ $retry_count -lt 30 ]; do
|
||||
if mongosh --quiet --eval "db.adminCommand('ping')" "mongodb://localhost:${MONGODB_PORT:-27019}/admin" >/dev/null 2>&1; then
|
||||
log_message "MongoDB 3 started successfully"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
retry_count=$((retry_count + 1))
|
||||
done
|
||||
|
||||
if [ $retry_count -eq 30 ]; then
|
||||
log_error "MongoDB 3 failed to start"
|
||||
kill $mongo3_pid 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Dump all databases from MongoDB 3
|
||||
log_message "Dumping databases from MongoDB 3"
|
||||
if ! mongodump --port "${MONGODB_PORT:-27019}" --out "$TEMP_DIR"; then
|
||||
log_error "Failed to dump databases from MongoDB 3"
|
||||
kill $mongo3_pid 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Stop MongoDB 3
|
||||
log_message "Stopping MongoDB 3"
|
||||
kill $mongo3_pid 2>/dev/null || true
|
||||
sleep 3
|
||||
|
||||
# Start MongoDB 7
|
||||
log_message "Starting MongoDB 7"
|
||||
local mongo7_pid
|
||||
mongod --dbpath "${SNAP_COMMON}" --port "${MONGODB_PORT:-27019}" --quiet &
|
||||
mongo7_pid=$!
|
||||
|
||||
# Wait for MongoDB 7 to start
|
||||
retry_count=0
|
||||
while [ $retry_count -lt 30 ]; do
|
||||
if mongosh --quiet --eval "db.adminCommand('ping')" "mongodb://localhost:${MONGODB_PORT:-27019}/admin" >/dev/null 2>&1; then
|
||||
log_message "MongoDB 7 started successfully"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
retry_count=$((retry_count + 1))
|
||||
done
|
||||
|
||||
if [ $retry_count -eq 30 ]; then
|
||||
log_error "MongoDB 7 failed to start"
|
||||
kill $mongo7_pid 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Restore databases to MongoDB 7
|
||||
log_message "Restoring databases to MongoDB 7"
|
||||
if ! mongorestore --port "${MONGODB_PORT:-27019}" "$TEMP_DIR"; then
|
||||
log_error "Failed to restore databases to MongoDB 7"
|
||||
kill $mongo7_pid 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Stop MongoDB 7
|
||||
log_message "Stopping MongoDB 7"
|
||||
kill $mongo7_pid 2>/dev/null || true
|
||||
sleep 3
|
||||
|
||||
# Clean up old MongoDB 3 files
|
||||
log_message "Cleaning up old MongoDB 3 files"
|
||||
find "${SNAP_COMMON}" -maxdepth 1 -name "*.0" -o -name "*.1" -o -name "*.ns" -o -name "j._*" -o -name "mongod.lock" | while read -r file; do
|
||||
if [ -f "$file" ]; then
|
||||
rm -f "$file"
|
||||
log_message "Removed old file: $file"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove journal directory if it exists
|
||||
if [ -d "${SNAP_COMMON}/journal" ]; then
|
||||
rm -rf "${SNAP_COMMON}/journal"
|
||||
log_message "Removed journal directory"
|
||||
fi
|
||||
|
||||
log_success "Raw database files migration completed successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Snap channel detection and switching functions
|
||||
get_current_snap_channel() {
|
||||
local snap_name="$1"
|
||||
snap list "$snap_name" 2>/dev/null | awk 'NR==2 {print $4}' || echo "unknown"
|
||||
}
|
||||
|
||||
is_wekan_snap() {
|
||||
local snap_name="$1"
|
||||
case "$snap_name" in
|
||||
wekan|wekan-gantt-gpl|wekan-ondra)
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
switch_to_stable_channel() {
|
||||
local snap_name="$1"
|
||||
local current_channel=$(get_current_snap_channel "$snap_name")
|
||||
|
||||
if [ "$current_channel" != "stable" ] && [ "$current_channel" != "unknown" ]; then
|
||||
log_message "Switching $snap_name from $current_channel to stable channel"
|
||||
|
||||
if snap refresh "$snap_name" --channel=stable; then
|
||||
log_success "Successfully switched $snap_name to stable channel"
|
||||
return 0
|
||||
else
|
||||
log_error "Failed to switch $snap_name to stable channel"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
log_message "$snap_name is already on stable channel or not installed"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
switch_all_wekan_snaps_to_stable() {
|
||||
log_message "Checking for Wekan-related snaps to switch to stable channel"
|
||||
|
||||
local wekan_snaps=("wekan" "wekan-gantt-gpl" "wekan-ondra")
|
||||
local switched_count=0
|
||||
local failed_count=0
|
||||
|
||||
for snap_name in "${wekan_snaps[@]}"; do
|
||||
if snap list "$snap_name" >/dev/null 2>&1; then
|
||||
if switch_to_stable_channel "$snap_name"; then
|
||||
switched_count=$((switched_count + 1))
|
||||
else
|
||||
failed_count=$((failed_count + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
log_message "Channel switching completed: $switched_count successful, $failed_count failed"
|
||||
|
||||
if [ "$failed_count" -gt 0 ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Get database collections
|
||||
get_collections() {
|
||||
local mongo_url="$1"
|
||||
local collections=$(mongosh --quiet --eval "db.getCollectionNames().join('\n')" "$mongo_url" 2>/dev/null | grep -v "^$" || echo "")
|
||||
echo "$collections"
|
||||
}
|
||||
|
||||
# Migrate a single collection
|
||||
migrate_collection() {
|
||||
local collection="$1"
|
||||
local mongo3_url="$2"
|
||||
local mongo7_url="$3"
|
||||
local step="$4"
|
||||
local total_steps="$5"
|
||||
|
||||
log_message "Migrating collection: $collection"
|
||||
|
||||
# Check disk space before each collection (estimate 2x collection size)
|
||||
local collection_size=$(mongosh --quiet --eval "db.$collection.stats().size" "$mongo3_url" 2>/dev/null || echo "0")
|
||||
local required_space=$((collection_size * 2 / 1024 / 1024 / 1024 + 1)) # Convert to GB and add 1GB buffer
|
||||
|
||||
if ! check_disk_space "$required_space"; then
|
||||
log_error "Insufficient disk space for collection $collection"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Dump collection
|
||||
local dump_file="${TEMP_DIR}/${collection}.bson"
|
||||
log_message "Dumping collection $collection to $dump_file"
|
||||
|
||||
if ! mongodump --db wekan --collection "$collection" --out "$TEMP_DIR" --port "${MONGODB_PORT:-27019}"; then
|
||||
log_error "Failed to dump collection $collection"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Restore collection
|
||||
log_message "Restoring collection $collection to MongoDB 7"
|
||||
if ! mongorestore --db wekan --collection "$collection" "$dump_file" --port "${MONGODB_PORT:-27019}"; then
|
||||
log_error "Failed to restore collection $collection"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Update progress
|
||||
update_progress "$step" "$total_steps" "Migrated collection: $collection"
|
||||
|
||||
# Clean up dump file
|
||||
rm -f "$dump_file"
|
||||
|
||||
log_success "Collection $collection migrated successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main migration function
|
||||
perform_migration() {
|
||||
local start_time=$(date +%s)
|
||||
|
||||
log_message "Starting MongoDB migration from version 3 to 7"
|
||||
|
||||
# Create backup before migration
|
||||
log_message "Creating backup before migration"
|
||||
if ! create_backup; then
|
||||
log_error "Failed to create backup, aborting migration"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Create temporary directory
|
||||
mkdir -p "$TEMP_DIR"
|
||||
|
||||
# Check if we need to migrate raw database files
|
||||
if detect_mongodb3_raw_files; then
|
||||
log_message "Raw MongoDB 3 database files detected, starting raw file migration"
|
||||
if ! migrate_raw_database_files; then
|
||||
log_error "Failed to migrate raw database files"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get MongoDB connection details
|
||||
local mongo3_url="mongodb://localhost:${MONGODB_PORT:-27019}/wekan"
|
||||
local mongo7_url="mongodb://localhost:${MONGODB_PORT:-27019}/wekan"
|
||||
|
||||
# Get collections to migrate
|
||||
log_message "Getting list of collections to migrate"
|
||||
local collections=$(get_collections "$mongo3_url")
|
||||
|
||||
if [ -z "$collections" ]; then
|
||||
log_error "No collections found to migrate"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local collection_count=$(echo "$collections" | wc -l)
|
||||
log_message "Found $collection_count collections to migrate"
|
||||
|
||||
# Migrate each collection
|
||||
local current_step=0
|
||||
for collection in $collections; do
|
||||
current_step=$((current_step + 1))
|
||||
|
||||
if ! migrate_collection "$collection" "$mongo3_url" "$mongo7_url" "$current_step" "$collection_count"; then
|
||||
log_error "Migration failed at collection $collection"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Update completion time estimate
|
||||
local estimated_time=$(estimate_completion_time "$start_time" "$current_step" "$collection_count")
|
||||
log_message "Estimated completion time: $estimated_time"
|
||||
done
|
||||
|
||||
# Mark migration as completed
|
||||
cat > "$MIGRATION_STATUS" << EOF
|
||||
{
|
||||
"step": $collection_count,
|
||||
"total_steps": $collection_count,
|
||||
"percentage": 100,
|
||||
"description": "Migration completed successfully",
|
||||
"timestamp": "$(date -Iseconds)",
|
||||
"status": "completed"
|
||||
}
|
||||
EOF
|
||||
|
||||
# Create MongoDB 7 version marker
|
||||
touch "${SNAP_COMMON}/mongodb-version-7"
|
||||
|
||||
# Clean up temporary files
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
# Switch Wekan snaps to stable channel after successful migration
|
||||
log_message "Switching Wekan snaps to stable channel after successful migration"
|
||||
if switch_all_wekan_snaps_to_stable; then
|
||||
log_success "All Wekan snaps switched to stable channel successfully"
|
||||
else
|
||||
log_error "Some Wekan snaps failed to switch to stable channel"
|
||||
# Don't fail the migration for channel switching issues
|
||||
fi
|
||||
|
||||
log_success "MongoDB migration completed successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Revert migration
|
||||
revert_migration() {
|
||||
log_message "Reverting MongoDB migration"
|
||||
|
||||
if [ ! -f "$REVERT_FILE" ]; then
|
||||
log_error "Revert file not found: $REVERT_FILE"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Stop MongoDB 7
|
||||
log_message "Stopping MongoDB 7"
|
||||
snapctl stop --disable "${SNAP_NAME}.mongodb"
|
||||
|
||||
# Remove MongoDB 7 version marker
|
||||
rm -f "${SNAP_COMMON}/mongodb-version-7"
|
||||
|
||||
# Find the most recent backup directory
|
||||
local latest_backup=$(ls -td "${SNAP_COMMON}/mongodb-backup-"* 2>/dev/null | head -1)
|
||||
|
||||
if [ -n "$latest_backup" ] && [ -d "$latest_backup" ]; then
|
||||
log_message "Restoring from backup: $latest_backup"
|
||||
|
||||
# Stop any running MongoDB processes
|
||||
pkill -f mongod || true
|
||||
sleep 2
|
||||
|
||||
# Remove current database directory
|
||||
rm -rf "${SNAP_COMMON}/wekan"
|
||||
|
||||
# Restore from backup
|
||||
cp -r "$latest_backup"/* "${SNAP_COMMON}/"
|
||||
|
||||
# Clean up backup directory
|
||||
rm -rf "$latest_backup"
|
||||
|
||||
log_success "Database restored from backup"
|
||||
else
|
||||
log_error "No backup found for revert"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Remove revert file
|
||||
rm -f "$REVERT_FILE"
|
||||
|
||||
# Clear migration status
|
||||
rm -f "$MIGRATION_STATUS"
|
||||
|
||||
# Start MongoDB 3
|
||||
log_message "Starting MongoDB 3"
|
||||
snapctl start --enable "${SNAP_NAME}.mongodb"
|
||||
|
||||
log_success "Migration reverted successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
log_message "MongoDB Migration Script started"
|
||||
|
||||
# Check if revert is requested
|
||||
if [ -f "$REVERT_FILE" ]; then
|
||||
revert_migration
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Check if migration is needed
|
||||
if ! check_migration_needed; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Perform migration
|
||||
if perform_migration; then
|
||||
log_success "Migration completed successfully"
|
||||
exit 0
|
||||
else
|
||||
log_error "Migration failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
126
snap-src/bin/mongodb-migration-status
Executable file
126
snap-src/bin/mongodb-migration-status
Executable file
|
|
@ -0,0 +1,126 @@
|
|||
#!/bin/bash
|
||||
|
||||
# MongoDB Migration Status Script
|
||||
# Provides status information about the migration process
|
||||
|
||||
# Source settings
|
||||
source $SNAP/bin/wekan-read-settings
|
||||
|
||||
# Configuration
|
||||
MIGRATION_STATUS="${SNAP_COMMON}/mongodb-migration-status.json"
|
||||
MIGRATION_LOG="${SNAP_COMMON}/mongodb-migration-log.txt"
|
||||
REVERT_FILE="${SNAP_COMMON}/revert-mongodb-migration.txt"
|
||||
|
||||
# Show migration status
|
||||
show_status() {
|
||||
if [ -f "$MIGRATION_STATUS" ]; then
|
||||
echo "=== MongoDB Migration Status ==="
|
||||
echo "Status: $(jq -r '.status' "$MIGRATION_STATUS" 2>/dev/null || echo "unknown")"
|
||||
echo "Progress: $(jq -r '.step' "$MIGRATION_STATUS" 2>/dev/null || echo "0")/$(jq -r '.total_steps' "$MIGRATION_STATUS" 2>/dev/null || echo "0") steps"
|
||||
echo "Percentage: $(jq -r '.percentage' "$MIGRATION_STATUS" 2>/dev/null || echo "0")%"
|
||||
echo "Current Step: $(jq -r '.description' "$MIGRATION_STATUS" 2>/dev/null || echo "Unknown")"
|
||||
echo "Last Updated: $(jq -r '.timestamp' "$MIGRATION_STATUS" 2>/dev/null || echo "Unknown")"
|
||||
echo ""
|
||||
|
||||
if [ -f "$MIGRATION_LOG" ]; then
|
||||
echo "=== Recent Migration Log ==="
|
||||
tail -10 "$MIGRATION_LOG"
|
||||
fi
|
||||
else
|
||||
echo "No migration in progress or completed."
|
||||
fi
|
||||
}
|
||||
|
||||
# Show migration log
|
||||
show_log() {
|
||||
if [ -f "$MIGRATION_LOG" ]; then
|
||||
echo "=== Full Migration Log ==="
|
||||
cat "$MIGRATION_LOG"
|
||||
else
|
||||
echo "No migration log found."
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if migration is needed
|
||||
check_needed() {
|
||||
if [ -d "${SNAP_COMMON}/wekan" ] && [ ! -f "${SNAP_COMMON}/mongodb-version-7" ]; then
|
||||
echo "Migration needed: MongoDB 3 data detected"
|
||||
return 0
|
||||
else
|
||||
echo "No migration needed"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Start migration
|
||||
start_migration() {
|
||||
if check_needed; then
|
||||
echo "Starting MongoDB migration..."
|
||||
$SNAP/bin/mongodb-migrate
|
||||
else
|
||||
echo "Migration not needed or already completed"
|
||||
fi
|
||||
}
|
||||
|
||||
# Request revert
|
||||
request_revert() {
|
||||
echo "Requesting migration revert..."
|
||||
touch "$REVERT_FILE"
|
||||
echo "Revert requested. Restart Wekan to apply revert."
|
||||
}
|
||||
|
||||
# Clear migration status
|
||||
clear_status() {
|
||||
echo "Clearing migration status..."
|
||||
rm -f "$MIGRATION_STATUS"
|
||||
rm -f "$MIGRATION_LOG"
|
||||
rm -f "$REVERT_FILE"
|
||||
echo "Migration status cleared."
|
||||
}
|
||||
|
||||
# Show help
|
||||
show_help() {
|
||||
echo "MongoDB Migration Status Tool"
|
||||
echo ""
|
||||
echo "Usage: $0 [command]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " status - Show current migration status (default)"
|
||||
echo " log - Show full migration log"
|
||||
echo " check - Check if migration is needed"
|
||||
echo " start - Start migration if needed"
|
||||
echo " revert - Request migration revert"
|
||||
echo " clear - Clear migration status"
|
||||
echo " help - Show this help"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Main execution
|
||||
case "${1:-status}" in
|
||||
"status")
|
||||
show_status
|
||||
;;
|
||||
"log")
|
||||
show_log
|
||||
;;
|
||||
"check")
|
||||
check_needed
|
||||
;;
|
||||
"start")
|
||||
start_migration
|
||||
;;
|
||||
"revert")
|
||||
request_revert
|
||||
;;
|
||||
"clear")
|
||||
clear_status
|
||||
;;
|
||||
"help"|"-h"|"--help")
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
168
snap-src/bin/mongodb-migration-web
Executable file
168
snap-src/bin/mongodb-migration-web
Executable file
|
|
@ -0,0 +1,168 @@
|
|||
#!/bin/bash
|
||||
|
||||
# MongoDB Migration Web Interface
|
||||
# Serves migration progress at ROOT_URL/migration-progress
|
||||
|
||||
# Source settings
|
||||
source $SNAP/bin/wekan-read-settings
|
||||
|
||||
# Configuration
|
||||
MIGRATION_STATUS="${SNAP_COMMON}/mongodb-migration-status.json"
|
||||
MIGRATION_LOG="${SNAP_COMMON}/mongodb-migration-log.txt"
|
||||
MIGRATION_PROGRESS="${SNAP_COMMON}/mongodb-migration-progress.html"
|
||||
PORT="${MIGRATION_WEB_PORT:-8081}"
|
||||
|
||||
# Create a simple HTTP server using netcat and bash
|
||||
serve_migration_progress() {
|
||||
while true; do
|
||||
{
|
||||
echo "HTTP/1.1 200 OK"
|
||||
echo "Content-Type: text/html; charset=utf-8"
|
||||
echo "Cache-Control: no-cache"
|
||||
echo "Connection: close"
|
||||
echo ""
|
||||
|
||||
# Generate HTML page
|
||||
if [ -f "$MIGRATION_STATUS" ]; then
|
||||
local status=$(jq -r '.status' "$MIGRATION_STATUS" 2>/dev/null || echo "unknown")
|
||||
local step=$(jq -r '.step' "$MIGRATION_STATUS" 2>/dev/null || echo "0")
|
||||
local total_steps=$(jq -r '.total_steps' "$MIGRATION_STATUS" 2>/dev/null || echo "0")
|
||||
local percentage=$(jq -r '.percentage' "$MIGRATION_STATUS" 2>/dev/null || echo "0")
|
||||
local description=$(jq -r '.description' "$MIGRATION_STATUS" 2>/dev/null || echo "Unknown")
|
||||
local timestamp=$(jq -r '.timestamp' "$MIGRATION_STATUS" 2>/dev/null || echo "Unknown")
|
||||
|
||||
cat << EOF
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>MongoDB Migration Progress</title>
|
||||
<meta http-equiv="refresh" content="5">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 40px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.progress-fill {
|
||||
height: 40px;
|
||||
background: linear-gradient(90deg, #4CAF50, #45a049);
|
||||
border-radius: 10px;
|
||||
width: ${percentage}%;
|
||||
transition: width 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
.status {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.error { color: #d32f2f; }
|
||||
.success { color: #388e3c; }
|
||||
.warning { color: #f57c00; }
|
||||
.info { color: #1976d2; }
|
||||
.log-container {
|
||||
margin-top: 30px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
background-color: #f5f5f5;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.status-indicator {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.status-running { background-color: #ff9800; }
|
||||
.status-completed { background-color: #4caf50; }
|
||||
.status-error { background-color: #f44336; }
|
||||
.status-unknown { background-color: #9e9e9e; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>MongoDB Migration Progress</h1>
|
||||
<p>Migrating from MongoDB 3 to MongoDB 7</p>
|
||||
</div>
|
||||
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill">${percentage}%</div>
|
||||
</div>
|
||||
|
||||
<div class="status">
|
||||
<p><span class="status-indicator status-${status}"></span><strong>Status:</strong> ${status}</p>
|
||||
<p><strong>Progress:</strong> $step of $total_steps steps</p>
|
||||
<p><strong>Current Step:</strong> $description</p>
|
||||
<p><strong>Last Updated:</strong> $timestamp</p>
|
||||
</div>
|
||||
|
||||
<div class="log-container">
|
||||
<h3>Migration Log (Last 20 lines):</h3>
|
||||
<pre>$(tail -20 "$MIGRATION_LOG" 2>/dev/null || echo "No log available")</pre>
|
||||
</div>
|
||||
|
||||
<p style="text-align: center; margin-top: 30px; color: #666;">
|
||||
<em>This page will refresh automatically every 5 seconds.</em><br>
|
||||
<em>Migration URL: ${ROOT_URL:-http://localhost:8080}/migration-progress</em>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
EOF
|
||||
else
|
||||
cat << EOF
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>MongoDB Migration Progress</title>
|
||||
<meta http-equiv="refresh" content="5">
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 40px; }
|
||||
.container { max-width: 800px; margin: 0 auto; text-align: center; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>MongoDB Migration</h1>
|
||||
<p>No migration in progress.</p>
|
||||
<p><em>This page will refresh automatically every 5 seconds.</em></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
EOF
|
||||
fi
|
||||
} | nc -l -p "$PORT" -q 1
|
||||
done
|
||||
}
|
||||
|
||||
# Start the web server
|
||||
serve_migration_progress
|
||||
141
snap-src/bin/snap-channel-manager
Executable file
141
snap-src/bin/snap-channel-manager
Executable file
|
|
@ -0,0 +1,141 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Snap Channel Manager for Wekan
|
||||
# Manages snap channels for Wekan-related packages
|
||||
|
||||
# Source settings
|
||||
source $SNAP/bin/wekan-read-settings
|
||||
|
||||
# Wekan-related snap packages
|
||||
WEKAN_SNAPS=("wekan" "wekan-gantt-gpl" "wekan-ondra")
|
||||
|
||||
# Get current channel for a snap
|
||||
get_current_channel() {
|
||||
local snap_name="$1"
|
||||
snap list "$snap_name" 2>/dev/null | awk 'NR==2 {print $4}' || echo "not-installed"
|
||||
}
|
||||
|
||||
# Check if snap is on stable channel
|
||||
is_stable_channel() {
|
||||
local snap_name="$1"
|
||||
local channel=$(get_current_channel "$snap_name")
|
||||
[ "$channel" = "stable" ]
|
||||
}
|
||||
|
||||
# Switch snap to stable channel
|
||||
switch_to_stable() {
|
||||
local snap_name="$1"
|
||||
local current_channel=$(get_current_channel "$snap_name")
|
||||
|
||||
if [ "$current_channel" = "not-installed" ]; then
|
||||
echo "Snap $snap_name is not installed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$current_channel" = "stable" ]; then
|
||||
echo "Snap $snap_name is already on stable channel"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Switching $snap_name from $current_channel to stable channel..."
|
||||
if snap refresh "$snap_name" --channel=stable; then
|
||||
echo "Successfully switched $snap_name to stable channel"
|
||||
return 0
|
||||
else
|
||||
echo "Failed to switch $snap_name to stable channel"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Show status of all Wekan snaps
|
||||
show_status() {
|
||||
echo "=== Wekan Snap Channel Status ==="
|
||||
echo ""
|
||||
|
||||
local all_stable=true
|
||||
|
||||
for snap_name in "${WEKAN_SNAPS[@]}"; do
|
||||
local channel=$(get_current_channel "$snap_name")
|
||||
local status=""
|
||||
|
||||
if [ "$channel" = "not-installed" ]; then
|
||||
status="[NOT INSTALLED]"
|
||||
elif [ "$channel" = "stable" ]; then
|
||||
status="[STABLE]"
|
||||
else
|
||||
status="[NON-STABLE: $channel]"
|
||||
all_stable=false
|
||||
fi
|
||||
|
||||
printf "%-20s %s\n" "$snap_name:" "$status"
|
||||
done
|
||||
|
||||
echo ""
|
||||
if [ "$all_stable" = true ]; then
|
||||
echo "All Wekan snaps are on stable channel ✓"
|
||||
else
|
||||
echo "Some Wekan snaps are not on stable channel ⚠"
|
||||
fi
|
||||
}
|
||||
|
||||
# Switch all Wekan snaps to stable
|
||||
switch_all_to_stable() {
|
||||
echo "=== Switching All Wekan Snaps to Stable Channel ==="
|
||||
echo ""
|
||||
|
||||
local success_count=0
|
||||
local total_count=0
|
||||
|
||||
for snap_name in "${WEKAN_SNAPS[@]}"; do
|
||||
if [ "$(get_current_channel "$snap_name")" != "not-installed" ]; then
|
||||
total_count=$((total_count + 1))
|
||||
if switch_to_stable "$snap_name"; then
|
||||
success_count=$((success_count + 1))
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
|
||||
echo "=== Summary ==="
|
||||
echo "Successfully switched: $success_count/$total_count snaps"
|
||||
|
||||
if [ "$success_count" -eq "$total_count" ]; then
|
||||
echo "All Wekan snaps are now on stable channel ✓"
|
||||
return 0
|
||||
else
|
||||
echo "Some snaps failed to switch to stable channel ⚠"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Show help
|
||||
show_help() {
|
||||
echo "Wekan Snap Channel Manager"
|
||||
echo ""
|
||||
echo "Usage: $0 [command]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " status - Show current channel status for all Wekan snaps"
|
||||
echo " switch - Switch all Wekan snaps to stable channel"
|
||||
echo " help - Show this help"
|
||||
echo ""
|
||||
echo "Wekan-related snaps: ${WEKAN_SNAPS[*]}"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
case "${1:-status}" in
|
||||
"status")
|
||||
show_status
|
||||
;;
|
||||
"switch")
|
||||
switch_all_to_stable
|
||||
;;
|
||||
"help"|"-h"|"--help")
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
@ -66,6 +66,20 @@ apps:
|
|||
command: ./bin/mongodb-restore
|
||||
plugs: [network, network-bind]
|
||||
|
||||
mongodb-migration:
|
||||
command: ./bin/mongodb-migrate
|
||||
plugs: [network, network-bind]
|
||||
|
||||
mongodb-migration-web:
|
||||
command: ./bin/mongodb-migration-web
|
||||
plugs: [network, network-bind]
|
||||
|
||||
mongodb-migration-status:
|
||||
command: ./bin/mongodb-migration-status
|
||||
|
||||
snap-channel-manager:
|
||||
command: ./bin/snap-channel-manager
|
||||
|
||||
parts:
|
||||
mongodb:
|
||||
source: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-7.0.25.tgz
|
||||
|
|
@ -99,6 +113,30 @@ parts:
|
|||
source: https://fastdl.mongodb.org/tools/db/mongodb-database-tools-ubuntu2404-x86_64-100.12.2.tgz
|
||||
plugin: dump
|
||||
|
||||
mongodb3:
|
||||
source: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1804-3.6.23.tgz
|
||||
plugin: dump
|
||||
stage-packages:
|
||||
- libssl1.1
|
||||
- libcurl3
|
||||
- libstemmer0d
|
||||
- zlib1g
|
||||
- libsnappy1v5
|
||||
- libyaml-cpp0.5v5
|
||||
- libpcre3
|
||||
- libpcrecpp0v5
|
||||
- libboost-system1.65.1
|
||||
- libboost-iostreams1.65.1
|
||||
- libboost-filesystem1.65.1
|
||||
- libboost-program-options1.65.1
|
||||
- libgoogle-perftools4
|
||||
stage:
|
||||
- bin
|
||||
- usr
|
||||
prime:
|
||||
- bin
|
||||
- usr
|
||||
|
||||
wekan:
|
||||
source: .
|
||||
plugin: npm
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue