Class: Pvectl::Presenters::Storage

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

Overview

Presenter for Proxmox cluster storage pools.

Defines column layout and formatting for table output. Standard columns show essential storage info. Wide columns add content types and shared status.

Examples:

Using with formatter

presenter = Storage.new
formatter = Formatters::Table.new
output = formatter.format(storage_pools, presenter)

See Also:

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#format_bytes, #format_firewall, #format_firewall_rules, #format_task_history, #resource, #tags_array, #tags_display, #template_display, #to_wide_row, #uptime_human, #wide_columns

Instance Attribute Details

#storageModels::Storage (readonly)

Returns the current storage being presented.

Returns:

  • the current storage being presented



234
235
236
# File 'lib/pvectl/presenters/storage.rb', line 234

def storage
  @storage
end

Instance Method Details

#avail_displayString

Returns available storage formatted with appropriate unit (GB or TB).

Returns:

  • formatted available storage (e.g., "55 GB" or "2.0 TB") or "-"



184
185
186
187
188
# File 'lib/pvectl/presenters/storage.rb', line 184

def avail_display
  return "-" unless storage.active? && avail_gb

  format_size(avail_gb)
end

#avail_gbFloat?

Returns available bytes in GB.

Returns:

  • available bytes in GB, or nil if unavailable



175
176
177
178
179
# File 'lib/pvectl/presenters/storage.rb', line 175

def avail_gb
  return nil if storage.avail.nil?

  (storage.avail.to_f / 1024 / 1024 / 1024).round(1)
end

#build_capacity_sectionHash

Builds the capacity section for describe output.

Returns:

  • capacity metrics



263
264
265
266
267
268
269
270
# File 'lib/pvectl/presenters/storage.rb', line 263

def build_capacity_section
  {
    "Total" => total_display,
    "Used" => used_display,
    "Available" => avail_display,
    "Usage" => usage_display
  }
end

#build_configuration_sectionHash, String

Builds the configuration section for describe output. Includes type-specific configuration fields.

Returns:

  • configuration fields or "-" if empty



276
277
278
279
280
281
282
283
284
285
286
# File 'lib/pvectl/presenters/storage.rb', line 276

def build_configuration_section
  config = {}
  config["Path"] = storage.path if storage.path
  config["Server"] = storage.server if storage.server
  config["Export"] = storage.export if storage.export
  config["Volume Group"] = storage.vgname if storage.vgname
  config["Thin Pool"] = storage.thinpool if storage.thinpool
  config["Pool"] = storage.pool if storage.pool
  config["Content Types"] = storage.content if storage.content
  config.empty? ? "-" : config
end

#columnsArray<String>

Returns column headers for standard table output.

Returns:

  • column headers



23
24
25
# File 'lib/pvectl/presenters/storage.rb', line 23

def columns
  %w[NAME TYPE STATUS USED TOTAL %USED NODE]
end

#content_displayString

Returns content types for display.

Returns:

  • comma-separated content types or "-"



220
221
222
# File 'lib/pvectl/presenters/storage.rb', line 220

def content_display
  storage.content.nil? || storage.content.empty? ? "-" : storage.content
end

#disk_total_gbFloat?

Returns total disk in GB.

Returns:

  • total disk in GB, or nil if unavailable



157
158
159
160
161
# File 'lib/pvectl/presenters/storage.rb', line 157

def disk_total_gb
  return nil if storage.maxdisk.nil?

  (storage.maxdisk.to_f / 1024 / 1024 / 1024).round(1)
end

#disk_used_gbFloat?

Returns disk used in GB.

Returns:

  • disk used in GB, or nil if unavailable



148
149
150
151
152
# File 'lib/pvectl/presenters/storage.rb', line 148

def disk_used_gb
  return nil if storage.disk.nil?

  (storage.disk.to_f / 1024 / 1024 / 1024).round(1)
end

#extra_columnsArray<String>

Returns additional column headers for wide output.

Returns:

  • extra column headers



30
31
32
# File 'lib/pvectl/presenters/storage.rb', line 30

def extra_columns
  %w[CONTENT SHARED]
end

#extra_values(model, **_context) ⇒ Array<String>

Returns additional values for wide output.

Parameters:

  • Storage model

  • optional context

Returns:

  • extra values matching extra_columns order



57
58
59
60
61
62
63
# File 'lib/pvectl/presenters/storage.rb', line 57

def extra_values(model, **_context)
  @storage = model
  [
    content_display,
    shared_display
  ]
end

#format_backup_retentionHash, String

Formats backup retention policy for describe output.

Returns:

  • retention settings or "-" if not configured



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/pvectl/presenters/storage.rb', line 312

def format_backup_retention
  return "-" if storage.prune_backups.nil?

  retention = {}
  prune = storage.prune_backups

  # Handle both string and symbol keys
  retention["Keep Last"] = prune[:"keep-last"] || prune["keep-last"] if prune[:"keep-last"] || prune["keep-last"]
  retention["Keep Daily"] = prune[:"keep-daily"] || prune["keep-daily"] if prune[:"keep-daily"] || prune["keep-daily"]
  retention["Keep Weekly"] = prune[:"keep-weekly"] || prune["keep-weekly"] if prune[:"keep-weekly"] || prune["keep-weekly"]
  retention["Keep Monthly"] = prune[:"keep-monthly"] || prune["keep-monthly"] if prune[:"keep-monthly"] || prune["keep-monthly"]
  retention["Keep Yearly"] = prune[:"keep-yearly"] || prune["keep-yearly"] if prune[:"keep-yearly"] || prune["keep-yearly"]

  retention.empty? ? "-" : retention
end

#format_content_summaryArray<Hash>, String

Formats content summary from volumes list. Groups volumes by type and calculates counts and sizes.

