Skip to content

Snapshot Policies Example

This example demonstrates how to create and manage automated snapshot policies on Qumulo clusters using the qumulo_snapshot_policy resource. Snapshot policies automate point-in-time data protection.

Features

Five snapshot schedule types are demonstrated:

  1. Daily - Snapshots at a specific time each day
  2. Hourly - Snapshots within business hours windows
  3. Weekly - Snapshots on specific days of the week
  4. Monthly - Snapshots on a specific day of the month
  5. Multi-department - Using for_each for bulk policy management

Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                         SNAPSHOT POLICY OVERVIEW                             │
└─────────────────────────────────────────────────────────────────────────────┘

                            QUMULO CLUSTER
┌─────────────────────────────────────────────────────────────────────────────┐
│                                                                             │
│   SNAPSHOT POLICIES (automated schedules)                                   │
│                                                                             │
│   ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐            │
│   │ daily-backup    │  │ business-hours  │  │ monthly-archive │            │
│   │ 2:00 AM daily   │  │ Hourly 9-5 M-F  │  │ 1st of month    │            │
│   │ Retain: 7 days  │  │ Retain: 24 hrs  │  │ Retain: forever │            │
│   └────────┬────────┘  └────────┬────────┘  └────────┬────────┘            │
│            │                    │                    │                      │
│            ▼                    ▼                    ▼                      │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │                        FILESYSTEM                                   │  │
│   │                                                                     │  │
│   │  /data ─────────────────► .snapshot/                               │  │
│   │                            ├── daily-backup_2024-01-15_02-00       │  │
│   │                            ├── daily-backup_2024-01-16_02-00       │  │
│   │                            ├── business-hours_2024-01-16_09-00     │  │
│   │                            ├── business-hours_2024-01-16_10-00     │  │
│   │                            └── monthly-archive_2024-01-01_00-00    │  │
│   │                                                                     │  │
│   │  /projects ─────────────► .snapshot/ (separate namespace)          │  │
│   │                                                                     │  │
│   │  /compliance-data ──────► .snapshot/ (90-day retention)            │  │
│   │                                                                     │  │
│   └─────────────────────────────────────────────────────────────────────┘  │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

    SNAPSHOT LIFECYCLE

    ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
    │  Create  │───►│  Active  │───►│  Expire  │───►│  Delete  │
    │(schedule)│    │ (retain) │    │  (TTL)   │    │(cleanup) │
    └──────────┘    └──────────┘    └──────────┘    └──────────┘

Prerequisites

  1. Qumulo cluster with REST API access (port 8000)
  2. Admin credentials for the cluster
  3. Existing filesystem paths for snapshot sources (or create them)

Usage

  1. Create a terraform.tfvars file:
cluster_endpoint = "https://cluster.example.com:8000"
cluster_username = "admin"
cluster_password = "cluster-admin-password"

# Optional: Configure per-department policies
department_snapshot_config = {
  engineering = {
    path      = "/departments/engineering"
    hour      = 3
    retention = "14days"
  }
  marketing = {
    path      = "/departments/marketing"
    hour      = 4
    retention = "7days"
  }
  research = {
    path      = "/departments/research"
    hour      = 5
    retention = "30days"
  }
}
  1. Initialize and apply:
terraform init -upgrade
terraform plan
terraform apply

Variables

Name Description Type Default
cluster_endpoint Qumulo cluster REST API endpoint string -
cluster_username Qumulo cluster admin username string "admin"
cluster_password Qumulo cluster admin password string -
department_snapshot_config Map of department names to snapshot config map(object) See example

Department Config Object

{
  path      = string  # Filesystem path to snapshot
  hour      = number  # Hour of day (0-23) to take snapshot
  retention = string  # Retention period (e.g., "7days", "24hours")
}

Outputs

Name Description
daily_backup_policy_id ID of the daily backup snapshot policy
daily_backup_schedule_id Schedule ID of the daily backup policy
daily_backup_source_file_id Resolved file ID for the daily backup source path
business_hours_policy_id ID of the business hours snapshot policy
monthly_archive_policy_id ID of the monthly archive snapshot policy
department_policy_ids Map of department names to their policy IDs

Schedule Types

Daily Snapshots

Take a snapshot every day at a specific time:

resource "qumulo_snapshot_policy" "daily" {
  connection_profile = "cluster1"

  policy_name = "daily-backup"
  source_path = "/data"

  schedule {
    timezone                = "America/Los_Angeles"
    frequency               = "SCHEDULE_DAILY_OR_WEEKLY"
    hour                    = 2
    minute                  = 0
    on_days                 = ["EVERY_DAY"]
    expiration_time_to_live = "7days"
  }
}

Hourly Snapshots (Business Hours)

Take snapshots every hour during specific windows:

resource "qumulo_snapshot_policy" "hourly" {
  connection_profile = "cluster1"

  policy_name = "business-hours"
  source_path = "/projects"

  schedule {
    timezone                = "UTC"
    frequency               = "SCHEDULE_HOURLY_OR_LESS"
    on_days                 = ["MON", "TUE", "WED", "THU", "FRI"]
    window_start_hour       = 9
    window_start_minute     = 0
    window_end_hour         = 17
    window_end_minute       = 0
    fire_every_interval     = "FIRE_IN_HOURS"
    fire_every              = 1
    expiration_time_to_live = "24hours"
  }
}

