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,205 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Template-specific functionality built on IrreversibleCommand.
|
|
6
|
+
#
|
|
7
|
+
# Converts VMs/containers to Proxmox templates (irreversible operation).
|
|
8
|
+
# Filters out resources that are already templates with a warning.
|
|
9
|
+
# Calls the repository's convert_to_template method for each resource.
|
|
10
|
+
#
|
|
11
|
+
# @example Including in a command class
|
|
12
|
+
# class TemplateVm
|
|
13
|
+
# include TemplateCommand
|
|
14
|
+
# RESOURCE_TYPE = :vm
|
|
15
|
+
# SUPPORTED_RESOURCES = %w[vm].freeze
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
module TemplateCommand
|
|
19
|
+
include IrreversibleCommand
|
|
20
|
+
|
|
21
|
+
# Hook called when module is included.
|
|
22
|
+
#
|
|
23
|
+
# @param base [Class] the class including this module
|
|
24
|
+
def self.included(base)
|
|
25
|
+
base.extend(IrreversibleCommand::ClassMethods)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# Overrides perform_operation to filter already-template resources.
|
|
31
|
+
#
|
|
32
|
+
# @return [Integer] exit code
|
|
33
|
+
def perform_operation
|
|
34
|
+
load_config
|
|
35
|
+
connection = Pvectl::Connection.new(@config)
|
|
36
|
+
|
|
37
|
+
resources = resolve_resources(connection)
|
|
38
|
+
return no_resources_found if resources.empty?
|
|
39
|
+
|
|
40
|
+
# Filter out already-template resources with warning
|
|
41
|
+
convertible, already_templates = resources.partition { |r| !r.template? }
|
|
42
|
+
|
|
43
|
+
already_templates.each do |r|
|
|
44
|
+
type_name = resource_type_symbol == :vm ? "VM" : "Container"
|
|
45
|
+
$stderr.puts "Warning: #{type_name} #{r.vmid} is already a template, skipping"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
return ExitCodes::SUCCESS if convertible.empty?
|
|
49
|
+
return ExitCodes::SUCCESS unless confirm_operation(convertible)
|
|
50
|
+
|
|
51
|
+
results = perform_service_call(convertible, connection)
|
|
52
|
+
output_results(results)
|
|
53
|
+
determine_exit_code(results)
|
|
54
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
55
|
+
Pvectl::Config::InvalidConfigError,
|
|
56
|
+
Pvectl::Config::ContextNotFoundError,
|
|
57
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
58
|
+
Pvectl::Config::UserNotFoundError
|
|
59
|
+
raise
|
|
60
|
+
rescue StandardError => e
|
|
61
|
+
$stderr.puts "Error: #{e.message}"
|
|
62
|
+
ExitCodes::GENERAL_ERROR
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Confirms template operation — uses --yes flag.
|
|
66
|
+
#
|
|
67
|
+
# @param resources [Array] Resources to convert
|
|
68
|
+
# @return [Boolean] true if operation should proceed
|
|
69
|
+
def confirm_operation(resources)
|
|
70
|
+
return true if @options[:yes]
|
|
71
|
+
|
|
72
|
+
$stdout.puts confirm_message(resources)
|
|
73
|
+
$stdout.puts ""
|
|
74
|
+
$stdout.puts irreversibility_warning
|
|
75
|
+
$stdout.print "Proceed? [y/N]: "
|
|
76
|
+
|
|
77
|
+
response = $stdin.gets&.strip&.downcase
|
|
78
|
+
%w[y yes].include?(response)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Returns confirmation message for template conversion.
|
|
82
|
+
#
|
|
83
|
+
# @param resources [Array] resources to convert
|
|
84
|
+
# @return [String] confirmation message
|
|
85
|
+
def confirm_message(resources)
|
|
86
|
+
type_name = resource_type_symbol == :vm ? "VM" : "container"
|
|
87
|
+
type_plural = resource_type_symbol == :vm ? "VMs" : "containers"
|
|
88
|
+
|
|
89
|
+
if resources.size == 1
|
|
90
|
+
r = resources.first
|
|
91
|
+
"You are about to convert #{type_name} #{r.vmid} (#{r.name || 'unnamed'}) on #{r.node} to a template."
|
|
92
|
+
else
|
|
93
|
+
lines = ["You are about to convert #{resources.size} #{type_plural} to templates:"]
|
|
94
|
+
resources.each { |r| lines << " - #{r.vmid} (#{r.name || 'unnamed'}) on #{r.node}" }
|
|
95
|
+
lines.join("\n")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Returns irreversibility warning for template conversion.
|
|
100
|
+
#
|
|
101
|
+
# @return [String] warning text
|
|
102
|
+
def irreversibility_warning
|
|
103
|
+
"This action is IRREVERSIBLE. Templates cannot be converted back and cannot be started."
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Performs template conversion for each resource.
|
|
107
|
+
#
|
|
108
|
+
# @param resources [Array] resources to convert
|
|
109
|
+
# @param connection [Connection] API connection
|
|
110
|
+
# @return [Array<Models::OperationResult>] results
|
|
111
|
+
def perform_service_call(resources, connection)
|
|
112
|
+
repo = build_repository(connection)
|
|
113
|
+
@task_repository = Pvectl::Repositories::Task.new(connection) if @options[:force]
|
|
114
|
+
resources.map do |resource|
|
|
115
|
+
convert_single(repo, resource)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Converts a single resource to template.
|
|
120
|
+
# Handles running resources: errors without --force, stops with --force.
|
|
121
|
+
#
|
|
122
|
+
# @param repo [Repositories::Base] repository
|
|
123
|
+
# @param resource [Models::Vm, Models::Container] resource to convert
|
|
124
|
+
# @return [Models::OperationResult] result
|
|
125
|
+
def convert_single(repo, resource)
|
|
126
|
+
if resource.status == "running"
|
|
127
|
+
return running_error(resource) unless @options[:force]
|
|
128
|
+
|
|
129
|
+
stop_result = stop_resource(repo, resource)
|
|
130
|
+
return stop_result if stop_result.failed?
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
if resource_type_symbol == :vm
|
|
134
|
+
repo.convert_to_template(resource.vmid, resource.node, disk: @options[:disk])
|
|
135
|
+
else
|
|
136
|
+
repo.convert_to_template(resource.vmid, resource.node)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
build_success_result(resource)
|
|
140
|
+
rescue StandardError => e
|
|
141
|
+
build_error_result(resource, e.message)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Returns error result for a running resource without --force.
|
|
145
|
+
#
|
|
146
|
+
# @param resource [Models::Vm, Models::Container] resource
|
|
147
|
+
# @return [Models::OperationResult] failed result
|
|
148
|
+
def running_error(resource)
|
|
149
|
+
type_name = resource_type_symbol == :vm ? "VM" : "Container"
|
|
150
|
+
build_error_result(resource, "#{type_name} #{resource.vmid} is running. Stop it first or use --force")
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Stops a running resource before template conversion.
|
|
154
|
+
#
|
|
155
|
+
# @param repo [Repositories::Base] repository
|
|
156
|
+
# @param resource [Models::Vm, Models::Container] resource
|
|
157
|
+
# @return [Models::OperationResult] result
|
|
158
|
+
def stop_resource(repo, resource)
|
|
159
|
+
upid = repo.stop(resource.vmid, resource.node)
|
|
160
|
+
timeout = @options[:timeout] || 60
|
|
161
|
+
task = @task_repository.wait(upid, timeout: timeout)
|
|
162
|
+
|
|
163
|
+
if task.successful?
|
|
164
|
+
build_success_result(resource)
|
|
165
|
+
else
|
|
166
|
+
build_error_result(resource, "Failed to stop: #{task.exitstatus}")
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Builds a successful operation result.
|
|
171
|
+
#
|
|
172
|
+
# @param resource [Models::Vm, Models::Container] resource
|
|
173
|
+
# @return [Models::OperationResult] success result
|
|
174
|
+
def build_success_result(resource)
|
|
175
|
+
result_class = resource_type_symbol == :vm ? Models::VmOperationResult : Models::ContainerOperationResult
|
|
176
|
+
attrs = { operation: :template, success: true }
|
|
177
|
+
attrs[resource_type_symbol == :vm ? :vm : :container] = resource
|
|
178
|
+
result_class.new(attrs)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Builds an error operation result.
|
|
182
|
+
#
|
|
183
|
+
# @param resource [Models::Vm, Models::Container] resource
|
|
184
|
+
# @param error_message [String] error message
|
|
185
|
+
# @return [Models::OperationResult] error result
|
|
186
|
+
def build_error_result(resource, error_message)
|
|
187
|
+
result_class = resource_type_symbol == :vm ? Models::VmOperationResult : Models::ContainerOperationResult
|
|
188
|
+
attrs = { operation: :template, success: false, error: error_message }
|
|
189
|
+
attrs[resource_type_symbol == :vm ? :vm : :container] = resource
|
|
190
|
+
result_class.new(attrs)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Builds presenter for template results.
|
|
194
|
+
#
|
|
195
|
+
# @return [Presenters::Base] presenter
|
|
196
|
+
def build_presenter
|
|
197
|
+
if resource_type_symbol == :vm
|
|
198
|
+
Pvectl::Presenters::VmOperationResult.new
|
|
199
|
+
else
|
|
200
|
+
Pvectl::Presenters::ContainerOperationResult.new
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl template container` command.
|
|
6
|
+
#
|
|
7
|
+
# Converts one or more containers to templates (irreversible).
|
|
8
|
+
# Always requires confirmation (--yes to skip).
|
|
9
|
+
# Running containers must be stopped first or use --force.
|
|
10
|
+
#
|
|
11
|
+
# @example Convert a single container
|
|
12
|
+
# pvectl template container 200 --yes
|
|
13
|
+
#
|
|
14
|
+
# @example Convert using ct alias
|
|
15
|
+
# pvectl template ct 200 --yes
|
|
16
|
+
#
|
|
17
|
+
# @example Force convert running container
|
|
18
|
+
# pvectl template container 200 --force --yes
|
|
19
|
+
#
|
|
20
|
+
class TemplateContainer
|
|
21
|
+
include TemplateCommand
|
|
22
|
+
|
|
23
|
+
RESOURCE_TYPE = :container
|
|
24
|
+
SUPPORTED_RESOURCES = %w[container ct].freeze
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl template vm` command.
|
|
6
|
+
#
|
|
7
|
+
# Converts one or more VMs to templates (irreversible).
|
|
8
|
+
# Always requires confirmation (--yes to skip).
|
|
9
|
+
# Running VMs must be stopped first or use --force.
|
|
10
|
+
#
|
|
11
|
+
# @example Convert a single VM
|
|
12
|
+
# pvectl template vm 100 --yes
|
|
13
|
+
#
|
|
14
|
+
# @example Convert multiple VMs
|
|
15
|
+
# pvectl template vm 100 101 102 --yes
|
|
16
|
+
#
|
|
17
|
+
# @example Force convert running VM (stops it first)
|
|
18
|
+
# pvectl template vm 100 --force --yes
|
|
19
|
+
#
|
|
20
|
+
# @example Convert specific disk only
|
|
21
|
+
# pvectl template vm 100 --disk scsi0 --yes
|
|
22
|
+
#
|
|
23
|
+
class TemplateVm
|
|
24
|
+
include TemplateCommand
|
|
25
|
+
|
|
26
|
+
# Registers the template command with the CLI.
|
|
27
|
+
#
|
|
28
|
+
# @param cli [GLI::App] the CLI application object
|
|
29
|
+
# @return [void]
|
|
30
|
+
def self.register(cli)
|
|
31
|
+
cli.desc "Convert a resource to a template (irreversible)"
|
|
32
|
+
cli.long_desc <<~HELP
|
|
33
|
+
Convert a virtual machine or container into a Proxmox template.
|
|
34
|
+
Templates are read-only base images used for linked cloning.
|
|
35
|
+
|
|
36
|
+
WARNING: This operation is irreversible. Once converted, the resource
|
|
37
|
+
cannot be converted back to a regular VM/container.
|
|
38
|
+
|
|
39
|
+
EXAMPLES
|
|
40
|
+
Convert a stopped VM to template:
|
|
41
|
+
$ pvectl template vm 100 --yes
|
|
42
|
+
|
|
43
|
+
Convert a running VM (stops it first):
|
|
44
|
+
$ pvectl template vm 100 --force --yes
|
|
45
|
+
|
|
46
|
+
Convert multiple VMs:
|
|
47
|
+
$ pvectl template vm 100 101 102 --yes
|
|
48
|
+
|
|
49
|
+
Convert a container:
|
|
50
|
+
$ pvectl template ct 200 --yes
|
|
51
|
+
|
|
52
|
+
NOTES
|
|
53
|
+
The resource must be stopped before conversion. Use --force to
|
|
54
|
+
automatically stop a running resource before converting.
|
|
55
|
+
|
|
56
|
+
--yes skips the confirmation prompt. Without it, you will be
|
|
57
|
+
asked to confirm the irreversible operation.
|
|
58
|
+
|
|
59
|
+
SEE ALSO
|
|
60
|
+
pvectl help clone Create linked clones from templates
|
|
61
|
+
pvectl help get templates List existing templates
|
|
62
|
+
HELP
|
|
63
|
+
cli.arg_name "RESOURCE_TYPE [ID...]"
|
|
64
|
+
cli.command :template do |c|
|
|
65
|
+
c.desc "Skip confirmation prompt"
|
|
66
|
+
c.switch [:yes, :y], negatable: false
|
|
67
|
+
|
|
68
|
+
c.desc "Force stop running VM/container before conversion"
|
|
69
|
+
c.switch [:force, :f], negatable: false
|
|
70
|
+
|
|
71
|
+
c.desc "Filter by node name"
|
|
72
|
+
c.flag [:node, :n], arg_name: "NODE"
|
|
73
|
+
|
|
74
|
+
c.desc "Filter by selector (e.g., status=stopped,tags=base)"
|
|
75
|
+
c.flag [:l, :selector], arg_name: "SELECTOR", multiple: true
|
|
76
|
+
|
|
77
|
+
c.desc "Select all resources of this type"
|
|
78
|
+
c.switch [:all, :A], negatable: false
|
|
79
|
+
|
|
80
|
+
c.desc "Specific disk to convert (VM only, e.g., scsi0)"
|
|
81
|
+
c.flag [:disk], arg_name: "DISK"
|
|
82
|
+
|
|
83
|
+
c.action do |global_options, options, args|
|
|
84
|
+
resource_type = args.shift
|
|
85
|
+
|
|
86
|
+
exit_code = case resource_type
|
|
87
|
+
when "vm"
|
|
88
|
+
Commands::TemplateVm.execute(resource_type, args, options, global_options)
|
|
89
|
+
when "container", "ct"
|
|
90
|
+
Commands::TemplateContainer.execute(resource_type, args, options, global_options)
|
|
91
|
+
else
|
|
92
|
+
$stderr.puts "Error: Unknown resource type: #{resource_type}"
|
|
93
|
+
$stderr.puts "Valid types: vm, container, ct"
|
|
94
|
+
ExitCodes::USAGE_ERROR
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
exit exit_code if exit_code != 0
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
RESOURCE_TYPE = :vm
|
|
103
|
+
SUPPORTED_RESOURCES = %w[vm].freeze
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Top
|
|
6
|
+
# Dispatcher for the `pvectl top <resource_type>` command.
|
|
7
|
+
#
|
|
8
|
+
# Displays resource usage metrics (CPU, memory, disk, swap) for
|
|
9
|
+
# cluster resources. Supports nodes, VMs, and containers.
|
|
10
|
+
#
|
|
11
|
+
# Uses Top::ResourceRegistry for handler lookup and Top-specific
|
|
12
|
+
# presenters for metrics-focused display. VMs and containers are
|
|
13
|
+
# filtered to running-only by default (use --all to show all).
|
|
14
|
+
#
|
|
15
|
+
# @example Basic usage
|
|
16
|
+
# Commands::Top::Command.execute("nodes", options, global_options)
|
|
17
|
+
#
|
|
18
|
+
class Command
|
|
19
|
+
# Resource types where running-only filtering does NOT apply.
|
|
20
|
+
SHOW_ALL_RESOURCE_TYPES = %w[nodes node].freeze
|
|
21
|
+
|
|
22
|
+
# Registers the top command with the CLI.
|
|
23
|
+
#
|
|
24
|
+
# @param cli [GLI::App] the CLI application object
|
|
25
|
+
# @return [void]
|
|
26
|
+
def self.register(cli)
|
|
27
|
+
cli.desc "Display resource usage metrics (CPU, memory, disk)"
|
|
28
|
+
cli.long_desc <<~HELP
|
|
29
|
+
Display real-time resource usage metrics for cluster resources.
|
|
30
|
+
Shows CPU, memory, disk, and network utilization in a table format.
|
|
31
|
+
|
|
32
|
+
By default, only running VMs and containers are shown. Use --all to
|
|
33
|
+
include stopped resources. Nodes always show all (including offline).
|
|
34
|
+
|
|
35
|
+
RESOURCE TYPES
|
|
36
|
+
nodes Cluster node metrics
|
|
37
|
+
vms Virtual machine metrics (running only by default)
|
|
38
|
+
containers Container metrics (running only by default)
|
|
39
|
+
|
|
40
|
+
EXAMPLES
|
|
41
|
+
Cluster node resource usage:
|
|
42
|
+
$ pvectl top nodes
|
|
43
|
+
|
|
44
|
+
VMs sorted by CPU usage:
|
|
45
|
+
$ pvectl top vms --sort-by cpu
|
|
46
|
+
|
|
47
|
+
All containers including stopped:
|
|
48
|
+
$ pvectl top containers --all
|
|
49
|
+
|
|
50
|
+
Memory usage in JSON format:
|
|
51
|
+
$ pvectl top vms --sort-by memory -o json
|
|
52
|
+
|
|
53
|
+
NOTES
|
|
54
|
+
Sort fields: cpu, memory, disk, netin, netout, name, node.
|
|
55
|
+
|
|
56
|
+
Stopped VMs/containers show 0% for all metrics. Use --all
|
|
57
|
+
if you need to see them alongside running resources.
|
|
58
|
+
|
|
59
|
+
SEE ALSO
|
|
60
|
+
pvectl help get List resources with status info
|
|
61
|
+
pvectl help describe Detailed resource information
|
|
62
|
+
HELP
|
|
63
|
+
cli.arg_name "RESOURCE_TYPE"
|
|
64
|
+
cli.command :top do |c|
|
|
65
|
+
c.desc "Sort by field (cpu, memory, disk, netin, netout, name, node)"
|
|
66
|
+
c.flag [:"sort-by"], arg_name: "FIELD"
|
|
67
|
+
|
|
68
|
+
c.desc "Show all (including stopped)"
|
|
69
|
+
c.switch [:all], default_value: false
|
|
70
|
+
|
|
71
|
+
c.action do |global_options, options, args|
|
|
72
|
+
resource_type = args[0]
|
|
73
|
+
exit_code = execute(resource_type, options, global_options)
|
|
74
|
+
exit exit_code if exit_code != 0
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Executes the top command.
|
|
80
|
+
#
|
|
81
|
+
# @param resource_type [String, nil] type of resource (e.g., "nodes")
|
|
82
|
+
# @param options [Hash] command-specific options
|
|
83
|
+
# - :"sort-by" [String] sort field (cpu, memory, disk)
|
|
84
|
+
# @param global_options [Hash] global CLI options
|
|
85
|
+
# - :output [String] output format (table, json, yaml, wide)
|
|
86
|
+
# - :color [Boolean, nil] explicit color setting
|
|
87
|
+
# @return [Integer] exit code
|
|
88
|
+
def self.execute(resource_type, options, global_options)
|
|
89
|
+
new(resource_type, options, global_options).execute
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Creates a new Top command instance.
|
|
93
|
+
#
|
|
94
|
+
# @param resource_type [String, nil] type of resource
|
|
95
|
+
# @param options [Hash] command options
|
|
96
|
+
# @param global_options [Hash] global CLI options
|
|
97
|
+
# @param handler [Object, nil] override handler for testing
|
|
98
|
+
# @param registry [Class] resource registry (default: Top::ResourceRegistry)
|
|
99
|
+
def initialize(resource_type, options, global_options,
|
|
100
|
+
handler: nil, registry: Top::ResourceRegistry)
|
|
101
|
+
@resource_type = resource_type
|
|
102
|
+
@options = options
|
|
103
|
+
@global_options = global_options
|
|
104
|
+
@handler = handler
|
|
105
|
+
@registry = registry
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Executes the top operation.
|
|
109
|
+
#
|
|
110
|
+
# @return [Integer] exit code
|
|
111
|
+
def execute
|
|
112
|
+
return missing_resource_type_error if @resource_type.nil?
|
|
113
|
+
|
|
114
|
+
handler = @handler || @registry.for(@resource_type)
|
|
115
|
+
return unknown_resource_error unless handler
|
|
116
|
+
|
|
117
|
+
models = handler.list(sort: @options[:"sort-by"])
|
|
118
|
+
models = filter_running(models) unless @options[:all]
|
|
119
|
+
output = format_output(models, handler.presenter)
|
|
120
|
+
puts output
|
|
121
|
+
|
|
122
|
+
ExitCodes::SUCCESS
|
|
123
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
124
|
+
Pvectl::Config::InvalidConfigError,
|
|
125
|
+
Pvectl::Config::ContextNotFoundError,
|
|
126
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
127
|
+
Pvectl::Config::UserNotFoundError => e
|
|
128
|
+
$stderr.puts "Error: #{e.message}"
|
|
129
|
+
ExitCodes::CONFIG_ERROR
|
|
130
|
+
rescue Timeout::Error => e
|
|
131
|
+
output_connection_error(e.message)
|
|
132
|
+
ExitCodes::CONNECTION_ERROR
|
|
133
|
+
rescue Errno::ECONNREFUSED => e
|
|
134
|
+
output_connection_error(e.message)
|
|
135
|
+
ExitCodes::CONNECTION_ERROR
|
|
136
|
+
rescue SocketError => e
|
|
137
|
+
output_connection_error(e.message)
|
|
138
|
+
ExitCodes::CONNECTION_ERROR
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private
|
|
142
|
+
|
|
143
|
+
# Outputs error for missing resource type argument.
|
|
144
|
+
#
|
|
145
|
+
# @return [Integer] USAGE_ERROR exit code
|
|
146
|
+
def missing_resource_type_error
|
|
147
|
+
$stderr.puts "Error: resource type is required"
|
|
148
|
+
$stderr.puts "Usage: pvectl top RESOURCE_TYPE [options]"
|
|
149
|
+
$stderr.puts "Available resources: nodes, vms, containers"
|
|
150
|
+
ExitCodes::USAGE_ERROR
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Outputs error for unknown resource type.
|
|
154
|
+
#
|
|
155
|
+
# @return [Integer] USAGE_ERROR exit code
|
|
156
|
+
def unknown_resource_error
|
|
157
|
+
$stderr.puts "Unknown resource type: #{@resource_type}"
|
|
158
|
+
$stderr.puts "Available resources: nodes, vms, containers"
|
|
159
|
+
ExitCodes::USAGE_ERROR
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Filters models to running-only for VM/CT resource types.
|
|
163
|
+
# Nodes always show all (offline nodes are important info).
|
|
164
|
+
#
|
|
165
|
+
# @param models [Array<Object>] models to filter
|
|
166
|
+
# @return [Array<Object>] filtered models
|
|
167
|
+
def filter_running(models)
|
|
168
|
+
return models if SHOW_ALL_RESOURCE_TYPES.include?(@resource_type)
|
|
169
|
+
return models unless models.first.respond_to?(:running?)
|
|
170
|
+
|
|
171
|
+
models.select(&:running?)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Outputs connection error message.
|
|
175
|
+
#
|
|
176
|
+
# @param message [String] the error message
|
|
177
|
+
# @return [void]
|
|
178
|
+
def output_connection_error(message)
|
|
179
|
+
$stderr.puts "Error: #{message}"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Formats models for output using the appropriate formatter.
|
|
183
|
+
#
|
|
184
|
+
# @param models [Array<Object>] collection of models
|
|
185
|
+
# @param presenter [Presenters::Base] presenter for the resource type
|
|
186
|
+
# @return [String] formatted output
|
|
187
|
+
def format_output(models, presenter)
|
|
188
|
+
format = @global_options[:output] || "table"
|
|
189
|
+
color_enabled = determine_color_enabled
|
|
190
|
+
formatter = Formatters::Registry.for(format)
|
|
191
|
+
formatter.format(models, presenter, color_enabled: color_enabled)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Determines if color output should be enabled.
|
|
195
|
+
#
|
|
196
|
+
# @return [Boolean] true if color should be enabled
|
|
197
|
+
def determine_color_enabled
|
|
198
|
+
explicit = @global_options[:color]
|
|
199
|
+
return explicit unless explicit.nil?
|
|
200
|
+
|
|
201
|
+
$stdout.tty?
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Top
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for Top command container metrics display.
|
|
8
|
+
#
|
|
9
|
+
# Wraps Get::Handlers::Containers to fetch container data and pairs it
|
|
10
|
+
# with TopContainer presenter for metrics-focused output.
|
|
11
|
+
#
|
|
12
|
+
# @example Using via ResourceRegistry
|
|
13
|
+
# handler = Top::ResourceRegistry.for("containers")
|
|
14
|
+
# containers = handler.list(sort: "cpu")
|
|
15
|
+
# presenter = handler.presenter
|
|
16
|
+
#
|
|
17
|
+
# @see Pvectl::Commands::Get::Handlers::Containers Get handler
|
|
18
|
+
# @see Pvectl::Presenters::TopContainer Top presenter
|
|
19
|
+
#
|
|
20
|
+
class Containers
|
|
21
|
+
include Top::ResourceHandler
|
|
22
|
+
|
|
23
|
+
# Creates handler with optional Get handler for dependency injection.
|
|
24
|
+
#
|
|
25
|
+
# @param get_handler [Get::Handlers::Containers, nil] handler (default: create new)
|
|
26
|
+
def initialize(get_handler: nil)
|
|
27
|
+
@get_handler = get_handler
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Lists containers with optional sorting.
|
|
31
|
+
#
|
|
32
|
+
# @param sort [String, nil] sort field (cpu, memory, disk)
|
|
33
|
+
# @return [Array<Models::Container>] collection of Container models
|
|
34
|
+
def list(sort: nil, **_)
|
|
35
|
+
get_handler.list(sort: sort)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Returns Top-specific presenter for containers.
|
|
39
|
+
#
|
|
40
|
+
# @return [Presenters::TopContainer] TopContainer presenter instance
|
|
41
|
+
def presenter
|
|
42
|
+
Presenters::TopContainer.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Returns Get handler, creating it if necessary.
|
|
48
|
+
#
|
|
49
|
+
# @return [Get::Handlers::Containers] Containers get handler
|
|
50
|
+
def get_handler
|
|
51
|
+
@get_handler ||= Get::Handlers::Containers.new
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
Pvectl::Commands::Top::ResourceRegistry.register(
|
|
60
|
+
"containers", Pvectl::Commands::Top::Handlers::Containers, aliases: ["container", "cts", "ct"]
|
|
61
|
+
)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Top
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for Top command node metrics display.
|
|
8
|
+
#
|
|
9
|
+
# Wraps Get::Handlers::Nodes to fetch node data and pairs it
|
|
10
|
+
# with TopNode presenter for metrics-focused output.
|
|
11
|
+
#
|
|
12
|
+
# @example Using via ResourceRegistry
|
|
13
|
+
# handler = Top::ResourceRegistry.for("nodes")
|
|
14
|
+
# nodes = handler.list(sort: "cpu")
|
|
15
|
+
# presenter = handler.presenter
|
|
16
|
+
#
|
|
17
|
+
# @see Pvectl::Commands::Get::Handlers::Nodes Get handler
|
|
18
|
+
# @see Pvectl::Presenters::TopNode Top presenter
|
|
19
|
+
#
|
|
20
|
+
class Nodes
|
|
21
|
+
include Top::ResourceHandler
|
|
22
|
+
|
|
23
|
+
# Creates handler with optional Get handler for dependency injection.
|
|
24
|
+
#
|
|
25
|
+
# @param get_handler [Get::Handlers::Nodes, nil] handler (default: create new)
|
|
26
|
+
def initialize(get_handler: nil)
|
|
27
|
+
@get_handler = get_handler
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Lists nodes with optional sorting.
|
|
31
|
+
#
|
|
32
|
+
# @param sort [String, nil] sort field (cpu, memory, disk)
|
|
33
|
+
# @return [Array<Models::Node>] collection of Node models
|
|
34
|
+
def list(sort: nil, **_)
|
|
35
|
+
get_handler.list(sort: sort)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Returns Top-specific presenter for nodes.
|
|
39
|
+
#
|
|
40
|
+
# @return [Presenters::TopNode] TopNode presenter instance
|
|
41
|
+
def presenter
|
|
42
|
+
Presenters::TopNode.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Returns Get handler, creating it if necessary.
|
|
48
|
+
#
|
|
49
|
+
# @return [Get::Handlers::Nodes] Nodes get handler
|
|
50
|
+
def get_handler
|
|
51
|
+
@get_handler ||= Get::Handlers::Nodes.new
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
Pvectl::Commands::Top::ResourceRegistry.register(
|
|
60
|
+
"nodes", Pvectl::Commands::Top::Handlers::Nodes, aliases: ["node"]
|
|
61
|
+
)
|