Class: Pvectl::Repositories::Vm

Inherits:
Base
  • Object
show all
Defined in:
lib/pvectl/repositories/vm.rb,
sig/pvectl/repositories/vm.rbs

Overview

Repository for QEMU virtual machines.

Uses the /cluster/resources API endpoint to list VMs across the cluster. Filters to only include QEMU VMs (excludes LXC containers).

Examples:

Listing all VMs

repo = Vm.new(connection)
vms = repo.list
vms.each { |vm| puts "#{vm.vmid}: #{vm.name}" }

Listing VMs on a specific node

vms = repo.list(node: "pve-node1")

Getting a single VM

vm = repo.get(100)
puts vm.name if vm

See Also:

Instance Attribute Summary

Attributes inherited from Base

#connection

Instance Method Summary collapse

Methods inherited from Base

#extract_data, #initialize, #models_from, #unwrap

Constructor Details

This class inherits a constructor from Pvectl::Repositories::Base

Instance Method Details

#build_describe_model(basic_data, describe_data) ⇒ Models::Vm

Builds VM model with describe-specific attributes.

Parameters:

  • basic_data (Hash)

    basic VM data from cluster/resources

  • describe_data (Hash)

    aggregated describe data

Returns:



592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
# File 'lib/pvectl/repositories/vm.rb', line 592

def build_describe_model(basic_data, describe_data)
  Models::Vm.new(
    vmid: basic_data[:vmid],
    name: basic_data[:name],
    status: basic_data[:status],
    node: basic_data[:node],
    cpu: basic_data[:cpu],
    maxcpu: basic_data[:maxcpu],
    mem: basic_data[:mem],
    maxmem: basic_data[:maxmem],
    disk: basic_data[:disk],
    maxdisk: basic_data[:maxdisk],
    uptime: basic_data[:uptime],
    template: basic_data[:template],
    tags: basic_data[:tags],
    hastate: basic_data[:hastate],
    netin: basic_data[:netin],
    netout: basic_data[:netout],
    type: basic_data[:type],
    describe_data: describe_data
  )
end

#build_model(data) ⇒ Models::Vm

Builds Vm model from API response data.

Parameters:

  • data (Hash)

    API response hash with string keys

Returns:



439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/pvectl/repositories/vm.rb', line 439

def build_model(data)
  Models::Vm.new(
    vmid: data[:vmid],
    name: data[:name],
    status: data[:status],
    node: data[:node],
    cpu: data[:cpu],
    maxcpu: data[:maxcpu],
    mem: data[:mem],
    maxmem: data[:maxmem],
    disk: data[:disk],
    maxdisk: data[:maxdisk],
    uptime: data[:uptime],
    template: data[:template],
    tags: data[:tags],
    hastate: data[:hastate],
    netin: data[:netin],
    netout: data[:netout],
    type: data[:type]
  )
end

#clone(vmid, node, new_vmid, options = {}) ⇒ String

Clones a VM to create a new VM.

Posts to /nodes/{node}/qemu/{vmid}/clone with the specified parameters.

Parameters:

  • vmid (Integer, String)

    source VM identifier

  • node (String)

    source node name

  • new_vmid (Integer)

    VMID for the new cloned VM

  • options (Hash) (defaults to: {})

    optional clone parameters

Options Hash (options):

  • :name (String)

    name for the new VM

  • :target (String)

    target node for the clone

  • :storage (String)

    target storage for the clone

  • :full (Boolean)

    full clone (true) or linked clone (false)

  • :description (String)

    description for the new VM

  • :pool (String)

    resource pool for the new VM

Returns:

  • (String)

    Task UPID



187
188
189
190
191
192
193
194
195
196
197
# File 'lib/pvectl/repositories/vm.rb', line 187

