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,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Repositories
|
|
5
|
+
# Repository for Proxmox node capabilities.
|
|
6
|
+
#
|
|
7
|
+
# Aggregates feature information from the two most useful capability
|
|
8
|
+
# endpoints — QEMU CPU models and QEMU machine types — into a flat
|
|
9
|
+
# collection of Capability models. The cpu-flags and migration
|
|
10
|
+
# capability endpoints are intentionally out of scope for the initial
|
|
11
|
+
# implementation (YAGNI); they can be added when there is a concrete
|
|
12
|
+
# consumer need.
|
|
13
|
+
#
|
|
14
|
+
# @example List capabilities for a node
|
|
15
|
+
# repo = Capabilities.new(connection)
|
|
16
|
+
# caps = repo.list(node: "pve1")
|
|
17
|
+
# caps.each { |c| puts "#{c.kind}: #{c.name}" }
|
|
18
|
+
#
|
|
19
|
+
# @see Pvectl::Models::Capability
|
|
20
|
+
#
|
|
21
|
+
class Capabilities < Base
|
|
22
|
+
# CPU capability endpoint path (without leading slash).
|
|
23
|
+
CPU_ENDPOINT = "capabilities/qemu/cpu"
|
|
24
|
+
|
|
25
|
+
# Machine type capability endpoint path (without leading slash).
|
|
26
|
+
MACHINES_ENDPOINT = "capabilities/qemu/machines"
|
|
27
|
+
|
|
28
|
+
# Lists capabilities for a node.
|
|
29
|
+
#
|
|
30
|
+
# Combines `GET /nodes/{node}/capabilities/qemu/cpu` and
|
|
31
|
+
# `GET /nodes/{node}/capabilities/qemu/machines`. Each entry becomes
|
|
32
|
+
# a Capability instance — CPU models first, then machine types.
|
|
33
|
+
#
|
|
34
|
+
# @param node [String] cluster node name (required)
|
|
35
|
+
# @return [Array<Models::Capability>]
|
|
36
|
+
# @raise [ArgumentError] when `node` is nil/empty
|
|
37
|
+
# @raise [StandardError] propagated from the API on auth/connection failure
|
|
38
|
+
def list(node:)
|
|
39
|
+
raise ArgumentError, "node is required" if node.nil? || node.to_s.empty?
|
|
40
|
+
|
|
41
|
+
cpus(node) + machines(node)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
# Fetches CPU model capabilities.
|
|
47
|
+
#
|
|
48
|
+
# @param node [String]
|
|
49
|
+
# @return [Array<Models::Capability>]
|
|
50
|
+
def cpus(node)
|
|
51
|
+
response = connection.client["nodes/#{node}/#{CPU_ENDPOINT}"].get
|
|
52
|
+
unwrap(response).map { |data| build_cpu(data, node) }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Fetches machine type capabilities.
|
|
56
|
+
#
|
|
57
|
+
# @param node [String]
|
|
58
|
+
# @return [Array<Models::Capability>]
|
|
59
|
+
def machines(node)
|
|
60
|
+
response = connection.client["nodes/#{node}/#{MACHINES_ENDPOINT}"].get
|
|
61
|
+
unwrap(response).map { |data| build_machine(data, node) }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Builds a CPU capability model.
|
|
65
|
+
#
|
|
66
|
+
# @param data [Hash] one entry from the CPU endpoint
|
|
67
|
+
# @param node [String]
|
|
68
|
+
# @return [Models::Capability]
|
|
69
|
+
def build_cpu(data, node)
|
|
70
|
+
Models::Capability.new(
|
|
71
|
+
node_name: node,
|
|
72
|
+
kind: :cpu,
|
|
73
|
+
name: data[:name],
|
|
74
|
+
vendor: data[:vendor],
|
|
75
|
+
custom: data[:custom] || false
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Builds a machine type capability model.
|
|
80
|
+
#
|
|
81
|
+
# @param data [Hash] one entry from the machines endpoint
|
|
82
|
+
# @param node [String]
|
|
83
|
+
# @return [Models::Capability]
|
|
84
|
+
def build_machine(data, node)
|
|
85
|
+
Models::Capability.new(
|
|
86
|
+
node_name: node,
|
|
87
|
+
kind: :machine,
|
|
88
|
+
name: data[:id],
|
|
89
|
+
machine_type: data[:type],
|
|
90
|
+
version: data[:version],
|
|
91
|
+
changes: data[:changes]
|
|
92
|
+
)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "task_list"
|
|
4
|
+
|
|
5
|
+
module Pvectl
|
|
6
|
+
module Repositories
|
|
7
|
+
# Repository for LXC containers.
|
|
8
|
+
#
|
|
9
|
+
# Uses the `/cluster/resources` API endpoint to list containers across the cluster.
|
|
10
|
+
# Filters to only include LXC containers (excludes QEMU VMs).
|
|
11
|
+
#
|
|
12
|
+
# @example Listing all containers
|
|
13
|
+
# repo = Container.new(connection)
|
|
14
|
+
# containers = repo.list
|
|
15
|
+
# containers.each { |ct| puts "#{ct.vmid}: #{ct.name}" }
|
|
16
|
+
#
|
|
17
|
+
# @example Listing containers on a specific node
|
|
18
|
+
# containers = repo.list(node: "pve-node1")
|
|
19
|
+
#
|
|
20
|
+
# @example Getting a single container
|
|
21
|
+
# ct = repo.get(100)
|
|
22
|
+
# puts ct.name if ct
|
|
23
|
+
#
|
|
24
|
+
# @see Pvectl::Models::Container Container model
|
|
25
|
+
# @see Pvectl::Connection API connection
|
|
26
|
+
#
|
|
27
|
+
class Container < Base
|
|
28
|
+
# Lists all containers in the cluster.
|
|
29
|
+
#
|
|
30
|
+
# Uses `/cluster/resources?type=lxc` endpoint for efficient cluster-wide
|
|
31
|
+
# listing. Filters to only include LXC containers (type == "lxc").
|
|
32
|
+
#
|
|
33
|
+
# @param node [String, nil] filter by node name
|
|
34
|
+
# @return [Array<Models::Container>] collection of Container models
|
|
35
|
+
def list(node: nil)
|
|
36
|
+
response = connection.client["cluster/resources"].get(params: { type: "vm" })
|
|
37
|
+
containers = unwrap(response).select { |r| r[:type] == "lxc" }
|
|
38
|
+
containers = containers.select { |r| r[:node] == node } if node
|
|
39
|
+
containers.map { |data| build_model(data) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Gets a single container by CTID.
|
|
43
|
+
#
|
|
44
|
+
# @param ctid [Integer, String] container identifier
|
|
45
|
+
# @return [Models::Container, nil] Container model or nil if not found
|
|
46
|
+
def get(ctid)
|
|
47
|
+
list.find { |ct| ct.vmid == ctid.to_i }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Describes a container with comprehensive details from multiple API endpoints.
|
|
51
|
+
#
|
|
52
|
+
# @param ctid [Integer, String] container identifier
|
|
53
|
+
# @return [Models::Container, nil] Container model with full details, or nil if not found
|
|
54
|
+
def describe(ctid)
|
|
55
|
+
ctid = ctid.to_i
|
|
56
|
+
|
|
57
|
+
basic_data = find_container_basic_data(ctid)
|
|
58
|
+
return nil if basic_data.nil?
|
|
59
|
+
|
|
60
|
+
node = basic_data[:node]
|
|
61
|
+
|
|
62
|
+
config = fetch_config(node, ctid)
|
|
63
|
+
status = fetch_status(node, ctid)
|
|
64
|
+
snapshots = fetch_snapshots(node, ctid)
|
|
65
|
+
tasks = fetch_tasks(node, ctid)
|
|
66
|
+
firewall = fetch_firewall(node, ctid)
|
|
67
|
+
|
|
68
|
+
build_describe_model(basic_data, config, status, snapshots, tasks, firewall)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Deletes a container from the cluster.
|
|
72
|
+
#
|
|
73
|
+
# @param ctid [Integer, String] Container identifier
|
|
74
|
+
# @param node [String] Node name
|
|
75
|
+
# @param destroy_disks [Boolean] destroy unreferenced disks (default: true)
|
|
76
|
+
# @param purge [Boolean] remove from HA, replication, backups (default: false)
|
|
77
|
+
# @param force [Boolean] force removal (default: false)
|
|
78
|
+
# @return [String] Task UPID
|
|
79
|
+
def delete(ctid, node, destroy_disks: true, purge: false, force: false)
|
|
80
|
+
params = {}
|
|
81
|
+
params["destroy-unreferenced-disks"] = 1 if destroy_disks
|
|
82
|
+
params[:purge] = 1 if purge
|
|
83
|
+
params[:force] = 1 if force
|
|
84
|
+
|
|
85
|
+
connection.client["nodes/#{node}/lxc/#{ctid}"].delete(params)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Starts a container.
|
|
89
|
+
#
|
|
90
|
+
# @param ctid [Integer, String] Container identifier
|
|
91
|
+
# @param node [String] Node name
|
|
92
|
+
# @return [String] Task UPID
|
|
93
|
+
def start(ctid, node)
|
|
94
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/status/start"].post
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Stops a container (hard stop).
|
|
98
|
+
#
|
|
99
|
+
# @param ctid [Integer, String] Container identifier
|
|
100
|
+
# @param node [String] Node name
|
|
101
|
+
# @return [String] Task UPID
|
|
102
|
+
def stop(ctid, node)
|
|
103
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/status/stop"].post
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Shuts down a container gracefully.
|
|
107
|
+
#
|
|
108
|
+
# @param ctid [Integer, String] Container identifier
|
|
109
|
+
# @param node [String] Node name
|
|
110
|
+
# @return [String] Task UPID
|
|
111
|
+
def shutdown(ctid, node)
|
|
112
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/status/shutdown"].post
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Clones a container to create a new container.
|
|
116
|
+
#
|
|
117
|
+
# Posts to `/nodes/{node}/lxc/{ctid}/clone` with the specified parameters.
|
|
118
|
+
# Note: LXC API uses `hostname` parameter (not `name` like QEMU).
|
|
119
|
+
#
|
|
120
|
+
# @param ctid [Integer, String] source container identifier
|
|
121
|
+
# @param node [String] source node name
|
|
122
|
+
# @param new_ctid [Integer] CTID for the new cloned container
|
|
123
|
+
# @param options [Hash] optional clone parameters
|
|
124
|
+
# @option options [String] :hostname hostname for the new container
|
|
125
|
+
# @option options [String] :target target node for the clone
|
|
126
|
+
# @option options [String] :storage target storage for the clone
|
|
127
|
+
# @option options [Boolean] :full full clone (true) or linked clone (false)
|
|
128
|
+
# @option options [String] :description description for the new container
|
|
129
|
+
# @option options [String] :pool resource pool for the new container
|
|
130
|
+
# @return [String] Task UPID
|
|
131
|
+
def clone(ctid, node, new_ctid, options = {})
|
|
132
|
+
params = { newid: new_ctid }
|
|
133
|
+
params[:hostname] = options[:hostname] if options[:hostname]
|
|
134
|
+
params[:target] = options[:target] if options[:target]
|
|
135
|
+
params[:storage] = options[:storage] if options[:storage]
|
|
136
|
+
params[:full] = options[:full] ? 1 : 0 if options.key?(:full)
|
|
137
|
+
params[:description] = options[:description] if options[:description]
|
|
138
|
+
params[:pool] = options[:pool] if options[:pool]
|
|
139
|
+
|
|
140
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/clone"].post(params)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Converts a container to a template.
|
|
144
|
+
#
|
|
145
|
+
# This is an irreversible operation. The container will become read-only
|
|
146
|
+
# and can only be used as a source for cloning.
|
|
147
|
+
#
|
|
148
|
+
# @param ctid [Integer, String] Container identifier
|
|
149
|
+
# @param node [String] Node name
|
|
150
|
+
# @return [void]
|
|
151
|
+
def convert_to_template(ctid, node)
|
|
152
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/template"].post({})
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Migrates a container to another node.
|
|
156
|
+
#
|
|
157
|
+
# @param ctid [Integer, String] container identifier
|
|
158
|
+
# @param node [String] current node name
|
|
159
|
+
# @param params [Hash] migration parameters (:target, :online, :restart, :targetstorage)
|
|
160
|
+
# @return [String] Task UPID
|
|
161
|
+
# @raise [ArgumentError] if node name or ctid format is invalid
|
|
162
|
+
def migrate(ctid, node, params = {})
|
|
163
|
+
unless node.match?(/\A[a-z][a-z0-9-]*\z/)
|
|
164
|
+
raise ArgumentError, "Invalid node name: #{node}"
|
|
165
|
+
end
|
|
166
|
+
unless ctid.is_a?(Integer) && ctid.positive?
|
|
167
|
+
raise ArgumentError, "Invalid CTID: #{ctid}"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/migrate"].post(params)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Moves a container volume to a different storage on the same node.
|
|
174
|
+
#
|
|
175
|
+
# POSTs to +/nodes/{node}/lxc/{ctid}/move_volume+ with the volume identifier
|
|
176
|
+
# and target storage. The operation is asynchronous — the returned UPID
|
|
177
|
+
# can be polled via Repositories::Task to track completion.
|
|
178
|
+
#
|
|
179
|
+
# @param ctid [Integer, String] container identifier
|
|
180
|
+
# @param node [String] node name where the container currently resides
|
|
181
|
+
# @param volume [String] volume identifier (e.g., "rootfs", "mp0")
|
|
182
|
+
# @param target_storage [String] destination storage ID
|
|
183
|
+
# @param delete [Boolean] delete the source volume after copy (default: false)
|
|
184
|
+
# @param bwlimit [Integer, nil] I/O bandwidth limit in KiB/s
|
|
185
|
+
# @return [String] Task UPID
|
|
186
|
+
#
|
|
187
|
+
# @example Move rootfs to a different storage
|
|
188
|
+
# repo.move_volume(200, "pve1", "rootfs", "local-lvm")
|
|
189
|
+
# #=> "UPID:pve1:..."
|
|
190
|
+
#
|
|
191
|
+
# @example Move and delete source volume
|
|
192
|
+
# repo.move_volume(200, "pve1", "mp0", "ceph-pool", delete: true)
|
|
193
|
+
def move_volume(ctid, node, volume, target_storage, delete: false, bwlimit: nil)
|
|
194
|
+
params = { volume: volume, storage: target_storage }
|
|
195
|
+
params[:delete] = 1 if delete
|
|
196
|
+
params[:bwlimit] = bwlimit if bwlimit
|
|
197
|
+
|
|
198
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/move_volume"].post(params)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Checks whether a feature (clone, snapshot, copy) is available for a container.
|
|
202
|
+
#
|
|
203
|
+
# Calls +GET /nodes/{node}/lxc/{vmid}/feature+ with the feature and
|
|
204
|
+
# optional snapshot name. The Proxmox LXC API returns +hasFeature+ (0/1).
|
|
205
|
+
# Unlike the QEMU variant, the LXC endpoint does not return a +nodes+ array;
|
|
206
|
+
# this method always returns +nodes: []+ for shape compatibility.
|
|
207
|
+
#
|
|
208
|
+
# @param ctid [Integer, String] container identifier
|
|
209
|
+
# @param node [String] node currently hosting the container
|
|
210
|
+
# @param feature [String] feature name (one of: clone, snapshot, copy)
|
|
211
|
+
# @param snapname [String, nil] snapshot name (required for some checks)
|
|
212
|
+
# @return [Hash] result with :available (Boolean) and :nodes (Array<String>)
|
|
213
|
+
#
|
|
214
|
+
# @example Check whether container 200 can be cloned
|
|
215
|
+
# repo.feature_available?(200, "pve1", "clone")
|
|
216
|
+
# #=> { available: true, nodes: [] }
|
|
217
|
+
def feature_available?(ctid, node, feature, snapname: nil)
|
|
218
|
+
params = { feature: feature }
|
|
219
|
+
params[:snapname] = snapname unless snapname.nil?
|
|
220
|
+
|
|
221
|
+
response = connection.client["nodes/#{node}/lxc/#{ctid}/feature"].get(params: params)
|
|
222
|
+
data = extract_data(response)
|
|
223
|
+
|
|
224
|
+
{
|
|
225
|
+
available: data[:hasFeature].to_i == 1,
|
|
226
|
+
nodes: Array(data[:nodes])
|
|
227
|
+
}
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Returns the next available CTID from the Proxmox cluster.
|
|
231
|
+
#
|
|
232
|
+
# Uses the +/cluster/nextid+ API endpoint which performs server-side allocation.
|
|
233
|
+
# This is more reliable than client-side scanning because it detects stale
|
|
234
|
+
# config files that don't appear in +/cluster/resources+.
|
|
235
|
+
#
|
|
236
|
+
# @return [Integer] next available CTID
|
|
237
|
+
def next_available_ctid
|
|
238
|
+
connection.client["cluster/nextid"].get.to_i
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Restarts a container (reboot).
|
|
242
|
+
#
|
|
243
|
+
# @param ctid [Integer, String] Container identifier
|
|
244
|
+
# @param node [String] Node name
|
|
245
|
+
# @return [String] Task UPID
|
|
246
|
+
def restart(ctid, node)
|
|
247
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/status/reboot"].post
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Opens a terminal proxy session for a container.
|
|
251
|
+
#
|
|
252
|
+
# @param ctid [Integer, String] Container identifier
|
|
253
|
+
# @param node [String] Node name
|
|
254
|
+
# @return [Hash] termproxy data with :port, :ticket, :user keys
|
|
255
|
+
def termproxy(ctid, node)
|
|
256
|
+
response = connection.client["nodes/#{node}/lxc/#{ctid}/termproxy"].post({})
|
|
257
|
+
extract_data(response)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Creates a new LXC container on the specified node.
|
|
261
|
+
#
|
|
262
|
+
# Posts to `/nodes/{node}/lxc` with the container configuration parameters.
|
|
263
|
+
# The ctid is merged into params automatically.
|
|
264
|
+
#
|
|
265
|
+
# @param node [String] target node name
|
|
266
|
+
# @param ctid [Integer] container identifier
|
|
267
|
+
# @param params [Hash] container configuration parameters (hostname, ostemplate, etc.)
|
|
268
|
+
# @return [String] Task UPID
|
|
269
|
+
#
|
|
270
|
+
# @example Create a basic container
|
|
271
|
+
# repo.create("pve1", 200, { hostname: "web-ct", ostemplate: "local:vztmpl/debian-12.tar.zst" })
|
|
272
|
+
# #=> "UPID:pve1:..."
|
|
273
|
+
def create(node, ctid, params = {})
|
|
274
|
+
api_params = params.merge(vmid: ctid)
|
|
275
|
+
connection.client["nodes/#{node}/lxc"].post(api_params)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Updates an existing LXC container configuration.
|
|
279
|
+
#
|
|
280
|
+
# PUTs to +/nodes/{node}/lxc/{ctid}/config+ with configuration parameters.
|
|
281
|
+
# This is a synchronous operation — changes are applied immediately.
|
|
282
|
+
#
|
|
283
|
+
# @param ctid [Integer, String] container identifier
|
|
284
|
+
# @param node [String] node name
|
|
285
|
+
# @param params [Hash] container configuration parameters to update
|
|
286
|
+
# @return [nil]
|
|
287
|
+
def update(ctid, node, params = {})
|
|
288
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/config"].put(params)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# Resizes a container disk.
|
|
292
|
+
#
|
|
293
|
+
# PUTs to +/nodes/{node}/lxc/{ctid}/resize+ with disk identifier
|
|
294
|
+
# and new size. This is a synchronous, irreversible operation —
|
|
295
|
+
# Proxmox does not support shrinking disks.
|
|
296
|
+
#
|
|
297
|
+
# @param ctid [Integer, String] container identifier
|
|
298
|
+
# @param node [String] node name
|
|
299
|
+
# @param disk [String] disk identifier (e.g., "rootfs", "mp0")
|
|
300
|
+
# @param size [String] new size, absolute ("50G") or relative ("+10G")
|
|
301
|
+
# @return [nil]
|
|
302
|
+
def resize(ctid, node, disk:, size:)
|
|
303
|
+
connection.client["nodes/#{node}/lxc/#{ctid}/resize"].put({ disk: disk, size: size })
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Fetches container configuration.
|
|
307
|
+
#
|
|
308
|
+
# @param node [String] node name
|
|
309
|
+
# @param ctid [Integer] container identifier
|
|
310
|
+
# @return [Hash] config data
|
|
311
|
+
def fetch_config(node, ctid)
|
|
312
|
+
resp = connection.client["nodes/#{node}/lxc/#{ctid}/config"].get
|
|
313
|
+
extract_data(resp)
|
|
314
|
+
rescue StandardError
|
|
315
|
+
{}
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
protected
|
|
319
|
+
|
|
320
|
+
# Builds Container model from API response data.
|
|
321
|
+
#
|
|
322
|
+
# @param data [Hash] API response hash
|
|
323
|
+
# @return [Models::Container] Container model instance
|
|
324
|
+
def build_model(data)
|
|
325
|
+
Models::Container.new(
|
|
326
|
+
vmid: data[:vmid],
|
|
327
|
+
name: data[:name],
|
|
328
|
+
status: data[:status],
|
|
329
|
+
node: data[:node],
|
|
330
|
+
cpu: data[:cpu],
|
|
331
|
+
maxcpu: data[:maxcpu],
|
|
332
|
+
mem: data[:mem],
|
|
333
|
+
maxmem: data[:maxmem],
|
|
334
|
+
swap: data[:swap],
|
|
335
|
+
maxswap: data[:maxswap],
|
|
336
|
+
disk: data[:disk],
|
|
337
|
+
maxdisk: data[:maxdisk],
|
|
338
|
+
uptime: data[:uptime],
|
|
339
|
+
template: data[:template],
|
|
340
|
+
tags: data[:tags],
|
|
341
|
+
pool: data[:pool],
|
|
342
|
+
lock: data[:lock],
|
|
343
|
+
netin: data[:netin],
|
|
344
|
+
netout: data[:netout],
|
|
345
|
+
type: data[:type]
|
|
346
|
+
)
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
private
|
|
350
|
+
|
|
351
|
+
# Finds container basic data from cluster resources.
|
|
352
|
+
#
|
|
353
|
+
# @param ctid [Integer] container identifier
|
|
354
|
+
# @return [Hash, nil] container data or nil if not found
|
|
355
|
+
def find_container_basic_data(ctid)
|
|
356
|
+
response = connection.client["cluster/resources"].get(params: { type: "vm" })
|
|
357
|
+
unwrap(response).find { |r| r[:type] == "lxc" && r[:vmid] == ctid }
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Fetches container runtime status.
|
|
361
|
+
#
|
|
362
|
+
# @param node [String] node name
|
|
363
|
+
# @param ctid [Integer] container identifier
|
|
364
|
+
# @return [Hash] status data
|
|
365
|
+
def fetch_status(node, ctid)
|
|
366
|
+
resp = connection.client["nodes/#{node}/lxc/#{ctid}/status/current"].get
|
|
367
|
+
extract_data(resp)
|
|
368
|
+
rescue StandardError
|
|
369
|
+
{}
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# Fetches container snapshots.
|
|
373
|
+
#
|
|
374
|
+
# @param node [String] node name
|
|
375
|
+
# @param ctid [Integer] container identifier
|
|
376
|
+
# @return [Array<Hash>] snapshots list (excluding "current")
|
|
377
|
+
def fetch_snapshots(node, ctid)
|
|
378
|
+
resp = connection.client["nodes/#{node}/lxc/#{ctid}/snapshot"].get
|
|
379
|
+
unwrap(resp).reject { |s| s[:name] == "current" }
|
|
380
|
+
rescue StandardError
|
|
381
|
+
[]
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Fetches firewall configuration (options, rules, aliases, IP sets).
|
|
385
|
+
#
|
|
386
|
+
# @param node [String] node name
|
|
387
|
+
# @param ctid [Integer] container identifier
|
|
388
|
+
# @return [Hash] firewall data with :options, :rules, :aliases, :ipset keys
|
|
389
|
+
def fetch_firewall(node, ctid)
|
|
390
|
+
base = "nodes/#{node}/lxc/#{ctid}/firewall"
|
|
391
|
+
options = (extract_data(connection.client["#{base}/options"].get) rescue {})
|
|
392
|
+
rules = (unwrap(connection.client["#{base}/rules"].get) rescue [])
|
|
393
|
+
aliases_data = (unwrap(connection.client["#{base}/aliases"].get) rescue [])
|
|
394
|
+
ipset = (unwrap(connection.client["#{base}/ipset"].get) rescue [])
|
|
395
|
+
{ options: options, rules: rules, aliases: aliases_data, ipset: ipset }
|
|
396
|
+
rescue StandardError
|
|
397
|
+
{}
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
# Fetches recent task history for the container.
|
|
401
|
+
#
|
|
402
|
+
# @param node [String] node name
|
|
403
|
+
# @param ctid [Integer] container identifier
|
|
404
|
+
# @param limit [Integer] max entries (default 10)
|
|
405
|
+
# @return [Array<Models::TaskEntry>] recent tasks
|
|
406
|
+
def fetch_tasks(node, ctid, limit: 10)
|
|
407
|
+
task_list_repo = TaskList.new(connection)
|
|
408
|
+
task_list_repo.list(node: node, vmid: ctid, limit: limit)
|
|
409
|
+
rescue StandardError
|
|
410
|
+
[]
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
# Extracts network interfaces from config.
|
|
414
|
+
# Network interfaces are stored as net0, net1, etc. keys.
|
|
415
|
+
#
|
|
416
|
+
# @param config [Hash] container config
|
|
417
|
+
# @return [Array<Hash>] parsed network interfaces
|
|
418
|
+
def extract_network_interfaces(config)
|
|
419
|
+
interfaces = []
|
|
420
|
+
config.each do |key, value|
|
|
421
|
+
next unless key.to_s.match?(/^net\d+$/)
|
|
422
|
+
|
|
423
|
+
parsed = parse_network_interface(key.to_s, value)
|
|
424
|
+
interfaces << parsed if parsed
|
|
425
|
+
end
|
|
426
|
+
interfaces
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# Parses a single network interface string.
|
|
430
|
+
#
|
|
431
|
+
# @param key [String] interface key (e.g., "net0")
|
|
432
|
+
# @param value [String] interface configuration string
|
|
433
|
+
# @return [Hash] parsed interface data
|
|
434
|
+
def parse_network_interface(key, value)
|
|
435
|
+
return nil unless value.is_a?(String)
|
|
436
|
+
|
|
437
|
+
interface = { id: key }
|
|
438
|
+
|
|
439
|
+
# Parse key=value pairs from the interface string
|
|
440
|
+
value.split(",").each do |part|
|
|
441
|
+
k, v = part.split("=", 2)
|
|
442
|
+
interface[k.to_sym] = v if k && v
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
interface
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
# Builds Container model with describe-specific attributes.
|
|
449
|
+
#
|
|
450
|
+
# @param basic_data [Hash] basic container data from cluster/resources
|
|
451
|
+
# @param config [Hash] container config from /nodes/{node}/lxc/{ctid}/config
|
|
452
|
+
# @param status [Hash] container status from /nodes/{node}/lxc/{ctid}/status/current
|
|
453
|
+
# @param snapshots [Array<Hash>] container snapshots
|
|
454
|
+
# @return [Models::Container] Container model
|
|
455
|
+
def build_describe_model(basic_data, config, status, snapshots = [], tasks = [], firewall = {})
|
|
456
|
+
network_interfaces = extract_network_interfaces(config)
|
|
457
|
+
|
|
458
|
+
Models::Container.new(
|
|
459
|
+
# Basic attributes from cluster/resources
|
|
460
|
+
vmid: basic_data[:vmid],
|
|
461
|
+
name: basic_data[:name],
|
|
462
|
+
status: basic_data[:status],
|
|
463
|
+
node: basic_data[:node],
|
|
464
|
+
type: basic_data[:type],
|
|
465
|
+
cpu: basic_data[:cpu],
|
|
466
|
+
maxcpu: basic_data[:maxcpu],
|
|
467
|
+
mem: basic_data[:mem],
|
|
468
|
+
maxmem: basic_data[:maxmem],
|
|
469
|
+
swap: basic_data[:swap],
|
|
470
|
+
maxswap: basic_data[:maxswap],
|
|
471
|
+
disk: basic_data[:disk],
|
|
472
|
+
maxdisk: basic_data[:maxdisk],
|
|
473
|
+
uptime: basic_data[:uptime],
|
|
474
|
+
template: basic_data[:template],
|
|
475
|
+
tags: basic_data[:tags],
|
|
476
|
+
pool: basic_data[:pool],
|
|
477
|
+
lock: basic_data[:lock],
|
|
478
|
+
netin: basic_data[:netin],
|
|
479
|
+
netout: basic_data[:netout],
|
|
480
|
+
|
|
481
|
+
# Config attributes (kept for backward compat)
|
|
482
|
+
ostype: config[:ostype],
|
|
483
|
+
arch: config[:arch],
|
|
484
|
+
unprivileged: config[:unprivileged],
|
|
485
|
+
features: config[:features],
|
|
486
|
+
rootfs: config[:rootfs],
|
|
487
|
+
description: config[:description],
|
|
488
|
+
hostname: config[:hostname],
|
|
489
|
+
|
|
490
|
+
# Status attributes
|
|
491
|
+
pid: status[:pid],
|
|
492
|
+
ha: status[:ha],
|
|
493
|
+
|
|
494
|
+
# Parsed network interfaces
|
|
495
|
+
network_interfaces: network_interfaces,
|
|
496
|
+
|
|
497
|
+
# Raw API data for comprehensive describe
|
|
498
|
+
describe_data: { config: config, status: status, snapshots: snapshots, tasks: tasks, firewall: firewall }
|
|
499
|
+
)
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Repositories
|
|
5
|
+
# Repository for physical disks on Proxmox nodes.
|
|
6
|
+
#
|
|
7
|
+
# Uses the `/nodes/{node}/disks/list` API endpoint to fetch
|
|
8
|
+
# physical disk information per node.
|
|
9
|
+
#
|
|
10
|
+
# @example Listing all disks across the cluster
|
|
11
|
+
# repo = Disk.new(connection)
|
|
12
|
+
# disks = repo.list
|
|
13
|
+
# disks.each { |d| puts "#{d.node}: #{d.devpath} (#{d.type})" }
|
|
14
|
+
#
|
|
15
|
+
# @example Listing disks on a specific node
|
|
16
|
+
# disks = repo.list(node: "pve1")
|
|
17
|
+
#
|
|
18
|
+
# @see Pvectl::Models::PhysicalDisk PhysicalDisk model
|
|
19
|
+
# @see Pvectl::Connection API connection
|
|
20
|
+
#
|
|
21
|
+
class Disk < Base
|
|
22
|
+
# Lists physical disks, optionally filtered by node.
|
|
23
|
+
#
|
|
24
|
+
# When node is nil, iterates over all online nodes in the cluster.
|
|
25
|
+
# When node is specified, queries only that node.
|
|
26
|
+
#
|
|
27
|
+
# @param node [String, nil] filter by node name
|
|
28
|
+
# @return [Array<Models::PhysicalDisk>] collection of PhysicalDisk models
|
|
29
|
+
def list(node: nil)
|
|
30
|
+
if node
|
|
31
|
+
disks_for_node(node)
|
|
32
|
+
else
|
|
33
|
+
online_nodes.flat_map { |node_name| disks_for_node(node_name) }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Fetches SMART data for a specific disk on a node.
|
|
38
|
+
#
|
|
39
|
+
# @param node_name [String] node name
|
|
40
|
+
# @param disk_path [String] device path (e.g., "/dev/nvme0n1")
|
|
41
|
+
# @return [Hash{Symbol => untyped}] SMART data with keys: :health, :type, :attributes, :text
|
|
42
|
+
def smart(node_name, disk_path)
|
|
43
|
+
response = connection.client["nodes/#{node_name}/disks/smart"].get(params: { disk: disk_path })
|
|
44
|
+
extract_data(response)
|
|
45
|
+
rescue StandardError
|
|
46
|
+
{}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
protected
|
|
50
|
+
|
|
51
|
+
# Builds PhysicalDisk model from API response data.
|
|
52
|
+
#
|
|
53
|
+
# @param data [Hash] API response hash
|
|
54
|
+
# @return [Models::PhysicalDisk] PhysicalDisk model instance
|
|
55
|
+
def build_model(data)
|
|
56
|
+
Models::PhysicalDisk.new(data)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
# Fetches disks for a single node.
|
|
62
|
+
#
|
|
63
|
+
# @param node_name [String] node name
|
|
64
|
+
# @return [Array<Models::PhysicalDisk>] disks on that node
|
|
65
|
+
def disks_for_node(node_name)
|
|
66
|
+
response = connection.client["nodes/#{node_name}/disks/list"].get
|
|
67
|
+
disks_data = unwrap(response)
|
|
68
|
+
disks_data.map { |data| build_model(data.merge(node: node_name)) }
|
|
69
|
+
rescue StandardError
|
|
70
|
+
[]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Fetches list of online node names.
|
|
74
|
+
#
|
|
75
|
+
# @return [Array<String>] online node names
|
|
76
|
+
def online_nodes
|
|
77
|
+
response = connection.client["nodes"].get
|
|
78
|
+
nodes_data = unwrap(response)
|
|
79
|
+
nodes_data
|
|
80
|
+
.select { |n| n[:status] == "online" }
|
|
81
|
+
.map { |n| n[:node] || n[:name] }
|
|
82
|
+
rescue StandardError
|
|
83
|
+
[]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|