Class: Pvectl::Services::SetVolume

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

Overview

Orchestrates non-interactive volume property updates.

Handles two types of changes:

  1. Size changes — delegates to ResizeVolume service (irreversible)
  2. Config changes (cache, discard, ssd, etc.) — rebuilds volume config string

Examples:

Resize only

service = SetVolume.new(repository: vm_repo, resource_type: :vm)
result = service.execute(id: 100, disk: "scsi0", params: { "size" => "+10G" }, node: "pve1")

Config change

service.execute(id: 100, disk: "scsi0", params: { "cache" => "writeback" }, node: "pve1")

Mixed (size + config)

service.execute(id: 100, disk: "scsi0",
  params: { "size" => "+10G", "cache" => "writeback" }, node: "pve1")

Instance Method Summary collapse

Constructor Details

#initialize(repository:, resource_type:) ⇒ SetVolume



25
26
27
28
# File 'lib/pvectl/services/set_volume.rb', line 25

def initialize(repository:, resource_type:)
  @repository = repository
  @resource_type = resource_type
end

Instance Method Details

#build_result(id, disk, node, **attrs) ⇒ Models::VolumeOperationResult

Builds a VolumeOperationResult with volume metadata.



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/pvectl/services/set_volume.rb', line 113

def build_result(id, disk, node, **attrs)
  volume = Models::Volume.new(
    name: disk,
    resource_type: @resource_type.to_s,
    resource_id: id,
    node: node
  )
  Models::VolumeOperationResult.new(
    operation: :set, volume: volume, **attrs
  )
end

#execute(id:, disk:, params:, node:) ⇒ Models::VolumeOperationResult

Executes the volume property update.

Separates size param (delegated to ResizeVolume) from config params (rebuilt into the disk config string). Both can be applied in a single call.



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

def execute(id:, disk:, params:, node:)
  config = @repository.fetch_config(node, id)
  disk_value = config[disk.to_sym]

  unless disk_value
    return build_result(id, disk, node, success: false,
                        error: "Volume '#{disk}' not found in config for resource #{id}")
  end

  # Separate size from config params (dup to avoid mutating caller's hash)
  params = params.dup
  size_param = params.delete("size") || params.delete(:size)
  config_params = params

  # Handle size change (resize)
  if size_param
    parsed_size = ResizeVolume.parse_size(size_param)
    resize_service = ResizeVolume.new(repository: @repository)
    resize_service.preflight(id, disk, parsed_size, node: node)
    resize_service.perform(id, disk, parsed_size.raw, node: node)
  end

  # Handle config changes (cache, discard, ssd, iothread, backup)
  unless config_params.empty?
    new_disk_value = rebuild_disk_config(disk_value, config_params)
    @repository.update(id, node, { disk.to_sym => new_disk_value })
  end

  build_result(id, disk, node, success: true)
rescue ResizeVolume::VolumeNotFoundError, ResizeVolume::SizeTooSmallError, ArgumentError => e
  build_result(id, disk, node, success: false, error: e.message)
rescue StandardError => e
  build_result(id, disk, node, success: false, error: e.message)
end

#rebuild_disk_config(current_value, updates) ⇒ String

Rebuilds a disk config string with updated properties.

Config format: "storage:volume-id,key1=val1,key2=val2" Replaces existing keys and appends new ones.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/pvectl/services/set_volume.rb', line 85

def rebuild_disk_config(current_value, updates)
  parts = current_value.to_s.split(",")
  base = parts.shift # "storage:volume-id"

  # Parse existing key=value pairs
  existing = {}
  parts.each do |part|
    key, value = part.split("=", 2)
    existing[key] = value
  end

  # Apply updates
  updates.each do |key, value|
    existing[key.to_s] = value.to_s
  end

  # Rebuild string
  config_parts = existing.map { |k, v| "#{k}=#{v}" }
  ([base] + config_parts).join(",")
end