]>
git.proxmox.com Git - qemu-server.git/blob - qm
10 use PVE
::Tools
qw(extract_param);
14 use PVE
::RPCEnvironment
;
17 use PVE
::JSONSchema
qw(get_standard_option);
22 use base
qw(PVE::CLIHandler);
24 $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
28 die "please run as root\n" if $> != 0;
30 PVE
::INotify
::inotify_init
();
32 my $rpcenv = PVE
::RPCEnvironment-
>init('cli');
34 $rpcenv->init_request();
35 $rpcenv->set_language($ENV{LANG
});
36 $rpcenv->set_user('root@pam');
40 my $status = PVE
::Tools
::upid_read_status
($upid);
41 exit($status eq 'OK' ?
0 : -1);
44 my $nodename = PVE
::INotify
::nodename
();
49 my $path = PVE
::QemuServer
::vnc_socket
($vmid);
51 my $s = IO
::Socket
::UNIX-
>new(Peer
=> $path, Timeout
=> 120);
53 die "unable to connect to socket '$path' - $!" if !$s;
55 my $select = new IO
::Select
;
57 $select->add(\
*STDIN
);
60 my $timeout = 60*15; # 15 minutes
63 while ($select->count &&
64 scalar(@handles = $select->can_read ($timeout))) {
65 foreach my $h (@handles) {
67 my $n = $h->sysread($buf, 4096);
77 syswrite(\
*STDOUT
, $buf);
87 __PACKAGE__-
>register_method ({
91 description
=> "Show command line which is used to start the VM (debug info).",
93 additionalProperties
=> 0,
95 vmid
=> get_standard_option
('pve-vmid'),
98 returns
=> { type
=> 'null'},
102 my $storecfg = PVE
::Storage
::config
();
103 print PVE
::QemuServer
::vm_commandline
($storecfg, $param->{vmid
}) . "\n";
108 __PACKAGE__-
>register_method ({
112 description
=> "Show VM status.",
114 additionalProperties
=> 0,
116 vmid
=> get_standard_option
('pve-vmid'),
118 description
=> "Verbose output format",
124 returns
=> { type
=> 'null'},
129 my $conf = PVE
::QemuServer
::load_config
($param->{vmid
});
131 my $vmstatus = PVE
::QemuServer
::vmstatus
($param->{vmid
});
132 my $stat = $vmstatus->{$param->{vmid
}};
133 if ($param->{verbose
}) {
134 foreach my $k (sort (keys %$stat)) {
135 next if $k eq 'cpu' || $k eq 'relcpu'; # always 0
137 next if !defined($v);
141 my $status = $stat->{status
} || 'unknown';
142 print "status: $status\n";
148 __PACKAGE__-
>register_method ({
152 description
=> "Proxy VM VNC traffic to stdin/stdout",
154 additionalProperties
=> 0,
156 vmid
=> get_standard_option
('pve-vmid'),
159 returns
=> { type
=> 'null'},
163 my $vmid = $param->{vmid
};
165 run_vnc_proxy
($vmid);
170 __PACKAGE__-
>register_method ({
174 description
=> "Unlock the VM.",
176 additionalProperties
=> 0,
178 vmid
=> get_standard_option
('pve-vmid'),
181 returns
=> { type
=> 'null'},
185 my $vmid = $param->{vmid
};
187 PVE
::QemuServer
::lock_config
($vmid, sub {
188 my $conf = PVE
::QemuServer
::load_config
($vmid);
189 delete $conf->{lock};
190 PVE
::QemuServer
::update_config_nolock
($vmid, $conf, 1);
196 __PACKAGE__-
>register_method ({
200 description
=> "Used by qmigrate - do not use manually.",
202 additionalProperties
=> 0,
205 returns
=> { type
=> 'null'},
209 if (!PVE
::Cluster
::check_cfs_quorum
(1)) {
214 print "tunnel online\n";
217 while (my $line = <>) {
219 last if $line =~ m/^quit$/;
225 __PACKAGE__-
>register_method ({
229 description
=> "Wait until the VM is stopped.",
231 additionalProperties
=> 0,
233 vmid
=> get_standard_option
('pve-vmid'),
235 description
=> "Timeout in seconds. Default is to wait forever.",
242 returns
=> { type
=> 'null'},
246 my $vmid = $param->{vmid
};
247 my $timeout = $param->{timeout
};
249 my $pid = PVE
::QemuServer
::check_running
($vmid);
252 print "waiting until VM $vmid stopps (PID $pid)\n";
255 while ((!$timeout || ($count < $timeout)) && PVE
::QemuServer
::check_running
($vmid)) {
260 die "wait failed - got timeout\n" if PVE
::QemuServer
::check_running
($vmid);
265 __PACKAGE__-
>register_method ({
269 description
=> "Enter Qemu Monitor interface.",
271 additionalProperties
=> 0,
273 vmid
=> get_standard_option
('pve-vmid'),
276 returns
=> { type
=> 'null'},
280 my $vmid = $param->{vmid
};
282 my $conf = PVE
::QemuServer
::load_config
($vmid); # check if VM exists
284 print "Entering Qemu Monitor for VM $vmid - type 'help' for help\n";
286 my $term = new Term
::ReadLine
('qm');
289 while (defined ($input = $term->readline('qm> '))) {
292 next if $input =~ m/^\s*$/;
294 last if $input =~ m/^\s*q(uit)?\s*$/;
297 print PVE
::QemuServer
::vm_human_monitor_command
($vmid, $input);
299 print "ERROR: $@" if $@;
306 __PACKAGE__-
>register_method ({
310 description
=> "Rescan all storages and update disk sizes and unused disk images.",
312 additionalProperties
=> 0,
314 vmid
=> get_standard_option
('pve-vmid', {optional
=> 1}),
317 returns
=> { type
=> 'null'},
321 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
323 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $param->{vmid
});
326 foreach my $storeid (keys %$info) {
327 foreach my $item (@{$info->{$storeid}}) {
328 next if !($item->{volid
} && $item->{size
});
329 $volid_hash->{$item->{volid
}} = $item;
336 my $conf = PVE
::QemuServer
::load_config
($vmid);
338 PVE
::QemuServer
::check_lock
($conf);
345 foreach my $opt (keys %$conf) {
346 if (PVE
::QemuServer
::valid_drivename
($opt)) {
347 my $drive = PVE
::QemuServer
::parse_drive
($opt, $conf->{$opt});
348 my $volid = $drive->{file
};
353 next if PVE
::QemuServer
::drive_is_cdrom
($drive);
354 next if !$volid_hash->{$volid};
356 $drive->{size
} = $volid_hash->{$volid}->{size
};
358 $conf->{$opt} = PVE
::QemuServer
::print_drive
($vmid, $drive);
363 foreach my $storeid (keys %$info) {
364 foreach my $item (@{$info->{$storeid}}) {
365 next if !($item->{volid
} && $item->{vmid
});
366 next if $item->{vmid
} ne $vmid;
367 next if $item->{volid
} =~ m/vm-$vmid-state-/;
368 next if $used->{$item->{volid
}};
370 PVE
::QemuServer
::add_unused_volume
($conf, $item->{volid
});
374 PVE
::QemuServer
::update_config_nolock
($vmid, $conf, 1) if $changes;
377 if (defined($param->{vmid
})) {
378 PVE
::QemuServer
::lock_config
($param->{vmid
}, $updatefn, $param->{vmid
});
380 my $vmlist = PVE
::QemuServer
::config_list
();
381 foreach my $vmid (keys %$vmlist) {
382 PVE
::QemuServer
::lock_config
($vmid, $updatefn, $vmid);
390 list
=> [ "PVE::API2::Qemu", 'vmlist', [],
391 { node
=> $nodename }, sub {
394 exit 0 if (!scalar(@$vmlist));
396 printf "%10s %-20s %-10s %-10s %12s %-10s\n",
397 qw(VMID NAME STATUS MEM(MB) BOOTDISK
(GB
) PID
);
399 foreach my $rec (sort { $a->{vmid
} <=> $b->{vmid
} } @$vmlist) {
400 printf "%10s %-20s %-10s %-10s %12.2f %-10s\n", $rec->{vmid
}, $rec->{name
},
402 ($rec->{maxmem
} || 0)/(1024*1024),
403 ($rec->{maxdisk
} || 0)/(1024*1024*1024),
410 create
=> [ "PVE::API2::Qemu", 'create_vm', ['vmid'], { node
=> $nodename }, $upid_exit ],
412 destroy
=> [ "PVE::API2::Qemu", 'destroy_vm', ['vmid'], { node
=> $nodename }, $upid_exit ],
414 migrate
=> [ "PVE::API2::Qemu", 'migrate_vm', ['vmid', 'target'], { node
=> $nodename }, $upid_exit ],
416 set
=> [ "PVE::API2::Qemu", 'update_vm', ['vmid'], { node
=> $nodename } ],
418 resize
=> [ "PVE::API2::Qemu", 'resize_vm', ['vmid', 'disk', 'size'], { node
=> $nodename } ],
420 unlink => [ "PVE::API2::Qemu", 'unlink', ['vmid', 'idlist'], { node
=> $nodename } ],
422 config
=> [ "PVE::API2::Qemu", 'vm_config', ['vmid'],
423 { node
=> $nodename }, sub {
425 foreach my $k (sort (keys %$config)) {
426 next if $k eq 'digest';
427 my $v = $config->{$k};
428 if ($k eq 'description') {
429 $v = PVE
::Tools
::encode_text
($v);
435 showcmd
=> [ __PACKAGE__
, 'showcmd', ['vmid']],
437 status
=> [ __PACKAGE__
, 'status', ['vmid']],
439 snapshot
=> [ "PVE::API2::Qemu", 'snapshot', ['vmid', 'snapname'], { node
=> $nodename } , $upid_exit ],
441 delsnapshot
=> [ "PVE::API2::Qemu", 'delsnapshot', ['vmid', 'snapname'], { node
=> $nodename } , $upid_exit ],
443 rollback
=> [ "PVE::API2::Qemu", 'rollback', ['vmid', 'snapname'], { node
=> $nodename } , $upid_exit ],
445 start
=> [ "PVE::API2::Qemu", 'vm_start', ['vmid'], { node
=> $nodename } , $upid_exit ],
447 stop
=> [ "PVE::API2::Qemu", 'vm_stop', ['vmid'], { node
=> $nodename }, $upid_exit ],
449 reset => [ "PVE::API2::Qemu", 'vm_reset', ['vmid'], { node
=> $nodename }, $upid_exit ],
451 shutdown => [ "PVE::API2::Qemu", 'vm_shutdown', ['vmid'], { node
=> $nodename }, $upid_exit ],
453 suspend
=> [ "PVE::API2::Qemu", 'vm_suspend', ['vmid'], { node
=> $nodename }, $upid_exit ],
455 resume
=> [ "PVE::API2::Qemu", 'vm_resume', ['vmid'], { node
=> $nodename }, $upid_exit ],
457 sendkey
=> [ "PVE::API2::Qemu", 'vm_sendkey', ['vmid', 'key'], { node
=> $nodename } ],
459 vncproxy
=> [ __PACKAGE__
, 'vncproxy', ['vmid']],
461 wait => [ __PACKAGE__
, 'wait', ['vmid']],
463 unlock
=> [ __PACKAGE__
, 'unlock', ['vmid']],
465 rescan
=> [ __PACKAGE__
, 'rescan', []],
467 monitor
=> [ __PACKAGE__
, 'monitor', ['vmid']],
469 mtunnel
=> [ __PACKAGE__
, 'mtunnel', []],
474 # Note: disable '+' prefix for Getopt::Long (for resize command)
475 use Getopt
::Long
qw(:config no_getopt_compat);
477 PVE
::CLIHandler
::handle_cmd
($cmddef, "qm", $cmd, \
@ARGV, undef, $0);
485 qm - qemu/kvm virtual machine manager
493 qm is a script to manage virtual machines with qemu/kvm. You can
494 create and destroy virtual machines, and control execution
495 (start/stop/suspend/resume). Besides that, you can use qm to set
496 parameters in the associated config file. It is also possible to
497 create and delete virtual disks.
501 All configuration files consists of lines in the form
505 See L<vm.conf|vm.conf> for a complete list of options.
507 Configuration files are stored inside the Proxmox configuration file system, and can be access at F</etc/pve/qemu-server/C<VMID>.conf>.
509 The default for option 'keyboard' is read from
510 F</etc/pve/datacenter.conf>.
514 Online migration and backups (vzdump) set a lock to prevent
515 unintentional action on such VMs. Sometimes you need remove such lock
516 manually (power failure).
522 # create a new VM with 4 GB ide disk
523 qm create 300 -ide0 4 -net0 e1000 -cdrom proxmox-mailgateway_2.1.iso
528 # send shutdown, then wait until VM is stopped
529 qm shutdown 300 && qm wait 300
531 # same as above, but only wait for 40 seconds
532 qm shutdown 300 && qm wait 300 -timeout 40
535 =include pve_copyright