Weekly Snapshots

Take snapshots on specific days:

resource "qumulo_snapshot_policy" "weekly" {
  connection_profile = "cluster1"

  policy_name = "weekly-compliance"
  source_path = "/compliance-data"

  schedule {
    timezone                = "UTC"
    frequency               = "SCHEDULE_DAILY_OR_WEEKLY"
    hour                    = 0
    minute                  = 0
    on_days                 = ["SUN"]
    expiration_time_to_live = "90days"
  }
}

Monthly Snapshots

Take snapshots on a specific day of the month:

resource "qumulo_snapshot_policy" "monthly" {
  connection_profile = "cluster1"

  policy_name    = "monthly-archive"
  source_file_id = "2"  # Root directory

  schedule {
    timezone                = "UTC"
    frequency               = "SCHEDULE_MONTHLY"
    day_of_month            = 1
    hour                    = 0
    minute                  = 0
    expiration_time_to_live = "never"
  }
}

Bulk Policies with for_each

Manage multiple policies with a single resource block:

variable "department_config" {
  type = map(object({
    path      = string
    hour      = number
    retention = string
  }))
}

resource "qumulo_snapshot_policy" "departments" {
  for_each = var.department_config

  connection_profile = "cluster1"

  policy_name = "${each.key}-daily-backup"
  source_path = each.value.path

  schedule {
    timezone                = "UTC"
    frequency               = "SCHEDULE_DAILY_OR_WEEKLY"
    hour                    = each.value.hour
    minute                  = 0
    on_days                 = ["EVERY_DAY"]
    expiration_time_to_live = each.value.retention
  }
}

Schedule Reference

Frequency Options

Frequency Description
SCHEDULE_HOURLY_OR_LESS Sub-daily intervals within a time window
SCHEDULE_DAILY_OR_WEEKLY Daily or specific days of the week
SCHEDULE_MONTHLY Specific day of the month

Day Options

Value Description
EVERY_DAY All days (for daily frequency)
MON, TUE, WED, THU, FRI Weekdays
SAT, SUN Weekend days

Retention Formats

Format Example Description
Hours 24hours Retain for 24 hours
Days 7days Retain for 7 days
Weeks 4weeks Retain for 4 weeks
Never never Never expire (permanent)

Security Considerations

  1. Retention Policies: Balance retention with storage costs. Longer retention requires more space.

  2. Compliance: For regulatory compliance, use "never" expiration and separate policies for compliance data.

  3. Access Control: Snapshots inherit permissions from the source directory. Users with read access can browse .snapshot directories.

  4. Recovery Testing: Regularly test snapshot recovery to ensure data can be restored when needed.

  5. Off-cluster Copies: Snapshots protect against user error but not hardware failure. Combine with replication for disaster recovery.

Full Configuration

# Example: Managing Snapshot Policies on a Qumulo Cluster
#
# This example demonstrates how to create and manage snapshot policies
# on an existing Qumulo cluster using the qumulo_snapshot_policy resource.
# Snapshot policies automate the creation of point-in-time snapshots on a schedule.

terraform {
  required_providers {
    qumulo = {
      source  = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
      version = "~> 1.0"
    }
  }
}

variable "cluster_endpoint" {
  description = "Qumulo cluster REST API endpoint (e.g., https://cluster:8000)"
  type        = string
}

variable "cluster_username" {
  description = "Qumulo cluster admin username"
  type        = string
  default     = "admin"
}

variable "cluster_password" {
  description = "Qumulo cluster admin password"
  type        = string
  sensitive   = true
}

# Define connection profile for the cluster
provider "qumulo" {
  connection_profiles = [
    {
      name                 = "cluster1"
      endpoint             = var.cluster_endpoint
      username             = var.cluster_username
      password             = var.cluster_password
      insecure_skip_verify = true # Required for clusters with self-signed certificates
    }
  ]
}

# -----------------------------------------------------------------------------
# Daily Backup Policy (using source_path)
# Takes a snapshot every day at 2 AM, keeps snapshots for 7 days
# -----------------------------------------------------------------------------
resource "qumulo_snapshot_policy" "daily_backup" {
  connection_profile = "cluster1"

  policy_name = "daily-backup"
  source_path = "/data" # Automatically resolved to file ID

  schedule {
    timezone                = "America/Los_Angeles"
    frequency               = "SCHEDULE_DAILY_OR_WEEKLY"
    hour                    = 2
    minute                  = 0
    on_days                 = ["EVERY_DAY"]
    expiration_time_to_live = "7days"
  }
}

