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.
Files changed (558) hide show
  1. checksums.yaml +7 -0
  2. data/.claude/rules/branch-before-changes.md +52 -0
  3. data/.claude/rules/documentation-updates.md +104 -0
  4. data/.claude/rules/git-workflow.md +84 -0
  5. data/.claude/rules/proxmox-api-docs.md +58 -0
  6. data/.claude/rules/rbs-signatures.md +80 -0
  7. data/.claude/rules/refactoring-as-design-option.md +35 -0
  8. data/.claude/scheduled_tasks.lock +1 -0
  9. data/.claude/settings.json +51 -0
  10. data/.mcp.json +8 -0
  11. data/.ruby-gemset +1 -0
  12. data/.ruby-version +1 -0
  13. data/CHANGELOG.md +138 -0
  14. data/CLAUDE.md +211 -0
  15. data/CODE_OF_CONDUCT.md +132 -0
  16. data/LICENSE.txt +21 -0
  17. data/README.md +143 -0
  18. data/Rakefile +8 -0
  19. data/docs/proxmox-api-update.sh +96 -0
  20. data/exe/pvectl +5 -0
  21. data/lib/pvectl/argv_preprocessor.rb +334 -0
  22. data/lib/pvectl/cli.rb +102 -0
  23. data/lib/pvectl/commands/apt.rb +389 -0
  24. data/lib/pvectl/commands/clone_container.rb +230 -0
  25. data/lib/pvectl/commands/clone_vm.rb +331 -0
  26. data/lib/pvectl/commands/cloudinit/command.rb +122 -0
  27. data/lib/pvectl/commands/cloudinit/dump.rb +94 -0
  28. data/lib/pvectl/commands/cloudinit/pending.rb +137 -0
  29. data/lib/pvectl/commands/cloudinit/regenerate.rb +79 -0
  30. data/lib/pvectl/commands/config/command.rb +65 -0
  31. data/lib/pvectl/commands/config/get_contexts.rb +68 -0
  32. data/lib/pvectl/commands/config/set_cluster.rb +103 -0
  33. data/lib/pvectl/commands/config/set_context.rb +136 -0
  34. data/lib/pvectl/commands/config/set_credentials.rb +181 -0
  35. data/lib/pvectl/commands/config/use_context.rb +69 -0
  36. data/lib/pvectl/commands/config/view.rb +67 -0
  37. data/lib/pvectl/commands/console.rb +93 -0
  38. data/lib/pvectl/commands/console_ct.rb +187 -0
  39. data/lib/pvectl/commands/console_vm.rb +187 -0
  40. data/lib/pvectl/commands/container_lifecycle_command.rb +77 -0
  41. data/lib/pvectl/commands/create_backup.rb +173 -0
  42. data/lib/pvectl/commands/create_container.rb +141 -0
  43. data/lib/pvectl/commands/create_resource_command.rb +244 -0
  44. data/lib/pvectl/commands/create_snapshot.rb +242 -0
  45. data/lib/pvectl/commands/create_vm.rb +267 -0
  46. data/lib/pvectl/commands/delete_backup.rb +139 -0
  47. data/lib/pvectl/commands/delete_command.rb +119 -0
  48. data/lib/pvectl/commands/delete_container.rb +30 -0
  49. data/lib/pvectl/commands/delete_snapshot.rb +248 -0
  50. data/lib/pvectl/commands/delete_vm.rb +127 -0
  51. data/lib/pvectl/commands/describe/command.rb +251 -0
  52. data/lib/pvectl/commands/edit_container.rb +56 -0
  53. data/lib/pvectl/commands/edit_dns.rb +149 -0
  54. data/lib/pvectl/commands/edit_hosts.rb +135 -0
  55. data/lib/pvectl/commands/edit_node.rb +54 -0
  56. data/lib/pvectl/commands/edit_resource_command.rb +180 -0
  57. data/lib/pvectl/commands/edit_vm.rb +154 -0
  58. data/lib/pvectl/commands/edit_volume.rb +189 -0
  59. data/lib/pvectl/commands/feature_command.rb +230 -0
  60. data/lib/pvectl/commands/feature_container.rb +21 -0
  61. data/lib/pvectl/commands/feature_vm.rb +94 -0
  62. data/lib/pvectl/commands/get/command.rb +360 -0
  63. data/lib/pvectl/commands/get/handlers/backups.rb +76 -0
  64. data/lib/pvectl/commands/get/handlers/capabilities.rb +107 -0
  65. data/lib/pvectl/commands/get/handlers/containers.rb +148 -0
  66. data/lib/pvectl/commands/get/handlers/disks.rb +107 -0
  67. data/lib/pvectl/commands/get/handlers/dns.rb +94 -0
  68. data/lib/pvectl/commands/get/handlers/hosts.rb +94 -0
  69. data/lib/pvectl/commands/get/handlers/nodes.rb +162 -0
  70. data/lib/pvectl/commands/get/handlers/services.rb +81 -0
  71. data/lib/pvectl/commands/get/handlers/snapshots.rb +97 -0
  72. data/lib/pvectl/commands/get/handlers/storage.rb +118 -0
  73. data/lib/pvectl/commands/get/handlers/subscription.rb +69 -0
  74. data/lib/pvectl/commands/get/handlers/tasks.rb +89 -0
  75. data/lib/pvectl/commands/get/handlers/templates.rb +175 -0
  76. data/lib/pvectl/commands/get/handlers/time.rb +118 -0
  77. data/lib/pvectl/commands/get/handlers/vms.rb +145 -0
  78. data/lib/pvectl/commands/get/handlers/volume.rb +134 -0
  79. data/lib/pvectl/commands/get/resource_handler.rb +63 -0
  80. data/lib/pvectl/commands/get/resource_registry.rb +18 -0
  81. data/lib/pvectl/commands/get/watch_loop.rb +129 -0
  82. data/lib/pvectl/commands/irreversible_command.rb +265 -0
  83. data/lib/pvectl/commands/logs/command.rb +275 -0
  84. data/lib/pvectl/commands/logs/handlers/journal.rb +46 -0
  85. data/lib/pvectl/commands/logs/handlers/syslog.rb +53 -0
  86. data/lib/pvectl/commands/logs/handlers/task_detail.rb +52 -0
  87. data/lib/pvectl/commands/logs/handlers/task_logs.rb +115 -0
  88. data/lib/pvectl/commands/logs/resource_handler.rb +46 -0
  89. data/lib/pvectl/commands/logs/resource_registry.rb +22 -0
  90. data/lib/pvectl/commands/migrate_command.rb +282 -0
  91. data/lib/pvectl/commands/migrate_container.rb +23 -0
  92. data/lib/pvectl/commands/migrate_vm.rb +122 -0
  93. data/lib/pvectl/commands/move_disk_command.rb +239 -0
  94. data/lib/pvectl/commands/move_disk_container.rb +21 -0
  95. data/lib/pvectl/commands/move_disk_vm.rb +127 -0
  96. data/lib/pvectl/commands/ping.rb +249 -0
  97. data/lib/pvectl/commands/pull.rb +342 -0
  98. data/lib/pvectl/commands/push.rb +352 -0
  99. data/lib/pvectl/commands/reset.rb +64 -0
  100. data/lib/pvectl/commands/resource_lifecycle_command.rb +277 -0
  101. data/lib/pvectl/commands/resource_registry.rb +73 -0
  102. data/lib/pvectl/commands/restart.rb +70 -0
  103. data/lib/pvectl/commands/restart_container.rb +18 -0
  104. data/lib/pvectl/commands/restore_backup.rb +236 -0
  105. data/lib/pvectl/commands/resume.rb +57 -0
  106. data/lib/pvectl/commands/rollback_snapshot.rb +228 -0
  107. data/lib/pvectl/commands/sendkey_vm.rb +205 -0
  108. data/lib/pvectl/commands/service.rb +293 -0
  109. data/lib/pvectl/commands/set_container.rb +50 -0
  110. data/lib/pvectl/commands/set_node.rb +52 -0
  111. data/lib/pvectl/commands/set_resource_command.rb +185 -0
  112. data/lib/pvectl/commands/set_vm.rb +136 -0
  113. data/lib/pvectl/commands/set_volume.rb +212 -0
  114. data/lib/pvectl/commands/shared_config_parsers.rb +126 -0
  115. data/lib/pvectl/commands/shared_flags.rb +155 -0
  116. data/lib/pvectl/commands/shutdown.rb +73 -0
  117. data/lib/pvectl/commands/shutdown_container.rb +18 -0
  118. data/lib/pvectl/commands/start.rb +79 -0
  119. data/lib/pvectl/commands/start_container.rb +18 -0
  120. data/lib/pvectl/commands/stop.rb +75 -0
  121. data/lib/pvectl/commands/stop_container.rb +18 -0
  122. data/lib/pvectl/commands/suspend.rb +64 -0
  123. data/lib/pvectl/commands/template_command.rb +205 -0
  124. data/lib/pvectl/commands/template_container.rb +27 -0
  125. data/lib/pvectl/commands/template_vm.rb +106 -0
  126. data/lib/pvectl/commands/top/command.rb +206 -0
  127. data/lib/pvectl/commands/top/handlers/containers.rb +61 -0
  128. data/lib/pvectl/commands/top/handlers/nodes.rb +61 -0
  129. data/lib/pvectl/commands/top/handlers/vms.rb +61 -0
  130. data/lib/pvectl/commands/top/resource_handler.rb +46 -0
  131. data/lib/pvectl/commands/top/resource_registry.rb +22 -0
  132. data/lib/pvectl/commands/unlink_disk_vm.rb +232 -0
  133. data/lib/pvectl/commands/vm_lifecycle_command.rb +77 -0
  134. data/lib/pvectl/commands/wakeonlan_node.rb +153 -0
  135. data/lib/pvectl/config/errors.rb +62 -0
  136. data/lib/pvectl/config/models/cluster.rb +180 -0
  137. data/lib/pvectl/config/models/context.rb +100 -0
  138. data/lib/pvectl/config/models/resolved_config.rb +171 -0
  139. data/lib/pvectl/config/models/user.rb +133 -0
  140. data/lib/pvectl/config/provider.rb +297 -0
  141. data/lib/pvectl/config/service.rb +300 -0
  142. data/lib/pvectl/config/store.rb +161 -0
  143. data/lib/pvectl/config/wizard.rb +309 -0
  144. data/lib/pvectl/config_serializer.rb +1034 -0
  145. data/lib/pvectl/connection/retry_handler.rb +161 -0
  146. data/lib/pvectl/connection.rb +157 -0
  147. data/lib/pvectl/console/terminal_session.rb +449 -0
  148. data/lib/pvectl/editor_session.rb +157 -0
  149. data/lib/pvectl/exit_codes.rb +43 -0
  150. data/lib/pvectl/formatters/base.rb +55 -0
  151. data/lib/pvectl/formatters/color_support.rb +90 -0
  152. data/lib/pvectl/formatters/json.rb +45 -0
  153. data/lib/pvectl/formatters/output_helper.rb +77 -0
  154. data/lib/pvectl/formatters/registry.rb +72 -0
  155. data/lib/pvectl/formatters/table.rb +235 -0
  156. data/lib/pvectl/formatters/wide.rb +93 -0
  157. data/lib/pvectl/formatters/yaml.rb +49 -0
  158. data/lib/pvectl/manifest_serializer.rb +142 -0
  159. data/lib/pvectl/models/apt_package.rb +107 -0
  160. data/lib/pvectl/models/backup.rb +173 -0
  161. data/lib/pvectl/models/base.rb +49 -0
  162. data/lib/pvectl/models/capability.rb +62 -0
  163. data/lib/pvectl/models/container.rb +205 -0
  164. data/lib/pvectl/models/container_operation_result.rb +27 -0
  165. data/lib/pvectl/models/dns_config.rb +54 -0
  166. data/lib/pvectl/models/hosts_file.rb +47 -0
  167. data/lib/pvectl/models/journal_entry.rb +16 -0
  168. data/lib/pvectl/models/network_interface.rb +85 -0
  169. data/lib/pvectl/models/node.rb +195 -0
  170. data/lib/pvectl/models/node_operation_result.rb +45 -0
  171. data/lib/pvectl/models/operation_result.rb +110 -0
  172. data/lib/pvectl/models/physical_disk.rb +193 -0
  173. data/lib/pvectl/models/service.rb +80 -0
  174. data/lib/pvectl/models/snapshot.rb +101 -0
  175. data/lib/pvectl/models/snapshot_description.rb +39 -0
  176. data/lib/pvectl/models/storage.rb +180 -0
  177. data/lib/pvectl/models/subscription.rb +87 -0
  178. data/lib/pvectl/models/syslog_entry.rb +17 -0
  179. data/lib/pvectl/models/task.rb +95 -0
  180. data/lib/pvectl/models/task_entry.rb +52 -0
  181. data/lib/pvectl/models/task_log_line.rb +17 -0
  182. data/lib/pvectl/models/time_config.rb +47 -0
  183. data/lib/pvectl/models/vm.rb +137 -0
  184. data/lib/pvectl/models/vm_operation_result.rb +27 -0
  185. data/lib/pvectl/models/volume.rb +133 -0
  186. data/lib/pvectl/models/volume_operation_result.rb +26 -0
  187. data/lib/pvectl/parsers/cloud_init_config.rb +92 -0
  188. data/lib/pvectl/parsers/disk_config.rb +97 -0
  189. data/lib/pvectl/parsers/lxc_mount_config.rb +98 -0
  190. data/lib/pvectl/parsers/lxc_net_config.rb +97 -0
  191. data/lib/pvectl/parsers/net_config.rb +95 -0
  192. data/lib/pvectl/parsers/smart_text.rb +42 -0
  193. data/lib/pvectl/plugin_loader.rb +157 -0
  194. data/lib/pvectl/presenters/apt_package.rb +99 -0
  195. data/lib/pvectl/presenters/backup.rb +128 -0
  196. data/lib/pvectl/presenters/base.rb +283 -0
  197. data/lib/pvectl/presenters/capability.rb +104 -0
  198. data/lib/pvectl/presenters/config/context.rb +80 -0
  199. data/lib/pvectl/presenters/container.rb +574 -0
  200. data/lib/pvectl/presenters/container_operation_result.rb +109 -0
  201. data/lib/pvectl/presenters/disk.rb +184 -0
  202. data/lib/pvectl/presenters/dns_config.rb +68 -0
  203. data/lib/pvectl/presenters/hosts_file.rb +61 -0
  204. data/lib/pvectl/presenters/journal_entry.rb +20 -0
  205. data/lib/pvectl/presenters/node.rb +762 -0
  206. data/lib/pvectl/presenters/node_operation_result.rb +50 -0
  207. data/lib/pvectl/presenters/operation_result.rb +61 -0
  208. data/lib/pvectl/presenters/service.rb +76 -0
  209. data/lib/pvectl/presenters/snapshot.rb +239 -0
  210. data/lib/pvectl/presenters/snapshot_operation_result.rb +125 -0
  211. data/lib/pvectl/presenters/storage.rb +329 -0
  212. data/lib/pvectl/presenters/subscription.rb +189 -0
  213. data/lib/pvectl/presenters/syslog_entry.rb +20 -0
  214. data/lib/pvectl/presenters/task_entry.rb +69 -0
  215. data/lib/pvectl/presenters/task_log_line.rb +20 -0
  216. data/lib/pvectl/presenters/template.rb +76 -0
  217. data/lib/pvectl/presenters/time_config.rb +86 -0
  218. data/lib/pvectl/presenters/top_container.rb +112 -0
  219. data/lib/pvectl/presenters/top_node.rb +115 -0
  220. data/lib/pvectl/presenters/top_presenter.rb +59 -0
  221. data/lib/pvectl/presenters/top_vm.rb +105 -0
  222. data/lib/pvectl/presenters/vm.rb +853 -0
  223. data/lib/pvectl/presenters/vm_operation_result.rb +109 -0
  224. data/lib/pvectl/presenters/volume.rb +136 -0
  225. data/lib/pvectl/presenters/volume_operation_result.rb +58 -0
  226. data/lib/pvectl/repositories/apt.rb +93 -0
  227. data/lib/pvectl/repositories/backup.rb +186 -0
  228. data/lib/pvectl/repositories/base.rb +110 -0
  229. data/lib/pvectl/repositories/capabilities.rb +96 -0
  230. data/lib/pvectl/repositories/container.rb +503 -0
  231. data/lib/pvectl/repositories/disk.rb +87 -0
  232. data/lib/pvectl/repositories/dns.rb +54 -0
  233. data/lib/pvectl/repositories/hosts.rb +63 -0
  234. data/lib/pvectl/repositories/journal.rb +23 -0
  235. data/lib/pvectl/repositories/node.rb +537 -0
  236. data/lib/pvectl/repositories/service.rb +139 -0
  237. data/lib/pvectl/repositories/snapshot.rb +133 -0
  238. data/lib/pvectl/repositories/storage.rb +302 -0
  239. data/lib/pvectl/repositories/subscription.rb +77 -0
  240. data/lib/pvectl/repositories/syslog.rb +25 -0
  241. data/lib/pvectl/repositories/task.rb +82 -0
  242. data/lib/pvectl/repositories/task_list.rb +30 -0
  243. data/lib/pvectl/repositories/task_log.rb +31 -0
  244. data/lib/pvectl/repositories/time_config.rb +53 -0
  245. data/lib/pvectl/repositories/vm.rb +616 -0
  246. data/lib/pvectl/repositories/volume.rb +306 -0
  247. data/lib/pvectl/selectors/base.rb +201 -0
  248. data/lib/pvectl/selectors/container.rb +116 -0
  249. data/lib/pvectl/selectors/disk.rb +59 -0
  250. data/lib/pvectl/selectors/vm.rb +116 -0
  251. data/lib/pvectl/selectors/volume.rb +59 -0
  252. data/lib/pvectl/services/backup.rb +209 -0
  253. data/lib/pvectl/services/clone_container.rb +260 -0
  254. data/lib/pvectl/services/clone_vm.rb +265 -0
  255. data/lib/pvectl/services/cloudinit.rb +96 -0
  256. data/lib/pvectl/services/console.rb +152 -0
  257. data/lib/pvectl/services/container_lifecycle.rb +124 -0
  258. data/lib/pvectl/services/create_container.rb +179 -0
  259. data/lib/pvectl/services/create_vm.rb +191 -0
  260. data/lib/pvectl/services/edit_container.rb +125 -0
  261. data/lib/pvectl/services/edit_dns.rb +159 -0
  262. data/lib/pvectl/services/edit_hosts.rb +78 -0
  263. data/lib/pvectl/services/edit_node.rb +147 -0
  264. data/lib/pvectl/services/edit_vm.rb +125 -0
  265. data/lib/pvectl/services/edit_volume.rb +224 -0
  266. data/lib/pvectl/services/get/resource_service.rb +98 -0
  267. data/lib/pvectl/services/move_disk.rb +132 -0
  268. data/lib/pvectl/services/pull_config.rb +94 -0
  269. data/lib/pvectl/services/push_config.rb +524 -0
  270. data/lib/pvectl/services/resize_volume.rb +253 -0
  271. data/lib/pvectl/services/resource_delete.rb +169 -0
  272. data/lib/pvectl/services/resource_migration.rb +170 -0
  273. data/lib/pvectl/services/sendkey.rb +108 -0
  274. data/lib/pvectl/services/service_lifecycle.rb +89 -0
  275. data/lib/pvectl/services/set_container.rb +128 -0
  276. data/lib/pvectl/services/set_node.rb +236 -0
  277. data/lib/pvectl/services/set_vm.rb +128 -0
  278. data/lib/pvectl/services/set_volume.rb +126 -0
  279. data/lib/pvectl/services/snapshot.rb +261 -0
  280. data/lib/pvectl/services/task_listing.rb +75 -0
  281. data/lib/pvectl/services/unlink_disk.rb +86 -0
  282. data/lib/pvectl/services/vm_lifecycle.rb +124 -0
  283. data/lib/pvectl/services/wakeonlan.rb +79 -0
  284. data/lib/pvectl/utils/resource_resolver.rb +80 -0
  285. data/lib/pvectl/version.rb +13 -0
  286. data/lib/pvectl/wizards/create_container.rb +105 -0
  287. data/lib/pvectl/wizards/create_vm.rb +98 -0
  288. data/lib/pvectl.rb +439 -0
  289. data/sig/external/gli.rbs +16 -0
  290. data/sig/external/proxmox_api.rbs +10 -0
  291. data/sig/pvectl/argv_preprocessor.rbs +53 -0
  292. data/sig/pvectl/cli.rbs +26 -0
  293. data/sig/pvectl/commands/apt.rbs +47 -0
  294. data/sig/pvectl/commands/clone_container.rbs +31 -0
  295. data/sig/pvectl/commands/clone_vm.rbs +33 -0
  296. data/sig/pvectl/commands/cloudinit/command.rbs +13 -0
  297. data/sig/pvectl/commands/cloudinit/dump.rbs +13 -0
  298. data/sig/pvectl/commands/cloudinit/pending.rbs +17 -0
  299. data/sig/pvectl/commands/cloudinit/regenerate.rbs +11 -0
  300. data/sig/pvectl/commands/config/command.rbs +9 -0
  301. data/sig/pvectl/commands/config/get_contexts.rbs +11 -0
  302. data/sig/pvectl/commands/config/set_cluster.rbs +11 -0
  303. data/sig/pvectl/commands/config/set_context.rbs +15 -0
  304. data/sig/pvectl/commands/config/set_credentials.rbs +15 -0
  305. data/sig/pvectl/commands/config/use_context.rbs +11 -0
  306. data/sig/pvectl/commands/config/view.rbs +11 -0
  307. data/sig/pvectl/commands/console.rbs +9 -0
  308. data/sig/pvectl/commands/console_ct.rbs +27 -0
  309. data/sig/pvectl/commands/console_vm.rbs +27 -0
  310. data/sig/pvectl/commands/container_lifecycle_command.rbs +25 -0
  311. data/sig/pvectl/commands/create_backup.rbs +29 -0
  312. data/sig/pvectl/commands/create_container.rbs +30 -0
  313. data/sig/pvectl/commands/create_resource_command.rbs +53 -0
  314. data/sig/pvectl/commands/create_snapshot.rbs +35 -0
  315. data/sig/pvectl/commands/create_vm.rbs +30 -0
  316. data/sig/pvectl/commands/delete_backup.rbs +25 -0
  317. data/sig/pvectl/commands/delete_command.rbs +45 -0
  318. data/sig/pvectl/commands/delete_container.rbs +11 -0
  319. data/sig/pvectl/commands/delete_snapshot.rbs +35 -0
  320. data/sig/pvectl/commands/delete_vm.rbs +13 -0
  321. data/sig/pvectl/commands/describe/command.rbs +27 -0
  322. data/sig/pvectl/commands/edit_container.rbs +17 -0
  323. data/sig/pvectl/commands/edit_dns.rbs +25 -0
  324. data/sig/pvectl/commands/edit_hosts.rbs +23 -0
  325. data/sig/pvectl/commands/edit_node.rbs +17 -0
  326. data/sig/pvectl/commands/edit_resource_command.rbs +35 -0
  327. data/sig/pvectl/commands/edit_vm.rbs +19 -0
  328. data/sig/pvectl/commands/edit_volume.rbs +24 -0
  329. data/sig/pvectl/commands/feature_command.rbs +43 -0
  330. data/sig/pvectl/commands/feature_container.rbs +10 -0
  331. data/sig/pvectl/commands/feature_vm.rbs +12 -0
  332. data/sig/pvectl/commands/get/command.rbs +42 -0
  333. data/sig/pvectl/commands/get/handlers/backups.rbs +23 -0
  334. data/sig/pvectl/commands/get/handlers/capabilities.rbs +29 -0
  335. data/sig/pvectl/commands/get/handlers/containers.rbs +35 -0
  336. data/sig/pvectl/commands/get/handlers/disks.rbs +27 -0
  337. data/sig/pvectl/commands/get/handlers/dns.rbs +25 -0
  338. data/sig/pvectl/commands/get/handlers/hosts.rbs +25 -0
  339. data/sig/pvectl/commands/get/handlers/nodes.rbs +33 -0
  340. data/sig/pvectl/commands/get/handlers/services.rbs +23 -0
  341. data/sig/pvectl/commands/get/handlers/snapshots.rbs +27 -0
  342. data/sig/pvectl/commands/get/handlers/storage.rbs +25 -0
  343. data/sig/pvectl/commands/get/handlers/subscription.rbs +25 -0
  344. data/sig/pvectl/commands/get/handlers/tasks.rbs +28 -0
  345. data/sig/pvectl/commands/get/handlers/templates.rbs +35 -0
  346. data/sig/pvectl/commands/get/handlers/time.rbs +29 -0
  347. data/sig/pvectl/commands/get/handlers/vms.rbs +35 -0
  348. data/sig/pvectl/commands/get/handlers/volume.rbs +27 -0
  349. data/sig/pvectl/commands/get/resource_handler.rbs +13 -0
  350. data/sig/pvectl/commands/get/resource_registry.rbs +8 -0
  351. data/sig/pvectl/commands/get/watch_loop.rbs +33 -0
  352. data/sig/pvectl/commands/irreversible_command.rbs +32 -0
  353. data/sig/pvectl/commands/logs/command.rbs +35 -0
  354. data/sig/pvectl/commands/logs/handlers/journal.rbs +21 -0
  355. data/sig/pvectl/commands/logs/handlers/syslog.rbs +21 -0
  356. data/sig/pvectl/commands/logs/handlers/task_detail.rbs +21 -0
  357. data/sig/pvectl/commands/logs/handlers/task_logs.rbs +35 -0
  358. data/sig/pvectl/commands/logs/resource_handler.rbs +11 -0
  359. data/sig/pvectl/commands/logs/resource_registry.rbs +8 -0
  360. data/sig/pvectl/commands/migrate_command.rbs +45 -0
  361. data/sig/pvectl/commands/migrate_container.rbs +11 -0
  362. data/sig/pvectl/commands/migrate_vm.rbs +13 -0
  363. data/sig/pvectl/commands/move_disk_command.rbs +43 -0
  364. data/sig/pvectl/commands/move_disk_container.rbs +11 -0
  365. data/sig/pvectl/commands/move_disk_vm.rbs +13 -0
  366. data/sig/pvectl/commands/ping.rbs +39 -0
  367. data/sig/pvectl/commands/pull.rbs +33 -0
  368. data/sig/pvectl/commands/push.rbs +32 -0
  369. data/sig/pvectl/commands/reset.rbs +11 -0
  370. data/sig/pvectl/commands/resource_lifecycle_command.rbs +55 -0
  371. data/sig/pvectl/commands/resource_registry.rbs +19 -0
  372. data/sig/pvectl/commands/restart.rbs +11 -0
  373. data/sig/pvectl/commands/restart_container.rbs +9 -0
  374. data/sig/pvectl/commands/restore_backup.rbs +27 -0
  375. data/sig/pvectl/commands/resume.rbs +11 -0
  376. data/sig/pvectl/commands/rollback_snapshot.rbs +31 -0
  377. data/sig/pvectl/commands/sendkey_vm.rbs +25 -0
  378. data/sig/pvectl/commands/service.rbs +38 -0
  379. data/sig/pvectl/commands/set_container.rbs +13 -0
  380. data/sig/pvectl/commands/set_node.rbs +13 -0
  381. data/sig/pvectl/commands/set_resource_command.rbs +25 -0
  382. data/sig/pvectl/commands/set_vm.rbs +15 -0
  383. data/sig/pvectl/commands/set_volume.rbs +24 -0
  384. data/sig/pvectl/commands/shared_config_parsers.rbs +19 -0
  385. data/sig/pvectl/commands/shared_flags.rbs +10 -0
  386. data/sig/pvectl/commands/shutdown.rbs +11 -0
  387. data/sig/pvectl/commands/shutdown_container.rbs +9 -0
  388. data/sig/pvectl/commands/start.rbs +11 -0
  389. data/sig/pvectl/commands/start_container.rbs +9 -0
  390. data/sig/pvectl/commands/stop.rbs +11 -0
  391. data/sig/pvectl/commands/stop_container.rbs +9 -0
  392. data/sig/pvectl/commands/suspend.rbs +11 -0
  393. data/sig/pvectl/commands/template_command.rbs +21 -0
  394. data/sig/pvectl/commands/template_container.rbs +10 -0
  395. data/sig/pvectl/commands/template_vm.rbs +12 -0
  396. data/sig/pvectl/commands/top/command.rbs +31 -0
  397. data/sig/pvectl/commands/top/handlers/containers.rbs +21 -0
  398. data/sig/pvectl/commands/top/handlers/nodes.rbs +21 -0
  399. data/sig/pvectl/commands/top/handlers/vms.rbs +21 -0
  400. data/sig/pvectl/commands/top/resource_handler.rbs +11 -0
  401. data/sig/pvectl/commands/top/resource_registry.rbs +8 -0
  402. data/sig/pvectl/commands/unlink_disk_vm.rbs +27 -0
  403. data/sig/pvectl/commands/vm_lifecycle_command.rbs +25 -0
  404. data/sig/pvectl/commands/wakeonlan_node.rbs +21 -0
  405. data/sig/pvectl/config/errors.rbs +24 -0
  406. data/sig/pvectl/config/models/cluster.rbs +39 -0
  407. data/sig/pvectl/config/models/context.rbs +23 -0
  408. data/sig/pvectl/config/models/resolved_config.rbs +51 -0
  409. data/sig/pvectl/config/models/user.rbs +31 -0
  410. data/sig/pvectl/config/provider.rbs +40 -0
  411. data/sig/pvectl/config/service.rbs +65 -0
  412. data/sig/pvectl/config/store.rbs +14 -0
  413. data/sig/pvectl/config/wizard.rbs +48 -0
  414. data/sig/pvectl/config_serializer.rbs +121 -0
  415. data/sig/pvectl/connection/retry_handler.rbs +31 -0
  416. data/sig/pvectl/connection.rbs +35 -0
  417. data/sig/pvectl/console/terminal_session.rbs +63 -0
  418. data/sig/pvectl/editor_session.rbs +33 -0
  419. data/sig/pvectl/exit_codes.rbs +19 -0
  420. data/sig/pvectl/formatters/base.rbs +13 -0
  421. data/sig/pvectl/formatters/color_support.rbs +13 -0
  422. data/sig/pvectl/formatters/json.rbs +7 -0
  423. data/sig/pvectl/formatters/output_helper.rbs +9 -0
  424. data/sig/pvectl/formatters/registry.rbs +13 -0
  425. data/sig/pvectl/formatters/table.rbs +25 -0
  426. data/sig/pvectl/formatters/wide.rbs +15 -0
  427. data/sig/pvectl/formatters/yaml.rbs +7 -0
  428. data/sig/pvectl/manifest_serializer.rbs +18 -0
  429. data/sig/pvectl/models/apt_package.rbs +26 -0
  430. data/sig/pvectl/models/backup.rbs +31 -0
  431. data/sig/pvectl/models/base.rbs +11 -0
  432. data/sig/pvectl/models/capability.rbs +16 -0
  433. data/sig/pvectl/models/container.rbs +44 -0
  434. data/sig/pvectl/models/container_operation_result.rbs +9 -0
  435. data/sig/pvectl/models/dns_config.rbs +15 -0
  436. data/sig/pvectl/models/hosts_file.rbs +13 -0
  437. data/sig/pvectl/models/journal_entry.rbs +10 -0
  438. data/sig/pvectl/models/network_interface.rbs +20 -0
  439. data/sig/pvectl/models/node.rbs +47 -0
  440. data/sig/pvectl/models/node_operation_result.rbs +12 -0
  441. data/sig/pvectl/models/operation_result.rbs +21 -0
  442. data/sig/pvectl/models/physical_disk.rbs +35 -0
  443. data/sig/pvectl/models/service.rbs +18 -0
  444. data/sig/pvectl/models/snapshot.rbs +21 -0
  445. data/sig/pvectl/models/snapshot_description.rbs +18 -0
  446. data/sig/pvectl/models/storage.rbs +39 -0
  447. data/sig/pvectl/models/subscription.rbs +24 -0
  448. data/sig/pvectl/models/syslog_entry.rbs +10 -0
  449. data/sig/pvectl/models/task.rbs +22 -0
  450. data/sig/pvectl/models/task_entry.rbs +24 -0
  451. data/sig/pvectl/models/task_log_line.rbs +10 -0
  452. data/sig/pvectl/models/time_config.rbs +12 -0
  453. data/sig/pvectl/models/vm.rbs +32 -0
  454. data/sig/pvectl/models/vm_operation_result.rbs +9 -0
  455. data/sig/pvectl/models/volume.rbs +29 -0
  456. data/sig/pvectl/models/volume_operation_result.rbs +9 -0
  457. data/sig/pvectl/parsers/cloud_init_config.rbs +15 -0
  458. data/sig/pvectl/parsers/disk_config.rbs +19 -0
  459. data/sig/pvectl/parsers/lxc_mount_config.rbs +19 -0
  460. data/sig/pvectl/parsers/lxc_net_config.rbs +19 -0
  461. data/sig/pvectl/parsers/net_config.rbs +19 -0
  462. data/sig/pvectl/parsers/smart_text.rbs +7 -0
  463. data/sig/pvectl/plugin_loader.rbs +25 -0
  464. data/sig/pvectl/presenters/apt_package.rbs +19 -0
  465. data/sig/pvectl/presenters/backup.rbs +25 -0
  466. data/sig/pvectl/presenters/base.rbs +41 -0
  467. data/sig/pvectl/presenters/capability.rbs +19 -0
  468. data/sig/pvectl/presenters/config/context.rbs +17 -0
  469. data/sig/pvectl/presenters/container.rbs +78 -0
  470. data/sig/pvectl/presenters/container_operation_result.rbs +19 -0
  471. data/sig/pvectl/presenters/disk.rbs +31 -0
  472. data/sig/pvectl/presenters/dns_config.rbs +13 -0
  473. data/sig/pvectl/presenters/hosts_file.rbs +13 -0
  474. data/sig/pvectl/presenters/journal_entry.rbs +11 -0
  475. data/sig/pvectl/presenters/node.rbs +118 -0
  476. data/sig/pvectl/presenters/node_operation_result.rbs +11 -0
  477. data/sig/pvectl/presenters/operation_result.rbs +17 -0
  478. data/sig/pvectl/presenters/service.rbs +15 -0
  479. data/sig/pvectl/presenters/snapshot.rbs +35 -0
  480. data/sig/pvectl/presenters/snapshot_operation_result.rbs +27 -0
  481. data/sig/pvectl/presenters/storage.rbs +59 -0
  482. data/sig/pvectl/presenters/subscription.rbs +36 -0
  483. data/sig/pvectl/presenters/syslog_entry.rbs +11 -0
  484. data/sig/pvectl/presenters/task_entry.rbs +21 -0
  485. data/sig/pvectl/presenters/task_log_line.rbs +11 -0
  486. data/sig/pvectl/presenters/template.rbs +15 -0
  487. data/sig/pvectl/presenters/time_config.rbs +19 -0
  488. data/sig/pvectl/presenters/top_container.rbs +17 -0
  489. data/sig/pvectl/presenters/top_node.rbs +17 -0
  490. data/sig/pvectl/presenters/top_presenter.rbs +13 -0
  491. data/sig/pvectl/presenters/top_vm.rbs +17 -0
  492. data/sig/pvectl/presenters/vm.rbs +91 -0
  493. data/sig/pvectl/presenters/vm_operation_result.rbs +19 -0
  494. data/sig/pvectl/presenters/volume.rbs +23 -0
  495. data/sig/pvectl/presenters/volume_operation_result.rbs +11 -0
  496. data/sig/pvectl/repositories/apt.rbs +17 -0
  497. data/sig/pvectl/repositories/backup.rbs +27 -0
  498. data/sig/pvectl/repositories/base.rbs +23 -0
  499. data/sig/pvectl/repositories/capabilities.rbs +20 -0
  500. data/sig/pvectl/repositories/container.rbs +63 -0
  501. data/sig/pvectl/repositories/disk.rbs +17 -0
  502. data/sig/pvectl/repositories/dns.rbs +13 -0
  503. data/sig/pvectl/repositories/hosts.rbs +13 -0
  504. data/sig/pvectl/repositories/journal.rbs +7 -0
  505. data/sig/pvectl/repositories/node.rbs +68 -0
  506. data/sig/pvectl/repositories/service.rbs +27 -0
  507. data/sig/pvectl/repositories/snapshot.rbs +19 -0
  508. data/sig/pvectl/repositories/storage.rbs +37 -0
  509. data/sig/pvectl/repositories/subscription.rbs +17 -0
  510. data/sig/pvectl/repositories/syslog.rbs +7 -0
  511. data/sig/pvectl/repositories/task.rbs +19 -0
  512. data/sig/pvectl/repositories/task_list.rbs +7 -0
  513. data/sig/pvectl/repositories/task_log.rbs +11 -0
  514. data/sig/pvectl/repositories/time_config.rbs +13 -0
  515. data/sig/pvectl/repositories/vm.rbs +85 -0
  516. data/sig/pvectl/repositories/volume.rbs +43 -0
  517. data/sig/pvectl/selectors/base.rbs +37 -0
  518. data/sig/pvectl/selectors/container.rbs +19 -0
  519. data/sig/pvectl/selectors/disk.rbs +13 -0
  520. data/sig/pvectl/selectors/vm.rbs +19 -0
  521. data/sig/pvectl/selectors/volume.rbs +13 -0
  522. data/sig/pvectl/services/backup.rbs +27 -0
  523. data/sig/pvectl/services/clone_container.rbs +35 -0
  524. data/sig/pvectl/services/clone_vm.rbs +35 -0
  525. data/sig/pvectl/services/cloudinit.rbs +19 -0
  526. data/sig/pvectl/services/console.rbs +23 -0
  527. data/sig/pvectl/services/container_lifecycle.rbs +26 -0
  528. data/sig/pvectl/services/create_container.rbs +64 -0
  529. data/sig/pvectl/services/create_vm.rbs +72 -0
  530. data/sig/pvectl/services/edit_container.rbs +17 -0
  531. data/sig/pvectl/services/edit_dns.rbs +23 -0
  532. data/sig/pvectl/services/edit_hosts.rbs +13 -0
  533. data/sig/pvectl/services/edit_node.rbs +21 -0
  534. data/sig/pvectl/services/edit_vm.rbs +17 -0
  535. data/sig/pvectl/services/edit_volume.rbs +18 -0
  536. data/sig/pvectl/services/get/resource_service.rbs +23 -0
  537. data/sig/pvectl/services/move_disk.rbs +21 -0
  538. data/sig/pvectl/services/pull_config.rbs +18 -0
  539. data/sig/pvectl/services/push_config.rbs +37 -0
  540. data/sig/pvectl/services/resize_volume.rbs +47 -0
  541. data/sig/pvectl/services/resource_delete.rbs +27 -0
  542. data/sig/pvectl/services/resource_migration.rbs +29 -0
  543. data/sig/pvectl/services/sendkey.rbs +19 -0
  544. data/sig/pvectl/services/service_lifecycle.rbs +17 -0
  545. data/sig/pvectl/services/set_container.rbs +14 -0
  546. data/sig/pvectl/services/set_node.rbs +23 -0
  547. data/sig/pvectl/services/set_vm.rbs +14 -0
  548. data/sig/pvectl/services/set_volume.rbs +12 -0
  549. data/sig/pvectl/services/snapshot.rbs +35 -0
  550. data/sig/pvectl/services/task_listing.rbs +13 -0
  551. data/sig/pvectl/services/unlink_disk.rbs +17 -0
  552. data/sig/pvectl/services/vm_lifecycle.rbs +26 -0
  553. data/sig/pvectl/services/wakeonlan.rbs +17 -0
  554. data/sig/pvectl/utils/resource_resolver.rbs +17 -0
  555. data/sig/pvectl/wizards/create_container.rbs +21 -0
  556. data/sig/pvectl/wizards/create_vm.rbs +21 -0
  557. data/sig/pvectl.rbs +9 -0
  558. metadata +675 -0
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Abstract base class for command resource registries.
6
+ #
7
+ # Provides handler registration and lookup. Each subclass maintains
8
+ # its own isolated set of handlers via +self.inherited+ callback.
9
+ #
10
+ # @abstract Subclass for each command namespace (Get, Top, Logs).
11
+ #
12
+ # @example Creating a command-specific registry
13
+ # module Pvectl::Commands::Logs
14
+ # class ResourceRegistry < Pvectl::Commands::ResourceRegistry; end
15
+ # end
16
+ #
17
+ class ResourceRegistry
18
+ @handlers = {}
19
+
20
+ def self.inherited(subclass)
21
+ super
22
+ subclass.instance_variable_set(:@handlers, {})
23
+ end
24
+
25
+ class << self
26
+ # Registers a handler class for a resource type.
27
+ #
28
+ # @param resource_type [String, Symbol] primary resource type name
29
+ # @param handler_class [Class] handler class
30
+ # @param aliases [Array<String, Symbol>] alternative names
31
+ # @return [void]
32
+ def register(resource_type, handler_class, aliases: [])
33
+ @handlers[resource_type.to_s] = handler_class
34
+ aliases.each { |a| @handlers[a.to_s] = handler_class }
35
+ end
36
+
37
+ # Returns a new handler instance for the resource type.
38
+ #
39
+ # @param resource_type [String, Symbol, nil] resource type name
40
+ # @return [Object, nil] handler instance or nil
41
+ def for(resource_type)
42
+ return nil if resource_type.nil?
43
+
44
+ handler_class = @handlers[resource_type.to_s]
45
+ handler_class&.new
46
+ end
47
+
48
+ # Returns all registered type names (including aliases).
49
+ #
50
+ # @return [Array<String>] registered type names
51
+ def registered_types
52
+ @handlers.keys
53
+ end
54
+
55
+ # Checks if a resource type is registered.
56
+ #
57
+ # @param resource_type [String, Symbol] resource type name
58
+ # @return [Boolean]
59
+ def registered?(resource_type)
60
+ @handlers.key?(resource_type.to_s)
61
+ end
62
+
63
+ # Clears all registered handlers.
64
+ #
65
+ # @return [void]
66
+ # @api private
67
+ def reset!
68
+ @handlers = {}
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl restart` command.
6
+ #
7
+ # Restarts one or more virtual machines (reboot).
8
+ #
9
+ # @example Restart a single VM
10
+ # pvectl restart vm 100
11
+ #
12
+ # @example Restart with sync mode
13
+ # pvectl restart vm 100 --wait
14
+ #
15
+ class Restart
16
+ include VmLifecycleCommand
17
+
18
+ # Registers the restart command with the CLI.
19
+ #
20
+ # @param cli [GLI::App] the CLI application object
21
+ # @return [void]
22
+ def self.register(cli)
23
+ cli.desc "Restart virtual machines or containers (reboot)"
24
+ cli.long_desc <<~HELP
25
+ Reboot one or more virtual machines or containers. Sends a reboot
26
+ signal to the guest OS for a clean restart.
27
+
28
+ EXAMPLES
29
+ Reboot a VM:
30
+ $ pvectl restart vm 100
31
+
32
+ Reboot a container:
33
+ $ pvectl restart ct 200
34
+
35
+ Reboot all VMs with a specific tag:
36
+ $ pvectl restart vm --all -l tags=webserver --yes
37
+
38
+ NOTES
39
+ For VMs, this sends an ACPI reboot signal (requires guest agent or
40
+ ACPI support). For containers, uses LXC reboot.
41
+
42
+ For a hard reset (equivalent to pressing the reset button), use
43
+ 'pvectl reset' instead (VMs only).
44
+
45
+ SEE ALSO
46
+ pvectl help reset Hard reset (VMs only)
47
+ pvectl help shutdown Graceful shutdown without restart
48
+ HELP
49
+ cli.arg_name "RESOURCE_TYPE [ID...]"
50
+ cli.command :restart do |c|
51
+ SharedFlags.lifecycle(c)
52
+
53
+ c.action do |global_options, options, args|
54
+ resource_type = args.shift
55
+ resource_ids = args
56
+ exit_code = case resource_type
57
+ when "container", "ct"
58
+ RestartContainer.execute(resource_type, resource_ids, options, global_options)
59
+ else
60
+ execute(resource_type, resource_ids, options, global_options)
61
+ end
62
+ exit exit_code if exit_code != 0
63
+ end
64
+ end
65
+ end
66
+
67
+ OPERATION = :restart
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl restart container` command.
6
+ #
7
+ # Restarts one or more LXC containers (reboot).
8
+ #
9
+ # @example Restart a single container
10
+ # pvectl restart container 200
11
+ #
12
+ class RestartContainer
13
+ include ContainerLifecycleCommand
14
+
15
+ OPERATION = :restart
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,236 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl restore backup` command.
6
+ #
7
+ # Restores a backup identified by its full volume ID (volid)
8
+ # to a new or existing VM/container.
9
+ # Requires --vmid and --yes flags.
10
+ #
11
+ # @example Restore a backup to new VM
12
+ # pvectl restore backup local:backup/vzdump-qemu-100-xxx.vma.zst --vmid 200 --yes
13
+ #
14
+ # @example Restore with overwrite
15
+ # pvectl restore backup local:backup/vzdump-qemu-100-xxx.vma.zst --vmid 100 --force --yes
16
+ #
17
+ class RestoreBackup
18
+ # Registers the restore command with the CLI.
19
+ #
20
+ # @param cli [GLI::App] the CLI application object
21
+ # @return [void]
22
+ def self.register(cli)
23
+ cli.desc "Restore a resource from backup"
24
+ cli.long_desc <<~HELP
25
+ Restore a virtual machine or container from a backup (vzdump) volume.
26
+ Creates a new or overwrites an existing VM/container with the backup data.
27
+
28
+ EXAMPLES
29
+ Restore to a new VMID:
30
+ $ pvectl restore backup local:backup/vzdump-qemu-100-2026_01_01.vma.zst --vmid 200 --yes
31
+
32
+ Restore to specific storage:
33
+ $ pvectl restore backup local:backup/vzdump-qemu-100-2026_01_01.vma.zst --vmid 200 --storage local-lvm --yes
34
+
35
+ Overwrite existing VM:
36
+ $ pvectl restore backup local:backup/vzdump-qemu-100-2026_01_01.vma.zst --vmid 100 --force --yes
37
+
38
+ Restore and start immediately:
39
+ $ pvectl restore backup local:backup/vzdump-qemu-100-2026_01_01.vma.zst --vmid 200 --start --yes
40
+
41
+ Regenerate unique properties (MAC, UUID):
42
+ $ pvectl restore backup local:backup/vzdump-qemu-100-2026_01_01.vma.zst --vmid 200 --unique --yes
43
+
44
+ NOTES
45
+ --vmid is required to specify the target VM/container ID.
46
+
47
+ --force overwrites an existing VM/container with the same VMID.
48
+ Without it, restore fails if the VMID already exists.
49
+
50
+ --unique regenerates MAC addresses and other unique properties,
51
+ useful when restoring alongside the original VM.
52
+
53
+ Use 'pvectl get backups' to find backup volume IDs.
54
+
55
+ SEE ALSO
56
+ pvectl help create backup Create a new backup
57
+ pvectl help get backups List available backups
58
+ pvectl help delete backup Delete backup volumes
59
+ HELP
60
+ cli.arg_name "RESOURCE_TYPE VOLID"
61
+ cli.command :restore do |c|
62
+ c.desc "Target VMID (required)"
63
+ c.flag [:vmid], arg_name: "VMID", type: Integer
64
+
65
+ c.desc "Target storage"
66
+ c.flag [:storage], arg_name: "STORAGE"
67
+
68
+ c.desc "Overwrite existing VM/container"
69
+ c.switch [:force], negatable: false
70
+
71
+ c.desc "Start after restore"
72
+ c.switch [:start], negatable: false
73
+
74
+ c.desc "Regenerate unique properties (MAC, UUID)"
75
+ c.switch [:unique], negatable: false
76
+
77
+ c.desc "Skip confirmation prompt (REQUIRED)"
78
+ c.switch [:yes, :y], negatable: false
79
+
80
+ c.desc "Timeout in seconds"
81
+ c.flag [:timeout], type: Integer, arg_name: "SECONDS"
82
+
83
+ c.desc "Force async mode"
84
+ c.switch [:async], negatable: false
85
+
86
+ c.action do |global_options, options, args|
87
+ resource_type = args.shift
88
+ volid = args.first
89
+
90
+ exit_code = case resource_type
91
+ when "backup"
92
+ Commands::RestoreBackup.execute(resource_type, volid, options, global_options)
93
+ else
94
+ $stderr.puts "Error: Unknown resource type: #{resource_type}"
95
+ $stderr.puts "Valid types: backup"
96
+ ExitCodes::USAGE_ERROR
97
+ end
98
+
99
+ exit exit_code if exit_code != 0
100
+ end
101
+ end
102
+ end
103
+
104
+ # Executes the restore backup command.
105
+ #
106
+ # @param resource_type [String, nil] resource type (backup)
107
+ # @param volid [String, nil] backup volume ID
108
+ # @param options [Hash] command options
109
+ # @param global_options [Hash] global CLI options
110
+ # @return [Integer] exit code
111
+ def self.execute(resource_type, volid, options, global_options)
112
+ new(resource_type, volid, options, global_options).execute
113
+ end
114
+
115
+ # Initializes a restore backup command.
116
+ #
117
+ # @param resource_type [String, nil] resource type (backup)
118
+ # @param volid [String, nil] backup volume ID
119
+ # @param options [Hash] command options
120
+ # @param global_options [Hash] global CLI options
121
+ def initialize(resource_type, volid, options, global_options)
122
+ @resource_type = resource_type
123
+ @volid = volid
124
+ @options = options
125
+ @global_options = global_options
126
+ end
127
+
128
+ # Executes the restore backup command.
129
+ #
130
+ # @return [Integer] exit code
131
+ def execute
132
+ return usage_error("Resource type required (backup)") unless @resource_type == "backup"
133
+ return usage_error("Backup volid is required") if @volid.nil? || @volid.empty?
134
+ return usage_error("--vmid is required") unless @options[:vmid]
135
+ return usage_error("Confirmation required: use --yes to confirm restore") unless @options[:yes]
136
+
137
+ perform_operation
138
+ end
139
+
140
+ private
141
+
142
+ # Performs the backup restore operation.
143
+ #
144
+ # @return [Integer] exit code
145
+ def perform_operation
146
+ load_config
147
+ connection = Pvectl::Connection.new(@config)
148
+
149
+ backup_repo = Pvectl::Repositories::Backup.new(connection)
150
+ resolver = Pvectl::Utils::ResourceResolver.new(connection)
151
+ task_repo = Pvectl::Repositories::Task.new(connection)
152
+
153
+ service = Pvectl::Services::Backup.new(
154
+ backup_repo: backup_repo,
155
+ resource_resolver: resolver,
156
+ task_repo: task_repo,
157
+ options: service_options
158
+ )
159
+
160
+ result = service.restore(
161
+ @volid,
162
+ vmid: @options[:vmid],
163
+ storage: @options[:storage],
164
+ force: @options[:force] || false,
165
+ start: @options[:start] || false,
166
+ unique: @options[:unique] || false
167
+ )
168
+
169
+ output_results([result])
170
+ determine_exit_code([result])
171
+ rescue Pvectl::Config::ConfigNotFoundError,
172
+ Pvectl::Config::InvalidConfigError,
173
+ Pvectl::Config::ContextNotFoundError,
174
+ Pvectl::Config::ClusterNotFoundError,
175
+ Pvectl::Config::UserNotFoundError
176
+ raise
177
+ rescue StandardError => e
178
+ $stderr.puts "Error: #{e.message}"
179
+ ExitCodes::GENERAL_ERROR
180
+ end
181
+
182
+ # Loads configuration from file or environment.
183
+ #
184
+ # @return [void]
185
+ def load_config
186
+ service = Pvectl::Config::Service.new
187
+ service.load(config: @global_options[:config])
188
+ @config = service.current_config
189
+ end
190
+
191
+ # Builds service options from command options.
192
+ #
193
+ # @return [Hash] service options
194
+ def service_options
195
+ opts = {}
196
+ opts[:timeout] = @options[:timeout] if @options[:timeout]
197
+ opts[:async] = true if @options[:async]
198
+ opts
199
+ end
200
+
201
+ # Outputs operation results using the configured formatter.
202
+ #
203
+ # @param results [Array<Models::OperationResult>] operation results
204
+ # @return [void]
205
+ def output_results(results)
206
+ presenter = Pvectl::Presenters::SnapshotOperationResult.new
207
+ format = @global_options[:output] || "table"
208
+ color_flag = @global_options[:color]
209
+
210
+ formatter = Pvectl::Formatters::Registry.for(format)
211
+ output = formatter.format(results, presenter, color: color_flag)
212
+ puts output
213
+ end
214
+
215
+ # Determines exit code based on results.
216
+ #
217
+ # @param results [Array<Models::OperationResult>] operation results
218
+ # @return [Integer] exit code
219
+ def determine_exit_code(results)
220
+ return ExitCodes::SUCCESS if results.all?(&:successful?)
221
+ return ExitCodes::SUCCESS if results.all?(&:pending?)
222
+
223
+ ExitCodes::GENERAL_ERROR
224
+ end
225
+
226
+ # Outputs usage error and returns exit code.
227
+ #
228
+ # @param message [String] error message
229
+ # @return [Integer] exit code
230
+ def usage_error(message)
231
+ $stderr.puts "Error: #{message}"
232
+ ExitCodes::USAGE_ERROR
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl resume` command.
6
+ #
7
+ # Resumes one or more suspended virtual machines.
8
+ #
9
+ # @example Resume a single VM
10
+ # pvectl resume vm 100
11
+ #
12
+ # @example Resume with JSON output
13
+ # pvectl resume vm 100 -o json
14
+ #
15
+ class Resume
16
+ include VmLifecycleCommand
17
+
18
+ # Registers the resume command with the CLI.
19
+ #
20
+ # @param cli [GLI::App] the CLI application object
21
+ # @return [void]
22
+ def self.register(cli)
23
+ cli.desc "Resume suspended virtual machines"
24
+ cli.long_desc <<~HELP
25
+ Resume one or more suspended (hibernated) virtual machines. Restores
26
+ the VM's memory state from disk and continues execution.
27
+
28
+ Only available for VMs. Containers do not support resume.
29
+
30
+ EXAMPLES
31
+ Resume a suspended VM:
32
+ $ pvectl resume vm 100
33
+
34
+ Resume all suspended VMs:
35
+ $ pvectl resume vm --all -l status=suspended --yes
36
+
37
+ SEE ALSO
38
+ pvectl help suspend Suspend (hibernate) VMs
39
+ pvectl help start Start a stopped VM (no state restore)
40
+ HELP
41
+ cli.arg_name "RESOURCE_TYPE [ID...]"
42
+ cli.command :resume do |c|
43
+ SharedFlags.lifecycle(c)
44
+
45
+ c.action do |global_options, options, args|
46
+ resource_type = args.shift
47
+ resource_ids = args
48
+ exit_code = execute(resource_type, resource_ids, options, global_options)
49
+ exit exit_code if exit_code != 0
50
+ end
51
+ end
52
+ end
53
+
54
+ OPERATION = :resume
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl rollback snapshot` command.
6
+ #
7
+ # Rolls back a VM/container to a snapshot.
8
+ # Requires --yes flag for confirmation. Only supports single VMID.
9
+ #
10
+ # @example Rollback to snapshot
11
+ # pvectl rollback snapshot 100 before-upgrade --yes
12
+ #
13
+ # @example Start after rollback (LXC only)
14
+ # pvectl rollback snapshot 100 before-upgrade --yes --start
15
+ #
16
+ class RollbackSnapshot
17
+ # Registers the rollback command with the CLI.
18
+ #
19
+ # @param cli [GLI::App] the CLI application object
20
+ # @return [void]
21
+ def self.register(cli)
22
+ cli.desc "Rollback to a snapshot"
23
+ cli.long_desc <<~HELP
24
+ Rollback a virtual machine or container to a previous snapshot,
25
+ restoring its disk (and optionally RAM) state to the snapshot point.
26
+
27
+ WARNING: All changes made after the snapshot will be lost.
28
+
29
+ EXAMPLES
30
+ Rollback a VM to a snapshot:
31
+ $ pvectl rollback snapshot 100 before-upgrade --yes
32
+
33
+ Rollback and start the VM after:
34
+ $ pvectl rollback snapshot 100 before-upgrade --yes --start
35
+
36
+ Async rollback:
37
+ $ pvectl rollback snapshot 100 before-upgrade --yes --async
38
+
39
+ NOTES
40
+ Rollback always operates on a single VM/container (not batch).
41
+
42
+ The VM/container will be stopped during rollback if running.
43
+
44
+ --yes is required — rollback is a destructive operation that
45
+ discards all changes since the snapshot.
46
+
47
+ SEE ALSO
48
+ pvectl help create snapshot Create a snapshot before changes
49
+ pvectl help get snapshots List available snapshots
50
+ pvectl help describe snapshot View snapshot details
51
+ HELP
52
+ cli.arg_name "RESOURCE_TYPE ID SNAPSHOT_NAME"
53
+ cli.command :rollback do |c|
54
+ c.desc "Skip confirmation prompt (REQUIRED for destructive operations)"
55
+ c.switch [:yes, :y], negatable: false
56
+
57
+ c.desc "Start VM/container after rollback (LXC only)"
58
+ c.switch [:start], negatable: false
59
+
60
+ c.desc "Timeout in seconds for sync operations"
61
+ c.flag [:timeout], type: Integer, arg_name: "SECONDS"
62
+
63
+ c.desc "Force async mode (return task ID immediately)"
64
+ c.switch [:async], negatable: false
65
+
66
+ c.action do |global_options, options, args|
67
+ resource_type = args.shift
68
+ exit_code = Commands::RollbackSnapshot.execute(
69
+ resource_type,
70
+ args,
71
+ options,
72
+ global_options
73
+ )
74
+ exit exit_code if exit_code != 0
75
+ end
76
+ end
77
+ end
78
+
79
+ SUPPORTED_RESOURCES = %w[snapshot].freeze
80
+
81
+ # Executes the rollback snapshot command.
82
+ #
83
+ # @param resource_type [String, nil] resource type (snapshot)
84
+ # @param args [Array<String>, String, nil] VMID and snapshot name
85
+ # @param options [Hash] command options
86
+ # @param global_options [Hash] global CLI options
87
+ # @return [Integer] exit code
88
+ def self.execute(resource_type, args, options, global_options)
89
+ new(resource_type, args, options, global_options).execute
90
+ end
91
+
92
+ # Initializes a rollback snapshot command.
93
+ #
94
+ # @param resource_type [String, nil] resource type (snapshot)
95
+ # @param args [Array<String>, String, nil] VMID and snapshot name
96
+ # @param options [Hash] command options
97
+ # @param global_options [Hash] global CLI options
98
+ def initialize(resource_type, args, options, global_options)
99
+ @resource_type = resource_type
100
+ @args = Array(args).compact
101
+ @options = options
102
+ @global_options = global_options
103
+ @too_many_args = false
104
+ parse_args!
105
+ end
106
+
107
+ # Executes the rollback snapshot command.
108
+ #
109
+ # @return [Integer] exit code
110
+ def execute
111
+ return usage_error("Resource type required (snapshot)") unless @resource_type
112
+ return usage_error("Unsupported resource: #{@resource_type}") unless SUPPORTED_RESOURCES.include?(@resource_type)
113
+ return usage_error("Rollback supports only single VMID") if @too_many_args
114
+ return usage_error("VMID and snapshot name required") if @vmid.nil? || @snapshot_name.nil?
115
+ return usage_error("Confirmation required: use --yes to confirm rollback") unless @options[:yes]
116
+
117
+ perform_operation
118
+ end
119
+
120
+ private
121
+
122
+ # Parses arguments: exactly 2 args - VMID and snapshot name.
123
+ #
124
+ # @return [void]
125
+ def parse_args!
126
+ if @args.size == 2
127
+ @vmid = @args[0].to_i
128
+ @snapshot_name = @args[1]
129
+ elsif @args.size > 2
130
+ # Too many args - rollback only supports single VMID
131
+ @vmid = nil
132
+ @snapshot_name = nil
133
+ @too_many_args = true
134
+ else
135
+ @vmid = nil
136
+ @snapshot_name = nil
137
+ end
138
+ end
139
+
140
+ # Performs the snapshot rollback operation.
141
+ #
142
+ # @return [Integer] exit code
143
+ def perform_operation
144
+ load_config
145
+ connection = Pvectl::Connection.new(@config)
146
+
147
+ snapshot_repo = Pvectl::Repositories::Snapshot.new(connection)
148
+ resolver = Pvectl::Utils::ResourceResolver.new(connection)
149
+ task_repo = Pvectl::Repositories::Task.new(connection)
150
+
151
+ service = Pvectl::Services::Snapshot.new(
152
+ snapshot_repo: snapshot_repo,
153
+ resource_resolver: resolver,
154
+ task_repo: task_repo,
155
+ options: service_options
156
+ )
157
+
158
+ result = service.rollback(@vmid, @snapshot_name, start: @options[:start] || false)
159
+ results = [result]
160
+
161
+ output_results(results)
162
+ determine_exit_code(results)
163
+ rescue Pvectl::Config::ConfigNotFoundError,
164
+ Pvectl::Config::InvalidConfigError,
165
+ Pvectl::Config::ContextNotFoundError,
166
+ Pvectl::Config::ClusterNotFoundError,
167
+ Pvectl::Config::UserNotFoundError
168
+ raise
169
+ rescue StandardError => e
170
+ $stderr.puts "Error: #{e.message}"
171
+ ExitCodes::GENERAL_ERROR
172
+ end
173
+
174
+ # Loads configuration from file or environment.
175
+ #
176
+ # @return [void]
177
+ def load_config
178
+ service = Pvectl::Config::Service.new
179
+ service.load(config: @global_options[:config])
180
+ @config = service.current_config
181
+ end
182
+
183
+ # Builds service options from command options.
184
+ #
185
+ # @return [Hash] service options
186
+ def service_options
187
+ opts = {}
188
+ opts[:timeout] = @options[:timeout] if @options[:timeout]
189
+ opts[:async] = true if @options[:async]
190
+ opts
191
+ end
192
+
193
+ # Outputs operation results using the configured formatter.
194
+ #
195
+ # @param results [Array<Models::OperationResult>] operation results
196
+ # @return [void]
197
+ def output_results(results)
198
+ presenter = Pvectl::Presenters::SnapshotOperationResult.new
199
+ format = @global_options[:output] || "table"
200
+ color_flag = @global_options[:color]
201
+
202
+ formatter = Pvectl::Formatters::Registry.for(format)
203
+ output = formatter.format(results, presenter, color: color_flag)
204
+ puts output
205
+ end
206
+
207
+ # Determines exit code based on results.
208
+ #
209
+ # @param results [Array<Models::OperationResult>] operation results
210
+ # @return [Integer] exit code
211
+ def determine_exit_code(results)
212
+ return ExitCodes::SUCCESS if results.all?(&:successful?)
213
+ return ExitCodes::SUCCESS if results.all?(&:pending?)
214
+
215
+ ExitCodes::GENERAL_ERROR
216
+ end
217
+
218
+ # Outputs usage error and returns exit code.
219
+ #
220
+ # @param message [String] error message
221
+ # @return [Integer] exit code
222
+ def usage_error(message)
223
+ $stderr.puts "Error: #{message}"
224
+ ExitCodes::USAGE_ERROR
225
+ end
226
+ end
227
+ end
228
+ end