def clone(vmid, node, new_vmid, options = {})
  params = { newid: new_vmid }
  params[:name] = options[:name] if options[:name]
  params[:target] = options[:target] if options[:target]
  params[:storage] = options[:storage] if options[:storage]
  params[:full] = options[:full] ? 1 : 0 if options.key?(:full)
  params[:description] = options[:description] if options[:description]
  params[:pool] = options[:pool] if options[:pool]

  connection.client["nodes/#{node}/qemu/#{vmid}/clone"].post(params)
end

#cloudinit_dump(node, vmid, type) ⇒ String

Dumps the generated cloud-init configuration for a VM.

GETs from /nodes/{node}/qemu/{vmid}/cloudinit/dump with the specified type query parameter. Returns the raw YAML/text body.

Parameters:

  • node (String)

    node name

  • vmid (Integer, String)

    VM identifier

  • type (String)

    config type — one of "user", "network", "meta"

Returns:

  • (String)

    cloud-init configuration as raw text



390
391
392
# File 'lib/pvectl/repositories/vm.rb', line 390

def cloudinit_dump(node, vmid, type)
  connection.client["nodes/#{node}/qemu/#{vmid}/cloudinit/dump"].get(params: { type: type })
end

#cloudinit_pending(node, vmid) ⇒ Array<Hash{Symbol => untyped}>

Fetches pending cloud-init configuration changes for a VM.

GETs from /nodes/{node}/qemu/{vmid}/cloudinit. Returns an array of pending entries, each with :key, :value, :pending, and optional :delete keys.

Parameters:

  • node (String)

    node name

  • vmid (Integer, String)

    VM identifier

Returns:

  • (Array<Hash{Symbol => untyped}>)

    pending entries



376
377
378
379
# File 'lib/pvectl/repositories/vm.rb', line 376

def cloudinit_pending(node, vmid)
  response = connection.client["nodes/#{node}/qemu/#{vmid}/cloudinit"].get
  normalize_response(response)
end

#cloudinit_regenerate(node, vmid) ⇒ nil

Regenerates the cloud-init configuration ISO for a VM.

PUTs to /nodes/{node}/qemu/{vmid}/cloudinit. The Proxmox API endpoint returns null on success.

Parameters:

  • node (String)

    node name

  • vmid (Integer, String)

    VM identifier

Returns:

  • (nil)


363
364
365
# File 'lib/pvectl/repositories/vm.rb', line 363

def cloudinit_regenerate(node, vmid)
  connection.client["nodes/#{node}/qemu/#{vmid}/cloudinit"].put
end

#convert_to_template(vmid, node, disk: nil) ⇒ void

This method returns an undefined value.

Converts a VM to a template.

This is an irreversible operation. The VM will become read-only and can only be used as a source for cloning.

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

  • disk (String, nil) (defaults to: nil)

    specific disk to convert (e.g., "scsi0")

  • disk: (String, nil) (defaults to: nil)


208
209
210
211
212
# File 'lib/pvectl/repositories/vm.rb', line 208

def convert_to_template(vmid, node, disk: nil)
  params = {}
  params[:disk] = disk if disk
  connection.client["nodes/#{node}/qemu/#{vmid}/template"].post(params)
end

#create(node, vmid, params = {}) ⇒ String

Creates a new VM on the specified node.

Posts to /nodes/{node}/qemu with the VM configuration parameters. The vmid is merged into params automatically.

Examples:

Create a basic VM

repo.create("pve1", 100, { name: "web-server", cores: 4, memory: 4096 })
#=> "UPID:pve1:..."

Parameters:

  • node (String)

    target node name

  • vmid (Integer)

    VM identifier

  • params (Hash) (defaults to: {})

    VM configuration parameters (name, cores, memory, etc.)

Returns:

  • (String)

    Task UPID



227
228
229
230
# File 'lib/pvectl/repositories/vm.rb', line 227

def create(node, vmid, params = {})
  api_params = params.merge(vmid: vmid)
  connection.client["nodes/#{node}/qemu"].post(api_params)
end

#delete(vmid, node, destroy_disks: true, purge: false, force: false) ⇒ String

