Class: Pvectl::Services::SetVm

Inherits:
Object
  • Object
show all
Defined in:
lib/pvectl/services/set_vm.rb,
sig/pvectl/services/set_vm.rbs

Overview

Orchestrates non-interactive VM configuration updates.

Takes key-value pairs directly (no editor), computes diff against current config, and applies changes via the API. Supports dry-run mode and optimistic locking via digest.

Examples:

Basic usage

service = SetVm.new(vm_repository: repo)
result = service.execute(vmid: 100, params: { memory: "8192", cores: "4" })

Dry run

service = SetVm.new(vm_repository: repo, options: { dry_run: true })
result = service.execute(vmid: 100, params: { memory: "8192" })

Instance Method Summary collapse

Constructor Details

#initialize(vm_repository:, options: {}) ⇒ SetVm

Creates a new SetVm service.

Parameters:

  • VM repository

  • (defaults to: {})

    options (dry_run)

  • (defaults to: {})


24
25
26
27
# File 'lib/pvectl/services/set_vm.rb', line 24

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

Instance Method Details

#build_result(resource_info, **attrs) ⇒ Models::VmOperationResult

Builds a VmOperationResult with the :set operation.

Parameters:

  • resource info (vmid, node, status)

  • additional result attributes

Returns:



112
113
114
115
116
117
# File 'lib/pvectl/services/set_vm.rb', line 112

def build_result(resource_info, **attrs)
  vm = Models::Vm.new(vmid: resource_info[:vmid], node: resource_info[:node])
  Models::VmOperationResult.new(
    operation: :set, vm: vm, resource: resource_info, **attrs
  )
end

#build_update_params(changes, original_config) ⇒ Hash

Builds API update parameters from diff.

Maps changed/added keys to their new values and includes digest from original config for optimistic locking.

Parameters:

  • diff hash with :changed, :added

  • original config (for digest)

Returns:

  • API parameters



99
100
101
102
103
104
105
# File 'lib/pvectl/services/set_vm.rb', line 99

def build_update_params(changes, original_config)
  params = {}
  changes[:changed].each { |key, (_old, new_val)| params[key] = new_val }
  changes[:added].each { |key, val| params[key] = val }
  params[:digest] = original_config[:digest] if original_config[:digest]
  params
end

#compute_diff(config, params) ⇒ Hash

Computes diff between current config and requested params.

Categorizes each requested param as :changed (value differs), :added (key not in current config), or unchanged (skipped).

Parameters:

  • current configuration

  • requested key-value changes

Returns:

  • diff with :changed, :added, :removed keys



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/pvectl/services/set_vm.rb', line 73

def compute_diff(config, params)
  changed = {}
  added = {}

  params.each do |key, value|
    sym_key = key.to_sym
    current = config[sym_key]

    if current.nil?
      added[sym_key] = value
    elsif current.to_s != value.to_s
      changed[sym_key] = [current.to_s, value.to_s]
    end
  end

  { changed: changed, added: added, removed: [] }
end

#execute(vmid:, params:) ⇒ Models::VmOperationResult?

Executes the non-interactive VM config update.

Fetches current config, computes diff against requested params, and applies changes via the API (unless dry-run).

Parameters:

  • VM identifier

  • key-value pairs to set

Returns:

  • result, or nil if no changes



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
# File 'lib/pvectl/services/set_vm.rb', line 37

def execute(vmid:, params:)
  vm = @vm_repository.get(vmid)
  return not_found_result(vmid) unless vm

  config = @vm_repository.fetch_config(vm.node, vmid)
  resource_info = { vmid: vmid, node: vm.node, status: vm.status }

  changes = compute_diff(config, params)

  if changes[:changed].empty? && changes[:added].empty? && changes[:removed].empty?
    return nil
  end

  resource_info[:diff] = changes

  if @options[:dry_run]
    return build_result(resource_info, success: true)
  end

  update_params = build_update_params(changes, config)
  @vm_repository.update(vmid, vm.node, update_params)
  build_result(resource_info, success: true)
rescue StandardError => e
  build_result({ vmid: vmid }, success: false, error: e.message)
end

#not_found_result(vmid) ⇒ Models::VmOperationResult

Builds a not-found error result.

Parameters:

  • VM identifier

Returns:



123
124
125
# File 'lib/pvectl/services/set_vm.rb', line 123

def not_found_result(vmid)
  build_result({ vmid: vmid }, success: false, error: "VM #{vmid} not found")
end