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,242 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl create snapshot` sub-command.
|
|
6
|
+
#
|
|
7
|
+
# Creates snapshots for VMs/containers. Snapshot name is the first
|
|
8
|
+
# positional argument, VMIDs are specified via --vmid flag.
|
|
9
|
+
# Without --vmid, operates on ALL VMs/CTs in the cluster.
|
|
10
|
+
#
|
|
11
|
+
# @example Create single snapshot
|
|
12
|
+
# pvectl create snapshot before-upgrade --vmid 100
|
|
13
|
+
#
|
|
14
|
+
# @example Create for multiple VMs
|
|
15
|
+
# pvectl create snapshot before-upgrade --vmid 100 --vmid 101
|
|
16
|
+
#
|
|
17
|
+
# @example Create cluster-wide
|
|
18
|
+
# pvectl create snapshot before-upgrade --yes
|
|
19
|
+
#
|
|
20
|
+
class CreateSnapshot
|
|
21
|
+
VMID_PATTERN = /\A[1-9]\d{0,8}\z/
|
|
22
|
+
|
|
23
|
+
# Registers as a sub-command under the parent create command.
|
|
24
|
+
#
|
|
25
|
+
# @param parent [GLI::Command] the parent create command
|
|
26
|
+
# @return [void]
|
|
27
|
+
def self.register_subcommand(parent)
|
|
28
|
+
parent.desc "Create a snapshot of VMs or containers"
|
|
29
|
+
parent.long_desc <<~HELP
|
|
30
|
+
Create a snapshot of one or more VMs or containers. Snapshots capture
|
|
31
|
+
the current state of disks (and optionally RAM) for later rollback.
|
|
32
|
+
|
|
33
|
+
EXAMPLES
|
|
34
|
+
Snapshot a single VM:
|
|
35
|
+
$ pvectl create snapshot before-upgrade --vmid 100
|
|
36
|
+
|
|
37
|
+
Snapshot multiple VMs:
|
|
38
|
+
$ pvectl create snapshot before-upgrade --vmid 100 --vmid 101
|
|
39
|
+
|
|
40
|
+
Snapshot with description and VM memory state:
|
|
41
|
+
$ pvectl create snapshot before-upgrade --vmid 100 --description "Pre-upgrade" --vmstate
|
|
42
|
+
|
|
43
|
+
Snapshot all VMs/containers cluster-wide:
|
|
44
|
+
$ pvectl create snapshot before-upgrade --yes
|
|
45
|
+
|
|
46
|
+
NOTES
|
|
47
|
+
--vmstate saves the VM's RAM state (QEMU only, not for containers).
|
|
48
|
+
This increases snapshot size but allows resuming from exact state.
|
|
49
|
+
|
|
50
|
+
Without --vmid, operates cluster-wide (requires --yes confirmation).
|
|
51
|
+
|
|
52
|
+
SEE ALSO
|
|
53
|
+
pvectl help rollback Rollback to a snapshot
|
|
54
|
+
pvectl help delete snapshot Delete snapshots
|
|
55
|
+
pvectl help get snapshots List existing snapshots
|
|
56
|
+
HELP
|
|
57
|
+
parent.command :snapshot do |s|
|
|
58
|
+
s.desc "VM/CT ID (repeatable)"
|
|
59
|
+
s.flag [:vmid], arg_name: "VMID", multiple: true
|
|
60
|
+
|
|
61
|
+
s.desc "Save VM memory state (QEMU only)"
|
|
62
|
+
s.switch [:vmstate], negatable: false
|
|
63
|
+
|
|
64
|
+
s.action do |global_options, options, args|
|
|
65
|
+
exit_code = execute(args, options, global_options)
|
|
66
|
+
exit exit_code if exit_code != 0
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Executes the create snapshot command.
|
|
72
|
+
#
|
|
73
|
+
# @param args [Array<String>] positional args (snapshot name)
|
|
74
|
+
# @param options [Hash] command options
|
|
75
|
+
# @param global_options [Hash] global CLI options
|
|
76
|
+
# @return [Integer] exit code
|
|
77
|
+
def self.execute(args, options, global_options)
|
|
78
|
+
new(args, options, global_options).execute
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Initializes a create snapshot command.
|
|
82
|
+
#
|
|
83
|
+
# @param args [Array<String>] positional args (snapshot name)
|
|
84
|
+
# @param options [Hash] command options
|
|
85
|
+
# @param global_options [Hash] global CLI options
|
|
86
|
+
def initialize(args, options, global_options)
|
|
87
|
+
@args = Array(args)
|
|
88
|
+
@options = options
|
|
89
|
+
@global_options = global_options
|
|
90
|
+
@snapshot_name = @args.first
|
|
91
|
+
@vmids = parse_vmids(options[:vmid])
|
|
92
|
+
@node = options[:node]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Executes the create snapshot command.
|
|
96
|
+
#
|
|
97
|
+
# @return [Integer] exit code
|
|
98
|
+
def execute
|
|
99
|
+
return usage_error("Snapshot name required") unless @snapshot_name
|
|
100
|
+
return usage_error("Invalid VMID: #{invalid_vmid}") if invalid_vmid
|
|
101
|
+
|
|
102
|
+
perform_operation
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
# Parses --vmid flag values to integer array.
|
|
108
|
+
#
|
|
109
|
+
# @param vmid_values [Array<String>, nil] raw vmid values
|
|
110
|
+
# @return [Array<Integer>] parsed VMIDs
|
|
111
|
+
def parse_vmids(vmid_values)
|
|
112
|
+
return [] if vmid_values.nil? || vmid_values.empty?
|
|
113
|
+
|
|
114
|
+
Array(vmid_values).map(&:to_i)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Finds first invalid VMID in options.
|
|
118
|
+
#
|
|
119
|
+
# @return [String, nil] invalid VMID value or nil
|
|
120
|
+
def invalid_vmid
|
|
121
|
+
return nil if @options[:vmid].nil? || @options[:vmid].empty?
|
|
122
|
+
|
|
123
|
+
Array(@options[:vmid]).find { |v| !VMID_PATTERN.match?(v.to_s) }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Performs the snapshot creation operation.
|
|
127
|
+
#
|
|
128
|
+
# @return [Integer] exit code
|
|
129
|
+
def perform_operation
|
|
130
|
+
load_config
|
|
131
|
+
connection = Pvectl::Connection.new(@config)
|
|
132
|
+
|
|
133
|
+
snapshot_repo = Pvectl::Repositories::Snapshot.new(connection)
|
|
134
|
+
resolver = Pvectl::Utils::ResourceResolver.new(connection)
|
|
135
|
+
task_repo = Pvectl::Repositories::Task.new(connection)
|
|
136
|
+
|
|
137
|
+
service = Pvectl::Services::Snapshot.new(
|
|
138
|
+
snapshot_repo: snapshot_repo,
|
|
139
|
+
resource_resolver: resolver,
|
|
140
|
+
task_repo: task_repo,
|
|
141
|
+
options: service_options
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
return ExitCodes::SUCCESS unless confirm_operation
|
|
145
|
+
|
|
146
|
+
results = service.create(
|
|
147
|
+
@vmids,
|
|
148
|
+
name: @snapshot_name,
|
|
149
|
+
description: @options[:description],
|
|
150
|
+
vmstate: @options[:vmstate] || false,
|
|
151
|
+
node: @node
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
output_results(results)
|
|
155
|
+
determine_exit_code(results)
|
|
156
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
157
|
+
Pvectl::Config::InvalidConfigError,
|
|
158
|
+
Pvectl::Config::ContextNotFoundError,
|
|
159
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
160
|
+
Pvectl::Config::UserNotFoundError
|
|
161
|
+
raise
|
|
162
|
+
rescue StandardError => e
|
|
163
|
+
$stderr.puts "Error: #{e.message}"
|
|
164
|
+
ExitCodes::GENERAL_ERROR
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Confirms operation with user prompt.
|
|
168
|
+
#
|
|
169
|
+
# @return [Boolean] true if operation should proceed
|
|
170
|
+
def confirm_operation
|
|
171
|
+
return true if @vmids.size == 1
|
|
172
|
+
return true if @options[:yes]
|
|
173
|
+
|
|
174
|
+
if @vmids.empty?
|
|
175
|
+
$stdout.puts "You are about to create snapshot '#{@snapshot_name}' for ALL VMs/CTs in the cluster."
|
|
176
|
+
else
|
|
177
|
+
$stdout.puts "You are about to create snapshot '#{@snapshot_name}' for #{@vmids.size} VMs:"
|
|
178
|
+
@vmids.each { |vmid| $stdout.puts " - #{vmid}" }
|
|
179
|
+
end
|
|
180
|
+
$stdout.puts ""
|
|
181
|
+
$stdout.print "Proceed? [y/N]: "
|
|
182
|
+
|
|
183
|
+
response = $stdin.gets&.strip&.downcase
|
|
184
|
+
%w[y yes].include?(response)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Loads configuration.
|
|
188
|
+
#
|
|
189
|
+
# @return [void]
|
|
190
|
+
def load_config
|
|
191
|
+
service = Pvectl::Config::Service.new
|
|
192
|
+
service.load(config: @global_options[:config])
|
|
193
|
+
@config = service.current_config
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Builds service options.
|
|
197
|
+
#
|
|
198
|
+
# @return [Hash] service options
|
|
199
|
+
def service_options
|
|
200
|
+
opts = {}
|
|
201
|
+
opts[:timeout] = @options[:timeout] if @options[:timeout]
|
|
202
|
+
opts[:async] = true if @options[:async]
|
|
203
|
+
opts[:fail_fast] = true if @options[:"fail-fast"]
|
|
204
|
+
opts
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Outputs operation results.
|
|
208
|
+
#
|
|
209
|
+
# @param results [Array<Models::OperationResult>] results
|
|
210
|
+
# @return [void]
|
|
211
|
+
def output_results(results)
|
|
212
|
+
presenter = Pvectl::Presenters::SnapshotOperationResult.new
|
|
213
|
+
format = @global_options[:output] || "table"
|
|
214
|
+
color_flag = @global_options[:color]
|
|
215
|
+
|
|
216
|
+
formatter = Pvectl::Formatters::Registry.for(format)
|
|
217
|
+
output = formatter.format(results, presenter, color: color_flag)
|
|
218
|
+
puts output
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Determines exit code.
|
|
222
|
+
#
|
|
223
|
+
# @param results [Array<Models::OperationResult>] results
|
|
224
|
+
# @return [Integer] exit code
|
|
225
|
+
def determine_exit_code(results)
|
|
226
|
+
return ExitCodes::SUCCESS if results.all?(&:successful?)
|
|
227
|
+
return ExitCodes::SUCCESS if results.all?(&:pending?)
|
|
228
|
+
|
|
229
|
+
ExitCodes::GENERAL_ERROR
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Outputs usage error.
|
|
233
|
+
#
|
|
234
|
+
# @param message [String] error message
|
|
235
|
+
# @return [Integer] exit code
|
|
236
|
+
def usage_error(message)
|
|
237
|
+
$stderr.puts "Error: #{message}"
|
|
238
|
+
ExitCodes::USAGE_ERROR
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl create vm` command.
|
|
6
|
+
#
|
|
7
|
+
# Includes CreateResourceCommand for shared workflow and overrides
|
|
8
|
+
# template methods with VM-specific behavior.
|
|
9
|
+
#
|
|
10
|
+
# @example Flag-based creation
|
|
11
|
+
# pvectl create vm --name web --node pve1 --cores 4 --memory 4096
|
|
12
|
+
#
|
|
13
|
+
# @example With disk and network
|
|
14
|
+
# pvectl create vm 100 --name web --node pve1 \
|
|
15
|
+
# --disk storage=local-lvm,size=32G --net bridge=vmbr0
|
|
16
|
+
#
|
|
17
|
+
# @example Dry-run mode
|
|
18
|
+
# pvectl create vm --name web --node pve1 --dry-run
|
|
19
|
+
#
|
|
20
|
+
class CreateVm
|
|
21
|
+
include CreateResourceCommand
|
|
22
|
+
include SharedConfigParsers
|
|
23
|
+
|
|
24
|
+
# Registers the create command with the CLI.
|
|
25
|
+
#
|
|
26
|
+
# @param cli [GLI::App] the CLI application object
|
|
27
|
+
# @return [void]
|
|
28
|
+
def self.register(cli)
|
|
29
|
+
cli.desc "Create a resource"
|
|
30
|
+
cli.long_desc <<~HELP
|
|
31
|
+
Create a new virtual machine, container, snapshot, or backup.
|
|
32
|
+
|
|
33
|
+
For VMs and containers, you can either specify configuration via flags
|
|
34
|
+
or use --interactive for a guided wizard. Use --dry-run to preview
|
|
35
|
+
the configuration without actually creating the resource.
|
|
36
|
+
|
|
37
|
+
SUBCOMMANDS
|
|
38
|
+
create vm [ID] Create a virtual machine
|
|
39
|
+
create container [ID] Create an LXC container
|
|
40
|
+
create snapshot NAME Create a snapshot (see: pvectl help create snapshot)
|
|
41
|
+
create backup ID... Create a backup (vzdump)
|
|
42
|
+
|
|
43
|
+
EXAMPLES
|
|
44
|
+
Create a VM with specific config:
|
|
45
|
+
$ pvectl create vm 100 --cores 4 --memory 8192 --disk storage=local-lvm,size=50G
|
|
46
|
+
|
|
47
|
+
Create a VM using interactive wizard:
|
|
48
|
+
$ pvectl create vm --interactive
|
|
49
|
+
|
|
50
|
+
Preview VM creation without executing:
|
|
51
|
+
$ pvectl create vm 100 --cores 2 --memory 4096 --dry-run
|
|
52
|
+
|
|
53
|
+
Create a container:
|
|
54
|
+
$ pvectl create container 200 --hostname nginx --ostemplate local:vztmpl/debian-12.tar.zst
|
|
55
|
+
|
|
56
|
+
Create a backup:
|
|
57
|
+
$ pvectl create backup 100 --storage nfs-backup --mode snapshot
|
|
58
|
+
|
|
59
|
+
NOTES
|
|
60
|
+
If no ID is specified for VM/container, Proxmox auto-assigns the
|
|
61
|
+
next available ID.
|
|
62
|
+
|
|
63
|
+
VM creation supports cloud-init configuration via --cloud-init flag.
|
|
64
|
+
|
|
65
|
+
Backup modes: snapshot (default, no downtime), suspend (brief pause),
|
|
66
|
+
stop (full stop during backup).
|
|
67
|
+
|
|
68
|
+
SEE ALSO
|
|
69
|
+
pvectl help clone Clone an existing VM or container
|
|
70
|
+
pvectl help delete Delete resources
|
|
71
|
+
pvectl help get templates List available templates
|
|
72
|
+
HELP
|
|
73
|
+
cli.arg_name "RESOURCE_TYPE [ID...]"
|
|
74
|
+
cli.command :create do |c|
|
|
75
|
+
c.desc "Resource name"
|
|
76
|
+
c.flag [:name], arg_name: "NAME"
|
|
77
|
+
|
|
78
|
+
c.desc "Description/notes"
|
|
79
|
+
c.flag [:description, :notes], arg_name: "TEXT"
|
|
80
|
+
|
|
81
|
+
# Backup-specific flags
|
|
82
|
+
c.desc "Target storage for backup"
|
|
83
|
+
c.flag [:storage], arg_name: "STORAGE"
|
|
84
|
+
|
|
85
|
+
c.desc "Backup mode (snapshot, suspend, stop)"
|
|
86
|
+
c.default_value "snapshot"
|
|
87
|
+
c.flag [:mode], arg_name: "MODE", must_match: %w[snapshot suspend stop]
|
|
88
|
+
|
|
89
|
+
c.desc "Compression (zstd, gzip, lzo, 0 for none)"
|
|
90
|
+
c.default_value "zstd"
|
|
91
|
+
c.flag [:compress], arg_name: "TYPE"
|
|
92
|
+
|
|
93
|
+
c.desc "Protect backup from deletion"
|
|
94
|
+
c.switch [:protected], negatable: false
|
|
95
|
+
|
|
96
|
+
# Common flags
|
|
97
|
+
c.desc "Skip confirmation prompt"
|
|
98
|
+
c.switch [:yes, :y], negatable: false
|
|
99
|
+
|
|
100
|
+
c.desc "Timeout in seconds for sync operations"
|
|
101
|
+
c.flag [:timeout], type: Integer, arg_name: "SECONDS"
|
|
102
|
+
|
|
103
|
+
c.desc "Force async mode (return task ID immediately)"
|
|
104
|
+
c.switch [:async], negatable: false
|
|
105
|
+
|
|
106
|
+
c.desc "Stop on first error (default: continue and report all)"
|
|
107
|
+
c.switch [:"fail-fast"], negatable: false
|
|
108
|
+
|
|
109
|
+
# Shared config flags (VM + container)
|
|
110
|
+
SharedFlags.common_config(c)
|
|
111
|
+
SharedFlags.vm_config(c)
|
|
112
|
+
SharedFlags.container_config(c)
|
|
113
|
+
|
|
114
|
+
c.desc "Resource pool"
|
|
115
|
+
c.flag [:pool], arg_name: "POOL"
|
|
116
|
+
|
|
117
|
+
c.desc "Force interactive wizard mode"
|
|
118
|
+
c.switch [:interactive], negatable: true
|
|
119
|
+
|
|
120
|
+
c.desc "Show what would happen without creating"
|
|
121
|
+
c.switch [:"dry-run"], negatable: false
|
|
122
|
+
|
|
123
|
+
# Container-specific create flags
|
|
124
|
+
c.desc "Container hostname (container)"
|
|
125
|
+
c.flag [:hostname], arg_name: "NAME"
|
|
126
|
+
|
|
127
|
+
c.desc "OS template path (container): storage:vztmpl/name.tar.zst"
|
|
128
|
+
c.flag [:ostemplate], arg_name: "TEMPLATE"
|
|
129
|
+
|
|
130
|
+
# Sub-commands
|
|
131
|
+
CreateSnapshot.register_subcommand(c)
|
|
132
|
+
|
|
133
|
+
c.action do |global_options, options, args|
|
|
134
|
+
resource_type = args.shift
|
|
135
|
+
resource_ids = args
|
|
136
|
+
|
|
137
|
+
exit_code = case resource_type
|
|
138
|
+
when "vm"
|
|
139
|
+
Commands::CreateVm.execute(resource_ids, options, global_options)
|
|
140
|
+
when "container", "ct"
|
|
141
|
+
Commands::CreateContainer.execute(resource_ids, options, global_options)
|
|
142
|
+
when "backup"
|
|
143
|
+
# Map :description to :notes for backup if notes not set
|
|
144
|
+
options[:notes] ||= options[:description]
|
|
145
|
+
Commands::CreateBackup.execute(resource_type, resource_ids, options, global_options)
|
|
146
|
+
else
|
|
147
|
+
$stderr.puts "Error: Unknown resource type: #{resource_type}"
|
|
148
|
+
$stderr.puts "Valid types: vm, container, backup (or use: create snapshot)"
|
|
149
|
+
ExitCodes::USAGE_ERROR
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
exit exit_code if exit_code != 0
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
private
|
|
158
|
+
|
|
159
|
+
# @return [String] human label for VM resources
|
|
160
|
+
def resource_label
|
|
161
|
+
"VM"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# @return [String] human label for VM IDs
|
|
165
|
+
def resource_id_label
|
|
166
|
+
"VMID"
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# @return [Boolean] true if --name is missing
|
|
170
|
+
def required_params_missing?
|
|
171
|
+
!@options[:name]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# @return [Object] VM creation wizard
|
|
175
|
+
def build_wizard
|
|
176
|
+
Pvectl::Wizards::CreateVm.new(@options, @global_options)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# @param connection [Connection] API connection
|
|
180
|
+
# @param task_repo [Repositories::Task] task repository
|
|
181
|
+
# @return [Services::CreateVm] VM creation service
|
|
182
|
+
def build_create_service(connection, task_repo)
|
|
183
|
+
vm_repo = Pvectl::Repositories::Vm.new(connection)
|
|
184
|
+
Pvectl::Services::CreateVm.new(
|
|
185
|
+
vm_repository: vm_repo,
|
|
186
|
+
task_repository: task_repo,
|
|
187
|
+
options: service_options
|
|
188
|
+
)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# @param result [Models::VmOperationResult] operation result
|
|
192
|
+
# @return [void]
|
|
193
|
+
def output_result(result)
|
|
194
|
+
presenter = Pvectl::Presenters::VmOperationResult.new
|
|
195
|
+
format = @global_options[:output] || "table"
|
|
196
|
+
color_flag = @global_options[:color]
|
|
197
|
+
|
|
198
|
+
formatter = Pvectl::Formatters::Registry.for(format)
|
|
199
|
+
output = formatter.format([result], presenter, color: color_flag)
|
|
200
|
+
puts output
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Validates flags and performs flag-based creation.
|
|
204
|
+
#
|
|
205
|
+
# Overrides shared #perform_create to add VM-specific validation.
|
|
206
|
+
#
|
|
207
|
+
# @return [Integer] exit code
|
|
208
|
+
def perform_create
|
|
209
|
+
return usage_error("--name is required") unless @options[:name]
|
|
210
|
+
|
|
211
|
+
super
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Extracts CLI options into a service params hash.
|
|
215
|
+
#
|
|
216
|
+
# Delegates VM config parsing to SharedConfigParsers#build_vm_config_params,
|
|
217
|
+
# then adds create-specific parameters.
|
|
218
|
+
#
|
|
219
|
+
# @return [Hash] service-compatible parameters
|
|
220
|
+
# @raise [ArgumentError] if parser validation fails
|
|
221
|
+
def build_params_from_flags
|
|
222
|
+
params = build_vm_config_params
|
|
223
|
+
params[:name] = @options[:name]
|
|
224
|
+
params[:node] = @options[:node] || resolve_default_node
|
|
225
|
+
params[:description] = @options[:description]
|
|
226
|
+
params[:pool] = @options[:pool]
|
|
227
|
+
|
|
228
|
+
vmid = @args.first
|
|
229
|
+
params[:vmid] = vmid.to_i if vmid
|
|
230
|
+
|
|
231
|
+
params.compact
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# @param params [Hash] VM creation parameters
|
|
235
|
+
# @return [void]
|
|
236
|
+
def display_resource_summary(params)
|
|
237
|
+
$stdout.puts " Name: #{params[:name]}"
|
|
238
|
+
$stdout.puts " Node: #{params[:node] || '(from context)'}"
|
|
239
|
+
|
|
240
|
+
if params[:cores] || params[:sockets]
|
|
241
|
+
$stdout.puts " CPU: #{params[:cores] || 1} cores, #{params[:sockets] || 1} socket(s)"
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
$stdout.puts " Memory: #{params[:memory] || 2048} MB"
|
|
245
|
+
|
|
246
|
+
if params[:disks]
|
|
247
|
+
params[:disks].each_with_index do |disk, i|
|
|
248
|
+
$stdout.puts " Disk#{i}: #{disk[:storage]}, #{disk[:size]}"
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
if params[:nets]
|
|
253
|
+
params[:nets].each_with_index do |net, i|
|
|
254
|
+
$stdout.puts " Net#{i}: #{net[:bridge]}, #{net[:model] || 'virtio'}"
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
$stdout.puts " OS Type: #{params[:ostype]}" if params[:ostype]
|
|
259
|
+
$stdout.puts " BIOS: #{params[:bios]}" if params[:bios]
|
|
260
|
+
$stdout.puts " CD-ROM: #{params[:cdrom]}" if params[:cdrom]
|
|
261
|
+
$stdout.puts " Agent: enabled" if params[:agent]
|
|
262
|
+
$stdout.puts " Tags: #{params[:tags]}" if params[:tags]
|
|
263
|
+
$stdout.puts " Pool: #{params[:pool]}" if params[:pool]
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl delete backup` command.
|
|
6
|
+
#
|
|
7
|
+
# Deletes a backup identified by its full volume ID (volid).
|
|
8
|
+
# Requires --yes flag for confirmation.
|
|
9
|
+
#
|
|
10
|
+
# @example Delete a backup
|
|
11
|
+
# pvectl delete backup local:backup/vzdump-qemu-100-2024_01_15.vma.zst --yes
|
|
12
|
+
#
|
|
13
|
+
class DeleteBackup
|
|
14
|
+
# Executes the delete backup command.
|
|
15
|
+
#
|
|
16
|
+
# @param resource_type [String, nil] resource type (backup)
|
|
17
|
+
# @param args [Array<String>, String, nil] backup volid
|
|
18
|
+
# @param options [Hash] command options
|
|
19
|
+
# @param global_options [Hash] global CLI options
|
|
20
|
+
# @return [Integer] exit code
|
|
21
|
+
def self.execute(resource_type, args, options, global_options)
|
|
22
|
+
new(resource_type, args, options, global_options).execute
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Initializes a delete backup command.
|
|
26
|
+
#
|
|
27
|
+
# @param resource_type [String, nil] resource type (backup)
|
|
28
|
+
# @param args [Array<String>, String, nil] backup volid
|
|
29
|
+
# @param options [Hash] command options
|
|
30
|
+
# @param global_options [Hash] global CLI options
|
|
31
|
+
def initialize(resource_type, args, options, global_options)
|
|
32
|
+
@resource_type = resource_type
|
|
33
|
+
@args = Array(args).compact
|
|
34
|
+
@options = options
|
|
35
|
+
@global_options = global_options
|
|
36
|
+
@volid = @args.first
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Executes the delete backup command.
|
|
40
|
+
#
|
|
41
|
+
# @return [Integer] exit code
|
|
42
|
+
def execute
|
|
43
|
+
return usage_error("Resource type required (backup)") unless @resource_type == "backup"
|
|
44
|
+
return usage_error("Backup volid is required") if @volid.nil? || @volid.empty?
|
|
45
|
+
return usage_error("Confirmation required: use --yes to confirm deletion") unless @options[:yes]
|
|
46
|
+
|
|
47
|
+
perform_operation
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
# Performs the backup deletion operation.
|
|
53
|
+
#
|
|
54
|
+
# @return [Integer] exit code
|
|
55
|
+
def perform_operation
|
|
56
|
+
load_config
|
|
57
|
+
connection = Pvectl::Connection.new(@config)
|
|
58
|
+
|
|
59
|
+
backup_repo = Pvectl::Repositories::Backup.new(connection)
|
|
60
|
+
resolver = Pvectl::Utils::ResourceResolver.new(connection)
|
|
61
|
+
task_repo = Pvectl::Repositories::Task.new(connection)
|
|
62
|
+
|
|
63
|
+
service = Pvectl::Services::Backup.new(
|
|
64
|
+
backup_repo: backup_repo,
|
|
65
|
+
resource_resolver: resolver,
|
|
66
|
+
task_repo: task_repo,
|
|
67
|
+
options: service_options
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
result = service.delete(@volid)
|
|
71
|
+
|
|
72
|
+
output_results([result])
|
|
73
|
+
determine_exit_code([result])
|
|
74
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
75
|
+
Pvectl::Config::InvalidConfigError,
|
|
76
|
+
Pvectl::Config::ContextNotFoundError,
|
|
77
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
78
|
+
Pvectl::Config::UserNotFoundError
|
|
79
|
+
raise
|
|
80
|
+
rescue StandardError => e
|
|
81
|
+
$stderr.puts "Error: #{e.message}"
|
|
82
|
+
ExitCodes::GENERAL_ERROR
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Loads configuration from file or environment.
|
|
86
|
+
#
|
|
87
|
+
# @return [void]
|
|
88
|
+
def load_config
|
|
89
|
+
service = Pvectl::Config::Service.new
|
|
90
|
+
service.load(config: @global_options[:config])
|
|
91
|
+
@config = service.current_config
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Builds service options from command options.
|
|
95
|
+
#
|
|
96
|
+
# @return [Hash] service options
|
|
97
|
+
def service_options
|
|
98
|
+
opts = {}
|
|
99
|
+
opts[:timeout] = @options[:timeout] if @options[:timeout]
|
|
100
|
+
opts[:async] = true if @options[:async]
|
|
101
|
+
opts
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Outputs operation results using the configured formatter.
|
|
105
|
+
#
|
|
106
|
+
# @param results [Array<Models::OperationResult>] operation results
|
|
107
|
+
# @return [void]
|
|
108
|
+
def output_results(results)
|
|
109
|
+
presenter = Pvectl::Presenters::SnapshotOperationResult.new
|
|
110
|
+
format = @global_options[:output] || "table"
|
|
111
|
+
color_flag = @global_options[:color]
|
|
112
|
+
|
|
113
|
+
formatter = Pvectl::Formatters::Registry.for(format)
|
|
114
|
+
output = formatter.format(results, presenter, color: color_flag)
|
|
115
|
+
puts output
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Determines exit code based on results.
|
|
119
|
+
#
|
|
120
|
+
# @param results [Array<Models::OperationResult>] operation results
|
|
121
|
+
# @return [Integer] exit code
|
|
122
|
+
def determine_exit_code(results)
|
|
123
|
+
return ExitCodes::SUCCESS if results.all?(&:successful?)
|
|
124
|
+
return ExitCodes::SUCCESS if results.all?(&:pending?)
|
|
125
|
+
|
|
126
|
+
ExitCodes::GENERAL_ERROR
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Outputs usage error and returns exit code.
|
|
130
|
+
#
|
|
131
|
+
# @param message [String] error message
|
|
132
|
+
# @return [Integer] exit code
|
|
133
|
+
def usage_error(message)
|
|
134
|
+
$stderr.puts "Error: #{message}"
|
|
135
|
+
ExitCodes::USAGE_ERROR
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|