Module: Pvectl::Commands::TemplateCommand
- Includes:
- IrreversibleCommand
- Included in:
- TemplateContainer, TemplateVm
- Defined in:
- lib/pvectl/commands/template_command.rb,
sig/pvectl/commands/template_command.rbs
Overview
Template-specific functionality built on IrreversibleCommand.
Converts VMs/containers to Proxmox templates (irreversible operation). Filters out resources that are already templates with a warning. Calls the repository's convert_to_template method for each resource.
Class Method Summary collapse
-
.included(base) ⇒ Object
Hook called when module is included.
Instance Method Summary collapse
-
#build_error_result(resource, error_message) ⇒ Models::OperationResult
Builds an error operation result.
-
#build_presenter ⇒ Presenters::Base
Builds presenter for template results.
-
#build_success_result(resource) ⇒ Models::OperationResult
Builds a successful operation result.
-
#confirm_message(resources) ⇒ String
Returns confirmation message for template conversion.
-
#confirm_operation(resources) ⇒ Boolean
Confirms template operation — uses --yes flag.
-
#convert_single(repo, resource) ⇒ Models::OperationResult
Converts a single resource to template.
-
#irreversibility_warning ⇒ String
Returns irreversibility warning for template conversion.
-
#perform_operation ⇒ Integer
Overrides perform_operation to filter already-template resources.
-
#perform_service_call(resources, connection) ⇒ Array<Models::OperationResult>
Performs template conversion for each resource.
-
#running_error(resource) ⇒ Models::OperationResult
Returns error result for a running resource without --force.
-
#stop_resource(repo, resource) ⇒ Models::OperationResult
Stops a running resource before template conversion.
Methods included from IrreversibleCommand
#apply_selectors, #build_repository, #determine_exit_code, #execute, #initialize, #load_config, #no_resources_found, #output_results, #resolve_resources, #resource_type_symbol, #selector_strings, #service_options, #supported_resource?, #supported_types, #usage_error
Class Method Details
.included(base) ⇒ Object
Hook called when module is included.
24 25 26 |
# File 'lib/pvectl/commands/template_command.rb', line 24 def self.included(base) base.extend(IrreversibleCommand::ClassMethods) end |
Instance Method Details
#build_error_result(resource, error_message) ⇒ Models::OperationResult
Builds an error operation result.
186 187 188 189 190 191 |
# File 'lib/pvectl/commands/template_command.rb', line 186 def build_error_result(resource, ) result_class = resource_type_symbol == :vm ? Models::VmOperationResult : Models::ContainerOperationResult attrs = { operation: :template, success: false, error: } attrs[resource_type_symbol == :vm ? :vm : :container] = resource result_class.new(attrs) end |
#build_presenter ⇒ Presenters::Base
Builds presenter for template results.
196 197 198 199 200 201 202 |
# File 'lib/pvectl/commands/template_command.rb', line 196 def build_presenter if resource_type_symbol == :vm Pvectl::Presenters::VmOperationResult.new else Pvectl::Presenters::ContainerOperationResult.new end end |
#build_success_result(resource) ⇒ Models::OperationResult
Builds a successful operation result.
174 175 176 177 178 179 |
# File 'lib/pvectl/commands/template_command.rb', line 174 def build_success_result(resource) result_class = resource_type_symbol == :vm ? Models::VmOperationResult : Models::ContainerOperationResult attrs = { operation: :template, success: true } attrs[resource_type_symbol == :vm ? :vm : :container] = resource result_class.new(attrs) end |
#confirm_message(resources) ⇒ String
Returns confirmation message for template conversion.
85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/pvectl/commands/template_command.rb', line 85 def (resources) type_name = resource_type_symbol == :vm ? "VM" : "container" type_plural = resource_type_symbol == :vm ? "VMs" : "containers" if resources.size == 1 r = resources.first "You are about to convert #{type_name} #{r.vmid} (#{r.name || 'unnamed'}) on #{r.node} to a template." else lines = ["You are about to convert #{resources.size} #{type_plural} to templates:"] resources.each { |r| lines << " - #{r.vmid} (#{r.name || 'unnamed'}) on #{r.node}" } lines.join("\n") end end |
#confirm_operation(resources) ⇒ Boolean
Confirms template operation — uses --yes flag.
69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/pvectl/commands/template_command.rb', line 69 def confirm_operation(resources) return true if [:yes] $stdout.puts (resources) $stdout.puts "" $stdout.puts irreversibility_warning $stdout.print "Proceed? [y/N]: " response = $stdin.gets&.strip&.downcase %w[y yes].include?(response) end |
#convert_single(repo, resource) ⇒ Models::OperationResult
Converts a single resource to template. Handles running resources: errors without --force, stops with --force.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/pvectl/commands/template_command.rb', line 125 def convert_single(repo, resource) if resource.status == "running" return running_error(resource) unless [:force] stop_result = stop_resource(repo, resource) return stop_result if stop_result.failed? end if resource_type_symbol == :vm repo.convert_to_template(resource.vmid, resource.node, disk: [:disk]) else repo.convert_to_template(resource.vmid, resource.node) end build_success_result(resource) rescue StandardError => e build_error_result(resource, e.) end |
#irreversibility_warning ⇒ String
Returns irreversibility warning for template conversion.
102 103 104 |
# File 'lib/pvectl/commands/template_command.rb', line 102 def irreversibility_warning "This action is IRREVERSIBLE. Templates cannot be converted back and cannot be started." end |
#perform_operation ⇒ Integer
Overrides perform_operation to filter already-template resources.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/pvectl/commands/template_command.rb', line 33 def perform_operation load_config connection = Pvectl::Connection.new(@config) resources = resolve_resources(connection) return no_resources_found if resources.empty? # Filter out already-template resources with warning convertible, already_templates = resources.partition { |r| !r.template? } already_templates.each do |r| type_name = resource_type_symbol == :vm ? "VM" : "Container" $stderr.puts "Warning: #{type_name} #{r.vmid} is already a template, skipping" end return ExitCodes::SUCCESS if convertible.empty? return ExitCodes::SUCCESS unless confirm_operation(convertible) results = perform_service_call(convertible, connection) output_results(results) determine_exit_code(results) rescue Pvectl::Config::ConfigNotFoundError, Pvectl::Config::InvalidConfigError, Pvectl::Config::ContextNotFoundError, Pvectl::Config::ClusterNotFoundError, Pvectl::Config::UserNotFoundError raise rescue StandardError => e $stderr.puts "Error: #{e.message}" ExitCodes::GENERAL_ERROR end |
#perform_service_call(resources, connection) ⇒ Array<Models::OperationResult>
Performs template conversion for each resource.
111 112 113 114 115 116 117 |
# File 'lib/pvectl/commands/template_command.rb', line 111 def perform_service_call(resources, connection) repo = build_repository(connection) @task_repository = Pvectl::Repositories::Task.new(connection) if [:force] resources.map do |resource| convert_single(repo, resource) end end |
#running_error(resource) ⇒ Models::OperationResult
Returns error result for a running resource without --force.
148 149 150 151 |
# File 'lib/pvectl/commands/template_command.rb', line 148 def running_error(resource) type_name = resource_type_symbol == :vm ? "VM" : "Container" build_error_result(resource, "#{type_name} #{resource.vmid} is running. Stop it first or use --force") end |
#stop_resource(repo, resource) ⇒ Models::OperationResult
Stops a running resource before template conversion.
158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/pvectl/commands/template_command.rb', line 158 def stop_resource(repo, resource) upid = repo.stop(resource.vmid, resource.node) timeout = [:timeout] || 60 task = @task_repository.wait(upid, timeout: timeout) if task.successful? build_success_result(resource) else build_error_result(resource, "Failed to stop: #{task.exitstatus}") end end |