pvectl 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.claude/rules/branch-before-changes.md +52 -0
- data/.claude/rules/documentation-updates.md +104 -0
- data/.claude/rules/git-workflow.md +84 -0
- data/.claude/rules/proxmox-api-docs.md +58 -0
- data/.claude/rules/rbs-signatures.md +80 -0
- data/.claude/rules/refactoring-as-design-option.md +35 -0
- data/.claude/scheduled_tasks.lock +1 -0
- data/.claude/settings.json +51 -0
- data/.mcp.json +8 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +138 -0
- data/CLAUDE.md +211 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +143 -0
- data/Rakefile +8 -0
- data/docs/proxmox-api-update.sh +96 -0
- data/exe/pvectl +5 -0
- data/lib/pvectl/argv_preprocessor.rb +334 -0
- data/lib/pvectl/cli.rb +102 -0
- data/lib/pvectl/commands/apt.rb +389 -0
- data/lib/pvectl/commands/clone_container.rb +230 -0
- data/lib/pvectl/commands/clone_vm.rb +331 -0
- data/lib/pvectl/commands/cloudinit/command.rb +122 -0
- data/lib/pvectl/commands/cloudinit/dump.rb +94 -0
- data/lib/pvectl/commands/cloudinit/pending.rb +137 -0
- data/lib/pvectl/commands/cloudinit/regenerate.rb +79 -0
- data/lib/pvectl/commands/config/command.rb +65 -0
- data/lib/pvectl/commands/config/get_contexts.rb +68 -0
- data/lib/pvectl/commands/config/set_cluster.rb +103 -0
- data/lib/pvectl/commands/config/set_context.rb +136 -0
- data/lib/pvectl/commands/config/set_credentials.rb +181 -0
- data/lib/pvectl/commands/config/use_context.rb +69 -0
- data/lib/pvectl/commands/config/view.rb +67 -0
- data/lib/pvectl/commands/console.rb +93 -0
- data/lib/pvectl/commands/console_ct.rb +187 -0
- data/lib/pvectl/commands/console_vm.rb +187 -0
- data/lib/pvectl/commands/container_lifecycle_command.rb +77 -0
- data/lib/pvectl/commands/create_backup.rb +173 -0
- data/lib/pvectl/commands/create_container.rb +141 -0
- data/lib/pvectl/commands/create_resource_command.rb +244 -0
- data/lib/pvectl/commands/create_snapshot.rb +242 -0
- data/lib/pvectl/commands/create_vm.rb +267 -0
- data/lib/pvectl/commands/delete_backup.rb +139 -0
- data/lib/pvectl/commands/delete_command.rb +119 -0
- data/lib/pvectl/commands/delete_container.rb +30 -0
- data/lib/pvectl/commands/delete_snapshot.rb +248 -0
- data/lib/pvectl/commands/delete_vm.rb +127 -0
- data/lib/pvectl/commands/describe/command.rb +251 -0
- data/lib/pvectl/commands/edit_container.rb +56 -0
- data/lib/pvectl/commands/edit_dns.rb +149 -0
- data/lib/pvectl/commands/edit_hosts.rb +135 -0
- data/lib/pvectl/commands/edit_node.rb +54 -0
- data/lib/pvectl/commands/edit_resource_command.rb +180 -0
- data/lib/pvectl/commands/edit_vm.rb +154 -0
- data/lib/pvectl/commands/edit_volume.rb +189 -0
- data/lib/pvectl/commands/feature_command.rb +230 -0
- data/lib/pvectl/commands/feature_container.rb +21 -0
- data/lib/pvectl/commands/feature_vm.rb +94 -0
- data/lib/pvectl/commands/get/command.rb +360 -0
- data/lib/pvectl/commands/get/handlers/backups.rb +76 -0
- data/lib/pvectl/commands/get/handlers/capabilities.rb +107 -0
- data/lib/pvectl/commands/get/handlers/containers.rb +148 -0
- data/lib/pvectl/commands/get/handlers/disks.rb +107 -0
- data/lib/pvectl/commands/get/handlers/dns.rb +94 -0
- data/lib/pvectl/commands/get/handlers/hosts.rb +94 -0
- data/lib/pvectl/commands/get/handlers/nodes.rb +162 -0
- data/lib/pvectl/commands/get/handlers/services.rb +81 -0
- data/lib/pvectl/commands/get/handlers/snapshots.rb +97 -0
- data/lib/pvectl/commands/get/handlers/storage.rb +118 -0
- data/lib/pvectl/commands/get/handlers/subscription.rb +69 -0
- data/lib/pvectl/commands/get/handlers/tasks.rb +89 -0
- data/lib/pvectl/commands/get/handlers/templates.rb +175 -0
- data/lib/pvectl/commands/get/handlers/time.rb +118 -0
- data/lib/pvectl/commands/get/handlers/vms.rb +145 -0
- data/lib/pvectl/commands/get/handlers/volume.rb +134 -0
- data/lib/pvectl/commands/get/resource_handler.rb +63 -0
- data/lib/pvectl/commands/get/resource_registry.rb +18 -0
- data/lib/pvectl/commands/get/watch_loop.rb +129 -0
- data/lib/pvectl/commands/irreversible_command.rb +265 -0
- data/lib/pvectl/commands/logs/command.rb +275 -0
- data/lib/pvectl/commands/logs/handlers/journal.rb +46 -0
- data/lib/pvectl/commands/logs/handlers/syslog.rb +53 -0
- data/lib/pvectl/commands/logs/handlers/task_detail.rb +52 -0
- data/lib/pvectl/commands/logs/handlers/task_logs.rb +115 -0
- data/lib/pvectl/commands/logs/resource_handler.rb +46 -0
- data/lib/pvectl/commands/logs/resource_registry.rb +22 -0
- data/lib/pvectl/commands/migrate_command.rb +282 -0
- data/lib/pvectl/commands/migrate_container.rb +23 -0
- data/lib/pvectl/commands/migrate_vm.rb +122 -0
- data/lib/pvectl/commands/move_disk_command.rb +239 -0
- data/lib/pvectl/commands/move_disk_container.rb +21 -0
- data/lib/pvectl/commands/move_disk_vm.rb +127 -0
- data/lib/pvectl/commands/ping.rb +249 -0
- data/lib/pvectl/commands/pull.rb +342 -0
- data/lib/pvectl/commands/push.rb +352 -0
- data/lib/pvectl/commands/reset.rb +64 -0
- data/lib/pvectl/commands/resource_lifecycle_command.rb +277 -0
- data/lib/pvectl/commands/resource_registry.rb +73 -0
- data/lib/pvectl/commands/restart.rb +70 -0
- data/lib/pvectl/commands/restart_container.rb +18 -0
- data/lib/pvectl/commands/restore_backup.rb +236 -0
- data/lib/pvectl/commands/resume.rb +57 -0
- data/lib/pvectl/commands/rollback_snapshot.rb +228 -0
- data/lib/pvectl/commands/sendkey_vm.rb +205 -0
- data/lib/pvectl/commands/service.rb +293 -0
- data/lib/pvectl/commands/set_container.rb +50 -0
- data/lib/pvectl/commands/set_node.rb +52 -0
- data/lib/pvectl/commands/set_resource_command.rb +185 -0
- data/lib/pvectl/commands/set_vm.rb +136 -0
- data/lib/pvectl/commands/set_volume.rb +212 -0
- data/lib/pvectl/commands/shared_config_parsers.rb +126 -0
- data/lib/pvectl/commands/shared_flags.rb +155 -0
- data/lib/pvectl/commands/shutdown.rb +73 -0
- data/lib/pvectl/commands/shutdown_container.rb +18 -0
- data/lib/pvectl/commands/start.rb +79 -0
- data/lib/pvectl/commands/start_container.rb +18 -0
- data/lib/pvectl/commands/stop.rb +75 -0
- data/lib/pvectl/commands/stop_container.rb +18 -0
- data/lib/pvectl/commands/suspend.rb +64 -0
- data/lib/pvectl/commands/template_command.rb +205 -0
- data/lib/pvectl/commands/template_container.rb +27 -0
- data/lib/pvectl/commands/template_vm.rb +106 -0
- data/lib/pvectl/commands/top/command.rb +206 -0
- data/lib/pvectl/commands/top/handlers/containers.rb +61 -0
- data/lib/pvectl/commands/top/handlers/nodes.rb +61 -0
- data/lib/pvectl/commands/top/handlers/vms.rb +61 -0
- data/lib/pvectl/commands/top/resource_handler.rb +46 -0
- data/lib/pvectl/commands/top/resource_registry.rb +22 -0
- data/lib/pvectl/commands/unlink_disk_vm.rb +232 -0
- data/lib/pvectl/commands/vm_lifecycle_command.rb +77 -0
- data/lib/pvectl/commands/wakeonlan_node.rb +153 -0
- data/lib/pvectl/config/errors.rb +62 -0
- data/lib/pvectl/config/models/cluster.rb +180 -0
- data/lib/pvectl/config/models/context.rb +100 -0
- data/lib/pvectl/config/models/resolved_config.rb +171 -0
- data/lib/pvectl/config/models/user.rb +133 -0
- data/lib/pvectl/config/provider.rb +297 -0
- data/lib/pvectl/config/service.rb +300 -0
- data/lib/pvectl/config/store.rb +161 -0
- data/lib/pvectl/config/wizard.rb +309 -0
- data/lib/pvectl/config_serializer.rb +1034 -0
- data/lib/pvectl/connection/retry_handler.rb +161 -0
- data/lib/pvectl/connection.rb +157 -0
- data/lib/pvectl/console/terminal_session.rb +449 -0
- data/lib/pvectl/editor_session.rb +157 -0
- data/lib/pvectl/exit_codes.rb +43 -0
- data/lib/pvectl/formatters/base.rb +55 -0
- data/lib/pvectl/formatters/color_support.rb +90 -0
- data/lib/pvectl/formatters/json.rb +45 -0
- data/lib/pvectl/formatters/output_helper.rb +77 -0
- data/lib/pvectl/formatters/registry.rb +72 -0
- data/lib/pvectl/formatters/table.rb +235 -0
- data/lib/pvectl/formatters/wide.rb +93 -0
- data/lib/pvectl/formatters/yaml.rb +49 -0
- data/lib/pvectl/manifest_serializer.rb +142 -0
- data/lib/pvectl/models/apt_package.rb +107 -0
- data/lib/pvectl/models/backup.rb +173 -0
- data/lib/pvectl/models/base.rb +49 -0
- data/lib/pvectl/models/capability.rb +62 -0
- data/lib/pvectl/models/container.rb +205 -0
- data/lib/pvectl/models/container_operation_result.rb +27 -0
- data/lib/pvectl/models/dns_config.rb +54 -0
- data/lib/pvectl/models/hosts_file.rb +47 -0
- data/lib/pvectl/models/journal_entry.rb +16 -0
- data/lib/pvectl/models/network_interface.rb +85 -0
- data/lib/pvectl/models/node.rb +195 -0
- data/lib/pvectl/models/node_operation_result.rb +45 -0
- data/lib/pvectl/models/operation_result.rb +110 -0
- data/lib/pvectl/models/physical_disk.rb +193 -0
- data/lib/pvectl/models/service.rb +80 -0
- data/lib/pvectl/models/snapshot.rb +101 -0
- data/lib/pvectl/models/snapshot_description.rb +39 -0
- data/lib/pvectl/models/storage.rb +180 -0
- data/lib/pvectl/models/subscription.rb +87 -0
- data/lib/pvectl/models/syslog_entry.rb +17 -0
- data/lib/pvectl/models/task.rb +95 -0
- data/lib/pvectl/models/task_entry.rb +52 -0
- data/lib/pvectl/models/task_log_line.rb +17 -0
- data/lib/pvectl/models/time_config.rb +47 -0
- data/lib/pvectl/models/vm.rb +137 -0
- data/lib/pvectl/models/vm_operation_result.rb +27 -0
- data/lib/pvectl/models/volume.rb +133 -0
- data/lib/pvectl/models/volume_operation_result.rb +26 -0
- data/lib/pvectl/parsers/cloud_init_config.rb +92 -0
- data/lib/pvectl/parsers/disk_config.rb +97 -0
- data/lib/pvectl/parsers/lxc_mount_config.rb +98 -0
- data/lib/pvectl/parsers/lxc_net_config.rb +97 -0
- data/lib/pvectl/parsers/net_config.rb +95 -0
- data/lib/pvectl/parsers/smart_text.rb +42 -0
- data/lib/pvectl/plugin_loader.rb +157 -0
- data/lib/pvectl/presenters/apt_package.rb +99 -0
- data/lib/pvectl/presenters/backup.rb +128 -0
- data/lib/pvectl/presenters/base.rb +283 -0
- data/lib/pvectl/presenters/capability.rb +104 -0
- data/lib/pvectl/presenters/config/context.rb +80 -0
- data/lib/pvectl/presenters/container.rb +574 -0
- data/lib/pvectl/presenters/container_operation_result.rb +109 -0
- data/lib/pvectl/presenters/disk.rb +184 -0
- data/lib/pvectl/presenters/dns_config.rb +68 -0
- data/lib/pvectl/presenters/hosts_file.rb +61 -0
- data/lib/pvectl/presenters/journal_entry.rb +20 -0
- data/lib/pvectl/presenters/node.rb +762 -0
- data/lib/pvectl/presenters/node_operation_result.rb +50 -0
- data/lib/pvectl/presenters/operation_result.rb +61 -0
- data/lib/pvectl/presenters/service.rb +76 -0
- data/lib/pvectl/presenters/snapshot.rb +239 -0
- data/lib/pvectl/presenters/snapshot_operation_result.rb +125 -0
- data/lib/pvectl/presenters/storage.rb +329 -0
- data/lib/pvectl/presenters/subscription.rb +189 -0
- data/lib/pvectl/presenters/syslog_entry.rb +20 -0
- data/lib/pvectl/presenters/task_entry.rb +69 -0
- data/lib/pvectl/presenters/task_log_line.rb +20 -0
- data/lib/pvectl/presenters/template.rb +76 -0
- data/lib/pvectl/presenters/time_config.rb +86 -0
- data/lib/pvectl/presenters/top_container.rb +112 -0
- data/lib/pvectl/presenters/top_node.rb +115 -0
- data/lib/pvectl/presenters/top_presenter.rb +59 -0
- data/lib/pvectl/presenters/top_vm.rb +105 -0
- data/lib/pvectl/presenters/vm.rb +853 -0
- data/lib/pvectl/presenters/vm_operation_result.rb +109 -0
- data/lib/pvectl/presenters/volume.rb +136 -0
- data/lib/pvectl/presenters/volume_operation_result.rb +58 -0
- data/lib/pvectl/repositories/apt.rb +93 -0
- data/lib/pvectl/repositories/backup.rb +186 -0
- data/lib/pvectl/repositories/base.rb +110 -0
- data/lib/pvectl/repositories/capabilities.rb +96 -0
- data/lib/pvectl/repositories/container.rb +503 -0
- data/lib/pvectl/repositories/disk.rb +87 -0
- data/lib/pvectl/repositories/dns.rb +54 -0
- data/lib/pvectl/repositories/hosts.rb +63 -0
- data/lib/pvectl/repositories/journal.rb +23 -0
- data/lib/pvectl/repositories/node.rb +537 -0
- data/lib/pvectl/repositories/service.rb +139 -0
- data/lib/pvectl/repositories/snapshot.rb +133 -0
- data/lib/pvectl/repositories/storage.rb +302 -0
- data/lib/pvectl/repositories/subscription.rb +77 -0
- data/lib/pvectl/repositories/syslog.rb +25 -0
- data/lib/pvectl/repositories/task.rb +82 -0
- data/lib/pvectl/repositories/task_list.rb +30 -0
- data/lib/pvectl/repositories/task_log.rb +31 -0
- data/lib/pvectl/repositories/time_config.rb +53 -0
- data/lib/pvectl/repositories/vm.rb +616 -0
- data/lib/pvectl/repositories/volume.rb +306 -0
- data/lib/pvectl/selectors/base.rb +201 -0
- data/lib/pvectl/selectors/container.rb +116 -0
- data/lib/pvectl/selectors/disk.rb +59 -0
- data/lib/pvectl/selectors/vm.rb +116 -0
- data/lib/pvectl/selectors/volume.rb +59 -0
- data/lib/pvectl/services/backup.rb +209 -0
- data/lib/pvectl/services/clone_container.rb +260 -0
- data/lib/pvectl/services/clone_vm.rb +265 -0
- data/lib/pvectl/services/cloudinit.rb +96 -0
- data/lib/pvectl/services/console.rb +152 -0
- data/lib/pvectl/services/container_lifecycle.rb +124 -0
- data/lib/pvectl/services/create_container.rb +179 -0
- data/lib/pvectl/services/create_vm.rb +191 -0
- data/lib/pvectl/services/edit_container.rb +125 -0
- data/lib/pvectl/services/edit_dns.rb +159 -0
- data/lib/pvectl/services/edit_hosts.rb +78 -0
- data/lib/pvectl/services/edit_node.rb +147 -0
- data/lib/pvectl/services/edit_vm.rb +125 -0
- data/lib/pvectl/services/edit_volume.rb +224 -0
- data/lib/pvectl/services/get/resource_service.rb +98 -0
- data/lib/pvectl/services/move_disk.rb +132 -0
- data/lib/pvectl/services/pull_config.rb +94 -0
- data/lib/pvectl/services/push_config.rb +524 -0
- data/lib/pvectl/services/resize_volume.rb +253 -0
- data/lib/pvectl/services/resource_delete.rb +169 -0
- data/lib/pvectl/services/resource_migration.rb +170 -0
- data/lib/pvectl/services/sendkey.rb +108 -0
- data/lib/pvectl/services/service_lifecycle.rb +89 -0
- data/lib/pvectl/services/set_container.rb +128 -0
- data/lib/pvectl/services/set_node.rb +236 -0
- data/lib/pvectl/services/set_vm.rb +128 -0
- data/lib/pvectl/services/set_volume.rb +126 -0
- data/lib/pvectl/services/snapshot.rb +261 -0
- data/lib/pvectl/services/task_listing.rb +75 -0
- data/lib/pvectl/services/unlink_disk.rb +86 -0
- data/lib/pvectl/services/vm_lifecycle.rb +124 -0
- data/lib/pvectl/services/wakeonlan.rb +79 -0
- data/lib/pvectl/utils/resource_resolver.rb +80 -0
- data/lib/pvectl/version.rb +13 -0
- data/lib/pvectl/wizards/create_container.rb +105 -0
- data/lib/pvectl/wizards/create_vm.rb +98 -0
- data/lib/pvectl.rb +439 -0
- data/sig/external/gli.rbs +16 -0
- data/sig/external/proxmox_api.rbs +10 -0
- data/sig/pvectl/argv_preprocessor.rbs +53 -0
- data/sig/pvectl/cli.rbs +26 -0
- data/sig/pvectl/commands/apt.rbs +47 -0
- data/sig/pvectl/commands/clone_container.rbs +31 -0
- data/sig/pvectl/commands/clone_vm.rbs +33 -0
- data/sig/pvectl/commands/cloudinit/command.rbs +13 -0
- data/sig/pvectl/commands/cloudinit/dump.rbs +13 -0
- data/sig/pvectl/commands/cloudinit/pending.rbs +17 -0
- data/sig/pvectl/commands/cloudinit/regenerate.rbs +11 -0
- data/sig/pvectl/commands/config/command.rbs +9 -0
- data/sig/pvectl/commands/config/get_contexts.rbs +11 -0
- data/sig/pvectl/commands/config/set_cluster.rbs +11 -0
- data/sig/pvectl/commands/config/set_context.rbs +15 -0
- data/sig/pvectl/commands/config/set_credentials.rbs +15 -0
- data/sig/pvectl/commands/config/use_context.rbs +11 -0
- data/sig/pvectl/commands/config/view.rbs +11 -0
- data/sig/pvectl/commands/console.rbs +9 -0
- data/sig/pvectl/commands/console_ct.rbs +27 -0
- data/sig/pvectl/commands/console_vm.rbs +27 -0
- data/sig/pvectl/commands/container_lifecycle_command.rbs +25 -0
- data/sig/pvectl/commands/create_backup.rbs +29 -0
- data/sig/pvectl/commands/create_container.rbs +30 -0
- data/sig/pvectl/commands/create_resource_command.rbs +53 -0
- data/sig/pvectl/commands/create_snapshot.rbs +35 -0
- data/sig/pvectl/commands/create_vm.rbs +30 -0
- data/sig/pvectl/commands/delete_backup.rbs +25 -0
- data/sig/pvectl/commands/delete_command.rbs +45 -0
- data/sig/pvectl/commands/delete_container.rbs +11 -0
- data/sig/pvectl/commands/delete_snapshot.rbs +35 -0
- data/sig/pvectl/commands/delete_vm.rbs +13 -0
- data/sig/pvectl/commands/describe/command.rbs +27 -0
- data/sig/pvectl/commands/edit_container.rbs +17 -0
- data/sig/pvectl/commands/edit_dns.rbs +25 -0
- data/sig/pvectl/commands/edit_hosts.rbs +23 -0
- data/sig/pvectl/commands/edit_node.rbs +17 -0
- data/sig/pvectl/commands/edit_resource_command.rbs +35 -0
- data/sig/pvectl/commands/edit_vm.rbs +19 -0
- data/sig/pvectl/commands/edit_volume.rbs +24 -0
- data/sig/pvectl/commands/feature_command.rbs +43 -0
- data/sig/pvectl/commands/feature_container.rbs +10 -0
- data/sig/pvectl/commands/feature_vm.rbs +12 -0
- data/sig/pvectl/commands/get/command.rbs +42 -0
- data/sig/pvectl/commands/get/handlers/backups.rbs +23 -0
- data/sig/pvectl/commands/get/handlers/capabilities.rbs +29 -0
- data/sig/pvectl/commands/get/handlers/containers.rbs +35 -0
- data/sig/pvectl/commands/get/handlers/disks.rbs +27 -0
- data/sig/pvectl/commands/get/handlers/dns.rbs +25 -0
- data/sig/pvectl/commands/get/handlers/hosts.rbs +25 -0
- data/sig/pvectl/commands/get/handlers/nodes.rbs +33 -0
- data/sig/pvectl/commands/get/handlers/services.rbs +23 -0
- data/sig/pvectl/commands/get/handlers/snapshots.rbs +27 -0
- data/sig/pvectl/commands/get/handlers/storage.rbs +25 -0
- data/sig/pvectl/commands/get/handlers/subscription.rbs +25 -0
- data/sig/pvectl/commands/get/handlers/tasks.rbs +28 -0
- data/sig/pvectl/commands/get/handlers/templates.rbs +35 -0
- data/sig/pvectl/commands/get/handlers/time.rbs +29 -0
- data/sig/pvectl/commands/get/handlers/vms.rbs +35 -0
- data/sig/pvectl/commands/get/handlers/volume.rbs +27 -0
- data/sig/pvectl/commands/get/resource_handler.rbs +13 -0
- data/sig/pvectl/commands/get/resource_registry.rbs +8 -0
- data/sig/pvectl/commands/get/watch_loop.rbs +33 -0
- data/sig/pvectl/commands/irreversible_command.rbs +32 -0
- data/sig/pvectl/commands/logs/command.rbs +35 -0
- data/sig/pvectl/commands/logs/handlers/journal.rbs +21 -0
- data/sig/pvectl/commands/logs/handlers/syslog.rbs +21 -0
- data/sig/pvectl/commands/logs/handlers/task_detail.rbs +21 -0
- data/sig/pvectl/commands/logs/handlers/task_logs.rbs +35 -0
- data/sig/pvectl/commands/logs/resource_handler.rbs +11 -0
- data/sig/pvectl/commands/logs/resource_registry.rbs +8 -0
- data/sig/pvectl/commands/migrate_command.rbs +45 -0
- data/sig/pvectl/commands/migrate_container.rbs +11 -0
- data/sig/pvectl/commands/migrate_vm.rbs +13 -0
- data/sig/pvectl/commands/move_disk_command.rbs +43 -0
- data/sig/pvectl/commands/move_disk_container.rbs +11 -0
- data/sig/pvectl/commands/move_disk_vm.rbs +13 -0
- data/sig/pvectl/commands/ping.rbs +39 -0
- data/sig/pvectl/commands/pull.rbs +33 -0
- data/sig/pvectl/commands/push.rbs +32 -0
- data/sig/pvectl/commands/reset.rbs +11 -0
- data/sig/pvectl/commands/resource_lifecycle_command.rbs +55 -0
- data/sig/pvectl/commands/resource_registry.rbs +19 -0
- data/sig/pvectl/commands/restart.rbs +11 -0
- data/sig/pvectl/commands/restart_container.rbs +9 -0
- data/sig/pvectl/commands/restore_backup.rbs +27 -0
- data/sig/pvectl/commands/resume.rbs +11 -0
- data/sig/pvectl/commands/rollback_snapshot.rbs +31 -0
- data/sig/pvectl/commands/sendkey_vm.rbs +25 -0
- data/sig/pvectl/commands/service.rbs +38 -0
- data/sig/pvectl/commands/set_container.rbs +13 -0
- data/sig/pvectl/commands/set_node.rbs +13 -0
- data/sig/pvectl/commands/set_resource_command.rbs +25 -0
- data/sig/pvectl/commands/set_vm.rbs +15 -0
- data/sig/pvectl/commands/set_volume.rbs +24 -0
- data/sig/pvectl/commands/shared_config_parsers.rbs +19 -0
- data/sig/pvectl/commands/shared_flags.rbs +10 -0
- data/sig/pvectl/commands/shutdown.rbs +11 -0
- data/sig/pvectl/commands/shutdown_container.rbs +9 -0
- data/sig/pvectl/commands/start.rbs +11 -0
- data/sig/pvectl/commands/start_container.rbs +9 -0
- data/sig/pvectl/commands/stop.rbs +11 -0
- data/sig/pvectl/commands/stop_container.rbs +9 -0
- data/sig/pvectl/commands/suspend.rbs +11 -0
- data/sig/pvectl/commands/template_command.rbs +21 -0
- data/sig/pvectl/commands/template_container.rbs +10 -0
- data/sig/pvectl/commands/template_vm.rbs +12 -0
- data/sig/pvectl/commands/top/command.rbs +31 -0
- data/sig/pvectl/commands/top/handlers/containers.rbs +21 -0
- data/sig/pvectl/commands/top/handlers/nodes.rbs +21 -0
- data/sig/pvectl/commands/top/handlers/vms.rbs +21 -0
- data/sig/pvectl/commands/top/resource_handler.rbs +11 -0
- data/sig/pvectl/commands/top/resource_registry.rbs +8 -0
- data/sig/pvectl/commands/unlink_disk_vm.rbs +27 -0
- data/sig/pvectl/commands/vm_lifecycle_command.rbs +25 -0
- data/sig/pvectl/commands/wakeonlan_node.rbs +21 -0
- data/sig/pvectl/config/errors.rbs +24 -0
- data/sig/pvectl/config/models/cluster.rbs +39 -0
- data/sig/pvectl/config/models/context.rbs +23 -0
- data/sig/pvectl/config/models/resolved_config.rbs +51 -0
- data/sig/pvectl/config/models/user.rbs +31 -0
- data/sig/pvectl/config/provider.rbs +40 -0
- data/sig/pvectl/config/service.rbs +65 -0
- data/sig/pvectl/config/store.rbs +14 -0
- data/sig/pvectl/config/wizard.rbs +48 -0
- data/sig/pvectl/config_serializer.rbs +121 -0
- data/sig/pvectl/connection/retry_handler.rbs +31 -0
- data/sig/pvectl/connection.rbs +35 -0
- data/sig/pvectl/console/terminal_session.rbs +63 -0
- data/sig/pvectl/editor_session.rbs +33 -0
- data/sig/pvectl/exit_codes.rbs +19 -0
- data/sig/pvectl/formatters/base.rbs +13 -0
- data/sig/pvectl/formatters/color_support.rbs +13 -0
- data/sig/pvectl/formatters/json.rbs +7 -0
- data/sig/pvectl/formatters/output_helper.rbs +9 -0
- data/sig/pvectl/formatters/registry.rbs +13 -0
- data/sig/pvectl/formatters/table.rbs +25 -0
- data/sig/pvectl/formatters/wide.rbs +15 -0
- data/sig/pvectl/formatters/yaml.rbs +7 -0
- data/sig/pvectl/manifest_serializer.rbs +18 -0
- data/sig/pvectl/models/apt_package.rbs +26 -0
- data/sig/pvectl/models/backup.rbs +31 -0
- data/sig/pvectl/models/base.rbs +11 -0
- data/sig/pvectl/models/capability.rbs +16 -0
- data/sig/pvectl/models/container.rbs +44 -0
- data/sig/pvectl/models/container_operation_result.rbs +9 -0
- data/sig/pvectl/models/dns_config.rbs +15 -0
- data/sig/pvectl/models/hosts_file.rbs +13 -0
- data/sig/pvectl/models/journal_entry.rbs +10 -0
- data/sig/pvectl/models/network_interface.rbs +20 -0
- data/sig/pvectl/models/node.rbs +47 -0
- data/sig/pvectl/models/node_operation_result.rbs +12 -0
- data/sig/pvectl/models/operation_result.rbs +21 -0
- data/sig/pvectl/models/physical_disk.rbs +35 -0
- data/sig/pvectl/models/service.rbs +18 -0
- data/sig/pvectl/models/snapshot.rbs +21 -0
- data/sig/pvectl/models/snapshot_description.rbs +18 -0
- data/sig/pvectl/models/storage.rbs +39 -0
- data/sig/pvectl/models/subscription.rbs +24 -0
- data/sig/pvectl/models/syslog_entry.rbs +10 -0
- data/sig/pvectl/models/task.rbs +22 -0
- data/sig/pvectl/models/task_entry.rbs +24 -0
- data/sig/pvectl/models/task_log_line.rbs +10 -0
- data/sig/pvectl/models/time_config.rbs +12 -0
- data/sig/pvectl/models/vm.rbs +32 -0
- data/sig/pvectl/models/vm_operation_result.rbs +9 -0
- data/sig/pvectl/models/volume.rbs +29 -0
- data/sig/pvectl/models/volume_operation_result.rbs +9 -0
- data/sig/pvectl/parsers/cloud_init_config.rbs +15 -0
- data/sig/pvectl/parsers/disk_config.rbs +19 -0
- data/sig/pvectl/parsers/lxc_mount_config.rbs +19 -0
- data/sig/pvectl/parsers/lxc_net_config.rbs +19 -0
- data/sig/pvectl/parsers/net_config.rbs +19 -0
- data/sig/pvectl/parsers/smart_text.rbs +7 -0
- data/sig/pvectl/plugin_loader.rbs +25 -0
- data/sig/pvectl/presenters/apt_package.rbs +19 -0
- data/sig/pvectl/presenters/backup.rbs +25 -0
- data/sig/pvectl/presenters/base.rbs +41 -0
- data/sig/pvectl/presenters/capability.rbs +19 -0
- data/sig/pvectl/presenters/config/context.rbs +17 -0
- data/sig/pvectl/presenters/container.rbs +78 -0
- data/sig/pvectl/presenters/container_operation_result.rbs +19 -0
- data/sig/pvectl/presenters/disk.rbs +31 -0
- data/sig/pvectl/presenters/dns_config.rbs +13 -0
- data/sig/pvectl/presenters/hosts_file.rbs +13 -0
- data/sig/pvectl/presenters/journal_entry.rbs +11 -0
- data/sig/pvectl/presenters/node.rbs +118 -0
- data/sig/pvectl/presenters/node_operation_result.rbs +11 -0
- data/sig/pvectl/presenters/operation_result.rbs +17 -0
- data/sig/pvectl/presenters/service.rbs +15 -0
- data/sig/pvectl/presenters/snapshot.rbs +35 -0
- data/sig/pvectl/presenters/snapshot_operation_result.rbs +27 -0
- data/sig/pvectl/presenters/storage.rbs +59 -0
- data/sig/pvectl/presenters/subscription.rbs +36 -0
- data/sig/pvectl/presenters/syslog_entry.rbs +11 -0
- data/sig/pvectl/presenters/task_entry.rbs +21 -0
- data/sig/pvectl/presenters/task_log_line.rbs +11 -0
- data/sig/pvectl/presenters/template.rbs +15 -0
- data/sig/pvectl/presenters/time_config.rbs +19 -0
- data/sig/pvectl/presenters/top_container.rbs +17 -0
- data/sig/pvectl/presenters/top_node.rbs +17 -0
- data/sig/pvectl/presenters/top_presenter.rbs +13 -0
- data/sig/pvectl/presenters/top_vm.rbs +17 -0
- data/sig/pvectl/presenters/vm.rbs +91 -0
- data/sig/pvectl/presenters/vm_operation_result.rbs +19 -0
- data/sig/pvectl/presenters/volume.rbs +23 -0
- data/sig/pvectl/presenters/volume_operation_result.rbs +11 -0
- data/sig/pvectl/repositories/apt.rbs +17 -0
- data/sig/pvectl/repositories/backup.rbs +27 -0
- data/sig/pvectl/repositories/base.rbs +23 -0
- data/sig/pvectl/repositories/capabilities.rbs +20 -0
- data/sig/pvectl/repositories/container.rbs +63 -0
- data/sig/pvectl/repositories/disk.rbs +17 -0
- data/sig/pvectl/repositories/dns.rbs +13 -0
- data/sig/pvectl/repositories/hosts.rbs +13 -0
- data/sig/pvectl/repositories/journal.rbs +7 -0
- data/sig/pvectl/repositories/node.rbs +68 -0
- data/sig/pvectl/repositories/service.rbs +27 -0
- data/sig/pvectl/repositories/snapshot.rbs +19 -0
- data/sig/pvectl/repositories/storage.rbs +37 -0
- data/sig/pvectl/repositories/subscription.rbs +17 -0
- data/sig/pvectl/repositories/syslog.rbs +7 -0
- data/sig/pvectl/repositories/task.rbs +19 -0
- data/sig/pvectl/repositories/task_list.rbs +7 -0
- data/sig/pvectl/repositories/task_log.rbs +11 -0
- data/sig/pvectl/repositories/time_config.rbs +13 -0
- data/sig/pvectl/repositories/vm.rbs +85 -0
- data/sig/pvectl/repositories/volume.rbs +43 -0
- data/sig/pvectl/selectors/base.rbs +37 -0
- data/sig/pvectl/selectors/container.rbs +19 -0
- data/sig/pvectl/selectors/disk.rbs +13 -0
- data/sig/pvectl/selectors/vm.rbs +19 -0
- data/sig/pvectl/selectors/volume.rbs +13 -0
- data/sig/pvectl/services/backup.rbs +27 -0
- data/sig/pvectl/services/clone_container.rbs +35 -0
- data/sig/pvectl/services/clone_vm.rbs +35 -0
- data/sig/pvectl/services/cloudinit.rbs +19 -0
- data/sig/pvectl/services/console.rbs +23 -0
- data/sig/pvectl/services/container_lifecycle.rbs +26 -0
- data/sig/pvectl/services/create_container.rbs +64 -0
- data/sig/pvectl/services/create_vm.rbs +72 -0
- data/sig/pvectl/services/edit_container.rbs +17 -0
- data/sig/pvectl/services/edit_dns.rbs +23 -0
- data/sig/pvectl/services/edit_hosts.rbs +13 -0
- data/sig/pvectl/services/edit_node.rbs +21 -0
- data/sig/pvectl/services/edit_vm.rbs +17 -0
- data/sig/pvectl/services/edit_volume.rbs +18 -0
- data/sig/pvectl/services/get/resource_service.rbs +23 -0
- data/sig/pvectl/services/move_disk.rbs +21 -0
- data/sig/pvectl/services/pull_config.rbs +18 -0
- data/sig/pvectl/services/push_config.rbs +37 -0
- data/sig/pvectl/services/resize_volume.rbs +47 -0
- data/sig/pvectl/services/resource_delete.rbs +27 -0
- data/sig/pvectl/services/resource_migration.rbs +29 -0
- data/sig/pvectl/services/sendkey.rbs +19 -0
- data/sig/pvectl/services/service_lifecycle.rbs +17 -0
- data/sig/pvectl/services/set_container.rbs +14 -0
- data/sig/pvectl/services/set_node.rbs +23 -0
- data/sig/pvectl/services/set_vm.rbs +14 -0
- data/sig/pvectl/services/set_volume.rbs +12 -0
- data/sig/pvectl/services/snapshot.rbs +35 -0
- data/sig/pvectl/services/task_listing.rbs +13 -0
- data/sig/pvectl/services/unlink_disk.rbs +17 -0
- data/sig/pvectl/services/vm_lifecycle.rbs +26 -0
- data/sig/pvectl/services/wakeonlan.rbs +17 -0
- data/sig/pvectl/utils/resource_resolver.rbs +17 -0
- data/sig/pvectl/wizards/create_container.rbs +21 -0
- data/sig/pvectl/wizards/create_vm.rbs +21 -0
- data/sig/pvectl.rbs +9 -0
- metadata +675 -0
|
@@ -0,0 +1,762 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Presenters
|
|
5
|
+
# Presenter for Proxmox cluster nodes.
|
|
6
|
+
#
|
|
7
|
+
# Defines column layout and formatting for table output.
|
|
8
|
+
# Standard columns show essential node info.
|
|
9
|
+
# Wide columns add detailed metrics (load, swap, storage, kernel).
|
|
10
|
+
#
|
|
11
|
+
# @example Using with formatter
|
|
12
|
+
# presenter = Node.new
|
|
13
|
+
# formatter = Formatters::Table.new
|
|
14
|
+
# output = formatter.format(nodes, presenter)
|
|
15
|
+
#
|
|
16
|
+
# @see Pvectl::Models::Node Node model
|
|
17
|
+
# @see Pvectl::Formatters::Table Table formatter
|
|
18
|
+
#
|
|
19
|
+
class Node < Base
|
|
20
|
+
# Returns column headers for standard table output.
|
|
21
|
+
#
|
|
22
|
+
# @return [Array<String>] column headers
|
|
23
|
+
def columns
|
|
24
|
+
%w[NAME STATUS VERSION CPU MEMORY GUESTS UPTIME]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Returns additional column headers for wide output.
|
|
28
|
+
#
|
|
29
|
+
# @return [Array<String>] extra column headers
|
|
30
|
+
def extra_columns
|
|
31
|
+
%w[LOAD SWAP STORAGE VMS CTS KERNEL IP]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Converts Node model to table row values.
|
|
35
|
+
#
|
|
36
|
+
# @param model [Models::Node] Node model
|
|
37
|
+
# @param context [Hash] optional context
|
|
38
|
+
# @return [Array<String>] row values matching columns order
|
|
39
|
+
def to_row(model, **_context)
|
|
40
|
+
@node = model
|
|
41
|
+
[
|
|
42
|
+
node.name,
|
|
43
|
+
node.status,
|
|
44
|
+
version_display,
|
|
45
|
+
cpu_percent,
|
|
46
|
+
memory_display,
|
|
47
|
+
node.guests_total.to_s,
|
|
48
|
+
uptime_human
|
|
49
|
+
]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns additional values for wide output.
|
|
53
|
+
#
|
|
54
|
+
# @param model [Models::Node] Node model
|
|
55
|
+
# @param context [Hash] optional context
|
|
56
|
+
# @return [Array<String>] extra values matching extra_columns order
|
|
57
|
+
def extra_values(model, **_context)
|
|
58
|
+
@node = model
|
|
59
|
+
[
|
|
60
|
+
load_display,
|
|
61
|
+
swap_display,
|
|
62
|
+
storage_display,
|
|
63
|
+
node.guests_vms.to_s,
|
|
64
|
+
node.guests_cts.to_s,
|
|
65
|
+
kernel_display,
|
|
66
|
+
ip_display
|
|
67
|
+
]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Converts Node model to hash for JSON/YAML output.
|
|
71
|
+
#
|
|
72
|
+
# Returns a structured hash with nested objects for complex data
|
|
73
|
+
# like CPU, memory, disk, uptime, swap, load, and guests.
|
|
74
|
+
#
|
|
75
|
+
# @param model [Models::Node] Node model
|
|
76
|
+
# @return [Hash] hash representation with string keys
|
|
77
|
+
def to_hash(model)
|
|
78
|
+
@node = model
|
|
79
|
+
{
|
|
80
|
+
"name" => node.name,
|
|
81
|
+
"status" => node.status,
|
|
82
|
+
"version" => node.version,
|
|
83
|
+
"kernel" => node.kernel,
|
|
84
|
+
"cpu" => {
|
|
85
|
+
"usage_percent" => node.cpu.nil? ? nil : (node.cpu * 100).round,
|
|
86
|
+
"cores" => node.maxcpu
|
|
87
|
+
},
|
|
88
|
+
"memory" => {
|
|
89
|
+
"used_bytes" => node.mem,
|
|
90
|
+
"total_bytes" => node.maxmem,
|
|
91
|
+
"used_gb" => memory_used_gb,
|
|
92
|
+
"total_gb" => memory_total_gb,
|
|
93
|
+
"usage_percent" => memory_percent(node)
|
|
94
|
+
},
|
|
95
|
+
"swap" => {
|
|
96
|
+
"used_bytes" => node.swap_used,
|
|
97
|
+
"total_bytes" => node.swap_total,
|
|
98
|
+
"usage_percent" => swap_percent(node)
|
|
99
|
+
},
|
|
100
|
+
"storage" => {
|
|
101
|
+
"used_bytes" => node.disk,
|
|
102
|
+
"total_bytes" => node.maxdisk,
|
|
103
|
+
"usage_percent" => storage_percent(node)
|
|
104
|
+
},
|
|
105
|
+
"load" => {
|
|
106
|
+
"avg1" => node.loadavg&.dig(0),
|
|
107
|
+
"avg5" => node.loadavg&.dig(1),
|
|
108
|
+
"avg15" => node.loadavg&.dig(2)
|
|
109
|
+
},
|
|
110
|
+
"guests" => {
|
|
111
|
+
"total" => node.guests_total,
|
|
112
|
+
"vms" => node.guests_vms,
|
|
113
|
+
"cts" => node.guests_cts
|
|
114
|
+
},
|
|
115
|
+
"uptime" => {
|
|
116
|
+
"seconds" => node.uptime,
|
|
117
|
+
"human" => uptime_human
|
|
118
|
+
},
|
|
119
|
+
"alerts" => alerts,
|
|
120
|
+
"network" => {
|
|
121
|
+
"ip" => node.ip
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Converts Node model to description format for describe command.
|
|
127
|
+
#
|
|
128
|
+
# Returns a structured Hash with sections for kubectl-style vertical output.
|
|
129
|
+
# Nested Hashes create indented subsections.
|
|
130
|
+
# Arrays of Hashes render as inline tables.
|
|
131
|
+
#
|
|
132
|
+
# @param model [Models::Node] Node model with describe details
|
|
133
|
+
# @return [Hash] structured hash for describe formatter
|
|
134
|
+
def to_description(model)
|
|
135
|
+
@node = model
|
|
136
|
+
return offline_description if node.offline?
|
|
137
|
+
|
|
138
|
+
{
|
|
139
|
+
"Name" => node.name,
|
|
140
|
+
"Status" => node.status,
|
|
141
|
+
"Subscription" => subscription_display,
|
|
142
|
+
"System" => {
|
|
143
|
+
"Version" => version_display,
|
|
144
|
+
"Kernel" => kernel_display,
|
|
145
|
+
"Boot Mode" => boot_mode,
|
|
146
|
+
"Uptime" => uptime_human
|
|
147
|
+
},
|
|
148
|
+
"CPU" => {
|
|
149
|
+
"Model" => cpu_model || "-",
|
|
150
|
+
"Cores" => cpu_cores || node.maxcpu || "-",
|
|
151
|
+
"Sockets" => cpu_sockets || "-",
|
|
152
|
+
"Usage" => cpu_percent
|
|
153
|
+
},
|
|
154
|
+
"Memory" => {
|
|
155
|
+
"Usage" => memory_percent_display(node),
|
|
156
|
+
"Used" => format_gib(node.mem),
|
|
157
|
+
"Total" => format_gib(node.maxmem)
|
|
158
|
+
},
|
|
159
|
+
"Swap" => {
|
|
160
|
+
"Usage" => swap_percent_display(node),
|
|
161
|
+
"Used" => format_gib(node.swap_used),
|
|
162
|
+
"Total" => format_gib(node.swap_total)
|
|
163
|
+
},
|
|
164
|
+
"Load Average" => {
|
|
165
|
+
"1 min" => node.loadavg&.dig(0)&.round(2) || "-",
|
|
166
|
+
"5 min" => node.loadavg&.dig(1)&.round(2) || "-",
|
|
167
|
+
"15 min" => node.loadavg&.dig(2)&.round(2) || "-"
|
|
168
|
+
},
|
|
169
|
+
"Root Filesystem" => rootfs_display,
|
|
170
|
+
"Network Interfaces" => format_network_interfaces(node.network_interfaces),
|
|
171
|
+
"DNS" => {
|
|
172
|
+
"Search" => dns_search,
|
|
173
|
+
"Nameservers" => dns_nameservers
|
|
174
|
+
},
|
|
175
|
+
"Time" => {
|
|
176
|
+
"Timezone" => timezone,
|
|
177
|
+
"Local Time" => local_time
|
|
178
|
+
},
|
|
179
|
+
"Services" => format_services(node.services),
|
|
180
|
+
"Storage Pools" => format_storage_pools(node.storage_pools),
|
|
181
|
+
"Physical Disks" => format_physical_disks(node.physical_disks),
|
|
182
|
+
"Capabilities" => {
|
|
183
|
+
"QEMU CPU Models" => format_cpu_models(node.qemu_cpu_models),
|
|
184
|
+
"QEMU Machines" => format_machines(node.qemu_machines)
|
|
185
|
+
},
|
|
186
|
+
"Guests" => {
|
|
187
|
+
"VMs" => node.guests_vms,
|
|
188
|
+
"Containers" => node.guests_cts,
|
|
189
|
+
"Total" => node.guests_total
|
|
190
|
+
},
|
|
191
|
+
"Updates" => {
|
|
192
|
+
"Available" => "#{node.updates_available} packages"
|
|
193
|
+
},
|
|
194
|
+
"Firewall" => format_firewall(node.firewall),
|
|
195
|
+
"Firewall Rules" => format_firewall_rules(node.firewall),
|
|
196
|
+
"Task History" => format_task_history(node.tasks),
|
|
197
|
+
"Alerts" => alerts_display
|
|
198
|
+
}
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# -----------------------------------------------------------------
|
|
202
|
+
# Display Methods (moved from Models::Node)
|
|
203
|
+
# -----------------------------------------------------------------
|
|
204
|
+
|
|
205
|
+
# Returns CPU usage as percentage string.
|
|
206
|
+
#
|
|
207
|
+
# @return [String] CPU percentage (e.g., "23%") or "-" if offline/unavailable
|
|
208
|
+
def cpu_percent
|
|
209
|
+
return "-" if node.offline? || node.cpu.nil?
|
|
210
|
+
|
|
211
|
+
"#{(node.cpu * 100).round}%"
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Returns memory used in GB.
|
|
215
|
+
#
|
|
216
|
+
# @return [Float, nil] memory used in GB, or nil if unavailable
|
|
217
|
+
def memory_used_gb
|
|
218
|
+
return nil if node.mem.nil?
|
|
219
|
+
|
|
220
|
+
(node.mem.to_f / 1024 / 1024 / 1024).round(1)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Returns total memory in GB.
|
|
224
|
+
#
|
|
225
|
+
# @return [Integer, nil] total memory in GB, or nil if unavailable
|
|
226
|
+
def memory_total_gb
|
|
227
|
+
return nil if node.maxmem.nil?
|
|
228
|
+
|
|
229
|
+
(node.maxmem.to_f / 1024 / 1024 / 1024).round(0)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Returns memory formatted as "used/total GB".
|
|
233
|
+
#
|
|
234
|
+
# @return [String] formatted memory (e.g., "45.2/128 GB") or "-" if offline
|
|
235
|
+
def memory_display
|
|
236
|
+
return "-" if node.offline? || memory_total_gb.nil?
|
|
237
|
+
return "-/#{memory_total_gb} GB" if memory_used_gb.nil?
|
|
238
|
+
|
|
239
|
+
"#{memory_used_gb}/#{memory_total_gb} GB"
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Returns disk used in GB.
|
|
243
|
+
#
|
|
244
|
+
# @return [Float, nil] disk used in GB, or nil if unavailable
|
|
245
|
+
def disk_used_gb
|
|
246
|
+
return nil if node.disk.nil?
|
|
247
|
+
|
|
248
|
+
(node.disk.to_f / 1024 / 1024 / 1024).round(1)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Returns total disk in GB.
|
|
252
|
+
#
|
|
253
|
+
# @return [Float, nil] total disk in GB, or nil if unavailable
|
|
254
|
+
def disk_total_gb
|
|
255
|
+
return nil if node.maxdisk.nil?
|
|
256
|
+
|
|
257
|
+
(node.maxdisk.to_f / 1024 / 1024 / 1024).round(1)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Returns disk formatted with appropriate unit (GB or TB).
|
|
261
|
+
#
|
|
262
|
+
# Uses GB for disks under 1 TB, TB for larger disks.
|
|
263
|
+
# This provides better readability for smaller storage.
|
|
264
|
+
#
|
|
265
|
+
# @return [String] formatted disk (e.g., "85/100 GB" or "1.2/4.0 TB") or "-" if offline
|
|
266
|
+
def storage_display
|
|
267
|
+
return "-" if node.offline? || node.maxdisk.nil?
|
|
268
|
+
|
|
269
|
+
total_gb = disk_total_gb
|
|
270
|
+
used_gb = disk_used_gb || 0.0
|
|
271
|
+
|
|
272
|
+
if total_gb >= 1024
|
|
273
|
+
# Use TB for disks >= 1 TB
|
|
274
|
+
used_tb = (used_gb / 1024).round(1)
|
|
275
|
+
total_tb = (total_gb / 1024).round(1)
|
|
276
|
+
"#{used_tb}/#{total_tb} TB"
|
|
277
|
+
else
|
|
278
|
+
# Use GB for smaller disks
|
|
279
|
+
"#{used_gb.round(0).to_i}/#{total_gb.round(0).to_i} GB"
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Returns swap used in GB.
|
|
284
|
+
#
|
|
285
|
+
# @return [Float, nil] swap used in GB, or nil if unavailable
|
|
286
|
+
def swap_used_gb
|
|
287
|
+
return nil if node.swap_used.nil?
|
|
288
|
+
|
|
289
|
+
(node.swap_used.to_f / 1024 / 1024 / 1024).round(1)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Returns total swap in GB.
|
|
293
|
+
#
|
|
294
|
+
# @return [Integer, nil] total swap in GB, or nil if unavailable
|
|
295
|
+
def swap_total_gb
|
|
296
|
+
return nil if node.swap_total.nil?
|
|
297
|
+
|
|
298
|
+
(node.swap_total.to_f / 1024 / 1024 / 1024).round(0)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Returns swap formatted as "used/total GB".
|
|
302
|
+
#
|
|
303
|
+
# @return [String] formatted swap (e.g., "0.0/8 GB") or "-" if offline
|
|
304
|
+
def swap_display
|
|
305
|
+
return "-" if node.offline? || swap_total_gb.nil?
|
|
306
|
+
|
|
307
|
+
"#{swap_used_gb}/#{swap_total_gb} GB"
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Returns 1-minute load average.
|
|
311
|
+
#
|
|
312
|
+
# @return [Float, nil] 1-minute load average, or nil if unavailable
|
|
313
|
+
def load_1m
|
|
314
|
+
return nil if node.loadavg.nil? || node.loadavg.empty?
|
|
315
|
+
|
|
316
|
+
node.loadavg[0]
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Returns load average display with high-load indicator.
|
|
320
|
+
#
|
|
321
|
+
# @return [String] load average (e.g., "0.45" or "2.31\u2191") or "-" if offline
|
|
322
|
+
def load_display
|
|
323
|
+
return "-" if node.offline? || load_1m.nil?
|
|
324
|
+
|
|
325
|
+
load = load_1m.round(2)
|
|
326
|
+
load > 2.0 ? "#{load}\u2191" : load.to_s
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Returns uptime in human-readable format.
|
|
330
|
+
#
|
|
331
|
+
# @return [String] formatted uptime (e.g., "45d 3h") or "-" if offline
|
|
332
|
+
def uptime_human
|
|
333
|
+
return "-" if node.offline? || node.uptime.nil? || node.uptime.zero?
|
|
334
|
+
|
|
335
|
+
days = node.uptime / 86_400
|
|
336
|
+
hours = (node.uptime % 86_400) / 3600
|
|
337
|
+
minutes = (node.uptime % 3600) / 60
|
|
338
|
+
|
|
339
|
+
if days.positive?
|
|
340
|
+
"#{days}d #{hours}h"
|
|
341
|
+
elsif hours.positive?
|
|
342
|
+
"#{hours}h #{minutes}m"
|
|
343
|
+
else
|
|
344
|
+
"#{minutes}m"
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# Returns version display.
|
|
349
|
+
#
|
|
350
|
+
# @return [String] version (e.g., "8.3.2") or "-" if unavailable
|
|
351
|
+
def version_display
|
|
352
|
+
node.version || "-"
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Returns kernel display.
|
|
356
|
+
#
|
|
357
|
+
# @return [String] kernel version or "-" if unavailable
|
|
358
|
+
def kernel_display
|
|
359
|
+
node.kernel || "-"
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# Returns IP address for display.
|
|
363
|
+
#
|
|
364
|
+
# @return [String] IP address or "-" if unavailable
|
|
365
|
+
def ip_display
|
|
366
|
+
node.ip || "-"
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# Returns array of alert messages for this node.
|
|
370
|
+
#
|
|
371
|
+
# Alerts are generated based on thresholds:
|
|
372
|
+
# - CPU >= 90%: critical
|
|
373
|
+
# - CPU >= 80%: warning
|
|
374
|
+
# - Memory >= 90%: critical
|
|
375
|
+
# - Memory >= 80%: warning
|
|
376
|
+
# - Status offline: always alert
|
|
377
|
+
#
|
|
378
|
+
# @return [Array<String>] list of alert messages
|
|
379
|
+
def alerts
|
|
380
|
+
result = []
|
|
381
|
+
result << "Node offline" if node.offline?
|
|
382
|
+
|
|
383
|
+
if node.online?
|
|
384
|
+
cpu_pct = node.cpu.nil? ? 0 : (node.cpu * 100).round
|
|
385
|
+
mem_pct = (node.maxmem.nil? || node.maxmem.zero?) ? 0 : ((node.mem.to_f / node.maxmem) * 100).round
|
|
386
|
+
|
|
387
|
+
result << "CPU critical (#{cpu_pct}%)" if cpu_pct >= 90
|
|
388
|
+
result << "CPU warning (#{cpu_pct}%)" if cpu_pct >= 80 && cpu_pct < 90
|
|
389
|
+
result << "Memory critical (#{mem_pct}%)" if mem_pct >= 90
|
|
390
|
+
result << "Memory warning (#{mem_pct}%)" if mem_pct >= 80 && mem_pct < 90
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
result
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
# Returns alerts as comma-separated string for display.
|
|
397
|
+
#
|
|
398
|
+
# @return [String] alerts (e.g., "CPU critical (92%), Memory warning") or "-" if none
|
|
399
|
+
def alerts_display
|
|
400
|
+
alerts.empty? ? "-" : alerts.join(", ")
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Checks if node has any alerts.
|
|
404
|
+
#
|
|
405
|
+
# @return [Boolean] true if alerts exist
|
|
406
|
+
def has_alerts?
|
|
407
|
+
!alerts.empty?
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# Returns CPU model name.
|
|
411
|
+
#
|
|
412
|
+
# @return [String, nil] CPU model
|
|
413
|
+
def cpu_model
|
|
414
|
+
node.cpuinfo&.dig(:model)
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# Returns CPU socket count.
|
|
418
|
+
#
|
|
419
|
+
# @return [Integer, nil] socket count
|
|
420
|
+
def cpu_sockets
|
|
421
|
+
node.cpuinfo&.dig(:sockets)
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
# Returns CPU core count (total).
|
|
425
|
+
#
|
|
426
|
+
# @return [Integer, nil] core count
|
|
427
|
+
def cpu_cores
|
|
428
|
+
node.cpuinfo&.dig(:cores)
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
# Returns boot mode.
|
|
432
|
+
#
|
|
433
|
+
# @return [String] "UEFI" or "BIOS" or "-"
|
|
434
|
+
def boot_mode
|
|
435
|
+
mode = node.boot_info&.dig(:mode)
|
|
436
|
+
case mode
|
|
437
|
+
when "efi" then "UEFI"
|
|
438
|
+
when "bios" then "BIOS"
|
|
439
|
+
else "-"
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
# Returns subscription status display.
|
|
444
|
+
#
|
|
445
|
+
# @return [String] e.g., "Active (Community)" or "Inactive"
|
|
446
|
+
def subscription_display
|
|
447
|
+
return "-" if node.subscription.nil?
|
|
448
|
+
|
|
449
|
+
status = node.subscription[:status]
|
|
450
|
+
level = node.subscription[:level]
|
|
451
|
+
|
|
452
|
+
level_name = case level
|
|
453
|
+
when "c" then "Community"
|
|
454
|
+
when "b" then "Basic"
|
|
455
|
+
when "s" then "Standard"
|
|
456
|
+
when "p" then "Premium"
|
|
457
|
+
else level
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
status == "Active" ? "Active (#{level_name})" : "Inactive"
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
# Returns timezone.
|
|
464
|
+
#
|
|
465
|
+
# @return [String] timezone or "-"
|
|
466
|
+
def timezone
|
|
467
|
+
node.time_info&.dig(:timezone) || "-"
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
# Returns local time formatted.
|
|
471
|
+
#
|
|
472
|
+
# @return [String] local time or "-"
|
|
473
|
+
def local_time
|
|
474
|
+
localtime = node.time_info&.dig(:localtime)
|
|
475
|
+
return "-" if localtime.nil?
|
|
476
|
+
|
|
477
|
+
Time.at(localtime).strftime("%Y-%m-%d %H:%M:%S")
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
# Returns DNS search domain.
|
|
481
|
+
#
|
|
482
|
+
# @return [String] search domain or "-"
|
|
483
|
+
def dns_search
|
|
484
|
+
node.dns&.dig(:search) || "-"
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
# Returns DNS nameservers.
|
|
488
|
+
#
|
|
489
|
+
# @return [String] comma-separated nameservers or "-"
|
|
490
|
+
def dns_nameservers
|
|
491
|
+
servers = [node.dns&.dig(:dns1), node.dns&.dig(:dns2), node.dns&.dig(:dns3)].compact
|
|
492
|
+
servers.empty? ? "-" : servers.join(", ")
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
# Returns rootfs usage percentage.
|
|
496
|
+
#
|
|
497
|
+
# @return [Integer, nil] percentage
|
|
498
|
+
def rootfs_usage_percent
|
|
499
|
+
return nil if node.rootfs.nil? || node.rootfs[:total].nil? || node.rootfs[:total].zero?
|
|
500
|
+
|
|
501
|
+
((node.rootfs[:used].to_f / node.rootfs[:total]) * 100).round
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
# Returns rootfs display.
|
|
505
|
+
#
|
|
506
|
+
# @return [String] e.g., "30% (1.2/4.0 TiB)"
|
|
507
|
+
def rootfs_display
|
|
508
|
+
return "-" if node.rootfs.nil?
|
|
509
|
+
|
|
510
|
+
used_gb = (node.rootfs[:used].to_f / 1024 / 1024 / 1024).round(1)
|
|
511
|
+
total_gb = (node.rootfs[:total].to_f / 1024 / 1024 / 1024).round(1)
|
|
512
|
+
pct = rootfs_usage_percent || 0
|
|
513
|
+
|
|
514
|
+
if total_gb >= 1024
|
|
515
|
+
"#{pct}% (#{(used_gb / 1024).round(1)}/#{(total_gb / 1024).round(1)} TiB)"
|
|
516
|
+
else
|
|
517
|
+
"#{pct}% (#{used_gb}/#{total_gb} GiB)"
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
private
|
|
522
|
+
|
|
523
|
+
# @return [Models::Node] the current node being presented
|
|
524
|
+
attr_reader :node
|
|
525
|
+
alias resource node
|
|
526
|
+
|
|
527
|
+
# Returns description for offline nodes.
|
|
528
|
+
#
|
|
529
|
+
# @return [Hash] minimal description
|
|
530
|
+
def offline_description
|
|
531
|
+
{
|
|
532
|
+
"Name" => node.name,
|
|
533
|
+
"Status" => node.status,
|
|
534
|
+
"Note" => node.offline_note || "Node is offline. Detailed metrics unavailable."
|
|
535
|
+
}
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
# Returns memory percentage for display.
|
|
539
|
+
#
|
|
540
|
+
# @param model [Models::Node] Node model
|
|
541
|
+
# @return [String] percentage string
|
|
542
|
+
def memory_percent_display(model)
|
|
543
|
+
pct = memory_percent(model)
|
|
544
|
+
pct ? "#{pct.round}%" : "-"
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
# Returns swap percentage for display.
|
|
548
|
+
#
|
|
549
|
+
# @param model [Models::Node] Node model
|
|
550
|
+
# @return [String] percentage string
|
|
551
|
+
def swap_percent_display(model)
|
|
552
|
+
pct = swap_percent(model)
|
|
553
|
+
pct ? "#{pct.round}%" : "-"
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
# Formats bytes to GiB string.
|
|
557
|
+
#
|
|
558
|
+
# @param bytes [Integer, nil] bytes value
|
|
559
|
+
# @return [String] formatted GiB string
|
|
560
|
+
def format_gib(bytes)
|
|
561
|
+
return "-" if bytes.nil?
|
|
562
|
+
|
|
563
|
+
"#{(bytes.to_f / 1024 / 1024 / 1024).round(1)} GiB"
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
# Formats network interfaces for table display.
|
|
567
|
+
#
|
|
568
|
+
# @param interfaces [Array<Hash>] network interfaces
|
|
569
|
+
# @return [Array<Hash>, String] formatted interfaces or "-"
|
|
570
|
+
def format_network_interfaces(interfaces)
|
|
571
|
+
return "-" if interfaces.nil? || interfaces.empty?
|
|
572
|
+
|
|
573
|
+
interfaces.map do |iface|
|
|
574
|
+
{
|
|
575
|
+
"Name" => iface[:iface],
|
|
576
|
+
"Type" => iface[:type],
|
|
577
|
+
"Address" => iface[:address] || iface[:cidr] || "-",
|
|
578
|
+
"Gateway" => iface[:gateway] || "-"
|
|
579
|
+
}
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
# Formats services for table display.
|
|
584
|
+
#
|
|
585
|
+
# @param services [Array<Hash>] services
|
|
586
|
+
# @return [Array<Hash>, String] formatted services or "-"
|
|
587
|
+
def format_services(services)
|
|
588
|
+
return "-" if services.nil? || services.empty?
|
|
589
|
+
|
|
590
|
+
services.map do |svc|
|
|
591
|
+
{
|
|
592
|
+
"Name" => svc[:service] || svc[:name],
|
|
593
|
+
"State" => svc[:state],
|
|
594
|
+
"Description" => svc[:desc] || "-"
|
|
595
|
+
}
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
# Formats storage pools for table display.
|
|
600
|
+
#
|
|
601
|
+
# Supports both Models::Storage instances (new format) and Hash (legacy).
|
|
602
|
+
#
|
|
603
|
+
# @param pools [Array<Models::Storage>, Array<Hash>] storage pools
|
|
604
|
+
# @return [Array<Hash>, String] formatted pools or "-"
|
|
605
|
+
def format_storage_pools(pools)
|
|
606
|
+
return "-" if pools.nil? || pools.empty?
|
|
607
|
+
|
|
608
|
+
# Handle both Models::Storage and Hash formats
|
|
609
|
+
pools.select { |p| storage_enabled?(p) }.map do |pool|
|
|
610
|
+
format_storage_pool(pool)
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
# Formats physical disks for table display.
|
|
615
|
+
#
|
|
616
|
+
# @param disks [Array<Hash>] physical disks
|
|
617
|
+
# @return [Array<Hash>, String] formatted disks or "-"
|
|
618
|
+
def format_physical_disks(disks)
|
|
619
|
+
return "-" if disks.nil? || disks.empty?
|
|
620
|
+
|
|
621
|
+
disks.map do |disk|
|
|
622
|
+
size_gb = disk[:size] ? (disk[:size].to_f / 1024 / 1024 / 1024).round(1) : 0
|
|
623
|
+
{
|
|
624
|
+
"Device" => disk[:devpath],
|
|
625
|
+
"Model" => disk[:model] || "-",
|
|
626
|
+
"Size" => format_storage_size(size_gb),
|
|
627
|
+
"Type" => disk[:type] || "-",
|
|
628
|
+
"Health" => disk[:health] || "-"
|
|
629
|
+
}
|
|
630
|
+
end
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
# Formats CPU models list as a table.
|
|
634
|
+
#
|
|
635
|
+
# @param models [Array<Hash>] CPU models from API
|
|
636
|
+
# @return [Array<Hash>, String] table rows or "-"
|
|
637
|
+
def format_cpu_models(models)
|
|
638
|
+
return "-" if models.nil? || models.empty?
|
|
639
|
+
|
|
640
|
+
models.map do |m|
|
|
641
|
+
{ "Name" => m[:name] || "-", "Vendor" => m[:vendor] || "-" }
|
|
642
|
+
end
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
# Formats machine types list as a table.
|
|
646
|
+
#
|
|
647
|
+
# @param machines [Array<Hash>] machine types from API
|
|
648
|
+
# @return [Array<Hash>, String] table rows or "-"
|
|
649
|
+
def format_machines(machines)
|
|
650
|
+
return "-" if machines.nil? || machines.empty?
|
|
651
|
+
|
|
652
|
+
machines.map do |m|
|
|
653
|
+
{ "ID" => m[:id] || "-", "Type" => m[:type] || "-" }
|
|
654
|
+
end
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
# Calculates memory usage percentage.
|
|
658
|
+
#
|
|
659
|
+
# @param model [Models::Node] Node model
|
|
660
|
+
# @return [Float, nil] memory usage percentage or nil if unavailable
|
|
661
|
+
def memory_percent(model)
|
|
662
|
+
return nil if model.maxmem.nil? || model.maxmem.zero? || model.mem.nil?
|
|
663
|
+
|
|
664
|
+
((model.mem.to_f / model.maxmem) * 100).round(1)
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
# Calculates swap usage percentage.
|
|
668
|
+
#
|
|
669
|
+
# @param model [Models::Node] Node model
|
|
670
|
+
# @return [Float, nil] swap usage percentage or nil if unavailable
|
|
671
|
+
def swap_percent(model)
|
|
672
|
+
return nil if model.swap_total.nil? || model.swap_total.zero? || model.swap_used.nil?
|
|
673
|
+
|
|
674
|
+
((model.swap_used.to_f / model.swap_total) * 100).round(1)
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
# Calculates storage usage percentage.
|
|
678
|
+
#
|
|
679
|
+
# @param model [Models::Node] Node model
|
|
680
|
+
# @return [Float, nil] storage usage percentage or nil if unavailable
|
|
681
|
+
def storage_percent(model)
|
|
682
|
+
return nil if model.maxdisk.nil? || model.maxdisk.zero? || model.disk.nil?
|
|
683
|
+
|
|
684
|
+
((model.disk.to_f / model.maxdisk) * 100).round(1)
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
# Checks if storage pool is enabled.
|
|
688
|
+
# Supports both Models::Storage and Hash formats.
|
|
689
|
+
#
|
|
690
|
+
# @param pool [Models::Storage, Hash] storage pool
|
|
691
|
+
# @return [Boolean] true if enabled
|
|
692
|
+
def storage_enabled?(pool)
|
|
693
|
+
if pool.respond_to?(:enabled?)
|
|
694
|
+
pool.enabled?
|
|
695
|
+
else
|
|
696
|
+
pool[:enabled] != 0
|
|
697
|
+
end
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
# Formats a single storage pool for display.
|
|
701
|
+
# Supports both Models::Storage and Hash formats.
|
|
702
|
+
#
|
|
703
|
+
# @param pool [Models::Storage, Hash] storage pool
|
|
704
|
+
# @return [Hash] formatted pool data
|
|
705
|
+
def format_storage_pool(pool)
|
|
706
|
+
if pool.respond_to?(:name)
|
|
707
|
+
# Models::Storage instance - use Storage presenter for display
|
|
708
|
+
format_storage_pool_model(pool)
|
|
709
|
+
else
|
|
710
|
+
# Hash format (legacy)
|
|
711
|
+
format_storage_pool_hash(pool)
|
|
712
|
+
end
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
# Formats a storage pool from Models::Storage instance.
|
|
716
|
+
# Uses Storage presenter for display formatting.
|
|
717
|
+
#
|
|
718
|
+
# @param pool [Models::Storage] storage pool model
|
|
719
|
+
# @return [Hash] formatted pool data
|
|
720
|
+
def format_storage_pool_model(pool)
|
|
721
|
+
storage_presenter = Storage.new
|
|
722
|
+
storage_presenter.to_row(pool) # Set up @storage in presenter
|
|
723
|
+
{
|
|
724
|
+
"Name" => pool.name,
|
|
725
|
+
"Type" => storage_presenter.type_display,
|
|
726
|
+
"Total" => storage_presenter.total_display,
|
|
727
|
+
"Used" => storage_presenter.used_display,
|
|
728
|
+
"Available" => storage_presenter.avail_display,
|
|
729
|
+
"Usage" => storage_presenter.usage_display
|
|
730
|
+
}
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
# Formats a storage pool from Hash data (legacy format).
|
|
734
|
+
#
|
|
735
|
+
# @param pool [Hash] storage pool hash
|
|
736
|
+
# @return [Hash] formatted pool data
|
|
737
|
+
def format_storage_pool_hash(pool)
|
|
738
|
+
total_gb = pool[:total] ? (pool[:total].to_f / 1024 / 1024 / 1024).round(1) : 0
|
|
739
|
+
used_gb = pool[:used] ? (pool[:used].to_f / 1024 / 1024 / 1024).round(1) : 0
|
|
740
|
+
avail_gb = pool[:avail] ? (pool[:avail].to_f / 1024 / 1024 / 1024).round(1) : 0
|
|
741
|
+
usage_pct = pool[:total] && pool[:total] > 0 ? ((pool[:used].to_f / pool[:total]) * 100).round : 0
|
|
742
|
+
|
|
743
|
+
{
|
|
744
|
+
"Name" => pool[:storage],
|
|
745
|
+
"Type" => pool[:type],
|
|
746
|
+
"Total" => format_storage_size(total_gb),
|
|
747
|
+
"Used" => format_storage_size(used_gb),
|
|
748
|
+
"Available" => format_storage_size(avail_gb),
|
|
749
|
+
"Usage" => "#{usage_pct}%"
|
|
750
|
+
}
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
# Formats storage size with appropriate unit.
|
|
754
|
+
#
|
|
755
|
+
# @param gb [Float] size in GB
|
|
756
|
+
# @return [String] formatted size
|
|
757
|
+
def format_storage_size(gb)
|
|
758
|
+
gb >= 1024 ? "#{(gb / 1024).round(1)} TiB" : "#{gb} GiB"
|
|
759
|
+
end
|
|
760
|
+
end
|
|
761
|
+
end
|
|
762
|
+
end
|