Deletes a VM from the cluster.

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

  • destroy_disks (Boolean) (defaults to: true)

    destroy unreferenced disks (default: true)

  • purge (Boolean) (defaults to: false)

    remove from HA, replication, backups (default: false)

  • force (Boolean) (defaults to: false)

    skip lock (default: false)

  • destroy_disks: (Boolean) (defaults to: true)
  • purge: (Boolean) (defaults to: false)
  • force: (Boolean) (defaults to: false)

Returns:

  • (String)

    Task UPID



163
164
165
166
167
168
169
170
# File 'lib/pvectl/repositories/vm.rb', line 163

def delete(vmid, node, destroy_disks: true, purge: false, force: false)
  params = {}
  params["destroy-unreferenced-disks"] = 1 if destroy_disks
  params[:purge] = 1 if purge
  params[:skiplock] = 1 if force

  connection.client["nodes/#{node}/qemu/#{vmid}"].delete(params)
end

#describe(vmid) ⇒ Models::Vm?

Describes a VM with comprehensive details from multiple API endpoints.

Parameters:

  • vmid (Integer, String)

    VM identifier

Returns:

  • (Models::Vm, nil)

    VM model with full details, or nil if not found



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/pvectl/repositories/vm.rb', line 55

def describe(vmid)
  vmid = vmid.to_i

  # 1. Find VM in cluster to get node
  basic_data = find_vm_basic_data(vmid)
  return nil if basic_data.nil?

  node = basic_data[:node]

  # 2. Fetch detailed data from node-specific endpoints
  describe_data = {
    config: fetch_config(node, vmid),
    status: fetch_status(node, vmid),
    snapshots: fetch_snapshots(node, vmid),
    agent_ips: fetch_agent_ips(node, vmid),
    pending: fetch_pending(node, vmid),
    tasks: fetch_tasks(node, vmid),
    firewall: fetch_firewall(node, vmid)
  }

  build_describe_model(basic_data, describe_data)
end

#feature_available?(vmid, node, feature, snapname: nil) ⇒ Hash

Checks whether a feature (clone, snapshot, copy) is available for a VM.

Calls GET /nodes/{node}/qemu/{vmid}/feature with the feature and optional snapshot name. The Proxmox API returns hasFeature (0/1) and a nodes array listing cluster nodes that satisfy the feature.

Examples:

Check whether VM 100 can be cloned

repo.feature_available?(100, "pve1", "clone")
#=> { available: true, nodes: ["pve1", "pve2"] }

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    node currently hosting the VM

  • feature (String)

    feature name (one of: clone, snapshot, copy)

  • snapname (String, nil) (defaults to: nil)

    snapshot name (required for some checks)

  • snapname: (String, nil) (defaults to: nil)

Returns:

  • (Hash)

    result with :available (Boolean) and :nodes (Array)



409
410
411
412
413
414
415
416
417
418
419
420
# File 'lib/pvectl/repositories/vm.rb', line 409

def feature_available?(vmid, node, feature, snapname: nil)
  params = { feature: feature }
  params[:snapname] = snapname unless snapname.nil?

  response = connection.client["nodes/#{node}/qemu/#{vmid}/feature"].get(params: params)
  data = normalize_hash_response(response)

  {
    available: data[:hasFeature].to_i == 1,
    nodes: Array(data[:nodes])
  }
end

#fetch_agent_ips(node, vmid) ⇒ Array<Hash>?

Fetches IP addresses from QEMU guest agent. Graceful failure - returns nil on any error.

Parameters:

  • node (String)

    node name

  • vmid (Integer)

    VM identifier

Returns:

  • (Array<Hash>, nil)

    interfaces or nil on error



512
513
514
515
516
517
518
# File 'lib/pvectl/repositories/vm.rb', line 512

def fetch_agent_ips(node, vmid)
  resp = connection.client["nodes/#{node}/qemu/#{vmid}/agent/network-get-interfaces"].get
  data = normalize_hash_response(resp)
  data[:result]