Returns:

  • formatted table data or "-" if no volumes



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/pvectl/presenters/storage.rb', line 292

def format_content_summary
  return "-" if storage.volumes.nil? || storage.volumes.empty?

  # Group volumes by content type
  grouped = storage.volumes.group_by { |v| v[:content] || v["content"] }

  grouped.map do |content_type, volumes|
    total_size = volumes.sum { |v| v[:size] || v["size"] || 0 }
    size_gb = (total_size.to_f / 1024 / 1024 / 1024).round(1)
    {
      "TYPE" => content_type || "-",
      "COUNT" => volumes.size.to_s,
      "SIZE" => format_size(size_gb)
    }
  end
end

#format_size(gb) ⇒ String

Formats size with appropriate unit (GB or TB).

Parameters:

  • size in GB

Returns:

  • formatted size



240
241
242
243
244
245
246
# File 'lib/pvectl/presenters/storage.rb', line 240

def format_size(gb)
  if gb >= 1024
    "#{(gb / 1024).round(1)} TB"
  else
    "#{gb.round(0).to_i} GB"
  end
end

#node_displayString

Returns node display. Shows "-" for shared storage (available on multiple nodes).

Returns:

  • node name or "-" for shared storage



141
142
143
# File 'lib/pvectl/presenters/storage.rb', line 141

def node_display
  storage.shared? ? "-" : (storage.node || "-")
end

#nodes_displayString

Returns nodes display for describe output. Shows "all" if nodes_allowed is nil (available on all nodes).

Returns:

  • nodes list or "all"



256
257
258
# File 'lib/pvectl/presenters/storage.rb', line 256

def nodes_display
  storage.nodes_allowed.nil? ? "all" : storage.nodes_allowed
end

#shared_displayString

Returns shared status for display.

Returns:

  • "yes" or "no"



227
228
229
# File 'lib/pvectl/presenters/storage.rb', line 227

def shared_display
  storage.shared? ? "yes" : "no"
end

#status_displayString

Returns status for display. Maps "available" to "active" for consistency with kubectl style.

Returns:

  • status (active, inactive)



133
134
135
# File 'lib/pvectl/presenters/storage.rb', line 133

def status_display
  storage.active? ? "active" : "inactive"
end

#to_description(model) ⇒ Hash

Converts Storage model to description format for describe command.

Returns a structured Hash with sections for kubectl-style vertical output. Nested Hashes create indented subsections. Arrays of Hashes render as inline tables.

Parameters:

  • Storage model with describe details

Returns:

  • structured hash for describe formatter



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/pvectl/presenters/storage.rb', line 98

def to_description(model)
  @storage = model

  {
    "Name" => storage.name,
    "Type" => type_display,
    "Status" => status_display,
    "Shared" => shared_display,
    "Nodes" => nodes_display,

    "Capacity" => build_capacity_section,

    "Configuration" => build_configuration_section,

    "Content Summary" => format_content_summary,

    "Backup Retention" => format_backup_retention
  }
end

#to_hash(model) ⇒ Hash

Converts Storage model to hash for JSON/YAML output.

Returns a structured hash with nested objects for complex data.

Parameters:

  • Storage model

Returns:

  • hash representation with string keys



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/pvectl/presenters/storage.rb', line 71

def to_hash(model)
  @storage = model
  {
    "name" => storage.name,
    "type" => storage.plugintype,
    "status" => storage.status,
    "node" => storage.node,
    "shared" => storage.shared?,
    "content" => storage.content,
    "disk" => {
      "used_bytes" => storage.disk,
      "total_bytes" => storage.maxdisk,
      "used_gb" => disk_used_gb,
      "total_gb" => disk_total_gb,
      "usage_percent" => usage_percent
    }
  }
end

#to_row(model, **_context) ⇒ Array<String>

Converts Storage model to table row values.

Parameters:

  • Storage model

  • optional context

Returns:

  • row values matching columns order



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/pvectl/presenters/storage.rb', line 39

def to_row(model, **_context)
  @storage = model
  [
    storage.name,
    type_display,
    status_display,
    used_display,
    total_display,
    usage_display,
    node_display
  ]
end

#total_displayString

Returns total storage formatted with appropriate unit (GB or TB).

Returns:

  • formatted total storage (e.g., "100 GB" or "2.0 TB") or "-"



202
203
204
205
206
# File 'lib/pvectl/presenters/storage.rb', line 202

def total_display
  return "-" if disk_total_gb.nil?

  format_size(disk_total_gb)
end

#type_displayString

Returns storage type for display.

Returns:

  • storage plugin type or "-"



125
126
127
# File 'lib/pvectl/presenters/storage.rb', line 125

def type_display
  storage.plugintype || "-"
end

#usage_displayString

Returns usage percentage for display.

Returns:

  • percentage (e.g., "45%") or "-" if unavailable



211
212
213
214
215
# File 'lib/pvectl/presenters/storage.rb', line 211

def usage_display
  return "-" unless storage.active? && usage_percent

  "#{usage_percent}%"
end

#usage_percentInteger?

Returns storage usage percentage.

Returns:

  • usage percentage (0-100), or nil if unavailable



166
167
168
169
170
# File 'lib/pvectl/presenters/storage.rb', line 166

def usage_percent
  return nil if storage.maxdisk.nil? || storage.maxdisk.zero? || storage.disk.nil?

  ((storage.disk.to_f / storage.maxdisk) * 100).round
end

#used_displayString

Returns used storage formatted with appropriate unit (GB or TB).

Returns:

  • formatted used storage (e.g., "45 GB" or "1.2 TB") or "-"



193
194
195
196
197
# File 'lib/pvectl/presenters/storage.rb', line 193

def used_display
  return "-" unless storage.active? && disk_used_gb

  format_size(disk_used_gb)
end