Class: Pvectl::Commands::CreateSnapshot
- Inherits:
-
Object
- Object
- Pvectl::Commands::CreateSnapshot
- Defined in:
- lib/pvectl/commands/create_snapshot.rb,
sig/pvectl/commands/create_snapshot.rbs
Overview
Handler for the pvectl create snapshot sub-command.
Creates snapshots for VMs/containers. Snapshot name is the first positional argument, VMIDs are specified via --vmid flag. Without --vmid, operates on ALL VMs/CTs in the cluster.
Constant Summary collapse
- VMID_PATTERN =
/\A[1-9]\d{0,8}\z/
Class Method Summary collapse
-
.execute(args, options, global_options) ⇒ Integer
Executes the create snapshot command.
-
.register_subcommand(parent) ⇒ void
Registers as a sub-command under the parent create command.
Instance Method Summary collapse
-
#confirm_operation ⇒ Boolean
Confirms operation with user prompt.
-
#determine_exit_code(results) ⇒ Integer
Determines exit code.
-
#execute ⇒ Integer
Executes the create snapshot command.
-
#initialize(args, options, global_options) ⇒ CreateSnapshot
constructor
Initializes a create snapshot command.
-
#invalid_vmid ⇒ String?
Finds first invalid VMID in options.
-
#load_config ⇒ void
Loads configuration.
-
#output_results(results) ⇒ void
Outputs operation results.
-
#parse_vmids(vmid_values) ⇒ Array<Integer>
Parses --vmid flag values to integer array.
-
#perform_operation ⇒ Integer
Performs the snapshot creation operation.
-
#service_options ⇒ Hash
Builds service options.
-
#usage_error(message) ⇒ Integer
Outputs usage error.
Constructor Details
#initialize(args, options, global_options) ⇒ CreateSnapshot
Initializes a create snapshot command.
86 87 88 89 90 91 92 93 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 86 def initialize(args, , ) @args = Array(args) = = @snapshot_name = @args.first @vmids = parse_vmids([:vmid]) @node = [:node] end |
Class Method Details
.execute(args, options, global_options) ⇒ Integer
Executes the create snapshot command.
77 78 79 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 77 def self.execute(args, , ) new(args, , ).execute end |
.register_subcommand(parent) ⇒ void
This method returns an undefined value.
Registers as a sub-command under the parent create command.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 27 def self.register_subcommand(parent) parent.desc "Create a snapshot of VMs or containers" parent.long_desc " Create a snapshot of one or more VMs or containers. Snapshots capture\n the current state of disks (and optionally RAM) for later rollback.\n\n EXAMPLES\n Snapshot a single VM:\n $ pvectl create snapshot before-upgrade --vmid 100\n\n Snapshot multiple VMs:\n $ pvectl create snapshot before-upgrade --vmid 100 --vmid 101\n\n Snapshot with description and VM memory state:\n $ pvectl create snapshot before-upgrade --vmid 100 --description \"Pre-upgrade\" --vmstate\n\n Snapshot all VMs/containers cluster-wide:\n $ pvectl create snapshot before-upgrade --yes\n\n NOTES\n --vmstate saves the VM's RAM state (QEMU only, not for containers).\n This increases snapshot size but allows resuming from exact state.\n\n Without --vmid, operates cluster-wide (requires --yes confirmation).\n\n SEE ALSO\n pvectl help rollback Rollback to a snapshot\n pvectl help delete snapshot Delete snapshots\n pvectl help get snapshots List existing snapshots\n HELP\n parent.command :snapshot do |s|\n s.desc \"VM/CT ID (repeatable)\"\n s.flag [:vmid], arg_name: \"VMID\", multiple: true\n\n s.desc \"Save VM memory state (QEMU only)\"\n s.switch [:vmstate], negatable: false\n\n s.action do |global_options, options, args|\n exit_code = execute(args, options, global_options)\n exit exit_code if exit_code != 0\n end\n end\nend\n" |
Instance Method Details
#confirm_operation ⇒ Boolean
Confirms operation with user prompt.
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 170 def confirm_operation return true if @vmids.size == 1 return true if [:yes] if @vmids.empty? $stdout.puts "You are about to create snapshot '#{@snapshot_name}' for ALL VMs/CTs in the cluster." else $stdout.puts "You are about to create snapshot '#{@snapshot_name}' for #{@vmids.size} VMs:" @vmids.each { |vmid| $stdout.puts " - #{vmid}" } end $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.
225 226 227 228 229 230 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 225 def determine_exit_code(results) return ExitCodes::SUCCESS if results.all?(&:successful?) return ExitCodes::SUCCESS if results.all?(&:pending?) ExitCodes::GENERAL_ERROR end |
#execute ⇒ Integer
Executes the create snapshot command.
98 99 100 101 102 103 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 98 def execute return usage_error("Snapshot name required") unless @snapshot_name return usage_error("Invalid VMID: #{invalid_vmid}") if invalid_vmid perform_operation end |
#invalid_vmid ⇒ String?
Finds first invalid VMID in options.
120 121 122 123 124 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 120 def invalid_vmid return nil if [:vmid].nil? || [:vmid].empty? Array([:vmid]).find { |v| !VMID_PATTERN.match?(v.to_s) } end |
#load_config ⇒ void
This method returns an undefined value.
Loads configuration.
190 191 192 193 194 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 190 def load_config service = Pvectl::Config::Service.new service.load(config: [:config]) @config = service.current_config end |
#output_results(results) ⇒ void
This method returns an undefined value.
Outputs operation results.
211 212 213 214 215 216 217 218 219 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 211 def output_results(results) presenter = Pvectl::Presenters::SnapshotOperationResult.new format = [:output] || "table" color_flag = [:color] formatter = Pvectl::Formatters::Registry.for(format) output = formatter.format(results, presenter, color: color_flag) puts output end |
#parse_vmids(vmid_values) ⇒ Array<Integer>
Parses --vmid flag values to integer array.
111 112 113 114 115 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 111 def parse_vmids(vmid_values) return [] if vmid_values.nil? || vmid_values.empty? Array(vmid_values).map(&:to_i) end |
#perform_operation ⇒ Integer
Performs the snapshot creation operation.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 129 def perform_operation load_config connection = Pvectl::Connection.new(@config) snapshot_repo = Pvectl::Repositories::Snapshot.new(connection) resolver = Pvectl::Utils::ResourceResolver.new(connection) task_repo = Pvectl::Repositories::Task.new(connection) service = Pvectl::Services::Snapshot.new( snapshot_repo: snapshot_repo, resource_resolver: resolver, task_repo: task_repo, options: ) return ExitCodes::SUCCESS unless confirm_operation results = service.create( @vmids, name: @snapshot_name, description: [:description], vmstate: [:vmstate] || false, node: @node ) 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_options ⇒ Hash
Builds service options.
199 200 201 202 203 204 205 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 199 def opts = {} opts[:timeout] = [:timeout] if [:timeout] opts[:async] = true if [:async] opts[:fail_fast] = true if [:"fail-fast"] opts end |
#usage_error(message) ⇒ Integer
Outputs usage error.
236 237 238 239 |
# File 'lib/pvectl/commands/create_snapshot.rb', line 236 def usage_error() $stderr.puts "Error: #{message}" ExitCodes::USAGE_ERROR end |