rescue StandardError
  nil
end

#fetch_config(node, vmid) ⇒ Hash

Fetches VM configuration.

Parameters:

  • node (String)

    node name

  • vmid (Integer)

    VM identifier

Returns:

  • (Hash)

    config data



299
300
301
302
303
304
# File 'lib/pvectl/repositories/vm.rb', line 299

def fetch_config(node, vmid)
  resp = connection.client["nodes/#{node}/qemu/#{vmid}/config"].get
  normalize_hash_response(resp)
rescue StandardError
  {}
end

#fetch_firewall(node, vmid) ⇒ Hash

Fetches firewall configuration (options, rules, aliases, IP sets).

Parameters:

  • node (String)

    node name

  • vmid (Integer)

    VM identifier

Returns:

  • (Hash)

    firewall data with :options, :rules, :aliases, :ipset keys



537
538
539
540
541
542
543
544
545
546
# File 'lib/pvectl/repositories/vm.rb', line 537

def fetch_firewall(node, vmid)
  base = "nodes/#{node}/qemu/#{vmid}/firewall"
  options = (normalize_hash_response(connection.client["#{base}/options"].get) rescue {})
  rules = (normalize_response(connection.client["#{base}/rules"].get) rescue [])
  aliases_data = (normalize_response(connection.client["#{base}/aliases"].get) rescue [])
  ipset = (normalize_response(connection.client["#{base}/ipset"].get) rescue [])
  { options: options, rules: rules, aliases: aliases_data, ipset: ipset }
rescue StandardError
  {}
end

#fetch_pending(node, vmid) ⇒ Array<Hash>

Fetches pending configuration changes.

Parameters:

  • node (String)

    node name

  • vmid (Integer)

    VM identifier

Returns:

  • (Array<Hash>)

    pending changes



525
526
527
528
529
530
# File 'lib/pvectl/repositories/vm.rb', line 525

def fetch_pending(node, vmid)
  resp = connection.client["nodes/#{node}/qemu/#{vmid}/pending"].get
  normalize_response(resp)
rescue StandardError
  []
end

#fetch_snapshots(node, vmid) ⇒ Array<Hash>

Fetches VM snapshots.

Parameters:

  • node (String)

    node name

  • vmid (Integer)

    VM identifier

Returns:

  • (Array<Hash>)

    snapshots list



499
500
501
502
503
504
# File 'lib/pvectl/repositories/vm.rb', line 499

def fetch_snapshots(node, vmid)
  resp = connection.client["nodes/#{node}/qemu/#{vmid}/snapshot"].get
  normalize_response(resp).reject { |s| s[:name] == "current" }
rescue StandardError
  []
end

#fetch_status(node, vmid) ⇒ Hash

Fetches VM runtime status.

Parameters:

  • node (String)

    node name

  • vmid (Integer)

    VM identifier

Returns:

  • (Hash)

    status data



487
488
489
490
491
492
# File 'lib/pvectl/repositories/vm.rb', line 487

def fetch_status(node, vmid)
  resp = connection.client["nodes/#{node}/qemu/#{vmid}/status/current"].get
  normalize_hash_response(resp)
rescue StandardError
  {}
end

#fetch_tasks(node, vmid, limit: 10) ⇒ Array<Models::TaskEntry>

Fetches recent task history for the VM.

Parameters:

  • node (String)

    node name

  • vmid (Integer)

    VM identifier

  • limit (Integer) (defaults to: 10)

    max entries (default 10)

  • limit: (Integer) (defaults to: 10)

Returns:



554
555
556
557
558
559
# File 'lib/pvectl/repositories/vm.rb', line 554

def fetch_tasks(node, vmid, limit: 10)
  task_list_repo = TaskList.new(connection)
  task_list_repo.list(node: node, vmid: vmid, limit: limit)
rescue StandardError
  []
end

