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,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl migrate vm` command.
|
|
6
|
+
#
|
|
7
|
+
# Migrates one or more virtual machines to another cluster node.
|
|
8
|
+
# Always requires --target and confirmation (--yes to skip).
|
|
9
|
+
#
|
|
10
|
+
# @example Migrate a single VM
|
|
11
|
+
# pvectl migrate vm 100 --target pve2 --yes
|
|
12
|
+
#
|
|
13
|
+
# @example Online migration
|
|
14
|
+
# pvectl migrate vm 100 --target pve2 --online --yes
|
|
15
|
+
#
|
|
16
|
+
class MigrateVm
|
|
17
|
+
include MigrateCommand
|
|
18
|
+
|
|
19
|
+
# Registers the migrate command with the CLI.
|
|
20
|
+
#
|
|
21
|
+
# @param cli [GLI::App] the CLI application object
|
|
22
|
+
# @return [void]
|
|
23
|
+
def self.register(cli)
|
|
24
|
+
cli.desc "Migrate a resource to another node"
|
|
25
|
+
cli.long_desc <<~HELP
|
|
26
|
+
Migrate virtual machines or containers between cluster nodes.
|
|
27
|
+
Supports live migration (--online) for zero-downtime moves.
|
|
28
|
+
|
|
29
|
+
EXAMPLES
|
|
30
|
+
Offline migration:
|
|
31
|
+
$ pvectl migrate vm 100 --target pve2
|
|
32
|
+
|
|
33
|
+
Live migration (zero downtime):
|
|
34
|
+
$ pvectl migrate vm 100 --target pve2 --online
|
|
35
|
+
|
|
36
|
+
Migrate a container with restart:
|
|
37
|
+
$ pvectl migrate ct 200 --target pve2 --restart
|
|
38
|
+
|
|
39
|
+
Migrate to different storage:
|
|
40
|
+
$ pvectl migrate vm 100 --target pve2 --target-storage local-lvm
|
|
41
|
+
|
|
42
|
+
Batch migrate all VMs from a node:
|
|
43
|
+
$ pvectl migrate vm --all --node pve1 --target pve2 --yes
|
|
44
|
+
|
|
45
|
+
Migrate VMs matching a selector:
|
|
46
|
+
$ pvectl migrate vm --all -l tags=web --target pve2 --yes
|
|
47
|
+
|
|
48
|
+
NOTES
|
|
49
|
+
--online (live migration) requires shared storage or migration
|
|
50
|
+
network configured between nodes.
|
|
51
|
+
|
|
52
|
+
Container migration with --restart briefly stops the container,
|
|
53
|
+
migrates, then starts it on the target node.
|
|
54
|
+
|
|
55
|
+
--target is required for all migrations.
|
|
56
|
+
|
|
57
|
+
Default timeout is 600 seconds. Use --timeout to adjust for
|
|
58
|
+
large VMs with lots of memory/disk.
|
|
59
|
+
|
|
60
|
+
SEE ALSO
|
|
61
|
+
pvectl help clone Clone instead of move
|
|
62
|
+
pvectl help get nodes List available target nodes
|
|
63
|
+
HELP
|
|
64
|
+
cli.arg_name "RESOURCE_TYPE [ID...]"
|
|
65
|
+
cli.command :migrate do |c|
|
|
66
|
+
c.desc "Target node (required)"
|
|
67
|
+
c.flag [:target, :t], arg_name: "NODE"
|
|
68
|
+
|
|
69
|
+
c.desc "Online/live migration"
|
|
70
|
+
c.switch [:online], negatable: false
|
|
71
|
+
|
|
72
|
+
c.desc "Restart migration (container only)"
|
|
73
|
+
c.switch [:restart], negatable: false
|
|
74
|
+
|
|
75
|
+
c.desc "Target storage mapping"
|
|
76
|
+
c.flag [:"target-storage"], arg_name: "STORAGE"
|
|
77
|
+
|
|
78
|
+
c.desc "Select all resources of this type"
|
|
79
|
+
c.switch [:all, :A], negatable: false
|
|
80
|
+
|
|
81
|
+
c.desc "Filter by source node"
|
|
82
|
+
c.flag [:node, :n], arg_name: "NODE"
|
|
83
|
+
|
|
84
|
+
c.desc "Filter by selector (e.g., status=running,tags=prod)"
|
|
85
|
+
c.flag [:l, :selector], arg_name: "SELECTOR", multiple: true
|
|
86
|
+
|
|
87
|
+
c.desc "Skip confirmation prompt"
|
|
88
|
+
c.switch [:yes, :y], negatable: false
|
|
89
|
+
|
|
90
|
+
c.desc "Stop on first error"
|
|
91
|
+
c.switch [:"fail-fast"], negatable: false
|
|
92
|
+
|
|
93
|
+
c.desc "Wait for migration to complete (sync mode)"
|
|
94
|
+
c.switch [:wait], negatable: false
|
|
95
|
+
|
|
96
|
+
c.desc "Timeout in seconds for sync operations (default: 600)"
|
|
97
|
+
c.flag [:timeout], type: Integer, arg_name: "SECONDS"
|
|
98
|
+
|
|
99
|
+
c.action do |global_options, options, args|
|
|
100
|
+
resource_type = args.shift
|
|
101
|
+
|
|
102
|
+
exit_code = case resource_type
|
|
103
|
+
when "vm"
|
|
104
|
+
Commands::MigrateVm.execute(args, options, global_options)
|
|
105
|
+
when "container", "ct"
|
|
106
|
+
Commands::MigrateContainer.execute(args, options, global_options)
|
|
107
|
+
else
|
|
108
|
+
$stderr.puts "Error: Unknown resource type: #{resource_type}"
|
|
109
|
+
$stderr.puts "Valid types: vm, container, ct"
|
|
110
|
+
ExitCodes::USAGE_ERROR
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
exit exit_code if exit_code != 0
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
RESOURCE_TYPE = :vm
|
|
119
|
+
SUPPORTED_RESOURCES = %w[vm].freeze
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Shared functionality for the move disk commands (move disk vm, move disk ct).
|
|
6
|
+
#
|
|
7
|
+
# Mirrors the structure of MigrateCommand but operates on a single resource
|
|
8
|
+
# (VM or container) and a single disk/volume rather than a batch.
|
|
9
|
+
#
|
|
10
|
+
# @example Including in a command class
|
|
11
|
+
# class MoveDiskVm
|
|
12
|
+
# include MoveDiskCommand
|
|
13
|
+
# RESOURCE_TYPE = :vm
|
|
14
|
+
# SUPPORTED_RESOURCES = %w[vm].freeze
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
module MoveDiskCommand
|
|
18
|
+
# Allowed target formats for VM disks (per Proxmox API).
|
|
19
|
+
VALID_FORMATS = %w[raw qcow2 vmdk].freeze
|
|
20
|
+
|
|
21
|
+
# Class methods added when the module is included.
|
|
22
|
+
module ClassMethods
|
|
23
|
+
# Executes the move disk command.
|
|
24
|
+
#
|
|
25
|
+
# @param args [Array<String>] command-positional args ([id, disk])
|
|
26
|
+
# @param options [Hash] command options
|
|
27
|
+
# @param global_options [Hash] global CLI options
|
|
28
|
+
# @return [Integer] exit code
|
|
29
|
+
def execute(args, options, global_options)
|
|
30
|
+
new(args, options, global_options).execute
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Hook called when the module is included.
|
|
35
|
+
#
|
|
36
|
+
# @param base [Class] the class including this module
|
|
37
|
+
def self.included(base)
|
|
38
|
+
base.extend(ClassMethods)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Initializes a move disk command.
|
|
42
|
+
#
|
|
43
|
+
# @param args [Array<String>] command-positional args ([id, disk])
|
|
44
|
+
# @param options [Hash] command options
|
|
45
|
+
# @param global_options [Hash] global CLI options
|
|
46
|
+
def initialize(args, options, global_options)
|
|
47
|
+
@args = Array(args).compact
|
|
48
|
+
@options = options
|
|
49
|
+
@global_options = global_options
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Executes the move disk command.
|
|
53
|
+
#
|
|
54
|
+
# @return [Integer] exit code
|
|
55
|
+
def execute
|
|
56
|
+
target = @options[:target]
|
|
57
|
+
return usage_error("--target is required") if target.nil? || target.to_s.empty?
|
|
58
|
+
|
|
59
|
+
return usage_error("#{id_label} and #{disk_label} are required") if @args.size < 2
|
|
60
|
+
|
|
61
|
+
id_str, disk = @args[0], @args[1]
|
|
62
|
+
|
|
63
|
+
unless id_str.to_s.match?(/\A\d+\z/)
|
|
64
|
+
return usage_error("Invalid #{id_label}: #{id_str}")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if @options[:format]
|
|
68
|
+
return usage_error("--format is not supported for containers") if resource_type_symbol == :container
|
|
69
|
+
return usage_error("Invalid format: #{@options[:format]} (allowed: #{VALID_FORMATS.join(', ')})") unless VALID_FORMATS.include?(@options[:format])
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
perform_operation(id_str.to_i, disk, target)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
# Returns the resource type symbol (:vm or :container).
|
|
78
|
+
#
|
|
79
|
+
# @return [Symbol]
|
|
80
|
+
def resource_type_symbol
|
|
81
|
+
self.class::RESOURCE_TYPE
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Returns the human label for the resource ID ("VMID" or "CTID").
|
|
85
|
+
#
|
|
86
|
+
# @return [String]
|
|
87
|
+
def id_label
|
|
88
|
+
resource_type_symbol == :vm ? "VMID" : "CTID"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Returns the human label for the disk/volume.
|
|
92
|
+
#
|
|
93
|
+
# @return [String]
|
|
94
|
+
def disk_label
|
|
95
|
+
resource_type_symbol == :vm ? "DISK" : "VOLUME"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Performs the move operation: loads config, resolves resource, prompts,
|
|
99
|
+
# invokes service, prints result.
|
|
100
|
+
#
|
|
101
|
+
# @param id [Integer] resource identifier
|
|
102
|
+
# @param disk [String] disk/volume key
|
|
103
|
+
# @param target [String] target storage
|
|
104
|
+
# @return [Integer] exit code
|
|
105
|
+
def perform_operation(id, disk, target)
|
|
106
|
+
load_config
|
|
107
|
+
connection = Pvectl::Connection.new(@config)
|
|
108
|
+
|
|
109
|
+
resource = resolve_resource(connection, id)
|
|
110
|
+
return resource_not_found(id) if resource.nil?
|
|
111
|
+
|
|
112
|
+
return ExitCodes::SUCCESS unless confirm_operation(resource, disk, target)
|
|
113
|
+
|
|
114
|
+
service = build_service(connection)
|
|
115
|
+
result = service.execute(resource_type_symbol, resource,
|
|
116
|
+
disk: disk, target_storage: target)
|
|
117
|
+
|
|
118
|
+
output_result(result)
|
|
119
|
+
result.failed? ? ExitCodes::GENERAL_ERROR : ExitCodes::SUCCESS
|
|
120
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
121
|
+
Pvectl::Config::InvalidConfigError,
|
|
122
|
+
Pvectl::Config::ContextNotFoundError,
|
|
123
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
124
|
+
Pvectl::Config::UserNotFoundError
|
|
125
|
+
raise
|
|
126
|
+
rescue StandardError => e
|
|
127
|
+
$stderr.puts "Error: #{e.message}"
|
|
128
|
+
ExitCodes::GENERAL_ERROR
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Resolves the single resource by ID using the appropriate repository.
|
|
132
|
+
#
|
|
133
|
+
# @param connection [Connection] API connection
|
|
134
|
+
# @param id [Integer] resource ID
|
|
135
|
+
# @return [Models::Vm, Models::Container, nil]
|
|
136
|
+
def resolve_resource(connection, id)
|
|
137
|
+
repo = resource_type_symbol == :vm ?
|
|
138
|
+
Pvectl::Repositories::Vm.new(connection) :
|
|
139
|
+
Pvectl::Repositories::Container.new(connection)
|
|
140
|
+
repo.get(id)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Builds the MoveDisk service with required dependencies.
|
|
144
|
+
#
|
|
145
|
+
# @param connection [Connection] API connection
|
|
146
|
+
# @return [Services::MoveDisk]
|
|
147
|
+
def build_service(connection)
|
|
148
|
+
Pvectl::Services::MoveDisk.new(
|
|
149
|
+
vm_repository: Pvectl::Repositories::Vm.new(connection),
|
|
150
|
+
container_repository: Pvectl::Repositories::Container.new(connection),
|
|
151
|
+
task_repository: Pvectl::Repositories::Task.new(connection),
|
|
152
|
+
options: service_options
|
|
153
|
+
)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Builds service options from command options.
|
|
157
|
+
#
|
|
158
|
+
# @return [Hash]
|
|
159
|
+
def service_options
|
|
160
|
+
opts = {}
|
|
161
|
+
opts[:format] = @options[:format] if @options[:format]
|
|
162
|
+
opts[:delete_source] = true if @options[:"delete-source"]
|
|
163
|
+
opts[:bandwidth] = @options[:bandwidth].to_i if @options[:bandwidth]
|
|
164
|
+
opts[:wait] = true if @options[:wait]
|
|
165
|
+
opts[:timeout] = @options[:timeout] if @options[:timeout]
|
|
166
|
+
opts
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Confirms the move operation with the user.
|
|
170
|
+
#
|
|
171
|
+
# @param resource [Models::Vm, Models::Container]
|
|
172
|
+
# @param disk [String]
|
|
173
|
+
# @param target [String]
|
|
174
|
+
# @return [Boolean] true if the operation should proceed
|
|
175
|
+
def confirm_operation(resource, disk, target)
|
|
176
|
+
return true if @options[:yes]
|
|
177
|
+
|
|
178
|
+
type_name = resource_type_symbol == :vm ? "VM" : "container"
|
|
179
|
+
$stdout.puts "You are about to move #{disk} of #{type_name} #{resource.vmid} " \
|
|
180
|
+
"(#{resource.name || 'unnamed'}) on #{resource.node} to storage #{target}."
|
|
181
|
+
$stdout.puts ""
|
|
182
|
+
if @options[:"delete-source"]
|
|
183
|
+
$stdout.puts "Source disk WILL be deleted after a successful copy."
|
|
184
|
+
else
|
|
185
|
+
$stdout.puts "Source disk will be kept as an unused entry."
|
|
186
|
+
end
|
|
187
|
+
$stdout.print "Proceed? [y/N]: "
|
|
188
|
+
|
|
189
|
+
response = $stdin.gets&.strip&.downcase
|
|
190
|
+
%w[y yes].include?(response)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Loads configuration from file or environment.
|
|
194
|
+
#
|
|
195
|
+
# @return [void]
|
|
196
|
+
def load_config
|
|
197
|
+
service = Pvectl::Config::Service.new
|
|
198
|
+
service.load(config: @global_options[:config])
|
|
199
|
+
@config = service.current_config
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Outputs the operation result using the configured formatter.
|
|
203
|
+
#
|
|
204
|
+
# @param result [Models::OperationResult]
|
|
205
|
+
# @return [void]
|
|
206
|
+
def output_result(result)
|
|
207
|
+
presenter = if resource_type_symbol == :vm
|
|
208
|
+
Pvectl::Presenters::VmOperationResult.new
|
|
209
|
+
else
|
|
210
|
+
Pvectl::Presenters::ContainerOperationResult.new
|
|
211
|
+
end
|
|
212
|
+
format = @global_options[:output] || "table"
|
|
213
|
+
color_flag = @global_options[:color]
|
|
214
|
+
|
|
215
|
+
formatter = Pvectl::Formatters::Registry.for(format)
|
|
216
|
+
output = formatter.format([result], presenter, color: color_flag)
|
|
217
|
+
puts output
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Outputs usage error and returns the usage exit code.
|
|
221
|
+
#
|
|
222
|
+
# @param message [String]
|
|
223
|
+
# @return [Integer]
|
|
224
|
+
def usage_error(message)
|
|
225
|
+
$stderr.puts "Error: #{message}"
|
|
226
|
+
ExitCodes::USAGE_ERROR
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Outputs "not found" error and returns the not-found exit code.
|
|
230
|
+
#
|
|
231
|
+
# @param id [Integer]
|
|
232
|
+
# @return [Integer]
|
|
233
|
+
def resource_not_found(id)
|
|
234
|
+
$stderr.puts "Error: No #{resource_type_symbol == :vm ? 'VM' : 'container'} found with ID #{id}"
|
|
235
|
+
ExitCodes::NOT_FOUND
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl move disk ct` command.
|
|
6
|
+
#
|
|
7
|
+
# Moves a container volume (rootfs / mpN) to a different storage on the
|
|
8
|
+
# same node. The --format flag is rejected because the LXC move_volume
|
|
9
|
+
# API does not accept a format.
|
|
10
|
+
#
|
|
11
|
+
# @example Move rootfs of container 200 to storage2
|
|
12
|
+
# pvectl move disk ct 200 rootfs --target storage2
|
|
13
|
+
#
|
|
14
|
+
class MoveDiskContainer
|
|
15
|
+
include MoveDiskCommand
|
|
16
|
+
|
|
17
|
+
RESOURCE_TYPE = :container
|
|
18
|
+
SUPPORTED_RESOURCES = %w[container ct].freeze
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl move disk vm` command.
|
|
6
|
+
#
|
|
7
|
+
# Moves a VM disk to a different storage on the same node.
|
|
8
|
+
# The Proxmox API call is asynchronous — the returned UPID is included
|
|
9
|
+
# in the OperationResult. Use --wait to block until the task completes.
|
|
10
|
+
#
|
|
11
|
+
# @example Move scsi0 of VM 100 to storage2
|
|
12
|
+
# pvectl move disk vm 100 scsi0 --target storage2
|
|
13
|
+
#
|
|
14
|
+
# @example Move and convert format, deleting source after copy
|
|
15
|
+
# pvectl move disk vm 100 scsi0 --target storage2 --format qcow2 --delete-source
|
|
16
|
+
#
|
|
17
|
+
class MoveDiskVm
|
|
18
|
+
include MoveDiskCommand
|
|
19
|
+
|
|
20
|
+
# Registers the move command with the CLI.
|
|
21
|
+
#
|
|
22
|
+
# @param cli [GLI::App] the CLI application object
|
|
23
|
+
# @return [void]
|
|
24
|
+
def self.register(cli)
|
|
25
|
+
cli.desc "Move a VM disk or container volume to another storage"
|
|
26
|
+
cli.long_desc <<~HELP
|
|
27
|
+
Move a VM disk or container volume to a different storage on the
|
|
28
|
+
same node. The source disk is kept as an unused entry by default;
|
|
29
|
+
pass --delete-source to remove it after a successful copy.
|
|
30
|
+
|
|
31
|
+
The operation is asynchronous: the returned task UPID can be
|
|
32
|
+
tracked with `pvectl get tasks` or `pvectl logs task <upid>`.
|
|
33
|
+
Pass --wait to block until the move completes (with --timeout).
|
|
34
|
+
|
|
35
|
+
EXAMPLES
|
|
36
|
+
Move VM disk to another storage:
|
|
37
|
+
$ pvectl move disk vm 100 scsi0 --target storage2
|
|
38
|
+
|
|
39
|
+
Move VM disk and convert format:
|
|
40
|
+
$ pvectl move disk vm 100 scsi0 --target storage2 --format qcow2
|
|
41
|
+
|
|
42
|
+
Move VM disk and delete source after copy:
|
|
43
|
+
$ pvectl move disk vm 100 scsi0 --target storage2 --delete-source
|
|
44
|
+
|
|
45
|
+
Move container rootfs to another storage:
|
|
46
|
+
$ pvectl move disk ct 200 rootfs --target storage2
|
|
47
|
+
|
|
48
|
+
Move container mount point with bandwidth cap (KiB/s):
|
|
49
|
+
$ pvectl move disk ct 200 mp0 --target storage2 --bandwidth 10240
|
|
50
|
+
|
|
51
|
+
Block until completion:
|
|
52
|
+
$ pvectl move disk vm 100 scsi0 --target storage2 --wait
|
|
53
|
+
|
|
54
|
+
NOTES
|
|
55
|
+
--target is required and must be a valid storage on the source node.
|
|
56
|
+
|
|
57
|
+
--format is only valid for VMs (raw, qcow2, vmdk). It is rejected
|
|
58
|
+
for containers because the LXC API does not accept a format.
|
|
59
|
+
|
|
60
|
+
--bandwidth is in KiB/s, matching the Proxmox API directly. The
|
|
61
|
+
operation defaults to the datacenter/storage move limit when omitted.
|
|
62
|
+
|
|
63
|
+
For VMs, allowed disk keys include ide0..ide3, scsi0..scsi30,
|
|
64
|
+
virtio0..virtio15, sata0..sata5, efidisk0, tpmstate0, unused*.
|
|
65
|
+
For containers, allowed volume keys include rootfs, mp0..mp255,
|
|
66
|
+
unused*.
|
|
67
|
+
|
|
68
|
+
SEE ALSO
|
|
69
|
+
pvectl help migrate Move a VM/container to another node
|
|
70
|
+
pvectl help clone Clone a VM or container
|
|
71
|
+
pvectl help get storage List storages on the cluster
|
|
72
|
+
HELP
|
|
73
|
+
cli.arg_name "SUBJECT RESOURCE_TYPE ID DISK"
|
|
74
|
+
cli.command :move do |c|
|
|
75
|
+
c.desc "Target storage (required)"
|
|
76
|
+
c.flag [:target, :t], arg_name: "STORAGE"
|
|
77
|
+
|
|
78
|
+
c.desc "Target disk format (VM only): raw, qcow2, or vmdk"
|
|
79
|
+
c.flag [:format, :f], arg_name: "FORMAT"
|
|
80
|
+
|
|
81
|
+
c.desc "Delete source disk after successful copy"
|
|
82
|
+
c.switch [:"delete-source"], negatable: false
|
|
83
|
+
|
|
84
|
+
c.desc "Bandwidth limit in KiB/s"
|
|
85
|
+
c.flag [:bandwidth, :b], type: Integer, arg_name: "KIBPS"
|
|
86
|
+
|
|
87
|
+
c.desc "Wait for the task to complete (sync mode)"
|
|
88
|
+
c.switch [:wait], negatable: false
|
|
89
|
+
|
|
90
|
+
c.desc "Timeout in seconds for sync operations (default: 600)"
|
|
91
|
+
c.flag [:timeout], type: Integer, arg_name: "SECONDS"
|
|
92
|
+
|
|
93
|
+
c.desc "Skip confirmation prompt"
|
|
94
|
+
c.switch [:yes, :y], negatable: false
|
|
95
|
+
|
|
96
|
+
c.action do |global_options, options, args|
|
|
97
|
+
subject = args.shift
|
|
98
|
+
resource_type = args.shift
|
|
99
|
+
|
|
100
|
+
exit_code =
|
|
101
|
+
if subject != "disk"
|
|
102
|
+
$stderr.puts "Error: Unknown subject: #{subject.inspect}"
|
|
103
|
+
$stderr.puts "Valid subjects: disk"
|
|
104
|
+
ExitCodes::USAGE_ERROR
|
|
105
|
+
else
|
|
106
|
+
case resource_type
|
|
107
|
+
when "vm"
|
|
108
|
+
Commands::MoveDiskVm.execute(args, options, global_options)
|
|
109
|
+
when "container", "ct"
|
|
110
|
+
Commands::MoveDiskContainer.execute(args, options, global_options)
|
|
111
|
+
else
|
|
112
|
+
$stderr.puts "Error: Unknown resource type: #{resource_type}"
|
|
113
|
+
$stderr.puts "Valid types: vm, container, ct"
|
|
114
|
+
ExitCodes::USAGE_ERROR
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
exit exit_code if exit_code != 0
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
RESOURCE_TYPE = :vm
|
|
124
|
+
SUPPORTED_RESOURCES = %w[vm].freeze
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|