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,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Logs
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for node systemd journal output.
|
|
8
|
+
#
|
|
9
|
+
# Fetches journal entries from a node via Repositories::Journal.
|
|
10
|
+
# Not registered in ResourceRegistry — created by Command
|
|
11
|
+
# when --journal flag is set.
|
|
12
|
+
#
|
|
13
|
+
# @see Pvectl::Repositories::Journal Journal repository
|
|
14
|
+
# @see Pvectl::Presenters::JournalEntry Journal presenter
|
|
15
|
+
#
|
|
16
|
+
class Journal
|
|
17
|
+
include Logs::ResourceHandler
|
|
18
|
+
|
|
19
|
+
def initialize(repository: nil)
|
|
20
|
+
@repository = repository
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def list(node:, limit: 50, since: nil, until_time: nil, **_)
|
|
24
|
+
repository.list(node: node, last_entries: limit, since: since,
|
|
25
|
+
until_time: until_time)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def presenter
|
|
29
|
+
Presenters::JournalEntry.new
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def repository
|
|
35
|
+
@repository ||= begin
|
|
36
|
+
config_service = Pvectl::Config::Service.new
|
|
37
|
+
config_service.load
|
|
38
|
+
connection = Pvectl::Connection.new(config_service.current_config)
|
|
39
|
+
Repositories::Journal.new(connection)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Logs
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for node syslog output.
|
|
8
|
+
#
|
|
9
|
+
# Fetches syslog entries from a node via Repositories::Syslog.
|
|
10
|
+
# Supports filtering by service name and time range.
|
|
11
|
+
#
|
|
12
|
+
# @example Using via registry
|
|
13
|
+
# handler = Logs::ResourceRegistry.for("node")
|
|
14
|
+
# entries = handler.list(node: "pve1", service: "pvedaemon")
|
|
15
|
+
#
|
|
16
|
+
# @see Pvectl::Repositories::Syslog Syslog repository
|
|
17
|
+
# @see Pvectl::Presenters::SyslogEntry Syslog presenter
|
|
18
|
+
#
|
|
19
|
+
class Syslog
|
|
20
|
+
include Logs::ResourceHandler
|
|
21
|
+
|
|
22
|
+
def initialize(repository: nil)
|
|
23
|
+
@repository = repository
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def list(node:, limit: 50, since: nil, until_time: nil, service: nil, **_)
|
|
27
|
+
repository.list(node: node, limit: limit, since: since,
|
|
28
|
+
until_time: until_time, service: service)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def presenter
|
|
32
|
+
Presenters::SyslogEntry.new
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def repository
|
|
38
|
+
@repository ||= begin
|
|
39
|
+
config_service = Pvectl::Config::Service.new
|
|
40
|
+
config_service.load
|
|
41
|
+
connection = Pvectl::Connection.new(config_service.current_config)
|
|
42
|
+
Repositories::Syslog.new(connection)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
Pvectl::Commands::Logs::ResourceRegistry.register(
|
|
52
|
+
"node", Pvectl::Commands::Logs::Handlers::Syslog, aliases: ["nodes"]
|
|
53
|
+
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Logs
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for task log drill-down by UPID.
|
|
8
|
+
#
|
|
9
|
+
# Fetches individual task log lines from the Proxmox API.
|
|
10
|
+
# Extracts the node name from the UPID for API routing.
|
|
11
|
+
#
|
|
12
|
+
# @example Using via registry
|
|
13
|
+
# handler = Logs::ResourceRegistry.for("task")
|
|
14
|
+
# lines = handler.list(upid: "UPID:pve1:000ABC:...")
|
|
15
|
+
#
|
|
16
|
+
# @see Pvectl::Repositories::TaskLog Task log repository
|
|
17
|
+
# @see Pvectl::Presenters::TaskLogLine Task log line presenter
|
|
18
|
+
#
|
|
19
|
+
class TaskDetail
|
|
20
|
+
include Logs::ResourceHandler
|
|
21
|
+
|
|
22
|
+
def initialize(repository: nil)
|
|
23
|
+
@repository = repository
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def list(upid:, start: 0, limit: 512, **_)
|
|
27
|
+
repository.list(upid: upid, start: start, limit: limit)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def presenter
|
|
31
|
+
Presenters::TaskLogLine.new
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def repository
|
|
37
|
+
@repository ||= begin
|
|
38
|
+
config_service = Pvectl::Config::Service.new
|
|
39
|
+
config_service.load
|
|
40
|
+
connection = Pvectl::Connection.new(config_service.current_config)
|
|
41
|
+
Repositories::TaskLog.new(connection)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Pvectl::Commands::Logs::ResourceRegistry.register(
|
|
51
|
+
"task", Pvectl::Commands::Logs::Handlers::TaskDetail
|
|
52
|
+
)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Logs
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for VM/CT task history logs.
|
|
8
|
+
#
|
|
9
|
+
# Resolves VM/CT node via repository, then delegates task listing
|
|
10
|
+
# to Services::TaskListing. With --all-nodes, passes node: nil
|
|
11
|
+
# to the service for cluster-wide iteration.
|
|
12
|
+
#
|
|
13
|
+
# @example Using via registry
|
|
14
|
+
# handler = Logs::ResourceRegistry.for("vm")
|
|
15
|
+
# entries = handler.list(vmid: 100, resource_type: "vm")
|
|
16
|
+
#
|
|
17
|
+
# @see Pvectl::Services::TaskListing Shared task listing service
|
|
18
|
+
# @see Pvectl::Presenters::TaskEntry Task entry presenter
|
|
19
|
+
#
|
|
20
|
+
class TaskLogs
|
|
21
|
+
include Logs::ResourceHandler
|
|
22
|
+
|
|
23
|
+
# Maps resource type aliases to repository classes.
|
|
24
|
+
RESOURCE_REPOS = {
|
|
25
|
+
"vm" => -> { Pvectl::Repositories::Vm },
|
|
26
|
+
"vms" => -> { Pvectl::Repositories::Vm },
|
|
27
|
+
"ct" => -> { Pvectl::Repositories::Container },
|
|
28
|
+
"container" => -> { Pvectl::Repositories::Container },
|
|
29
|
+
"containers" => -> { Pvectl::Repositories::Container },
|
|
30
|
+
"cts" => -> { Pvectl::Repositories::Container }
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
def initialize(task_list_repository: nil, vm_repository: nil, node_repository: nil)
|
|
34
|
+
@task_list_repository = task_list_repository
|
|
35
|
+
@vm_repository = vm_repository
|
|
36
|
+
@node_repository = node_repository
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def list(vmid:, resource_type: "vm", all_nodes: false, limit: 50,
|
|
40
|
+
since: nil, until_time: nil, type_filter: nil, status_filter: nil, **_)
|
|
41
|
+
if all_nodes
|
|
42
|
+
service.list(
|
|
43
|
+
vmid: vmid, limit: limit, since: since,
|
|
44
|
+
until_time: until_time, type_filter: type_filter,
|
|
45
|
+
status_filter: status_filter
|
|
46
|
+
)
|
|
47
|
+
else
|
|
48
|
+
node = resolve_node(vmid, resource_type)
|
|
49
|
+
service.list(
|
|
50
|
+
node: node, vmid: vmid, limit: limit, since: since,
|
|
51
|
+
until_time: until_time, type_filter: type_filter,
|
|
52
|
+
status_filter: status_filter
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def presenter
|
|
58
|
+
Presenters::TaskEntry.new
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def resolve_node(vmid, resource_type)
|
|
64
|
+
resource = resource_repository(resource_type).get(vmid)
|
|
65
|
+
raise ResourceNotFoundError, "Resource not found: #{vmid}" unless resource
|
|
66
|
+
|
|
67
|
+
resource.node
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def resource_repository(resource_type)
|
|
71
|
+
@vm_repository || build_resource_repository(resource_type)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def build_resource_repository(resource_type)
|
|
75
|
+
repo_class = RESOURCE_REPOS.fetch(resource_type, -> { Pvectl::Repositories::Vm }).call
|
|
76
|
+
connection = build_connection
|
|
77
|
+
repo_class.new(connection)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def service
|
|
81
|
+
@service ||= Pvectl::Services::TaskListing.new(
|
|
82
|
+
task_list_repository: task_list_repository,
|
|
83
|
+
node_repository: node_repository
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def task_list_repository
|
|
88
|
+
@task_list_repository ||= begin
|
|
89
|
+
connection = build_connection
|
|
90
|
+
Repositories::TaskList.new(connection)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def node_repository
|
|
95
|
+
@node_repository ||= begin
|
|
96
|
+
connection = build_connection
|
|
97
|
+
Repositories::Node.new(connection)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def build_connection
|
|
102
|
+
config_service = Pvectl::Config::Service.new
|
|
103
|
+
config_service.load
|
|
104
|
+
Pvectl::Connection.new(config_service.current_config)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
Pvectl::Commands::Logs::ResourceRegistry.register(
|
|
113
|
+
"vm", Pvectl::Commands::Logs::Handlers::TaskLogs,
|
|
114
|
+
aliases: ["vms", "ct", "container", "containers", "cts"]
|
|
115
|
+
)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Logs
|
|
6
|
+
# Interface module for Logs command handlers.
|
|
7
|
+
#
|
|
8
|
+
# Each handler fetches log data from a specific source (task list,
|
|
9
|
+
# syslog, journal, or task detail) and returns an appropriate presenter.
|
|
10
|
+
#
|
|
11
|
+
# @abstract Include in handler class and implement required methods.
|
|
12
|
+
#
|
|
13
|
+
# @example Implementing a handler
|
|
14
|
+
# class SyslogHandler
|
|
15
|
+
# include Logs::ResourceHandler
|
|
16
|
+
#
|
|
17
|
+
# def list(node:, limit: 50, **_)
|
|
18
|
+
# repository.list(node: node, limit: limit)
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# def presenter
|
|
22
|
+
# Presenters::SyslogEntry.new
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
module ResourceHandler
|
|
27
|
+
# Lists log entries with filtering options.
|
|
28
|
+
#
|
|
29
|
+
# @param options [Hash] keyword arguments specific to each handler
|
|
30
|
+
# @return [Array<Object>] collection of model objects
|
|
31
|
+
# @raise [NotImplementedError] if not implemented by including class
|
|
32
|
+
def list(**options)
|
|
33
|
+
raise NotImplementedError, "#{self.class}#list must be implemented"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Returns the presenter for this log type.
|
|
37
|
+
#
|
|
38
|
+
# @return [Presenters::Base] presenter instance
|
|
39
|
+
# @raise [NotImplementedError] if not implemented by including class
|
|
40
|
+
def presenter
|
|
41
|
+
raise NotImplementedError, "#{self.class}#presenter must be implemented"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Logs
|
|
6
|
+
# Registry for Logs command resource handlers.
|
|
7
|
+
#
|
|
8
|
+
# Inherits registration and lookup from Commands::ResourceRegistry,
|
|
9
|
+
# maintaining its own isolated set of handlers for log operations.
|
|
10
|
+
#
|
|
11
|
+
# @example Registering a handler
|
|
12
|
+
# Logs::ResourceRegistry.register("vm", Handlers::TaskLogs, aliases: ["vms"])
|
|
13
|
+
#
|
|
14
|
+
# @example Looking up a handler
|
|
15
|
+
# handler = Logs::ResourceRegistry.for("vm")
|
|
16
|
+
#
|
|
17
|
+
# @see Pvectl::Commands::ResourceRegistry Base registry
|
|
18
|
+
#
|
|
19
|
+
class ResourceRegistry < Commands::ResourceRegistry; end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Shared functionality for migrate commands (migrate vm, migrate container).
|
|
6
|
+
#
|
|
7
|
+
# This module extracts common code used by MigrateVm and MigrateContainer.
|
|
8
|
+
# Pattern: identical to DeleteCommand module but with migrate-specific behavior:
|
|
9
|
+
# - Requires --target flag (no default)
|
|
10
|
+
# - Validates --restart only for containers
|
|
11
|
+
# - Async is default (no --async flag), --wait for sync
|
|
12
|
+
# - partition_by_target logic is in Service layer
|
|
13
|
+
#
|
|
14
|
+
# @example Including in a command class
|
|
15
|
+
# class MigrateVm
|
|
16
|
+
# include MigrateCommand
|
|
17
|
+
# RESOURCE_TYPE = :vm
|
|
18
|
+
# SUPPORTED_RESOURCES = %w[vm].freeze
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
module MigrateCommand
|
|
22
|
+
# Valid Proxmox node name format: lowercase alphanumeric, starting with letter, hyphens allowed.
|
|
23
|
+
NODE_NAME_FORMAT = /\A[a-z][a-z0-9-]*\z/
|
|
24
|
+
|
|
25
|
+
# Class methods added when the module is included.
|
|
26
|
+
module ClassMethods
|
|
27
|
+
# Executes the migrate command.
|
|
28
|
+
#
|
|
29
|
+
# @param args [Array<String>] resource identifiers
|
|
30
|
+
# @param options [Hash] command options
|
|
31
|
+
# @param global_options [Hash] global CLI options
|
|
32
|
+
# @return [Integer] exit code
|
|
33
|
+
def execute(args, options, global_options)
|
|
34
|
+
new(args, options, global_options).execute
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Hook called when module is included.
|
|
39
|
+
#
|
|
40
|
+
# @param base [Class] the class including this module
|
|
41
|
+
def self.included(base)
|
|
42
|
+
base.extend(ClassMethods)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Initializes a migrate command.
|
|
46
|
+
#
|
|
47
|
+
# @param args [Array<String>] resource identifiers
|
|
48
|
+
# @param options [Hash] command options
|
|
49
|
+
# @param global_options [Hash] global CLI options
|
|
50
|
+
def initialize(args, options, global_options)
|
|
51
|
+
@resource_ids = Array(args).compact
|
|
52
|
+
@options = options
|
|
53
|
+
@global_options = global_options
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Executes the migrate command.
|
|
57
|
+
#
|
|
58
|
+
# @return [Integer] exit code
|
|
59
|
+
def execute
|
|
60
|
+
target = @options[:target]
|
|
61
|
+
return usage_error("--target is required") if target.nil? || target.empty?
|
|
62
|
+
|
|
63
|
+
unless target.match?(NODE_NAME_FORMAT)
|
|
64
|
+
return usage_error("Invalid target node name: #{target}")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
return usage_error("--restart is only supported for containers") if restart_not_allowed?
|
|
68
|
+
|
|
69
|
+
if @resource_ids.empty? && !@options[:all] && selector_strings.empty?
|
|
70
|
+
return usage_error("VMID, --all, or -l selector required")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
perform_operation
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
# Returns the resource type symbol (:vm or :container).
|
|
79
|
+
#
|
|
80
|
+
# @return [Symbol] resource type
|
|
81
|
+
def resource_type_symbol
|
|
82
|
+
self.class::RESOURCE_TYPE
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Checks if --restart is used for a non-container resource.
|
|
86
|
+
#
|
|
87
|
+
# @return [Boolean] true if restart flag is invalid
|
|
88
|
+
def restart_not_allowed?
|
|
89
|
+
@options[:restart] && resource_type_symbol == :vm
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Performs the migrate operation.
|
|
93
|
+
#
|
|
94
|
+
# @return [Integer] exit code
|
|
95
|
+
def perform_operation
|
|
96
|
+
load_config
|
|
97
|
+
connection = Pvectl::Connection.new(@config)
|
|
98
|
+
|
|
99
|
+
resources = resolve_resources(connection)
|
|
100
|
+
return no_resources_found if resources.empty?
|
|
101
|
+
|
|
102
|
+
target = @options[:target]
|
|
103
|
+
return ExitCodes::SUCCESS unless confirm_operation(resources, target)
|
|
104
|
+
|
|
105
|
+
vm_repo = Pvectl::Repositories::Vm.new(connection)
|
|
106
|
+
container_repo = Pvectl::Repositories::Container.new(connection)
|
|
107
|
+
task_repo = Pvectl::Repositories::Task.new(connection)
|
|
108
|
+
|
|
109
|
+
service = Pvectl::Services::ResourceMigration.new(
|
|
110
|
+
vm_repository: vm_repo,
|
|
111
|
+
container_repository: container_repo,
|
|
112
|
+
task_repository: task_repo,
|
|
113
|
+
options: service_options
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
results = service.execute(resource_type_symbol, resources, target: target)
|
|
117
|
+
return ExitCodes::SUCCESS if results.empty?
|
|
118
|
+
|
|
119
|
+
output_results(results)
|
|
120
|
+
determine_exit_code(results)
|
|
121
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
122
|
+
Pvectl::Config::InvalidConfigError,
|
|
123
|
+
Pvectl::Config::ContextNotFoundError,
|
|
124
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
125
|
+
Pvectl::Config::UserNotFoundError
|
|
126
|
+
raise
|
|
127
|
+
rescue StandardError => e
|
|
128
|
+
$stderr.puts "Error: #{e.message}"
|
|
129
|
+
ExitCodes::GENERAL_ERROR
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Resolves resources based on IDs, --all flag, or selectors.
|
|
133
|
+
#
|
|
134
|
+
# @param connection [Connection] API connection
|
|
135
|
+
# @return [Array<Models::Vm, Models::Container>] resolved resources
|
|
136
|
+
def resolve_resources(connection)
|
|
137
|
+
repo = resource_type_symbol == :vm ?
|
|
138
|
+
Pvectl::Repositories::Vm.new(connection) :
|
|
139
|
+
Pvectl::Repositories::Container.new(connection)
|
|
140
|
+
|
|
141
|
+
resources = if @options[:all]
|
|
142
|
+
repo.list(node: @options[:node])
|
|
143
|
+
elsif @resource_ids.any?
|
|
144
|
+
@resource_ids.each do |id|
|
|
145
|
+
unless id.match?(/\A\d+\z/)
|
|
146
|
+
raise ArgumentError, "Invalid VMID/CTID: #{id}"
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
resolved = @resource_ids.map { |id| repo.get(id.to_i) }.compact
|
|
150
|
+
resolved = resolved.select { |r| r.node == @options[:node] } if @options[:node]
|
|
151
|
+
resolved
|
|
152
|
+
else
|
|
153
|
+
return [] if selector_strings.empty?
|
|
154
|
+
repo.list(node: @options[:node])
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
apply_selectors(resources)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Returns selector strings from options.
|
|
161
|
+
#
|
|
162
|
+
# @return [Array<String>] selector strings
|
|
163
|
+
def selector_strings
|
|
164
|
+
Array(@options[:selector] || @options[:l])
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Applies selectors to resource collection.
|
|
168
|
+
#
|
|
169
|
+
# @param resources [Array] Resources to filter
|
|
170
|
+
# @return [Array] Filtered resources
|
|
171
|
+
def apply_selectors(resources)
|
|
172
|
+
return resources if selector_strings.empty?
|
|
173
|
+
|
|
174
|
+
selector_class = resource_type_symbol == :vm ? Selectors::Vm : Selectors::Container
|
|
175
|
+
selector = selector_class.parse_all(selector_strings)
|
|
176
|
+
selector.apply(resources)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Confirms migrate operation with user.
|
|
180
|
+
#
|
|
181
|
+
# @param resources [Array] Resources to migrate
|
|
182
|
+
# @param target [String] Target node name
|
|
183
|
+
# @return [Boolean] true if operation should proceed
|
|
184
|
+
def confirm_operation(resources, target)
|
|
185
|
+
return true if @options[:yes]
|
|
186
|
+
|
|
187
|
+
type_name = resource_type_symbol == :vm ? "VM" : "container"
|
|
188
|
+
type_plural = resource_type_symbol == :vm ? "VMs" : "containers"
|
|
189
|
+
|
|
190
|
+
if resources.size == 1
|
|
191
|
+
r = resources.first
|
|
192
|
+
$stdout.puts "You are about to migrate #{type_name} #{r.vmid} (#{r.name || 'unnamed'}) from #{r.node} to #{target}."
|
|
193
|
+
else
|
|
194
|
+
$stdout.puts "You are about to migrate #{resources.size} #{type_plural} to #{target}:"
|
|
195
|
+
resources.each { |r| $stdout.puts " - #{r.vmid} (#{r.name || 'unnamed'}) on #{r.node}" }
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
$stdout.puts ""
|
|
199
|
+
$stdout.puts "This will migrate the #{type_plural} to node #{target}."
|
|
200
|
+
$stdout.print "Proceed? [y/N]: "
|
|
201
|
+
|
|
202
|
+
response = $stdin.gets&.strip&.downcase
|
|
203
|
+
%w[y yes].include?(response)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Loads configuration from file or environment.
|
|
207
|
+
#
|
|
208
|
+
# @return [void]
|
|
209
|
+
def load_config
|
|
210
|
+
service = Pvectl::Config::Service.new
|
|
211
|
+
service.load(config: @global_options[:config])
|
|
212
|
+
@config = service.current_config
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Builds service options from command options.
|
|
216
|
+
#
|
|
217
|
+
# @return [Hash] service options
|
|
218
|
+
def service_options
|
|
219
|
+
opts = {}
|
|
220
|
+
opts[:timeout] = @options[:timeout] if @options[:timeout]
|
|
221
|
+
opts[:wait] = true if @options[:wait]
|
|
222
|
+
opts[:online] = true if @options[:online]
|
|
223
|
+
opts[:restart] = true if @options[:restart]
|
|
224
|
+
opts[:target_storage] = @options[:"target-storage"] if @options[:"target-storage"]
|
|
225
|
+
opts[:fail_fast] = true if @options[:"fail-fast"]
|
|
226
|
+
opts
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Outputs operation results using the configured formatter.
|
|
230
|
+
#
|
|
231
|
+
# @param results [Array<Models::OperationResult>] operation results
|
|
232
|
+
# @return [void]
|
|
233
|
+
def output_results(results)
|
|
234
|
+
presenter = if resource_type_symbol == :vm
|
|
235
|
+
Pvectl::Presenters::VmOperationResult.new
|
|
236
|
+
else
|
|
237
|
+
Pvectl::Presenters::ContainerOperationResult.new
|
|
238
|
+
end
|
|
239
|
+
format = @global_options[:output] || "table"
|
|
240
|
+
color_flag = @global_options[:color]
|
|
241
|
+
|
|
242
|
+
formatter = Pvectl::Formatters::Registry.for(format)
|
|
243
|
+
output = formatter.format(results, presenter, color: color_flag)
|
|
244
|
+
puts output
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Determines exit code based on results.
|
|
248
|
+
#
|
|
249
|
+
# @param results [Array<Models::OperationResult>] operation results
|
|
250
|
+
# @return [Integer] exit code
|
|
251
|
+
def determine_exit_code(results)
|
|
252
|
+
return ExitCodes::SUCCESS if results.all?(&:successful?)
|
|
253
|
+
return ExitCodes::SUCCESS if results.all?(&:pending?)
|
|
254
|
+
|
|
255
|
+
ExitCodes::GENERAL_ERROR
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# Outputs usage error and returns exit code.
|
|
259
|
+
#
|
|
260
|
+
# @param message [String] error message
|
|
261
|
+
# @return [Integer] exit code
|
|
262
|
+
def usage_error(message)
|
|
263
|
+
$stderr.puts "Error: #{message}"
|
|
264
|
+
ExitCodes::USAGE_ERROR
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Outputs no resources found error and returns exit code.
|
|
268
|
+
#
|
|
269
|
+
# @return [Integer] exit code
|
|
270
|
+
def no_resources_found
|
|
271
|
+
type_plural = resource_type_symbol == :vm ? "VMs" : "containers"
|
|
272
|
+
msg = if @options[:all] || selector_strings.any?
|
|
273
|
+
@options[:node] ? "No #{type_plural} found on node #{@options[:node]}" : "No #{type_plural} found matching criteria"
|
|
274
|
+
else
|
|
275
|
+
"No #{type_plural} found for given IDs"
|
|
276
|
+
end
|
|
277
|
+
$stderr.puts "Error: #{msg}"
|
|
278
|
+
ExitCodes::NOT_FOUND
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl migrate container` command.
|
|
6
|
+
#
|
|
7
|
+
# Migrates one or more LXC containers to another cluster node.
|
|
8
|
+
# Always requires --target and confirmation (--yes to skip).
|
|
9
|
+
#
|
|
10
|
+
# @example Migrate a single container
|
|
11
|
+
# pvectl migrate container 200 --target pve2 --yes
|
|
12
|
+
#
|
|
13
|
+
# @example Restart migration
|
|
14
|
+
# pvectl migrate container 200 --target pve2 --restart --yes
|
|
15
|
+
#
|
|
16
|
+
class MigrateContainer
|
|
17
|
+
include MigrateCommand
|
|
18
|
+
|
|
19
|
+
RESOURCE_TYPE = :container
|
|
20
|
+
SUPPORTED_RESOURCES = %w[container ct].freeze
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|