#find_vm_basic_data(vmid) ⇒ Hash?

Finds VM basic data from cluster resources.

Parameters:

  • vmid (Integer)

    VM identifier

Returns:

  • (Hash, nil)

    VM data or nil if not found



477
478
479
480
# File 'lib/pvectl/repositories/vm.rb', line 477

def find_vm_basic_data(vmid)
  response = connection.client["cluster/resources"].get(params: { type: "vm" })
  response.find { |r| r[:type] == "qemu" && r[:vmid] == vmid }
end

#get(vmid) ⇒ Models::Vm?

Gets a single VM by VMID.

Parameters:

  • vmid (Integer, String)

    VM identifier

Returns:

  • (Models::Vm, nil)

    VM model or nil if not found



47
48
49
# File 'lib/pvectl/repositories/vm.rb', line 47

def get(vmid)
  list.find { |vm| vm.vmid == vmid.to_i }
end

#list(node: nil) ⇒ Array<Models::Vm>

Lists all VMs in the cluster.

Uses /cluster/resources?type=vm endpoint for efficient cluster-wide listing. Filters to only include QEMU VMs (type == "qemu").

Parameters:

  • node (String, nil) (defaults to: nil)

    filter by node name

  • node: (String, nil) (defaults to: nil)

Returns:



36
37
38
39
40
41
# File 'lib/pvectl/repositories/vm.rb', line 36

def list(node: nil)
  response = connection.client["cluster/resources"].get(params: { type: "vm" })
  vms = response.select { |r| r[:type] == "qemu" }
  vms = vms.select { |r| r[:node] == node } if node
  vms.map { |data| build_model(data) }
end

#migrate(vmid, node, params = {}) ⇒ String

Migrates a VM to another node.

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    current node name

  • params (Hash) (defaults to: {})

    migration parameters (:target, :online, :"with-local-disks", :targetstorage)

Returns:

  • (String)

    Task UPID

Raises:

  • (ArgumentError)

    if node name or vmid format is invalid



313
314
315
316
317
318
319
320
321
322
# File 'lib/pvectl/repositories/vm.rb', line 313

def migrate(vmid, node, params = {})
  unless node.match?(/\A[a-z][a-z0-9-]*\z/)
    raise ArgumentError, "Invalid node name: #{node}"
  end
  unless vmid.is_a?(Integer) && vmid.positive?
    raise ArgumentError, "Invalid VMID: #{vmid}"
  end

  connection.client["nodes/#{node}/qemu/#{vmid}/migrate"].post(params)
end

#move_disk(vmid, node, disk, target_storage, format: nil, delete: false, bwlimit: nil) ⇒ String

Moves a VM disk to a different storage on the same node.

POSTs to /nodes/{node}/qemu/{vmid}/move_disk with the disk identifier and target storage. The operation is asynchronous — the returned UPID can be polled via Repositories::Task to track completion.

Examples:

Move scsi0 to local-lvm storage

repo.move_disk(100, "pve1", "scsi0", "local-lvm")
#=> "UPID:pve1:..."

Move and convert format, delete source

repo.move_disk(100, "pve1", "scsi0", "local-lvm",
               format: "qcow2", delete: true)

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    node name where the VM currently resides

  • disk (String)

    disk identifier (e.g., "scsi0", "virtio0")

  • target_storage (String)

    destination storage ID

  • format (String, nil) (defaults to: nil)

    target disk format ("raw", "qcow2", "vmdk")

  • delete (Boolean) (defaults to: false)

    delete the source disk after copy (default: false)

  • bwlimit (Integer, nil) (defaults to: nil)

    I/O bandwidth limit in KiB/s

  • format: (String, nil) (defaults to: nil)
  • delete: (Boolean) (defaults to: false)
  • bwlimit: (Integer, nil) (defaults to: nil)

Returns:

  • (String)

    Task UPID



346
347
348
349
350
351
352
353
# File 'lib/pvectl/repositories/vm.rb', line 346

