Migration Script for Migrating an S3 Service to plusserver S3 Service with Versioning and Object-Lock

This extension of our documentation guides you through the use of migration scripts provided by plusserver for seamlessly transitioning from an existing S3 service to our plusserver S3 service. Our script takes into account important aspects such as versioning, tags, metadata, and, most importantly, essential Object-Lock information.

Step 1: Install and Set Up Minio Client

For the installation and setup of the Minio client and setting up an alias, you can use the following short guide:

  1. You can download the Minio client from the official website.

  2. Execute the following commands to download the Minio client, make it executable, and make it available in your path:

   curl https://dl.min.io/client/mc/release/linux-amd64/mc \
     --create-dirs \
     -o $HOME/minio-binaries/mc

   chmod +x $HOME/minio-binaries/mc
   export PATH=$PATH:$HOME/minio-binaries/

Verify the installation by running the command mc –help. If the Minio client is installed correctly, you will see the help guide.

Step 2: Set Up an Alias

To access your plusserver S3 service, you need to create an alias. Replace ACCESS_KEY and SECRET_KEY with your actual access credentials.

mc alias set plusserver https://s3.de-west-1.psmanaged.com ACCESS_KEY SECRET_KEY

With this alias, you can now access your plusserver S3 storage and transfer files. Repeat this process with your existing S3 storage.

Step 3: Check for Outdated Object-Lock Data

To ensure the migration script works smoothly, it is important to confirm that there are no expired Object-Lock information for your objects. You can check this with the following command:

mc retention info --recursive ALIAS/BUCKET --versions | grep "EXPIRED"

Replace ALIAS with your Alias and BUCKET with the Bucket Name you want to check. If objects with expired Object-Lock information are present, they will look like this:

[ GOVERNANCE EXPIRED ] fe11a6df-af76-c69f-b8d3-5cba2c687bf8 ALIAS/BUCKET/test-governance/file1.txt

In this case, you should either delete the expired Object-Lock information or the affected object, or extend the Object-Lock information into the future. Otherwise, the migration script will not be successful, and an error message will be displayed, as retention cannot be set in the past. Ensure that all objects you want to migrate have valid Object-Lock information.

Step 3a: (Optional) Delete Object-Lock Information

If you want to delete the Object-Lock information of a specific object using the Minio client, you can use the following command:

mc retention clear ALIAS/BUCKET/PATH --version-id VERSIONID

Replace:

  • ALIAS with your alias for the S3 service.
  • BUCKET with the name of the bucket where the object is located.
  • PATH with the path to the object in the bucket.
  • VERSIONID with the ID of the version of the object whose Object-Lock information you want to delete.

By executing this command, the Object-Lock information for the specified object and version will be deleted. Ensure you have the appropriate permissions and authorizations for this action, as deleting Object-Lock information in your S3 service may be restricted.

Step 4: Save the Script to Your System

Download the migration script to your system. This script is used to migrate data from your source profile and source bucket to your destination profile and destination bucket.

migration_script.sh

#!/bin/bash

# Check if the required arguments have been provided
if [ $# -ne 4 ]; then
  echo "Usage: $0 sourceprofile sourcebucket destinationprofil destinationbucket"
  exit 1
fi

SOURCE_PROFILE="$1"
SOURCE_BUCKET="$2"
DESTINATION_PROFILE="$3"
DESTINATION_BUCKET="$4"
LOG_FILE="migration_log.txt"

# Helper function to check application availability
check_application_availablility() {
  # Check if MinIO (mc) is installed
  if ! command -v mc &>/dev/null; then
    echo "Error: MinIO (mc) is not installed."
    exit 1
  fi

  # Check if jq is installed
  if ! command -v jq &>/dev/null; then
    echo "Error: jq is not installed."
    exit 1
  fi
}

copy_tags() {
  local version_id="$1"
  local filename="$2"

  local tags_json=$(mc tag list "$SOURCE_PROFILE/$SOURCE_BUCKET/$filename" --version-id "$version_id" --json)

  # Check if tags are present
  if [[ $tags_json == *"\"tagset\":{"* ]]; then
    # Extract and format tags from JSON
    local formatted_tags=$(echo "$tags_json" | jq -r '.tagset | to_entries | map("\(.key)=\(.value)") | join("&")')
    if [ -n "$formatted_tags" ]; then
      mc tag set "$DESTINATION_PROFILE/$DESTINATION_BUCKET/$filename" "$formatted_tags"
      if [ $? -eq 0 ]; then
        echo "Tags for $filename (Version ID: $version_id) transferred successfully."
      else
        echo "Error setting tags for $filename (Version ID: $version_id). The script will abort."
        exit 1
      fi
    else
      echo "No tags found."
    fi
  else
    echo "No tags found."
  fi
}

# Function to copy a single object
copy_object() {
  local version_id=$1
  local filename="$2"
  local destination_path=$(dirname "$2")/

  if [ "$destination_path" = "./" ]; then
    destination_path=""
  fi

  mc cp --recursive "$SOURCE_PROFILE/$SOURCE_BUCKET/$filename" "$DESTINATION_PROFILE/$DESTINATION_BUCKET/$destination_path" --version-id "$version_id"
  if [ $? -eq 0 ]; then
    echo "Object $filename with Version ID $version_id transferred successfully."
  else
    echo "Error copying $filename (Version ID: $version_id). The script will abort."
    exit 1
  fi
  # Call copy_tags
  copy_tags "$version_id" "$filename"
}

# Main function for migrating buckets
migrate_bucket() {
  local output_file="object_list.txt"
  mc ls --recursive "$SOURCE_PROFILE/$SOURCE_BUCKET" --versions | grep PUT | sort -t "v" -k 2,2n | awk '{print $6 " " $9}'  > "$output_file"

  # Read the file and process the objects
  while IFS= read -r object; do
    local version_id filename
    read -r version_id filename <<< "$object"

    local log_entry="$version_id $filename"
    if [ ! -f "$LOG_FILE" ] || ! grep -q "$log_entry" "$LOG_FILE"; then
      echo "Copy $filename with Version ID $version_id"
      if copy_object "$version_id" "$filename"; then
        echo "$log_entry" >> "$LOG_FILE"
      fi
    fi
  done < "$output_file"
  rm "$output_file"
}

# Call the helper function to check configurations
check_application_availablility
# Start the migration
migrate_bucket

Make the script executable: Ensure that the downloaded script is executable. Use the command chmod +x SCRIPT_NAME, where SCRIPT_NAME is the name of the script.

Run the script as follows:

./SCRIPT_NAME sourceprofile sourcebucket destinationprofile destinationbucket

Please replace sourceprofile, sourcebucket, destinationprofile, and destinationbucket with the corresponding profile and bucket names you want to use for your migration.

After copying the script to your system and making it executable, you can execute it with the correct parameters to start the data migration.

Last modified 03.05.2024: dos2unix mansvc files (d79b1ea)