Class: Pvectl::Commands::CreateBackup

Inherits:
Object
  • Object
show all
Defined in:
lib/pvectl/commands/create_backup.rb,
sig/pvectl/commands/create_backup.rbs

Overview

Handler for the pvectl create backup command.

Creates backups for one or more VMs/containers. Supports multiple VMIDs with optional confirmation prompt.

Examples:

Create single backup

pvectl create backup 100 --storage local

Create backup for multiple VMs

pvectl create backup 100 101 102 --storage nfs --mode snapshot

Create backup with options

pvectl create backup 100 --storage local --compress zstd --notes "Pre-upgrade" --protected

Constant Summary collapse

SUPPORTED_RESOURCES =
%w[backup].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(resource_type, resource_ids, options, global_options) ⇒ CreateBackup

Initializes a create backup command.



39
40
41
42
43
44
# File 'lib/pvectl/commands/create_backup.rb', line 39

def initialize(resource_type, resource_ids, options, global_options)
  @resource_type = resource_type
  @resource_ids = Array(resource_ids).compact.map(&:to_i)
  @options = options
  @global_options = global_options
end

Class Method Details

.execute(resource_type, resource_ids, options, global_options) ⇒ Integer

Executes the create backup command.



29
30
31
# File 'lib/pvectl/commands/create_backup.rb', line 29

def self.execute(resource_type, resource_ids, options, global_options)
  new(resource_type, resource_ids, options, global_options).execute
end

Instance Method Details

#confirm_operationBoolean

Confirms multi-VMID operation with user.



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/pvectl/commands/create_backup.rb', line 105

def confirm_operation
  return true if @resource_ids.size == 1
  return true if @options[:yes]

  $stdout.puts "You are about to create backups for #{@resource_ids.size} VMs:"
  @resource_ids.each { |vmid| $stdout.puts "  - #{vmid}" }
  $stdout.puts ""
  $stdout.print "Proceed? [y/N]: "

  response = $stdin.gets&.strip&.downcase
  %w[y yes].include?(response)
end

#determine_exit_code(results) ⇒ Integer

Determines exit code based on results.



156
157
158
159
160
161
# File 'lib/pvectl/commands/create_backup.rb', line 156

def determine_exit_code(results)
  return ExitCodes::SUCCESS if results.all?(&:successful?)
  return ExitCodes::SUCCESS if results.all?(&:pending?)

  ExitCodes::GENERAL_ERROR
end

#executeInteger

Executes the create backup command.



49
50
51
52
53
54
55
56
# File 'lib/pvectl/commands/create_backup.rb', line 49

def execute
  return usage_error("Resource type required (backup)") unless @resource_type
  return usage_error("Unsupported resource: #{@resource_type}") unless SUPPORTED_RESOURCES.include?(@resource_type)
  return usage_error("At least one VMID is required") if @resource_ids.empty?
  return usage_error("--storage is required") unless @options[:storage]

  perform_operation
end

#load_configvoid

This method returns an undefined value.

Loads configuration from file or environment.



121
122
123
124
125
# File 'lib/pvectl/commands/create_backup.rb', line 121

def load_config
  service = Pvectl::Config::Service.new
  service.load(config: @global_options[:config])
  @config = service.current_config
end

#output_results(results) ⇒ void

This method returns an undefined value.

Outputs operation results using the configured formatter.



142
143
144
145
146
147
148
149
150
# File 'lib/pvectl/commands/create_backup.rb', line 142

def output_results(results)
  presenter = Pvectl::Presenters::SnapshotOperationResult.new
  format = @global_options[:output] || "table"
  color_flag = @global_options[:color]

  formatter = Pvectl::Formatters::Registry.for(format)
  output = formatter.format(results, presenter, color: color_flag)
  puts output
end

#perform_operationInteger

Performs the backup creation operation.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/pvectl/commands/create_backup.rb', line 63

def perform_operation
  load_config
  connection = Pvectl::Connection.new(@config)

  backup_repo = Pvectl::Repositories::Backup.new(connection)
  resolver = Pvectl::Utils::ResourceResolver.new(connection)
  task_repo = Pvectl::Repositories::Task.new(connection)

  service = Pvectl::Services::Backup.new(
    backup_repo: backup_repo,
    resource_resolver: resolver,
    task_repo: task_repo,
    options: service_options
  )

  return ExitCodes::SUCCESS unless confirm_operation

  results = service.create(
    @resource_ids,
    storage: @options[:storage],
    mode: @options[:mode] || "snapshot",
    compress: @options[:compress] || "zstd",
    notes: @options[:notes],
    protected: @options[:protected] || false
  )

  output_results(results)
  determine_exit_code(results)
rescue Pvectl::Config::ConfigNotFoundError,
       Pvectl::Config::InvalidConfigError,
       Pvectl::Config::ContextNotFoundError,
       Pvectl::Config::ClusterNotFoundError,
       Pvectl::Config::UserNotFoundError
  raise
rescue StandardError => e
  $stderr.puts "Error: #{e.message}"
  ExitCodes::GENERAL_ERROR
end

#service_optionsHash

Builds service options from command options.



130
131
132
133
134
135
136
# File 'lib/pvectl/commands/create_backup.rb', line 130

def service_options
  opts = {}
  opts[:timeout] = @options[:timeout] if @options[:timeout]
  opts[:async] = true if @options[:async]
  opts[:fail_fast] = true if @options[:"fail-fast"]
  opts
end

#usage_error(message) ⇒ Integer

Outputs usage error and returns exit code.



167
168
169
170
# File 'lib/pvectl/commands/create_backup.rb', line 167

def usage_error(message)
  $stderr.puts "Error: #{message}"
  ExitCodes::USAGE_ERROR
end