Class: Pvectl::Services::Console

Inherits:
Object
  • Object
show all
Defined in:
lib/pvectl/services/console.rb

Overview

Orchestrates an interactive console session to a VM or container.

Handles: authentication (session ticket), termproxy setup, WebSocket URL construction, and terminal session lifecycle.

Examples:

Basic usage

service = Console.new
service.run(resource: vm, resource_path: "qemu/100", server: "https://pve1:8006",
            username: "root@pam", password: "secret", verify_ssl: true)

Defined Under Namespace

Classes: AuthenticationError, ResourceNotRunningError

Instance Method Summary collapse

Instance Method Details

#build_websocket_url(server:, node:, resource_path:, port:, ticket:) ⇒ String

Builds the WebSocket URL for vncwebsocket endpoint.

Parameters:

  • server (String)

    Proxmox server URL (e.g. “pve1:8006”)

  • node (String)

    node name

  • resource_path (String)

    resource path (e.g. “qemu/100” or “lxc/200”)

  • port (Integer)

    termproxy port

  • ticket (String)

    PVEVNC ticket

Returns:

  • (String)

    full WebSocket URL



34
35
36
37
38
39
40
41
42
43
# File 'lib/pvectl/services/console.rb', line 34

def build_websocket_url(server:, node:, resource_path:, port:, ticket:)
  uri = URI.parse(server)
  scheme = uri.scheme == "https" ? "wss" : "ws"
  host = uri.host
  ws_port = uri.port || 8006
  encoded_ticket = URI.encode_www_form_component(ticket)

  "#{scheme}://#{host}:#{ws_port}/api2/json/nodes/#{node}/#{resource_path}/vncwebsocket" \
    "?port=#{port}&vncticket=#{encoded_ticket}"
end

#run(resource:, resource_path:, server:, username:, password:, verify_ssl:) ⇒ void

This method returns an undefined value.

Runs a console session end-to-end.

All API calls (authenticate, termproxy) use the same session-based REST client to ensure PVEVNC ticket and PVEAuthCookie share the same identity. Using a token-based connection for termproxy would generate a ticket bound to the token identity (e.g., “root@pam!pvectl”), which is rejected by the WebSocket endpoint expecting a session cookie for “root@pam”.

Parameters:

  • resource (Models::Vm, Models::Container)

    target resource

  • resource_path (String)

    API path segment (“qemu/vmid” or “lxc/ctid”)

  • server (String)

    Proxmox server URL

  • username (String)

    username for auth

  • password (String)

    password for auth

  • verify_ssl (Boolean)

    SSL verification flag



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
101
102
103
104
105
106
107
# File 'lib/pvectl/services/console.rb', line 73

def run(resource:, resource_path:, server:, username:, password:, verify_ssl:)
  validate_resource_running!(resource)

  # All operations use one session-authenticated REST client
  api_url = "#{server}/api2/json/"
  session_client = RestClient::Resource.new(api_url, verify_ssl: verify_ssl)

  # 1. Authenticate
  auth = authenticate_with_client(session_client, username, password)

  # 2. Open termproxy (using session ticket, not API token)
  termproxy_data = open_termproxy(
    session_client, auth,
    node: resource.node, resource_path: resource_path
  )

  # 3. Build websocket URL
  url = build_websocket_url(
    server: server,
    node: resource.node,
    resource_path: resource_path,
    port: termproxy_data[:port],
    ticket: termproxy_data[:ticket]
  )

  # 4. Run terminal session
  session = Pvectl::Console::TerminalSession.new(
    url: url,
    cookie: "PVEAuthCookie=#{auth[:ticket]}",
    user: termproxy_data[:user],
    ticket: termproxy_data[:ticket],
    verify_ssl: verify_ssl
  )
  session.run
end

#validate_resource_running!(resource) ⇒ void

This method returns an undefined value.

Validates that the resource is in a running state.

Parameters:

Raises:



50
51
52
53
54
55
# File 'lib/pvectl/services/console.rb', line 50

def validate_resource_running!(resource)
  return if resource.status == "running"

  raise ResourceNotRunningError,
        "Resource #{resource.vmid} is not running (status: #{resource.status})"
end