Class: Pvectl::Services::CloneVm

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

Overview

Orchestrates VM clone operations.

Handles validation, auto-generation of VMID/name, and sync/async modes. Supports both full clones and linked clones (templates only).

Examples:

Full clone with auto-generated VMID

service = CloneVm.new(vm_repository: vm_repo, task_repository: task_repo)
result = service.execute(vmid: 100)

Linked clone to specific node

service = CloneVm.new(vm_repository: vm_repo, task_repository: task_repo)
result = service.execute(vmid: 100, linked: true, target_node: "pve2")

Async clone with custom timeout

service = CloneVm.new(vm_repository: vm_repo, task_repository: task_repo, options: { async: true })
result = service.execute(vmid: 100, new_vmid: 200, name: "web-clone")

Constant Summary collapse

DEFAULT_TIMEOUT =
300
START_TIMEOUT =

Returns Default timeout for start operations (seconds).

Returns:

  • (Integer)

    Default timeout for start operations (seconds)

60

Instance Method Summary collapse

Constructor Details

#initialize(vm_repository:, task_repository:, options: {}) ⇒ CloneVm

Creates a new CloneVm service.

Parameters:

  • vm_repository (Repositories::Vm)

    VM repository

  • task_repository (Repositories::Task)

    Task repository

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

    Options (timeout, async)



33
34
35
36
37
# File 'lib/pvectl/services/clone_vm.rb', line 33

def initialize(vm_repository:, task_repository:, options: {})
  @vm_repository = vm_repository
  @task_repository = task_repository
  @options = options
end

Instance Method Details

#execute(vmid:, node: nil, new_vmid: nil, name: nil, target_node: nil, storage: nil, linked: false, pool: nil, description: nil, config_params: {}) ⇒ Models::OperationResult

Executes clone operation.

Performs a two-step flow: clone the VM first, then optionally apply config updates via PUT /nodes/node/qemu/vmid/config.

Parameters:

  • vmid (Integer)

    Source VM identifier

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

    Source node (auto-detected from VM if nil)

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

    New VMID (auto-selected if nil)

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

    Name for clone (auto-generated if nil)

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

    Target node for clone

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

    Target storage

  • linked (Boolean) (defaults to: false)

    Linked clone (default: false, requires template)

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

    Resource pool

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

    Description

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

    VM config parameters to apply after clone

Returns:



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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/pvectl/services/clone_vm.rb', line 55

def execute(vmid:, node: nil, new_vmid: nil, name: nil, target_node: nil,
            storage: nil, linked: false, pool: nil, description: nil,
            config_params: {})
  source_vm = @vm_repository.get(vmid)
  return vm_not_found_error(vmid) unless source_vm

  if linked && !source_vm.template?
    return linked_clone_error(source_vm)
  end

  node ||= source_vm.node
  new_vmid ||= @vm_repository.next_available_vmid
  name ||= generate_name(source_vm)

  clone_options = build_clone_options(
    name: name, target_node: target_node, storage: storage,
    linked: linked, pool: pool, description: description
  )

  upid = @vm_repository.clone(vmid, node, new_vmid, clone_options)
  resource_info = { new_vmid: new_vmid, name: name, node: target_node || node }

  if @options[:async]
    Models::VmOperationResult.new(
      vm: source_vm, operation: :clone,
      task_upid: upid, success: :pending,
      resource: resource_info
    )
  else
    task = @task_repository.wait(upid, timeout: timeout)

    unless task.successful?
      return Models::VmOperationResult.new(
        vm: source_vm, operation: :clone,
        task: task, success: task.successful?,
        resource: resource_info
      )
    end

    if config_params.any?
      apply_config_update(source_vm, new_vmid, resource_info[:node], config_params, resource_info)
    else
      start_vm(new_vmid, resource_info[:node]) if @options[:start]
      Models::VmOperationResult.new(
        vm: source_vm, operation: :clone,
        task: task, success: true,
        resource: resource_info
      )
    end
  end
rescue StandardError => e
  Models::VmOperationResult.new(
    vm: source_vm, operation: :clone,
    success: false, error: e.message
  )
end