Module: Pvectl::Commands::MoveDiskCommand
- Included in:
- MoveDiskContainer, MoveDiskVm
- Defined in:
- lib/pvectl/commands/move_disk_command.rb,
sig/pvectl/commands/move_disk_command.rbs
Overview
Shared functionality for the move disk commands (move disk vm, move disk ct).
Mirrors the structure of MigrateCommand but operates on a single resource (VM or container) and a single disk/volume rather than a batch.
Defined Under Namespace
Modules: ClassMethods
Constant Summary collapse
- VALID_FORMATS =
Allowed target formats for VM disks (per Proxmox API).
%w[raw qcow2 vmdk].freeze
Class Method Summary collapse
-
.included(base) ⇒ void
Hook called when the module is included.
Instance Method Summary collapse
-
#build_service(connection) ⇒ Services::MoveDisk
Builds the MoveDisk service with required dependencies.
-
#confirm_operation(resource, disk, target) ⇒ Boolean
Confirms the move operation with the user.
-
#disk_label ⇒ String
Returns the human label for the disk/volume.
-
#execute ⇒ Integer
Executes the move disk command.
-
#id_label ⇒ String
Returns the human label for the resource ID ("VMID" or "CTID").
-
#initialize(args, options, global_options) ⇒ MoveDiskCommand
Initializes a move disk command.
-
#load_config ⇒ void
Loads configuration from file or environment.
-
#output_result(result) ⇒ void
Outputs the operation result using the configured formatter.
-
#perform_operation(id, disk, target) ⇒ Integer
Performs the move operation: loads config, resolves resource, prompts, invokes service, prints result.
-
#resolve_resource(connection, id) ⇒ Models::Vm, ...
Resolves the single resource by ID using the appropriate repository.
-
#resource_not_found(id) ⇒ Integer
Outputs "not found" error and returns the not-found exit code.
-
#resource_type_symbol ⇒ Symbol
Returns the resource type symbol (:vm or :container).
-
#service_options ⇒ Hash
Builds service options from command options.
-
#usage_error(message) ⇒ Integer
Outputs usage error and returns the usage exit code.
Class Method Details
.included(base) ⇒ void
This method returns an undefined value.
Hook called when the module is included.
37 38 39 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 37 def self.included(base) base.extend(ClassMethods) end |
Instance Method Details
#build_service(connection) ⇒ Services::MoveDisk
Builds the MoveDisk service with required dependencies.
147 148 149 150 151 152 153 154 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 147 def build_service(connection) Pvectl::Services::MoveDisk.new( vm_repository: Pvectl::Repositories::Vm.new(connection), container_repository: Pvectl::Repositories::Container.new(connection), task_repository: Pvectl::Repositories::Task.new(connection), options: ) end |
#confirm_operation(resource, disk, target) ⇒ Boolean
Confirms the move operation with the user.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 175 def confirm_operation(resource, disk, target) return true if @options[:yes] type_name = resource_type_symbol == :vm ? "VM" : "container" $stdout.puts "You are about to move #{disk} of #{type_name} #{resource.vmid} " \ "(#{resource.name || 'unnamed'}) on #{resource.node} to storage #{target}." $stdout.puts "" if @options[:"delete-source"] $stdout.puts "Source disk WILL be deleted after a successful copy." else $stdout.puts "Source disk will be kept as an unused entry." end $stdout.print "Proceed? [y/N]: " response = $stdin.gets&.strip&.downcase %w[y yes].include?(response) end |
#disk_label ⇒ String
Returns the human label for the disk/volume.
94 95 96 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 94 def disk_label resource_type_symbol == :vm ? "DISK" : "VOLUME" end |
#execute ⇒ Integer
Executes the move disk command.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 55 def execute target = @options[:target] return usage_error("--target is required") if target.nil? || target.to_s.empty? return usage_error("#{id_label} and #{disk_label} are required") if @args.size < 2 id_str, disk = @args[0], @args[1] unless id_str.to_s.match?(/\A\d+\z/) return usage_error("Invalid #{id_label}: #{id_str}") end if @options[:format] return usage_error("--format is not supported for containers") if resource_type_symbol == :container return usage_error("Invalid format: #{@options[:format]} (allowed: #{VALID_FORMATS.join(', ')})") unless VALID_FORMATS.include?(@options[:format]) end perform_operation(id_str.to_i, disk, target) end |
#id_label ⇒ String
Returns the human label for the resource ID ("VMID" or "CTID").
87 88 89 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 87 def id_label resource_type_symbol == :vm ? "VMID" : "CTID" end |
#initialize(args, options, global_options) ⇒ MoveDiskCommand
Initializes a move disk command.
46 47 48 49 50 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 46 def initialize(args, , ) @args = Array(args).compact @options = @global_options = end |
#load_config ⇒ void
This method returns an undefined value.
Loads configuration from file or environment.
196 197 198 199 200 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 196 def load_config service = Pvectl::Config::Service.new service.load(config: @global_options[:config]) @config = service.current_config end |
#output_result(result) ⇒ void
This method returns an undefined value.
Outputs the operation result using the configured formatter.
206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 206 def output_result(result) presenter = if resource_type_symbol == :vm Pvectl::Presenters::VmOperationResult.new else Pvectl::Presenters::ContainerOperationResult.new end format = @global_options[:output] || "table" color_flag = @global_options[:color] formatter = Pvectl::Formatters::Registry.for(format) output = formatter.format([result], presenter, color: color_flag) puts output end |
#perform_operation(id, disk, target) ⇒ Integer
Performs the move operation: loads config, resolves resource, prompts, invokes service, prints result.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 105 def perform_operation(id, disk, target) load_config connection = Pvectl::Connection.new(@config) resource = resolve_resource(connection, id) return resource_not_found(id) if resource.nil? return ExitCodes::SUCCESS unless confirm_operation(resource, disk, target) service = build_service(connection) result = service.execute(resource_type_symbol, resource, disk: disk, target_storage: target) output_result(result) result.failed? ? ExitCodes::GENERAL_ERROR : ExitCodes::SUCCESS rescue Pvectl::Config::ConfigNotFoundError, Pvectl::Config::InvalidConfigError, Pvectl::Config::ContextNotFoundError, Pvectl::Config::ClusterNotFoundError, Pvectl::Config::UserNotFoundError raise rescue StandardError => e $stderr.puts "Error: #{e.}" ExitCodes::GENERAL_ERROR end |
#resolve_resource(connection, id) ⇒ Models::Vm, ...
Resolves the single resource by ID using the appropriate repository.
136 137 138 139 140 141 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 136 def resolve_resource(connection, id) repo = resource_type_symbol == :vm ? Pvectl::Repositories::Vm.new(connection) : Pvectl::Repositories::Container.new(connection) repo.get(id) end |
#resource_not_found(id) ⇒ Integer
Outputs "not found" error and returns the not-found exit code.
233 234 235 236 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 233 def resource_not_found(id) $stderr.puts "Error: No #{resource_type_symbol == :vm ? 'VM' : 'container'} found with ID #{id}" ExitCodes::NOT_FOUND end |
#resource_type_symbol ⇒ Symbol
Returns the resource type symbol (:vm or :container).
80 81 82 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 80 def resource_type_symbol self.class::RESOURCE_TYPE end |
#service_options ⇒ Hash
Builds service options from command options.
159 160 161 162 163 164 165 166 167 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 159 def opts = {} opts[:format] = @options[:format] if @options[:format] opts[:delete_source] = true if @options[:"delete-source"] opts[:bandwidth] = @options[:bandwidth].to_i if @options[:bandwidth] opts[:wait] = true if @options[:wait] opts[:timeout] = @options[:timeout] if @options[:timeout] opts end |
#usage_error(message) ⇒ Integer
Outputs usage error and returns the usage exit code.
224 225 226 227 |
# File 'lib/pvectl/commands/move_disk_command.rb', line 224 def usage_error() $stderr.puts "Error: #{}" ExitCodes::USAGE_ERROR end |