Class: Pvectl::Commands::SendkeyVm
- Inherits:
-
Object
- Object
- Pvectl::Commands::SendkeyVm
- Defined in:
- lib/pvectl/commands/sendkey_vm.rb,
sig/pvectl/commands/sendkey_vm.rbs
Overview
Handler for the pvectl sendkey vm command.
Sends a single QEMU monitor key event to a running VM. The key string
uses QEMU's qcode format (e.g., ctrl-alt-delete, ret, f1) and is
forwarded verbatim to the Proxmox API.
Class Method Summary collapse
-
.execute(args, options, global_options) ⇒ Integer
Executes the sendkey VM command.
-
.register(cli) ⇒ void
Registers the sendkey command with the CLI.
Instance Method Summary collapse
-
#execute ⇒ Integer
Executes the sendkey VM command.
-
#initialize(args, options, global_options) ⇒ SendkeyVm
constructor
Initializes a sendkey VM command.
-
#load_config ⇒ void
Loads configuration from file or environment.
-
#output_result(result) ⇒ void
Outputs the operation result using the configured formatter.
-
#perform_sendkey(vmid, key) ⇒ Integer
Loads the config, builds the service, and dispatches the call.
-
#usage_error(message) ⇒ Integer
Writes a usage error and returns the exit code.
-
#vm_not_found?(result) ⇒ Boolean
Detects the "VM not found" failure case.
Constructor Details
#initialize(args, options, global_options) ⇒ SendkeyVm
Initializes a sendkey VM command.
106 107 108 109 110 |
# File 'lib/pvectl/commands/sendkey_vm.rb', line 106 def initialize(args, , ) @args = Array(args) @options = || {} @global_options = || {} end |
Class Method Details
.execute(args, options, global_options) ⇒ Integer
Executes the sendkey VM command.
97 98 99 |
# File 'lib/pvectl/commands/sendkey_vm.rb', line 97 def self.execute(args, , ) new(args, , ).execute end |
.register(cli) ⇒ void
This method returns an undefined value.
Registers the sendkey command with the CLI.
22 23 24 25 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 |
# File 'lib/pvectl/commands/sendkey_vm.rb', line 22 def self.register(cli) cli.desc "Send a QEMU monitor key event to a VM" cli.long_desc <<~HELP Send a single QEMU monitor key event to a running virtual machine. The key string is forwarded verbatim to the Proxmox API and is interpreted by QEMU using its qcode key format. Common key codes: - ctrl-alt-delete Reboot signal (Linux/Windows) - ctrl-alt-f1..f6 Switch Linux virtual terminals - ret Enter / Return - esc Escape - tab, spc, backspace Single character keys (letters, digits) are also accepted as-is. EXAMPLES Trigger Ctrl+Alt+Del on a running VM: $ pvectl sendkey vm 100 ctrl-alt-delete Send Enter (e.g., dismiss a bootloader prompt): $ pvectl sendkey vm 100 ret Send Escape: $ pvectl sendkey vm 100 esc Switch to TTY 1 on a Linux guest: $ pvectl sendkey vm 100 ctrl-alt-f1 Resolve VM on a specific node: $ pvectl sendkey vm 100 ret --node pve1 NOTES Only VMs are supported — LXC containers do not have a QEMU monitor. The VM must be running. If it is not, the command exits with an error before issuing the API call. Composite keys are dash-separated qcodes (e.g., "ctrl-alt-f1"), not the literal "+" notation. Refer to QEMU's qcode reference for the full list. SEE ALSO pvectl help console vm Interactive console (recommended for sustained typing) pvectl help start Start a stopped VM HELP cli.arg_name "RESOURCE_TYPE ID KEY" cli.command :sendkey do |c| c.desc "Node hosting the VM (used to disambiguate lookup)" c.flag [:node, :n], arg_name: "NODE" c.action do |, , args| resource_type = args.shift exit_code = case resource_type when "vm" SendkeyVm.execute(args, , ) else $stderr.puts "Error: Unknown resource type: #{resource_type}" $stderr.puts "Valid types: vm" ExitCodes::USAGE_ERROR end exit exit_code if exit_code != 0 end end end |
Instance Method Details
#execute ⇒ Integer
Executes the sendkey VM command.
115 116 117 118 119 120 121 122 123 124 |
# File 'lib/pvectl/commands/sendkey_vm.rb', line 115 def execute vmid_arg = @args[0] key = @args[1] return usage_error("VMID is required") if vmid_arg.nil? || vmid_arg.to_s.strip.empty? return usage_error("VMID must be numeric: #{vmid_arg}") unless vmid_arg.to_s.match?(/\A\d+\z/) return usage_error("key argument is required") if key.nil? || key.to_s.strip.empty? perform_sendkey(vmid_arg.to_i, key) end |
#load_config ⇒ void
This method returns an undefined value.
Loads configuration from file or environment.
168 169 170 171 172 |
# File 'lib/pvectl/commands/sendkey_vm.rb', line 168 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.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/pvectl/commands/sendkey_vm.rb', line 178 def output_result(result) # When the VM could not be resolved we have no VM info — write a # plain stderr error instead of a presenter row referencing nil. if result.failed? && result.vm.nil? $stderr.puts "Error: #{result.error}" return end 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) puts output end |
#perform_sendkey(vmid, key) ⇒ Integer
Loads the config, builds the service, and dispatches the call.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/pvectl/commands/sendkey_vm.rb', line 133 def perform_sendkey(vmid, key) load_config connection = Pvectl::Connection.new(@config) vm_repo = Pvectl::Repositories::Vm.new(connection) service = Pvectl::Services::Sendkey.new(vm_repository: vm_repo) result = service.execute(vmid: vmid, key: key, node: @options[:node]) output_result(result) return ExitCodes::NOT_FOUND if vm_not_found?(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 |
#usage_error(message) ⇒ Integer
Writes a usage error and returns the exit code.
199 200 201 202 |
# File 'lib/pvectl/commands/sendkey_vm.rb', line 199 def usage_error() $stderr.puts "Error: #{}" ExitCodes::USAGE_ERROR end |
#vm_not_found?(result) ⇒ Boolean
Detects the "VM not found" failure case.
161 162 163 |
# File 'lib/pvectl/commands/sendkey_vm.rb', line 161 def vm_not_found?(result) result.failed? && result.vm.nil? && result.error.to_s.include?("not found") end |