# -----------------------------------------------------------------------------
# Business Hours Policy (hourly snapshots)
# Takes a snapshot every hour during business hours on weekdays
# -----------------------------------------------------------------------------
resource "qumulo_snapshot_policy" "business_hours" {
  connection_profile = "cluster1"

  policy_name = "business-hours"
  source_path = "/projects"

  schedule {
    timezone                = "UTC"
    frequency               = "SCHEDULE_HOURLY_OR_LESS"
    on_days                 = ["MON", "TUE", "WED", "THU", "FRI"]
    window_start_hour       = 9
    window_start_minute     = 0
    window_end_hour         = 17
    window_end_minute       = 0
    fire_every_interval     = "FIRE_IN_HOURS"
    fire_every              = 1
    expiration_time_to_live = "24hours"
  }
}

# -----------------------------------------------------------------------------
# Monthly Archive Policy (using source_file_id)
# Takes a snapshot on the 1st of each month, never expires
# -----------------------------------------------------------------------------
resource "qumulo_snapshot_policy" "monthly_archive" {
  connection_profile = "cluster1"

  policy_name    = "monthly-archive"
  source_file_id = "2" # Root directory, use source_path for most cases

  schedule {
    timezone                = "UTC"
    frequency               = "SCHEDULE_MONTHLY"
    day_of_month            = 1
    hour                    = 0
    minute                  = 0
    expiration_time_to_live = "never"
  }
}

# -----------------------------------------------------------------------------
# Weekly Compliance Policy
# Takes a snapshot every Sunday at midnight for compliance retention
# -----------------------------------------------------------------------------
resource "qumulo_snapshot_policy" "weekly_compliance" {
  connection_profile = "cluster1"

  policy_name = "weekly-compliance"
  source_path = "/compliance-data"

  schedule {
    timezone                = "UTC"
    frequency               = "SCHEDULE_DAILY_OR_WEEKLY"
    hour                    = 0
    minute                  = 0
    on_days                 = ["SUN"]
    expiration_time_to_live = "90days"
  }
}

# -----------------------------------------------------------------------------
# Department Snapshot Policies using for_each
# Demonstrates managing multiple policies with a single resource block
# -----------------------------------------------------------------------------
variable "department_snapshot_config" {
  description = "Map of department names to their snapshot configuration"
  type = map(object({
    path      = string
    hour      = number
    retention = string
  }))
  default = {
    engineering = {
      path      = "/departments/engineering"
      hour      = 3
      retention = "14days"
    }
    marketing = {
      path      = "/departments/marketing"
      hour      = 4
      retention = "7days"
    }
    research = {
      path      = "/departments/research"
      hour      = 5
      retention = "30days"
    }
  }
}

resource "qumulo_snapshot_policy" "departments" {
  for_each = var.department_snapshot_config

  connection_profile = "cluster1"

  policy_name = "${each.key}-daily-backup"
  source_path = each.value.path

  schedule {
    timezone                = "UTC"
    frequency               = "SCHEDULE_DAILY_OR_WEEKLY"
    hour                    = each.value.hour
    minute                  = 0
    on_days                 = ["EVERY_DAY"]
    expiration_time_to_live = each.value.retention
  }
}

# -----------------------------------------------------------------------------
# Multi-Cluster Example
# Demonstrates managing snapshot policies across multiple clusters
# -----------------------------------------------------------------------------
variable "clusters" {
  description = "Map of cluster names to their connection configuration"
  type = map(object({
    endpoint = string
    username = string
    password = string
  }))
  default = {}
}

# Note: To use multi-cluster, configure connection_profiles dynamically:
# provider "qumulo" {
#   connection_profiles = [
#     for name, config in var.clusters : {
#       name     = name
#       endpoint = config.endpoint
#       username = config.username
#       password = config.password
#     }
#   ]
# }
#
# resource "qumulo_snapshot_policy" "multi_cluster_backup" {
#   for_each = var.clusters
#
#   connection_profile = each.key
#
#   policy_name = "standard-backup"
#   source_path = "/data"
#
#   schedule {
#     timezone                = "UTC"
#     frequency               = "SCHEDULE_DAILY_OR_WEEKLY"
#     hour                    = 3
#     minute                  = 0
#     on_days                 = ["EVERY_DAY"]
#     expiration_time_to_live = "14days"
#   }
# }

# -----------------------------------------------------------------------------
# Outputs
# -----------------------------------------------------------------------------
output "daily_backup_policy_id" {
  description = "ID of the daily backup snapshot policy"
  value       = qumulo_snapshot_policy.daily_backup.id
}

output "daily_backup_schedule_id" {
  description = "Schedule ID of the daily backup policy"
  value       = qumulo_snapshot_policy.daily_backup.schedule_id
}

output "daily_backup_source_file_id" {
  description = "Resolved file ID for the daily backup source path"
  value       = qumulo_snapshot_policy.daily_backup.source_file_id
}

output "business_hours_policy_id" {
  description = "ID of the business hours snapshot policy"
  value       = qumulo_snapshot_policy.business_hours.id
}

output "monthly_archive_policy_id" {
  description = "ID of the monthly archive snapshot policy"
  value       = qumulo_snapshot_policy.monthly_archive.id
}

output "department_policy_ids" {
  description = "Map of department names to their snapshot policy IDs"
  value       = { for k, v in qumulo_snapshot_policy.departments : k => v.id }
}