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,574 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "set"
|
|
4
|
+
|
|
5
|
+
module Pvectl
|
|
6
|
+
module Presenters
|
|
7
|
+
# Presenter for LXC containers.
|
|
8
|
+
#
|
|
9
|
+
# Defines column layout and formatting for table output.
|
|
10
|
+
# Used by formatters to render container data in various formats.
|
|
11
|
+
#
|
|
12
|
+
# Standard columns: NAME, CTID, STATUS, NODE, CPU, MEMORY
|
|
13
|
+
# Wide columns add: UPTIME, TEMPLATE, TAGS, SWAP, DISK, NETIN, NETOUT, POOL
|
|
14
|
+
#
|
|
15
|
+
# Description output is organized by Proxmox VE web UI tabs:
|
|
16
|
+
# Summary, Resources, Network, DNS, Options, Task History, Snapshots, HA.
|
|
17
|
+
#
|
|
18
|
+
# @example Using with formatter
|
|
19
|
+
# presenter = Container.new
|
|
20
|
+
# formatter = Formatters::Table.new
|
|
21
|
+
# output = formatter.format(containers, presenter)
|
|
22
|
+
#
|
|
23
|
+
# @see Pvectl::Models::Container Container model
|
|
24
|
+
# @see Pvectl::Formatters::Table Table formatter
|
|
25
|
+
#
|
|
26
|
+
class Container < Base
|
|
27
|
+
# Returns column headers for standard table output.
|
|
28
|
+
#
|
|
29
|
+
# @return [Array<String>] column headers
|
|
30
|
+
def columns
|
|
31
|
+
%w[NAME CTID STATUS NODE CPU MEMORY]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Returns additional column headers for wide output.
|
|
35
|
+
#
|
|
36
|
+
# @return [Array<String>] extra column headers
|
|
37
|
+
def extra_columns
|
|
38
|
+
%w[UPTIME TEMPLATE TAGS SWAP DISK NETIN NETOUT POOL]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Converts Container model to table row values.
|
|
42
|
+
#
|
|
43
|
+
# @param model [Models::Container] Container model
|
|
44
|
+
# @param context [Hash] optional context
|
|
45
|
+
# @return [Array<String>] row values matching columns order
|
|
46
|
+
def to_row(model, **_context)
|
|
47
|
+
@container = model
|
|
48
|
+
[
|
|
49
|
+
display_name,
|
|
50
|
+
container.vmid.to_s,
|
|
51
|
+
container.status,
|
|
52
|
+
container.node,
|
|
53
|
+
cpu_percent,
|
|
54
|
+
memory_display
|
|
55
|
+
]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns additional values for wide output.
|
|
59
|
+
#
|
|
60
|
+
# @param model [Models::Container] Container model
|
|
61
|
+
# @param context [Hash] optional context
|
|
62
|
+
# @return [Array<String>] extra values matching extra_columns order
|
|
63
|
+
def extra_values(model, **_context)
|
|
64
|
+
@container = model
|
|
65
|
+
[
|
|
66
|
+
uptime_human,
|
|
67
|
+
template_display,
|
|
68
|
+
tags_display,
|
|
69
|
+
swap_display,
|
|
70
|
+
disk_display,
|
|
71
|
+
netin_display,
|
|
72
|
+
netout_display,
|
|
73
|
+
pool_display
|
|
74
|
+
]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Converts Container model to hash for JSON/YAML output.
|
|
78
|
+
#
|
|
79
|
+
# Returns a structured hash with nested objects for complex data
|
|
80
|
+
# like CPU, memory, swap, disk, uptime, and network.
|
|
81
|
+
#
|
|
82
|
+
# @param model [Models::Container] Container model
|
|
83
|
+
# @return [Hash] hash representation with string keys
|
|
84
|
+
def to_hash(model)
|
|
85
|
+
@container = model
|
|
86
|
+
{
|
|
87
|
+
"ctid" => container.vmid,
|
|
88
|
+
"name" => container.name,
|
|
89
|
+
"status" => container.status,
|
|
90
|
+
"node" => container.node,
|
|
91
|
+
"template" => container.template?,
|
|
92
|
+
"pool" => container.pool,
|
|
93
|
+
"cpu" => {
|
|
94
|
+
"usage_percent" => container.cpu.nil? ? nil : (container.cpu * 100).round,
|
|
95
|
+
"cores" => container.maxcpu
|
|
96
|
+
},
|
|
97
|
+
"memory" => {
|
|
98
|
+
"used_gib" => memory_used_gib,
|
|
99
|
+
"total_gib" => memory_total_gib,
|
|
100
|
+
"used_bytes" => container.mem,
|
|
101
|
+
"total_bytes" => container.maxmem
|
|
102
|
+
},
|
|
103
|
+
"swap" => {
|
|
104
|
+
"used_mib" => swap_used_mib,
|
|
105
|
+
"total_mib" => swap_total_mib,
|
|
106
|
+
"used_bytes" => container.swap,
|
|
107
|
+
"total_bytes" => container.maxswap
|
|
108
|
+
},
|
|
109
|
+
"disk" => {
|
|
110
|
+
"used_gib" => disk_used_gib,
|
|
111
|
+
"total_gib" => disk_total_gib,
|
|
112
|
+
"used_bytes" => container.disk,
|
|
113
|
+
"total_bytes" => container.maxdisk
|
|
114
|
+
},
|
|
115
|
+
"uptime" => {
|
|
116
|
+
"seconds" => container.uptime,
|
|
117
|
+
"human" => uptime_human
|
|
118
|
+
},
|
|
119
|
+
"network" => {
|
|
120
|
+
"in_bytes" => container.netin,
|
|
121
|
+
"out_bytes" => container.netout
|
|
122
|
+
},
|
|
123
|
+
"tags" => tags_array
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Converts Container model to description format for describe command.
|
|
128
|
+
#
|
|
129
|
+
# Returns a structured Hash organized by Proxmox VE web UI tabs:
|
|
130
|
+
# Summary, Resources, Network, DNS, Options, Task History, Snapshots,
|
|
131
|
+
# High Availability. Nested Hashes create indented subsections.
|
|
132
|
+
# Arrays of Hashes render as inline tables.
|
|
133
|
+
#
|
|
134
|
+
# @param model [Models::Container] Container model with describe details
|
|
135
|
+
# @return [Hash] structured hash for describe formatter
|
|
136
|
+
def to_description(model)
|
|
137
|
+
@container = model
|
|
138
|
+
@consumed_keys = Set.new
|
|
139
|
+
data = container.describe_data || {}
|
|
140
|
+
config = data[:config] || {}
|
|
141
|
+
|
|
142
|
+
consume(:hostname, :description, :tags, :pool, :template, :lxc)
|
|
143
|
+
|
|
144
|
+
{
|
|
145
|
+
"Name" => display_name,
|
|
146
|
+
"CTID" => container.vmid,
|
|
147
|
+
"Status" => container.status,
|
|
148
|
+
"Node" => container.node,
|
|
149
|
+
"Tags" => tags_display,
|
|
150
|
+
"Description" => container.description || config[:description] || "-",
|
|
151
|
+
"Summary" => format_summary,
|
|
152
|
+
"Resources" => format_resources(config),
|
|
153
|
+
"Network" => format_network_interfaces(config),
|
|
154
|
+
"DNS" => format_dns(config),
|
|
155
|
+
"Options" => format_options(config),
|
|
156
|
+
"Firewall" => format_firewall(data[:firewall]),
|
|
157
|
+
"Firewall Rules" => format_firewall_rules(data[:firewall]),
|
|
158
|
+
"Task History" => format_task_history(data[:tasks]),
|
|
159
|
+
"Snapshots" => format_snapshots(data[:snapshots]),
|
|
160
|
+
"High Availability" => format_ha,
|
|
161
|
+
"Additional Configuration" => format_remaining(config)
|
|
162
|
+
}
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# ---------------------------
|
|
166
|
+
# Display Methods
|
|
167
|
+
# ---------------------------
|
|
168
|
+
|
|
169
|
+
# Returns display name, falling back to "CT-{ctid}" if name is nil.
|
|
170
|
+
#
|
|
171
|
+
# @return [String] display name
|
|
172
|
+
def display_name
|
|
173
|
+
container.name || "CT-#{container.vmid}"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Returns CPU usage as percentage string.
|
|
177
|
+
#
|
|
178
|
+
# For running containers, shows actual usage percentage.
|
|
179
|
+
# For stopped containers, shows "-" for usage but includes core count if available.
|
|
180
|
+
#
|
|
181
|
+
# @return [String] CPU percentage (e.g., "12%/4") or "-/4" for stopped containers
|
|
182
|
+
def cpu_percent
|
|
183
|
+
return "-" if container.maxcpu.nil?
|
|
184
|
+
return "-/#{container.maxcpu}" unless container.running?
|
|
185
|
+
return "-/#{container.maxcpu}" if container.cpu.nil?
|
|
186
|
+
|
|
187
|
+
"#{(container.cpu * 100).round}%/#{container.maxcpu}"
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Returns memory used in GiB.
|
|
191
|
+
#
|
|
192
|
+
# @return [Float, nil] memory used in GiB, or nil if unavailable
|
|
193
|
+
def memory_used_gib
|
|
194
|
+
return nil if container.mem.nil?
|
|
195
|
+
|
|
196
|
+
(container.mem.to_f / 1024 / 1024 / 1024).round(1)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Returns total memory in GiB.
|
|
200
|
+
#
|
|
201
|
+
# @return [Float, nil] total memory in GiB, or nil if unavailable
|
|
202
|
+
def memory_total_gib
|
|
203
|
+
return nil if container.maxmem.nil?
|
|
204
|
+
|
|
205
|
+
(container.maxmem.to_f / 1024 / 1024 / 1024).round(1)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Returns memory formatted as "used/total GiB".
|
|
209
|
+
#
|
|
210
|
+
# For running containers, shows actual usage and total.
|
|
211
|
+
# For stopped containers, shows "-" for usage but includes total if available.
|
|
212
|
+
#
|
|
213
|
+
# @return [String] formatted memory (e.g., "2.1/4.0 GiB") or "-/4.0 GiB" for stopped
|
|
214
|
+
def memory_display
|
|
215
|
+
return "-" if memory_total_gib.nil?
|
|
216
|
+
return "-/#{memory_total_gib} GiB" unless container.running?
|
|
217
|
+
return "-/#{memory_total_gib} GiB" if memory_used_gib.nil?
|
|
218
|
+
|
|
219
|
+
"#{memory_used_gib}/#{memory_total_gib} GiB"
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Returns swap used in MiB.
|
|
223
|
+
#
|
|
224
|
+
# @return [Float, nil] swap used in MiB, or nil if unavailable
|
|
225
|
+
def swap_used_mib
|
|
226
|
+
return nil if container.swap.nil?
|
|
227
|
+
|
|
228
|
+
(container.swap.to_f / 1024 / 1024).round(1)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Returns total swap in MiB.
|
|
232
|
+
#
|
|
233
|
+
# @return [Float, nil] total swap in MiB, or nil if unavailable
|
|
234
|
+
def swap_total_mib
|
|
235
|
+
return nil if container.maxswap.nil?
|
|
236
|
+
|
|
237
|
+
(container.maxswap.to_f / 1024 / 1024).round(1)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Returns swap formatted as "used/total MiB".
|
|
241
|
+
#
|
|
242
|
+
# @return [String] formatted swap (e.g., "128/512 MiB") or "-" if unavailable
|
|
243
|
+
def swap_display
|
|
244
|
+
return "-" if swap_total_mib.nil? || swap_total_mib.zero?
|
|
245
|
+
return "-/#{swap_total_mib.round} MiB" unless container.running?
|
|
246
|
+
return "-/#{swap_total_mib.round} MiB" if swap_used_mib.nil?
|
|
247
|
+
|
|
248
|
+
"#{swap_used_mib.round}/#{swap_total_mib.round} MiB"
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Returns disk used in GiB.
|
|
252
|
+
#
|
|
253
|
+
# @return [Float, nil] disk used in GiB, or nil if unavailable
|
|
254
|
+
def disk_used_gib
|
|
255
|
+
return nil if container.disk.nil?
|
|
256
|
+
|
|
257
|
+
(container.disk.to_f / 1024 / 1024 / 1024).round(1)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Returns total disk in GiB.
|
|
261
|
+
#
|
|
262
|
+
# @return [Float, nil] total disk in GiB, or nil if unavailable
|
|
263
|
+
def disk_total_gib
|
|
264
|
+
return nil if container.maxdisk.nil?
|
|
265
|
+
|
|
266
|
+
(container.maxdisk.to_f / 1024 / 1024 / 1024).round(1)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Returns disk formatted as "used/total GiB".
|
|
270
|
+
#
|
|
271
|
+
# @return [String] formatted disk (e.g., "15.0/50.0 GiB") or "-" if unavailable
|
|
272
|
+
def disk_display
|
|
273
|
+
return "-" if disk_used_gib.nil?
|
|
274
|
+
|
|
275
|
+
"#{disk_used_gib}/#{disk_total_gib} GiB"
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Returns pool display string.
|
|
279
|
+
#
|
|
280
|
+
# @return [String] pool name or "-" if no pool
|
|
281
|
+
def pool_display
|
|
282
|
+
container.pool || "-"
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# Returns network in bytes formatted.
|
|
286
|
+
#
|
|
287
|
+
# @return [String] formatted network in (e.g., "117.7 MiB") or "-"
|
|
288
|
+
def netin_display
|
|
289
|
+
format_bytes(container.netin)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Returns network out bytes formatted.
|
|
293
|
+
#
|
|
294
|
+
# @return [String] formatted network out (e.g., "941.9 MiB") or "-"
|
|
295
|
+
def netout_display
|
|
296
|
+
format_bytes(container.netout)
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
private
|
|
300
|
+
|
|
301
|
+
# @return [Models::Container] current container model
|
|
302
|
+
attr_reader :container
|
|
303
|
+
alias resource container
|
|
304
|
+
|
|
305
|
+
# Formats Summary section (PVE Summary tab).
|
|
306
|
+
#
|
|
307
|
+
# Shows resource usage and (for running containers) runtime info
|
|
308
|
+
# including uptime, PID, and network I/O statistics.
|
|
309
|
+
#
|
|
310
|
+
# @return [Hash] summary info
|
|
311
|
+
def format_summary
|
|
312
|
+
cpu_usage = if container.running? && container.cpu
|
|
313
|
+
"#{(container.cpu * 100).round(2)}% of #{container.maxcpu || '-'} core(s)"
|
|
314
|
+
else
|
|
315
|
+
"-"
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
mem_usage = if container.running? && container.mem && container.maxmem && container.maxmem > 0
|
|
319
|
+
pct = ((container.mem.to_f / container.maxmem) * 100).round(2)
|
|
320
|
+
"#{pct}% (#{format_bytes(container.mem)} of #{format_bytes(container.maxmem)})"
|
|
321
|
+
else
|
|
322
|
+
"-"
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
swap_usage = if container.running? && container.swap && container.maxswap && container.maxswap > 0
|
|
326
|
+
"#{format_bytes(container.swap)} / #{format_bytes(container.maxswap)}"
|
|
327
|
+
else
|
|
328
|
+
"-"
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
rootfs_usage = if container.disk && container.maxdisk && container.maxdisk > 0
|
|
332
|
+
"#{format_bytes(container.disk)} / #{format_bytes(container.maxdisk)}"
|
|
333
|
+
else
|
|
334
|
+
"-"
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
result = {
|
|
338
|
+
"CPU Usage" => cpu_usage,
|
|
339
|
+
"Memory Usage" => mem_usage,
|
|
340
|
+
"Swap Usage" => swap_usage,
|
|
341
|
+
"Root FS Usage" => rootfs_usage
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if container.running?
|
|
345
|
+
result["Uptime"] = uptime_human
|
|
346
|
+
result["PID"] = (container.pid || "-").to_s
|
|
347
|
+
result["Network In"] = format_bytes(container.netin)
|
|
348
|
+
result["Network Out"] = format_bytes(container.netout)
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
result
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Formats Resources section (PVE Resources tab).
|
|
355
|
+
#
|
|
356
|
+
# Shows configured memory, swap, cores, rootfs, and mountpoints.
|
|
357
|
+
#
|
|
358
|
+
# @param config [Hash] raw config hash for key consumption
|
|
359
|
+
# @return [Hash] resources info
|
|
360
|
+
def format_resources(config)
|
|
361
|
+
consume(:memory, :swap, :cores, :rootfs)
|
|
362
|
+
|
|
363
|
+
mem_mb = config[:memory]
|
|
364
|
+
memory_str = if mem_mb
|
|
365
|
+
"#{(mem_mb.to_f / 1024).round(2)} GiB"
|
|
366
|
+
else
|
|
367
|
+
container.maxmem ? format_bytes(container.maxmem) : "-"
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
swap_mb = config[:swap]
|
|
371
|
+
swap_str = if swap_mb
|
|
372
|
+
"#{swap_mb} MiB"
|
|
373
|
+
else
|
|
374
|
+
container.maxswap ? format_bytes(container.maxswap) : "-"
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
{
|
|
378
|
+
"Memory" => memory_str,
|
|
379
|
+
"Swap" => swap_str,
|
|
380
|
+
"Cores" => (config[:cores] || container.maxcpu || "-").to_s,
|
|
381
|
+
"Root Filesystem" => format_rootfs(config),
|
|
382
|
+
"Mountpoints" => format_mountpoints(config)
|
|
383
|
+
}
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
# Formats rootfs section.
|
|
387
|
+
#
|
|
388
|
+
# @param config [Hash] raw config hash for key consumption
|
|
389
|
+
# @return [Hash] rootfs info
|
|
390
|
+
def format_rootfs(config = {})
|
|
391
|
+
size_gib = disk_total_gib ? "#{disk_total_gib} GiB" : "-"
|
|
392
|
+
used_gib = disk_used_gib ? "#{disk_used_gib} GiB" : "-"
|
|
393
|
+
|
|
394
|
+
{
|
|
395
|
+
"Size" => size_gib,
|
|
396
|
+
"Used" => used_gib
|
|
397
|
+
}
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
# Formats network interfaces for table display.
|
|
401
|
+
#
|
|
402
|
+
# @param config [Hash] raw config hash for key consumption
|
|
403
|
+
# @return [Array<Hash>, String] network interfaces or "-"
|
|
404
|
+
def format_network_interfaces(config = {})
|
|
405
|
+
consume_matching(config, /^net\d+$/)
|
|
406
|
+
interfaces = container.network_interfaces
|
|
407
|
+
return "-" if interfaces.nil? || interfaces.empty?
|
|
408
|
+
|
|
409
|
+
interfaces.map do |iface|
|
|
410
|
+
{
|
|
411
|
+
"NAME" => iface[:name] || "-",
|
|
412
|
+
"BRIDGE" => iface[:bridge] || "-",
|
|
413
|
+
"IP" => iface[:ip] || "-",
|
|
414
|
+
"MAC" => iface[:hwaddr] || "-"
|
|
415
|
+
}
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# Formats features for display.
|
|
420
|
+
#
|
|
421
|
+
# @param config [Hash] raw config hash for key consumption
|
|
422
|
+
# @return [String] formatted features or "-"
|
|
423
|
+
def format_features(config = {})
|
|
424
|
+
consume(:features)
|
|
425
|
+
features_str = container.features || config[:features]
|
|
426
|
+
return "-" if features_str.nil? || features_str.empty?
|
|
427
|
+
|
|
428
|
+
# Parse "nesting=1,keyctl=1" to "nesting, keyctl"
|
|
429
|
+
features_str.split(",").map do |f|
|
|
430
|
+
key, value = f.split("=")
|
|
431
|
+
value == "1" ? key : nil
|
|
432
|
+
end.compact.join(", ")
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
# Formats mountpoints section (mp0-mp255).
|
|
436
|
+
#
|
|
437
|
+
# @param config [Hash] container config
|
|
438
|
+
# @return [Array<Hash>, String] mountpoints table or "-"
|
|
439
|
+
def format_mountpoints(config)
|
|
440
|
+
mp_keys = config.keys.select { |k| k.to_s.match?(/^mp\d+$/) }
|
|
441
|
+
consume_matching(config, /^mp\d+$/)
|
|
442
|
+
consume_matching(config, /^unused\d+$/)
|
|
443
|
+
return "-" if mp_keys.empty?
|
|
444
|
+
|
|
445
|
+
mp_keys.sort.map do |key|
|
|
446
|
+
parts = config[key].to_s.split(",")
|
|
447
|
+
storage_part = parts.first
|
|
448
|
+
storage = storage_part.include?(":") ? storage_part.split(":").first : storage_part
|
|
449
|
+
mp_path = nil
|
|
450
|
+
size = nil
|
|
451
|
+
parts[1..].each do |part|
|
|
452
|
+
k, v = part.split("=", 2)
|
|
453
|
+
case k
|
|
454
|
+
when "mp" then mp_path = v
|
|
455
|
+
when "size" then size = v
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
{ "NAME" => key.to_s, "PATH" => mp_path || "-", "STORAGE" => storage, "SIZE" => size || "-" }
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
# Formats DNS section.
|
|
463
|
+
#
|
|
464
|
+
# @param config [Hash] container config
|
|
465
|
+
# @return [Hash, String] DNS info or "-"
|
|
466
|
+
def format_dns(config)
|
|
467
|
+
consume(:nameserver, :searchdomain)
|
|
468
|
+
ns = config[:nameserver]
|
|
469
|
+
sd = config[:searchdomain]
|
|
470
|
+
return "-" if ns.nil? && sd.nil?
|
|
471
|
+
|
|
472
|
+
{ "Nameserver" => ns || "-", "Search Domain" => sd || "-" }
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
# Formats Options section (PVE Options tab).
|
|
476
|
+
#
|
|
477
|
+
# Shows boot, startup, OS type, architecture, security, and
|
|
478
|
+
# other container options.
|
|
479
|
+
#
|
|
480
|
+
# @param config [Hash] container config
|
|
481
|
+
# @return [Hash] options info
|
|
482
|
+
def format_options(config)
|
|
483
|
+
consume(:onboot, :startup, :ostype, :arch, :unprivileged,
|
|
484
|
+
:features, :cmode, :tty, :protection, :lock, :hookscript)
|
|
485
|
+
|
|
486
|
+
on_boot = config[:onboot] == 1 ? "Yes" : "No"
|
|
487
|
+
startup = config[:startup]
|
|
488
|
+
startup_display = startup ? startup.to_s : "-"
|
|
489
|
+
ostype = container.ostype || config[:ostype] || "-"
|
|
490
|
+
arch = container.arch || config[:arch] || "-"
|
|
491
|
+
unpriv = container.unprivileged? ? "Yes" : "No"
|
|
492
|
+
features = format_features(config)
|
|
493
|
+
cmode = config[:cmode] || "tty"
|
|
494
|
+
tty_count = (config[:tty] || 2).to_s
|
|
495
|
+
protection = config[:protection] == 1 ? "Yes" : "No"
|
|
496
|
+
hookscript = config[:hookscript] || "-"
|
|
497
|
+
|
|
498
|
+
{
|
|
499
|
+
"Start at Boot" => on_boot,
|
|
500
|
+
"Startup Order" => startup_display,
|
|
501
|
+
"OS Type" => ostype,
|
|
502
|
+
"Architecture" => arch,
|
|
503
|
+
"Unprivileged" => unpriv,
|
|
504
|
+
"Features" => features,
|
|
505
|
+
"Console Mode" => cmode,
|
|
506
|
+
"TTY" => tty_count,
|
|
507
|
+
"Protection" => protection,
|
|
508
|
+
"Hookscript" => hookscript
|
|
509
|
+
}
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
# Formats snapshots section.
|
|
513
|
+
#
|
|
514
|
+
# @param snapshots [Array<Hash>, nil] snapshots from API
|
|
515
|
+
# @return [Array<Hash>, String] snapshots table or "No snapshots"
|
|
516
|
+
def format_snapshots(snapshots)
|
|
517
|
+
return "No snapshots" if snapshots.nil? || snapshots.empty?
|
|
518
|
+
|
|
519
|
+
snapshots.map do |snap|
|
|
520
|
+
snaptime = snap[:snaptime]
|
|
521
|
+
date = snaptime ? Time.at(snaptime).strftime("%Y-%m-%d %H:%M:%S") : "-"
|
|
522
|
+
{
|
|
523
|
+
"NAME" => snap[:name],
|
|
524
|
+
"DATE" => date,
|
|
525
|
+
"DESCRIPTION" => snap[:description] || "-"
|
|
526
|
+
}
|
|
527
|
+
end
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
# Formats High Availability section.
|
|
531
|
+
#
|
|
532
|
+
# @return [Hash] HA info
|
|
533
|
+
def format_ha
|
|
534
|
+
ha = container.ha
|
|
535
|
+
return { "State" => "-", "Group" => "-" } if ha.nil?
|
|
536
|
+
|
|
537
|
+
{
|
|
538
|
+
"State" => ha[:managed] == 1 ? "managed" : "-",
|
|
539
|
+
"Group" => ha[:group] || "-"
|
|
540
|
+
}
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
# Registers config keys as consumed by a format method.
|
|
544
|
+
#
|
|
545
|
+
# @param keys [Array<Symbol>] config keys to mark as consumed
|
|
546
|
+
# @return [void]
|
|
547
|
+
def consume(*keys)
|
|
548
|
+
@consumed_keys.merge(keys.map(&:to_sym))
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
# Consumes all config keys matching a pattern.
|
|
552
|
+
#
|
|
553
|
+
# @param config [Hash] config hash
|
|
554
|
+
# @param pattern [Regexp] pattern to match key names
|
|
555
|
+
# @return [void]
|
|
556
|
+
def consume_matching(config, pattern)
|
|
557
|
+
config.keys.select { |k| k.to_s.match?(pattern) }.each { |k| consume(k) }
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
# Formats remaining unconsumed config keys as catch-all table.
|
|
561
|
+
#
|
|
562
|
+
# @param config [Hash] full config hash
|
|
563
|
+
# @return [Array<Hash>, String] remaining keys table or "-"
|
|
564
|
+
def format_remaining(config)
|
|
565
|
+
excluded = %i[digest]
|
|
566
|
+
remaining = config.keys.map(&:to_sym) - @consumed_keys.to_a - excluded
|
|
567
|
+
return "-" if remaining.empty?
|
|
568
|
+
|
|
569
|
+
remaining.sort.map { |k| { "KEY" => k.to_s, "VALUE" => config[k].to_s } }
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Presenters
|
|
5
|
+
# Presenter for container lifecycle operation results.
|
|
6
|
+
#
|
|
7
|
+
# Formats ContainerOperationResult models for table/JSON/YAML output.
|
|
8
|
+
#
|
|
9
|
+
# @example Using with formatter
|
|
10
|
+
# presenter = ContainerOperationResult.new
|
|
11
|
+
# formatter = Formatters::Table.new
|
|
12
|
+
# output = formatter.format(results, presenter)
|
|
13
|
+
#
|
|
14
|
+
class ContainerOperationResult < OperationResult
|
|
15
|
+
# Returns column headers for standard table output.
|
|
16
|
+
#
|
|
17
|
+
# @return [Array<String>] column headers
|
|
18
|
+
def columns
|
|
19
|
+
%w[CTID NAME NODE STATUS MESSAGE]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns additional columns for wide output.
|
|
23
|
+
#
|
|
24
|
+
# @return [Array<String>] extra column headers
|
|
25
|
+
def extra_columns
|
|
26
|
+
%w[TASK DURATION]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Converts result to table row values.
|
|
30
|
+
#
|
|
31
|
+
# For clone operations, displays the new (cloned) container data.
|
|
32
|
+
# For all other operations, displays the source container data.
|
|
33
|
+
#
|
|
34
|
+
# @param model [Models::ContainerOperationResult] result model
|
|
35
|
+
# @param context [Hash] optional context
|
|
36
|
+
# @return [Array<String>] row values
|
|
37
|
+
def to_row(model, **_context)
|
|
38
|
+
if model.operation == :clone && model.resource
|
|
39
|
+
[
|
|
40
|
+
model.resource[:new_ctid].to_s,
|
|
41
|
+
model.resource[:hostname] || "CT-#{model.resource[:new_ctid]}",
|
|
42
|
+
model.resource[:node] || model.container&.node,
|
|
43
|
+
status_display(model),
|
|
44
|
+
model.message
|
|
45
|
+
]
|
|
46
|
+
else
|
|
47
|
+
[
|
|
48
|
+
model.container.vmid.to_s,
|
|
49
|
+
display_name(model.container),
|
|
50
|
+
model.container.node,
|
|
51
|
+
status_display(model),
|
|
52
|
+
model.message
|
|
53
|
+
]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Returns additional values for wide output.
|
|
58
|
+
#
|
|
59
|
+
# @param model [Models::ContainerOperationResult] result model
|
|
60
|
+
# @param context [Hash] optional context
|
|
61
|
+
# @return [Array<String>] extra values
|
|
62
|
+
def extra_values(model, **_context)
|
|
63
|
+
[
|
|
64
|
+
task_upid(model),
|
|
65
|
+
duration_display(model)
|
|
66
|
+
]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Converts result to hash for JSON/YAML output.
|
|
70
|
+
#
|
|
71
|
+
# For clone operations, displays the new (cloned) container data.
|
|
72
|
+
# For all other operations, displays the source container data.
|
|
73
|
+
#
|
|
74
|
+
# @param model [Models::ContainerOperationResult] result model
|
|
75
|
+
# @return [Hash] hash representation
|
|
76
|
+
def to_hash(model)
|
|
77
|
+
if model.operation == :clone && model.resource
|
|
78
|
+
{
|
|
79
|
+
"ctid" => model.resource[:new_ctid],
|
|
80
|
+
"name" => model.resource[:hostname],
|
|
81
|
+
"node" => model.resource[:node] || model.container&.node,
|
|
82
|
+
"status" => model.status_text,
|
|
83
|
+
"message" => model.message,
|
|
84
|
+
"task_upid" => model.task_upid || model.task&.upid
|
|
85
|
+
}
|
|
86
|
+
else
|
|
87
|
+
{
|
|
88
|
+
"ctid" => model.container.vmid,
|
|
89
|
+
"name" => model.container.name,
|
|
90
|
+
"node" => model.container.node,
|
|
91
|
+
"status" => model.status_text,
|
|
92
|
+
"message" => model.message,
|
|
93
|
+
"task_upid" => model.task_upid || model.task&.upid
|
|
94
|
+
}
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
# Returns display name for container.
|
|
101
|
+
#
|
|
102
|
+
# @param container [Models::Container] container model
|
|
103
|
+
# @return [String] display name
|
|
104
|
+
def display_name(container)
|
|
105
|
+
container.name || "CT-#{container.vmid}"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|