Class: Pvectl::Commands::CloneVm

Inherits:
Object
  • Object
show all
Includes:
SharedConfigParsers
Defined in:
lib/pvectl/commands/clone_vm.rb

Overview

Handler for the ‘pvectl clone vm` command.

Clones a VM by VMID, supporting full and linked clones, custom name, target node, storage, pool, and description. No batch operations - clones exactly one VM at a time.

Examples:

Full clone with auto-generated VMID

pvectl clone vm 100

Clone with custom name and target VMID

pvectl clone vm 100 --vmid 200 --name web-clone

Linked clone to different node

pvectl clone vm 100 --linked --target pve2

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SharedConfigParsers

#build_ct_config_params, #build_vm_config_params, #parse_ct_mountpoints, #parse_ct_nets, #parse_vm_cloud_init, #parse_vm_disks, #parse_vm_nets

Constructor Details

#initialize(args, options, global_options) ⇒ CloneVm

Initializes a clone VM command.

Parameters:

  • args (Array<String>)

    command arguments

  • options (Hash)

    command options

  • global_options (Hash)

    global CLI options



141
142
143
144
145
# File 'lib/pvectl/commands/clone_vm.rb', line 141

def initialize(args, options, global_options)
  @args = args
  @options = options
  @global_options = global_options
end

Class Method Details

.execute(args, options, global_options) ⇒ Integer

Executes the clone VM command.

Parameters:

  • args (Array<String>)

    command arguments (VMID)

  • options (Hash)

    command options

  • global_options (Hash)

    global CLI options

Returns:

  • (Integer)

    exit code



132
133
134
# File 'lib/pvectl/commands/clone_vm.rb', line 132

def self.execute(args, options, global_options)
  new(args, options, global_options).execute
end

.register(cli) ⇒ void

This method returns an undefined value.

Registers the clone command with the CLI.

Parameters:

  • cli (GLI::App)

    the CLI application object



27
28
29
30
31
32
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/pvectl/commands/clone_vm.rb', line 27

def self.register(cli)
  cli.desc "Clone a resource"
  cli.long_desc <<~HELP
    Clone a virtual machine or container, optionally modifying the
    configuration of the clone (CPU, memory, disks, network).

    Supports full clones (independent copy) and linked clones (shares
    base image with source — requires source to be a template).

    EXAMPLES
      Clone a VM to the same node:
        $ pvectl clone vm 100 --name web-clone

      Clone to a different node:
        $ pvectl clone vm 100 --name web-prod --target pve2

      Clone with modified configuration:
        $ pvectl clone vm 100 --name web-prod --cores 4 --memory 8192

      Linked clone (thin provisioning, requires template):
        $ pvectl clone vm 100 --linked --name thin-clone

      Clone a container with new network config:
        $ pvectl clone ct 200 --name db-clone --memory 4096 --net bridge=vmbr1

      Clone with explicit new ID:
        $ pvectl clone vm 100 --newid 150 --name web-test

    NOTES
      Config modification is a two-step process: clone first, then update
      configuration via the Proxmox API. If the config update fails, the
      clone still exists but with the original configuration.

      Linked clones share the base disk with the source. They are faster
      to create and use less storage, but the source cannot be deleted.

      If --name is not specified, Proxmox auto-generates a name.

    SEE ALSO
      pvectl help create          Create new VMs/containers from scratch
      pvectl help migrate         Move resources between nodes
      pvectl help template        Convert to template for linked clones
  HELP
  cli.arg_name "RESOURCE_TYPE ID"
  cli.command :clone do |c|
    c.desc "Name/hostname for the new resource"
    c.flag [:name, :n], arg_name: "NAME"

    c.desc "ID for the new resource (auto-selected if not specified)"
    c.flag [:newid], type: Integer, arg_name: "ID"

    c.desc "Target node for the clone"
    c.flag [:target, :t], arg_name: "NODE"

    c.desc "Target storage for the clone"
    c.flag [:storage, :s], arg_name: "STORAGE"

    c.desc "Create a linked clone (requires source to be a template)"
    c.switch [:linked], negatable: false

    c.desc "Resource pool for the new resource"
    c.flag [:pool, :p], arg_name: "POOL"

    c.desc "Description for the new resource"
    c.flag [:description, :d], arg_name: "DESCRIPTION"

    c.desc "Timeout in seconds for sync operations (default: 300)"
    c.flag [:timeout], type: Integer, arg_name: "SECONDS"

    c.desc "Async mode (return task ID immediately)"
    c.switch [:async], negatable: false

    c.desc "Skip confirmation prompt"
    c.switch [:yes, :y], negatable: false

    # Shared config flags for VM/container modification after clone
    SharedFlags.common_config(c)
    SharedFlags.vm_config(c)
    SharedFlags.container_config(c)

    c.action do |global_options, options, args|
      resource_type = args.shift

      exit_code = case resource_type
      when "vm"
        Commands::CloneVm.execute(args, options, global_options)
      when "container", "ct"
        Commands::CloneContainer.execute(args, options, global_options)
      else
        $stderr.puts "Error: Unknown resource type: #{resource_type}"
        $stderr.puts "Valid types: vm, container, ct"
        ExitCodes::USAGE_ERROR
      end

      exit exit_code if exit_code != 0
    end
  end
end

Instance Method Details

#executeInteger

Executes the clone VM command.

Builds config params from shared flags, validates async+config compatibility, and delegates to the clone operation.

Returns:

  • (Integer)

    exit code



153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/pvectl/commands/clone_vm.rb', line 153

def execute
  vmid = @args.first
  return usage_error("Source VMID required") unless vmid

  config_params = build_vm_config_params

  if @options[:async] && !config_params.empty?
    return usage_error("Config flags require sync mode (remove --async)")
  end

  perform_clone(vmid.to_i, config_params)
end