def move_disk(vmid, node, disk, target_storage, format: nil, delete: false, bwlimit: nil)
  params = { disk: disk, storage: target_storage }
  params[:format] = format if format
  params[:delete] = 1 if delete
  params[:bwlimit] = bwlimit if bwlimit

  connection.client["nodes/#{node}/qemu/#{vmid}/move_disk"].post(params)
end

#next_available_vmidInteger

Returns the next available VMID from the Proxmox cluster.

Uses the /cluster/nextid API endpoint which performs server-side allocation. This is more reliable than client-side scanning because it detects stale config files that don't appear in /cluster/resources.

Returns:

  • (Integer)

    next available VMID



429
430
431
# File 'lib/pvectl/repositories/vm.rb', line 429

def next_available_vmid
  connection.client["cluster/nextid"].get.to_i
end

#normalize_hash_response(response) ⇒ Hash

Normalizes hash response that may be wrapped in :data key.

Parameters:

  • response (Hash)

    API response

Returns:

  • (Hash)

    normalized hash



565
566
567
568
569
570
571
# File 'lib/pvectl/repositories/vm.rb', line 565

def normalize_hash_response(response)
  if response.is_a?(Hash) && response[:data]
    response[:data]
  else
    response || {}
  end
end

#normalize_response(response) ⇒ Array<Hash>

Normalizes array response.

Parameters:

  • response (Array, Hash)

    API response

Returns:

  • (Array<Hash>)

    normalized array



577
578
579
580
581
582
583
584
585
# File 'lib/pvectl/repositories/vm.rb', line 577

def normalize_response(response)
  if response.is_a?(Array)
    response
  elsif response.is_a?(Hash) && response[:data]
    response[:data]
  else
    response.to_a
  end
end

#post_status(vmid, node, action) ⇒ String

Posts to VM status endpoint.

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

  • action (String)

    Action (start, stop, etc.)

Returns:

  • (String)

    Task UPID



469
470
471
# File 'lib/pvectl/repositories/vm.rb', line 469

def post_status(vmid, node, action)
  connection.client["nodes/#{node}/qemu/#{vmid}/status/#{action}"].post
end

#reset(vmid, node) ⇒ String

Resets a VM (hard reset).

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

Returns:

  • (String)

    Task UPID



123
124
125
# File 'lib/pvectl/repositories/vm.rb', line 123

def reset(vmid, node)
  post_status(vmid, node, "reset")
end

#resize(vmid, node, disk:, size:) ⇒ nil

Resizes a VM disk.

PUTs to /nodes/{node}/qemu/{vmid}/resize with disk and size parameters. Size can be absolute (e.g., "50G") or relative (e.g., "+10G").

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    node name

  • disk (String)

    disk name (e.g., "scsi0", "virtio0")

  • size (String)

    new size or size increment (e.g., "50G", "+10G")

  • disk: (String)
  • size: (String)

Returns:

  • (nil)


255
256
257
# File 'lib/pvectl/repositories/vm.rb', line 255

def resize(vmid, node, disk:, size:)
  connection.client["nodes/#{node}/qemu/#{vmid}/resize"].put({ disk: disk, size: size })
end

#restart(vmid, node) ⇒ String

Restarts a VM (reboot).

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

Returns:

  • (String)

    Task UPID



114
115
116
# File 'lib/pvectl/repositories/vm.rb', line 114

def restart(vmid, node)
  post_status(vmid, node, "reboot")
end

#resume(vmid, node) ⇒ String

Resumes a suspended VM.

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

Returns:

  • (String)

    Task UPID



141
142
143
# File 'lib/pvectl/repositories/vm.rb', line 141

def resume(vmid, node)
  post_status(vmid, node, "resume")
end

#sendkey(vmid, node, key) ⇒ nil

Sends a QEMU monitor key event to a running VM.

