Class: Pvectl::Commands::UnlinkDiskVm
- Inherits:
-
Object
- Object
- Pvectl::Commands::UnlinkDiskVm
- Defined in:
- lib/pvectl/commands/unlink_disk_vm.rb,
sig/pvectl/commands/unlink_disk_vm.rbs
Overview
Handler for the pvectl unlink disk vm command.
Removes one or more disks from a VM configuration. By default, the
disk entry is converted to unused[n] (the underlying volume is
preserved). With --force, the underlying volume is physically
deleted.
Class Method Summary collapse
-
.execute(args, options, global_options) ⇒ Integer
Executes the unlink disk vm command.
-
.register(cli) ⇒ void
Registers the unlink command with the CLI.
Instance Method Summary collapse
-
#build_repository ⇒ Repositories::Vm
Builds the VM repository.
-
#confirm_operation(vmid, disk_list) ⇒ Boolean
Confirms the unlink operation with the user, if not auto-approved.
-
#execute ⇒ Integer
Executes the unlink disk vm command.
-
#initialize(args, options, global_options) ⇒ UnlinkDiskVm
constructor
A new instance of UnlinkDiskVm.
-
#load_config ⇒ void
Loads configuration.
-
#output_result(result) ⇒ void
Outputs the operation result via the configured formatter.
-
#resolve_node(vmid) ⇒ String?
Resolves the node for a VMID.
-
#usage_error(message) ⇒ Integer
Outputs a usage error message and returns the corresponding exit code.
Constructor Details
#initialize(args, options, global_options) ⇒ UnlinkDiskVm
Returns a new instance of UnlinkDiskVm.
105 106 107 108 109 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 105 def initialize(args, , ) @args = args @options = @global_options = end |
Class Method Details
.execute(args, options, global_options) ⇒ Integer
Executes the unlink disk vm command.
98 99 100 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 98 def self.execute(args, , ) new(args, , ).execute end |
.register(cli) ⇒ void
This method returns an undefined value.
Registers the unlink command with the CLI.
26 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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 26 def self.register(cli) cli.desc "Unlink a disk from a resource" cli.long_desc <<~HELP DESCRIPTION Remove one or more disks from a VM configuration. By default, the disk entry is moved to `unused[n]` in the VM config — the underlying volume is preserved so it can be re-attached or inspected later. With --force, the underlying volume is physically deleted and cannot be recovered. Multiple disks may be removed in a single call by passing a comma-separated list (e.g. "scsi1,virtio0"). EXAMPLES Soft unlink (keeps the volume as unused0): $ pvectl unlink disk vm 100 scsi1 Unlink multiple disks at once: $ pvectl unlink disk vm 100 scsi1,virtio0 Permanently delete the underlying volume: $ pvectl unlink disk vm 100 scsi1 --force --yes Skip confirmation prompt: $ pvectl unlink disk vm 100 scsi1 -y NOTES --force is destructive: the underlying volume is removed and cannot be recovered. Without --force, the volume can be re-attached later (e.g. via `pvectl set vm`). The command operates only on QEMU virtual machines; LXC containers are not supported by the Proxmox /unlink endpoint. SEE ALSO pvectl help describe vm Show VM configuration including disks pvectl help edit volume Edit volume properties interactively pvectl help set vm Modify VM configuration (re-attach unused) HELP cli.arg_name "RESOURCE_TYPE ID DISK_LIST" cli.command :unlink do |c| c.desc "Skip confirmation prompt" c.switch [:yes, :y], negatable: false c.desc "Physically delete the underlying volume(s)" c.switch [:force], negatable: false c.action do |, , args| resource_type = args.shift scope = args.shift exit_code = case [resource_type, scope] when %w[disk vm] Commands::UnlinkDiskVm.execute(args, , ) else $stderr.puts "Error: Unknown unlink target: #{resource_type} #{scope}".strip $stderr.puts "Valid form: unlink disk vm <id> <disk_list>" ExitCodes::USAGE_ERROR end exit exit_code if exit_code != 0 end end end |
Instance Method Details
#build_repository ⇒ Repositories::Vm
Builds the VM repository.
182 183 184 185 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 182 def build_repository connection = Pvectl::Connection.new(@config) Pvectl::Repositories::Vm.new(connection) end |
#confirm_operation(vmid, disk_list) ⇒ Boolean
Confirms the unlink operation with the user, if not auto-approved.
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 192 def confirm_operation(vmid, disk_list) return true if @options[:yes] $stdout.puts "About to unlink disk(s) #{disk_list} from VM #{vmid}." if @options[:force] $stdout.puts "" $stdout.puts "WARNING: --force will delete the underlying volume(s) permanently." $stdout.puts "" end $stdout.print "Proceed? [y/N]: " $stdout.flush answer = $stdin.gets&.strip&.downcase answer == "y" end |
#execute ⇒ Integer
Executes the unlink disk vm command.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 114 def execute vmid_arg = @args[0] disk_list = @args[1] return usage_error("VMID required") if vmid_arg.nil? || vmid_arg.to_s.empty? return usage_error("Disk list required (e.g., scsi1 or scsi1,virtio0)") if disk_list.nil? || disk_list.to_s.empty? return usage_error("Invalid VMID: #{vmid_arg}") unless vmid_arg.to_s.match?(/\A\d+\z/) vmid = vmid_arg.to_i load_config node = resolve_node(vmid) return ExitCodes::NOT_FOUND if node.nil? return ExitCodes::SUCCESS unless confirm_operation(vmid, disk_list) repo = build_repository service = Pvectl::Services::UnlinkDisk.new(repository: repo) result = service.execute( vmid: vmid, node: node, disk_ids: disk_list, force: @options[:force] == true ) 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 |
#load_config ⇒ void
This method returns an undefined value.
Loads configuration.
156 157 158 159 160 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 156 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 via the configured formatter.
212 213 214 215 216 217 218 219 220 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 212 def output_result(result) presenter = Pvectl::Presenters::VmOperationResult.new format = @global_options[:output] || "table" color_flag = @global_options[:color] formatter = Pvectl::Formatters::Registry.for(format) output = formatter.format([result], presenter, color: color_flag) $stdout.puts output end |
#resolve_node(vmid) ⇒ String?
Resolves the node for a VMID.
166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 166 def resolve_node(vmid) connection = Pvectl::Connection.new(@config) resolver = Pvectl::Utils::ResourceResolver.new(connection) resolved = resolver.resolve(vmid) unless resolved && resolved[:type] == :qemu $stderr.puts "Error: VM #{vmid} not found" return nil end resolved[:node] end |
#usage_error(message) ⇒ Integer
Outputs a usage error message and returns the corresponding exit code.
226 227 228 229 |
# File 'lib/pvectl/commands/unlink_disk_vm.rb', line 226 def usage_error() $stderr.puts "Error: #{}" ExitCodes::USAGE_ERROR end |