PUTs to /nodes/{node}/qemu/{vmid}/sendkey with the key parameter. The key uses QEMU qcode format (e.g., "ctrl-alt-delete", "ret", "f1"). This is a synchronous operation — Proxmox returns null on success.

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    node name

  • key (String)

    QEMU qcode key sequence (e.g., "ctrl-alt-delete")

Returns:

  • (nil)


269
270
271
# File 'lib/pvectl/repositories/vm.rb', line 269

def sendkey(vmid, node, key)
  connection.client["nodes/#{node}/qemu/#{vmid}/sendkey"].put({ key: key })
end

#shutdown(vmid, node) ⇒ String

Shuts down a VM gracefully (ACPI).

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

Returns:

  • (String)

    Task UPID



105
106
107
# File 'lib/pvectl/repositories/vm.rb', line 105

def shutdown(vmid, node)
  post_status(vmid, node, "shutdown")
end

#start(vmid, node) ⇒ String

Starts a VM.

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

Returns:

  • (String)

    Task UPID



87
88
89
# File 'lib/pvectl/repositories/vm.rb', line 87

def start(vmid, node)
  post_status(vmid, node, "start")
end

#stop(vmid, node) ⇒ String

Stops a VM immediately (hard stop).

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

Returns:

  • (String)

    Task UPID



96
97
98
# File 'lib/pvectl/repositories/vm.rb', line 96

def stop(vmid, node)
  post_status(vmid, node, "stop")
end

#suspend(vmid, node) ⇒ String

Suspends a VM (hibernate).

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

Returns:

  • (String)

    Task UPID



132
133
134
# File 'lib/pvectl/repositories/vm.rb', line 132

def suspend(vmid, node)
  post_status(vmid, node, "suspend")
end

#termproxy(vmid, node) ⇒ Hash

Opens a terminal proxy session for a VM.

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    Node name

Returns:

  • (Hash)

    termproxy data with :port, :ticket, :user keys



150
151
152
153
# File 'lib/pvectl/repositories/vm.rb', line 150

def termproxy(vmid, node)
  response = connection.client["nodes/#{node}/qemu/#{vmid}/termproxy"].post({})
  normalize_hash_response(response)
end

Unlinks (removes) one or more disks from a VM configuration.

PUTs to /nodes/{node}/qemu/{vmid}/unlink with the comma-separated list of disk IDs. By default, Proxmox keeps removed volumes as unused[n] entries in the config; with force: true the underlying volume is physically removed.

Parameters:

  • node (String)

    node name

  • vmid (Integer, String)

    VM identifier

  • disk_ids (Array<String>, String)

    disk identifiers (e.g., "scsi0" or %w[scsi0 scsi1] or "scsi0,scsi1")

  • force (Boolean) (defaults to: false)

    physically delete the underlying volume(s) (default: false — keep as unused)

  • force: (Boolean) (defaults to: false)

Returns:

  • (nil)

    this is a synchronous operation and returns no UPID



287
288
289
290
291
292
# File 'lib/pvectl/repositories/vm.rb', line 287

def unlink_disks(node, vmid, disk_ids, force: false)
  idlist = Array(disk_ids).flat_map { |id| id.to_s.split(",") }.map(&:strip).reject(&:empty?).join(",")
  connection.client["nodes/#{node}/qemu/#{vmid}/unlink"].put(
    { idlist: idlist, force: force ? 1 : 0 }
  )
end

#update(vmid, node, params = {}) ⇒ nil

Updates an existing VM configuration.

PUTs to /nodes/{node}/qemu/{vmid}/config with configuration parameters. This is a synchronous operation — changes are applied immediately.

Parameters:

  • vmid (Integer, String)

    VM identifier

  • node (String)

    node name

  • params (Hash) (defaults to: {})

    VM configuration parameters to update

Returns:

  • (nil)


241
242
243
# File 'lib/pvectl/repositories/vm.rb', line 241

def update(vmid, node, params = {})
  connection.client["nodes/#{node}/qemu/#{vmid}/config"].put(params)
end