qemu-server/qm.old
2011-08-23 07:47:04 +02:00

1074 lines
26 KiB
Perl
Executable File

#!/usr/bin/perl -w
use strict;
use Term::ReadLine;
use PVE::QemuServer;
use IO::Socket::INET;
use File::Path;
use Sys::Syslog;
use PVE::Storage;
# VNC proxy example:
# nc -l -p 5900 -w 20 -c "/usr/sbin/qm vncproxy 200 <ticket>"
# where ticket(password) is an arbitrary string containing
# [A-Za-z0-9\+\/] (base64 charset)
# simple vncproxy example: nc -l -p 5900 -c "qm vncproxy 200 test"
# command used by the vnc option
my $vnccmd = "echo -e '__TICKET__\\n__TICKET__' |vncpasswd __TMPFILE__;vncviewer localhost:__DISPLAY__ -passwd __TMPFILE__";
openlog ('qm', 'cons,pid', 'daemon');
sub print_usage {
my ($msg) = @_;
if ($msg) {
print STDERR "ERROR: $msg\n";
}
print STDERR "qm <command> <vmid> [OPTIONS]\n";
print STDERR "qm [create|set] <vmid>\n";
print STDERR "\t--memory <MBYTES> memory in MB (64 - 8192)\n";
print STDERR "\t--sockets <N> set number of CPU sockets <N>\n";
print STDERR "\t--cores <N> set cores per socket to <N>\n";
print STDERR "\t--ostype NAME specify OS type\n";
print STDERR "\t--onboot [yes|no] start at boot\n";
print STDERR "\t--keyboard XX set vnc keyboard layout\n";
print STDERR "\t--cpuunits <num> CPU weight for a VM\n";
print STDERR "\t--name <text> set a name for the VM\n";
print STDERR "\t--description <text> set VM description\n";
print STDERR "\t--boot [a|c|d|n] specify boot order\n";
print STDERR "\t--bootdisk <disk> enable booting from <disk>\n";
print STDERR "\t--acpi (yes|no) enable/disable ACPI\n";
print STDERR "\t--kvm (yes|no) enable/disable KVM\n";
print STDERR "\t--tdf (yes|no) enable/disable time drift fix\n";
print STDERR "\t--localtime (yes|no) set the RTC to local time\n";
print STDERR "\t--vga (gd5446|vesa) specify VGA type\n";
print STDERR "\n";
print STDERR "\t--vlan[0-9u] MODEL=XX:XX:XX:XX:XX:XX[,MODEL=YY:YY:YY:YY:YY:YY]\n";
print STDERR "\n";
print STDERR "\t--ide<N> [volume=]volume,[,media=cdrom|disk]\n";
print STDERR "\t [,cyls=c,heads=h,secs=s[,trans=t]]\n";
print STDERR "\t [,cache=none|writethrough|writeback]\n";
print STDERR "\t [,snapshot=on|off][,cache=on|off][,format=f]\n";
print STDERR "\t [,werror=enospc|ignore|report|stop]\n";
print STDERR "\t [,rerror=ignore|report|stop]\n";
print STDERR "\t--ide<N> <GBYTES> create new disk\n";
print STDERR "\t--ide<N> delete remove drive - destroy image\n";
print STDERR "\t--ide<N> undef remove drive - keep image\n";
print STDERR "\t--cdrom <file> is an alias for --ide2 <file>,media=cdrom\n";
print STDERR "\n";
print STDERR "\t--scsi<N> [volume=]volume,[,media=cdrom|disk]\n";
print STDERR "\t [,cyls=c,heads=h,secs=s[,trans=t]]\n";
print STDERR "\t [,snapshot=on|off][,format=f]\n";
print STDERR "\t [,cache=none|writethrough|writeback]\n";
print STDERR "\t [,werror=enospc|ignore|report|stop]\n";
print STDERR "\t--scsi<N> <GBYTES> create new disk\n";
print STDERR "\t--scsi<N> delete remove drive - destroy image\n";
print STDERR "\t--scsi<N> undef remove drive - keep image\n";
print STDERR "\n";
print STDERR "\t--virtio<N> [volume=]volume,[,media=cdrom|disk]\n";
print STDERR "\t [,cyls=c,heads=h,secs=s[,trans=t]]\n";
print STDERR "\t [,snapshot=on|off][,format=f]\n";
print STDERR "\t [,cache=none|writethrough|writeback]\n";
print STDERR "\t [,werror=enospc|ignore|report|stop]\n";
print STDERR "\t [,rerror=ignore|report|stop]\n";
print STDERR "\t--virtio<N> <GBYTES> create new disk\n";
print STDERR "\t--virtio<N> delete remove drive - destroy image\n";
print STDERR "\t--virtio<N> undef remove drive - keep image\n";
print STDERR "\n";
print STDERR "qm monitor <vmid> connect to vm control monitor\n";
print STDERR "qm start <vmid> start vm\n";
print STDERR "qm shutdown <vmid> gracefully stop vm (send poweroff)\n";
print STDERR "qm wait <vmid> [time] wait until vm is stopped\n";
print STDERR "qm stop <vmid> kill vm (immediate stop)\n";
print STDERR "qm reset <vmid> reset vm (stop, start)\n";
print STDERR "qm suspend <vmid> suspend vm\n";
print STDERR "qm resume <vmid> resume vm\n";
print STDERR "qm cad <vmid> sendkey ctrl-alt-delete\n";
print STDERR "qm destroy <vmid> destroy vm (delete all used/owned volumes)\n";
print STDERR "qm unlock <vmid> clear migrate/backup lock\n";
print STDERR "qm status <vmid> shows the container status\n";
print STDERR "\n";
print STDERR "qm cdrom <vmid> [<device>] <path> set cdrom path. <device is ide2 by default>\n";
print STDERR "qm cdrom <vmid> [<device>] eject eject cdrom\n";
print STDERR "\n";
print STDERR "qm unlink <vmid> <volume> delete unused disk images\n";
print STDERR "qm vncproxy <vmid> <ticket> open vnc proxy\n";
print STDERR "qm vnc <vmid> start (X11) vncviewer (experimental)\n";
print STDERR "qm showcmd <vmid> show command line (debug info)\n";
print STDERR "qm list list all virtual machines\n";
print STDERR "\n";
print STDERR "qm startall start all virtual machines (when onboot=1)\n";
print STDERR "qm stopall [timeout] stop all virtual machines (default timeout is 3 minutes)
\n";
}
sub __next_vnc_port {
for (my $p = 5900; $p < 6000; $p++) {
my $sock = IO::Socket::INET->new (Listen => 5,
LocalAddr => 'localhost',
LocalPort => $p,
ReuseAddr => 1,
Proto => 0);
if ($sock) {
close ($sock);
return $p;
}
}
die "unable to find free vnc port";
}
sub run_vnc_proxy {
my ($vmid) = @_;
my $path = PVE::QemuServer::vnc_socket ($vmid);
my $s = IO::Socket::UNIX->new (Peer => $path, Timeout => 120);
die "unable to connect to socket '$path' - $!" if !$s;
my $select = new IO::Select;
$select->add (\*STDIN);
$select->add ($s);
my $timeout = 60*15; # 15 minutes
my @handles;
while ($select->count &&
scalar (@handles = $select->can_read ($timeout))) {
foreach my $h (@handles) {
my $buf;
my $n = $h->sysread ($buf, 4096);
if ($h == \*STDIN) {
if ($n) {
syswrite ($s, $buf);
} else {
exit (0);
}
} elsif ($h == $s) {
if ($n) {
syswrite (\*STDOUT, $buf);
} else {
exit (0);
}
}
}
}
exit (0);
}
if (scalar (@ARGV) == 0) {
print_usage ();
exit (-1);
}
my $cmd = shift @ARGV;
my $skiplock;
if ($cmd =~ m/^--?skiplock$/) {
$skiplock = 1;
$cmd = shift @ARGV;
}
my $shortcmds = {
list => 1,
startall => 1,
stopall => 1,
mtunnel => 1,
};
my $vmid;
my @disks = PVE::QemuServer::disknames();
my $qm = PVE::QemuServer->new();
if (!defined ($shortcmds->{$cmd})) {
if (scalar (@ARGV) == 0) {
print_usage ("no <vmid>");
exit (-1);
}
$vmid = shift @ARGV;
if ($vmid !~ m/^\d+$/) {
print_usage ("unable to parse <vmid>");
exit (-1);
}
}
sub add_random_macs {
my ($settings) = @_;
foreach my $opt (keys %$settings) {
next if $opt !~ m/^vlan(\d+|u)$/;
my $vlan = PVE::QemuServer::parse_vlan ($settings->{$opt});
next if !$vlan;
$settings->{$opt} = PVE::QemuServer::print_vlan ($vlan);
}
}
sub create_disks {
my ($storecfg, $vmid, $settings) = @_;
my $vollist = [];
eval {
foreach my $ds (@disks) {
next if !$settings->{$ds};
my $disk = PVE::QemuServer::parse_drive ($ds, $settings->{$ds});
next if PVE::QemuServer::drive_is_cdrom ($disk);
my $file = $disk->{file};
if ($file =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
my $storeid = $2 || 'local';
my $size = $3;
my $defformat = PVE::Storage::storage_default_format ($storecfg, $storeid);
my $fmt = $disk->{format} || $defformat;
syslog ('info', "VM $vmid creating new disk - size is $size GB");
my $volid = PVE::Storage::vdisk_alloc ($storecfg, $storeid, $vmid,
$fmt, undef, $size*1024*1024);
$disk->{file} = $volid;
delete ($disk->{format}); # no longer needed
push @$vollist, $volid;
$settings->{$ds} = PVE::QemuServer::print_drive ($vmid, $disk);
} else {
my $path;
if ($disk->{file} =~ m|^/dev/.+|) {
$path = $disk->{file};
} else {
$path = PVE::Storage::path ($storecfg, $disk->{file});
}
if (!(-f $path || -b $path)) {
die "image '$path' does not exists\n";
}
}
}
};
my $err = $@;
if ($err) {
syslog ('err', "VM $vmid create disk failed - $err");
foreach my $volid (@$vollist) {
PVE::Storage::vdisk_free ($storecfg, $volid);
}
die $err;
}
return $vollist;
}
if ($cmd eq 'set') {
my $settings;
if (!($settings = $qm->parse_options ($vmid, 0))) {
exit (-1);
}
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::lock_config ($vmid, sub {
my $conf = PVE::QemuServer::load_config ($vmid);
PVE::QemuServer::check_lock ($conf) if !$skiplock;
my $unset = {};
foreach my $opt (keys %$settings) {
my $value = $settings->{$opt};
next if !defined ($value);
if ($value eq 'delete') {
foreach my $ds (@disks) {
next if $ds ne $opt;
my $disk = $conf->{diskinfo}->{$opt};
next if !$disk;
if (!PVE::QemuServer::drive_is_cdrom ($disk)) {
PVE::QemuServer::unlink_image ($qm->{storecfg}, $vmid, $disk->{file});
}
last;
}
$unset->{$opt} = 1;
delete $settings->{$opt};
} elsif ($value eq '' || $value eq 'undef') {
$unset->{$opt} = 1;
delete $settings->{$opt};
}
}
add_random_macs ($settings);
create_disks ($qm->{storecfg}, $vmid, $settings);
PVE::QemuServer::change_config_nolock ($vmid, $settings, $unset, 1);
});
my $err = $@;
die "setting parameters failed - $err" if $err;
exit (0);
} elsif ($cmd eq 'create') {
my $vollist = [];
my $filename = PVE::QemuServer::config_file ($vmid);
my $settings;
# first test (befor locking)
die "unable to create vm $vmid: config file already exists\n"
if -f $filename;
if (!($settings = $qm->parse_options ($vmid, 1))) {
exit (-1);
}
add_random_macs ($settings);
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
syslog ('info', "VM $vmid creating new virtual machine");
PVE::QemuServer::lock_config ($vmid, sub {
# second test (after locking test is accurate)
die "unable to create vm $vmid: config file already exists\n"
if -f $filename;
$vollist = create_disks ($qm->{storecfg}, $vmid, $settings);
# try to be smart about bootdisk
my @disks = PVE::QemuServer::disknames();
my $firstdisk;
foreach my $ds (reverse @disks) {
next if !$settings->{$ds};
my $disk = PVE::QemuServer::parse_drive ($ds, $settings->{$ds});
next if PVE::QemuServer::drive_is_cdrom ($disk);
$firstdisk = $ds;
}
if (!$settings->{bootdisk} && $firstdisk) {
$settings->{bootdisk} = $firstdisk;
}
PVE::QemuServer::create_conf_nolock ($vmid, $settings);
});
my $err = $@;
if ($err) {
syslog ('err', "VM $vmid create failed - $err");
foreach my $volid (@$vollist) {
eval { PVE::Storage::vdisk_free ($qm->{storecfg}, $volid); };
warn $@ if $@;
}
die "create failed - $err";
}
exit (0);
} elsif ($cmd eq 'unlink') {
if (scalar (@ARGV) == 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::lock_config ($vmid, sub {
my $conf = PVE::QemuServer::load_config ($vmid);
PVE::QemuServer::check_lock ($conf) if !$skiplock;
my $di = $conf->{diskinfo} || {};
foreach my $file (@ARGV) {
my $found;
foreach my $ds (keys %$di) {
if ($di->{$ds}->{file} eq $file) {
$found = 1;
last;
}
}
die "disk image '$file' is used - unable to unlink\n" if $found;
PVE::QemuServer::unlink_image ($qm->{storecfg}, $vmid, $file);
}
});
die $@ if $@;
exit 0;
}
if ($cmd eq 'monitor') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
print "Entering Qemu Monitor for VM $vmid - type 'help' for help\n";
my $term = new Term::ReadLine ('qm');
my $input;
while (defined ($input = $term->readline('qm> '))) {
chomp $input;
next if $input =~ m/^\s*$/;
if ($input =~ m/^\s*q(uit)?\s*$/) {
exit (0);
}
eval {
print PVE::QemuServer::vm_monitor_command ($vmid, $input);
};
print "ERROR: $@" if $@;
}
} elsif ($cmd eq 'showcmd') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
print vm_commandline ($qm->{storecfg}, $vmid) . "\n";
} elsif ($cmd eq 'start') {
my $statefile;
if (scalar (@ARGV) == 2 && ($ARGV[0] =~ m/^\-\-?i(ncoming)?$/)) {
$statefile = $ARGV[1];
} elsif (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::vm_start ($qm->{storecfg}, $vmid, $statefile, $skiplock);
} elsif ($cmd eq 'startall') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
$qm->vm_startall_old ();
} elsif ($cmd eq 'reset') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::vm_reset ($vmid, $skiplock);
} elsif ($cmd eq 'shutdown') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
vm_shutdown ($vmid, $skiplock);
} elsif ($cmd eq 'wait') {
my $timeout = shift || 0;
if ($timeout !~ m/^\d+$/) {
print_usage ("timeout must be numeric");
exit (-1);
}
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
$qm->vm_wait_old ($vmid, $timeout);
} elsif ($cmd eq 'stopall') {
my $timeout = shift || 0;
if ($timeout !~ m/^\d+$/) {
print_usage ("timeout must be numeric");
exit (-1);
}
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::vm_stopall($timeout);
} elsif ($cmd eq 'stop') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
vm_stop ($vmid, $skiplock);
} elsif ($cmd eq 'destroy') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::vm_destroy ($qm->{storecfg}, $vmid, $skiplock);
} elsif ($cmd eq 'suspend') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::vm_suspend ($vmid, $skiplock);
} elsif ($cmd eq 'resume') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::vm_resume ($vmid, $skiplock);
} elsif ($cmd eq 'cad') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::vm_cad ($vmid, $skiplock);
} elsif ($cmd eq 'vncticket') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
my $ticket = PVE::QemuServer::vm_vncticket ($vmid);
print "TICKET:$ticket\n";
} elsif ($cmd eq 'cdrom') {
my ($device, $path);
if (scalar (@ARGV) == 1) {
$path = shift @ARGV;
$device = 'ide2';
} elsif (scalar (@ARGV) == 2) {
my $dev;
($dev, $path) = @ARGV;
foreach my $ds (@disks) {
if (($ds eq $dev) || ("-$ds" eq $dev) || ("--$ds" eq $dev)) {
$device = $ds;
last;
}
}
} else {
print_usage ();
exit (-1);
}
if (!$path || !$device) {
print_usage ();
exit (-1);
}
$path = 'none' if $path eq 'eject';
if (!($path eq 'none' || $path eq 'cdrom')) {
my ($vtype, $volid) = PVE::Storage::path_to_volume_id ($qm->{storecfg}, $path);
if (!($vtype eq 'iso')) {
die "path '$path' does not point to a valid cdrom image\n";
}
$path = $volid;
}
$qm->vm_cdrom ($vmid, $device, $path);
} elsif ($cmd eq 'vncproxy') {
my $ticket = shift @ARGV;
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
if ($ticket) {
die "illegal characters in ticket\n" if $ticket =~ m/[^A-Za-z0-9\+\/]/;
$qm->vm_vncticket ($vmid, $ticket);
}
run_vnc_proxy ($vmid, $ticket);
} elsif ($cmd eq 'vnc') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
my $port = __next_vnc_port();
my $display = $port - 5900;
my $ticket = $qm->vm_vncticket ($vmid);
$ticket = substr ($ticket, 0, 8);
my $mpf = "/tmp/.qmvncpw$$";
$vnccmd =~ s/__TICKET__/$ticket/g;
$vnccmd =~ s/__TMPFILE__/$mpf/g;
$vnccmd =~ s/__DISPLAY__/$display/g;
$vnccmd =~ s/__PORT__/$port/g;
system ("$vnccmd &");
system ("nc -l -p $port -c 'qm vncproxy $vmid'");
unlink $mpf;
} elsif ($cmd eq 'list') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
my $vzlist = PVE::QemuServer::vzlist();
exit 0 if (!scalar(keys %$vzlist));
printf "%10s %-20s %-10s %-10s %12s %-10s\n",
qw(VMID NAME STATUS MEM(MB) BOOTDISK(GB) PID);
foreach my $vmid (sort keys %$vzlist) {
my $conf = PVE::QemuServer::load_config ($vmid);
my $name = $conf->{name} || '-';
my $status = $vzlist->{$vmid}->{pid} ? 'running' : 'stopped';
my $pid = $vzlist->{$vmid}->{pid} || 0;
printf "%10s %-20s %-10s %-10s %12.2f %-10s\n", $vmid, $name, $status,
$conf->{memory}||0, $conf->{disksize}||0, $pid;
}
} elsif ($cmd eq 'unlock') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
PVE::QemuServer::lock_config ($vmid, sub {
PVE::QemuServer::change_config_nolock ($vmid, {}, { lock => 1 }, 1);
});
die $@ if $@;
} elsif ($cmd eq 'status') {
if (scalar (@ARGV) != 0) {
print_usage ();
exit (-1);
}
my $status = 'unknown';
eval {
if (PVE::QemuServer::check_running($vmid)) {
$status = 'running';
} else {
$status = 'stopped';
}
};
print "$status\n";
} elsif ($cmd eq 'mtunnel') {
print "tunnel online\n";
*STDOUT->flush();
while (my $line = <>) {
chomp $line;
last if $line =~ m/^quit$/;
}
exit (0);
} else {
print_usage ();
exit (-1);
}
exit (0);
__END__
=head1 NAME
qm - qemu/kvm manager
=head1 SYNOPSIS
qm [--skiplock] <command> <vmid> [OPTIONS]
type qm to see a list of valid commands
=head1 DESCRIPTION
qm is a script to manage virtual machines with qemu/kvm. You can
create and destroy virtual machines, and control execution
(start/stop/suspend/resume). Besides that, you can use qm to set
parameters in the associated config file. It is also possible to
create and delete virtual disks.
=head1 CONFIGURATION
Global server configuration is stored in /etc/pve/qemu-server.cfg.
All configuration files consists of lines in the form
PARAMETER: value
The following defaults can be specified:
=over 1
=item keyboard: XX
Keybord layout used for vnc server (for example C<fr> for French)
=item onboot: (yes|no)
Specifies whether a VM will be started during system bootup.
Default is no, meaning the VM will not be started if ONBOOT
parameter is omitted.
=item autostart: (yes|no)
Automatic restart after crash. Default is no. This value is
currently ignored (because we have no monitor).
=item memory: num
Amount of RAM for the VM in MB. Default value is 512.
=item cpuunits: num
CPU weight for a VM. Argument is positive non-zero number, passed to
and used in the kernel fair scheduler. The larger the number is,
the more CPU time this VM gets. Maximum value is 500000, minimal
is 8. Number is relative to weights of all the other running VMs.
If cpuunits are not specified, default value of 1000 is used.
NOTE: You can disable fair-scheduler configuration by setting this to 0.
=item vga: (std|cirrus)
Select VGA type. Default is a Cirrus Logic GD5446 PCI VGA card (cirrus).
If you want to use high resolution modes (>= 1280x1024x16) then you should
use option C<std>.
=item tdf: (yes|no)
enable/disable time drift fix [default=yes]
=item tablet: (yes|no)
enable/disable the usb tablet device [default=yes]. This device is usually
needed to allow absolute mouse positioning. Else the mouse runs out of
sync with normal vnc clients. If you're running lots of console-only guests
on one host, you may consider setting "tablet: no" to save some context switches.
=item migrate_downtime: num
set maximum tolerated downtime (in seconds) for migrations. [default=1]
=item migrate_speed: num
set maximum speed (in MB/s) for migrations. [default=0 (no limit)]
=back
=head1 VM CONFIGURATION
Each VM is identified by an unique ID (integer). Configuration for
a VM is stored at C</etc/qemu-server/ID.conf>
Currently, the following parameters are supported:
=over 1
=item keyboard: XX
Default is read from global configuration file.
=item onboot: (yes|no)
Default is read from global configuration file.
=item autostart: (yes|no)
Default is read from global configuration file.
=item memory: num
Default is read from global configuration file.
=item cpuunits: num
Default is read from global configuration file.
=item migrate_downtime: num
Default is read from global configuration file.
=item migrate_speed: num
Default is read from global configuration file.
=item reboot: (yes|no)
Exit instead of rebooting.
=item name: text
Set a name for the VM. Only used on the configuration
web interface.
=item description: text
Description for the VM. Only used on the configuration
web interface.
=item boot: [a|c|d|n]
boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)
default is C<cad> (disk, floppy, cdrom)
=item bootdisk: <disk>
enable booting from <disk>
<disk> = <ide0|ide1|ide2|ide3|scsi0|scsi1|scsi2|...
=item smp: num (please use C<sockets> instead)
set the number of CPUs to C<num> [default=1]
=item sockets: num
set the number of CPU sockets to C<num> [default=1]
=item cores: num
set the number of cores per socket to C<num> [default=1]
=item acpi: (yes|no)
enable/disable ACPI [default=yes]
=item kvm: (yes|no)
enable/disable KVM hardware virtualization [default=yes]
=item tdf: (yes|no)
Default is read from global configuration file.
=item tablet: (yes|no)
Default is read from global configuration file.
=item localtime: (yes|no)
set the real time clock to local time
=item startdate: (now|YYYY-MM-DD|YYYY-MM-DDTHH-MM-SS)
Set the initial date of the real time clock. Valid format
for date are: C<now> or C<2006-06-17T16:01:21> or C<2006-06-17>.
The default value is C<now>.
=item freeze: (yes|no)
freeze CPU at startup (use C<c> monitor command to start execution)
=item vlan0: MODEL=XX:XX:XX:XX:XX:XX[,MODEL=YY:YY:YY:YY:YY:YY]
Specify network devices connected to vlan0. Currently, vlan0 is
connected to vmbr0.
MODEL is one of: ne2k_pci e1000 rtl8139 pcnet virtio
ne2k_isa i82551 i82557b i82559er
XX:XX:XX:XX:XX:XX should be an unique MAC address
=item vlan[1-4094]: MODEL=XX:XX:XX:XX:XX:XX[,MODEL=YY:YY:YY:YY:YY:YY]
Same as vlan0, but vlanX is bridged to vmbrX
=item vlanu: MODEL=XX:XX:XX:XX:XX:XX[,MODEL=YY:YY:YY:YY:YY:YY]
Same as vlan0, but vlanu uses user mode network stack (NAT).
Provides DHCP and DNS services. The following addresses are used:
10.0.2.2 Gateway
10.0.2.3 DNS Server
10.0.2.4 SMB Server
The DHCP server assign addresses to the hosts starting from 10.0.2.15.
=item ostype: (other|wxp|w2k|w2k3|w2k8|wvista|l24|l26)
Used to enable special optimization/features for specific
operating systems:
other => unspecified OS
wxp => Microsoft Windows XP
w2k => Microsoft Windows 2000
w2k3 => Microsoft Windows 2003
w2k8 => Microsoft Windows 2008
wvista => Microsoft Windows Vista
l24 => Linux 2.4 Kernel
l26 => Linux 2.6 Kernel
other|l24|l26 ... no special behaviour
wxp|w2k|w2k3|w2k8|wvista ... use --localtime switch
=item vga: (std|cirrus)
Default is read from global configuration file.
=item ide0 - ide3: [volume=]volume,][,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough"|writeback] [,format=f]
Use volume as IDE hard disk or CD-ROM.
=item scsi0 - scsi15: [volume=]volume,][,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough"|writeback] [,format=f]
Use volume as SCSI hard disk or CD-ROM.
=item virtio0 - virtio15: [volume=]volume,][,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough"|writeback] [,format=f]
Use file as VIRTIO hard disk.
=item hostpci: [HOSTPCIDEVICE][,HOSTPCIDEVICE]*
Map host pci devices. HOSTPCIDEVICE syntax is:
C<bus:dev.func> (hexadecimal numbers)
You can us the C<lspci> command to list existing pci devices.
Note: This option allows direct access to host hardware. So it is no
longer possible to migrate such machines - use with special care.
Experimental: user reported problems with this option
=item hostusb: [HOSTUSBDEVICE][,HOSTUSBDEVICE]*
Map host usb devices. HOSTUSBDEVICE syntax is:
C<bus.addr> (decimal numbers) or C<vendor_id:product_id> (hexadeciaml numbers)
You can us the C<lsusb> command to list existing usb devices (or take a
look at C</proc/bus/usb/devices>).
Note: This option allows direct access to host hardware. So it is no
longer possible to migrate such machines - use with special care.
=item serial: [SERIALDEVICE][,SERIALDEVICE]*
Experimental: user reported problems with this option
Map host serial devices. SERIALDEVICE syntax is /dev/ttyS*
Note: This option allows direct access to host hardware. So it is no
longer possible to migrate such machines - use with special care.
=item parallel: [PARALLELDEVICE][,PARALLELDEVICE]*
Experimental: user reported problems with this option
Map host parallel devices. PARALLELDEVICE syntax is /dev/parport*
Note: This option allows direct access to host hardware. So it is no
longer possible to migrate such machines - use with special care.
=item args: ...
Note: this option is for experts only. It allows you to pass arbitrary
arguments to kvm, for example:
args: -no-reboot -no-hpet
=item lock: (migrate|backup)
This value is set during online migration (migrate) and vzdump
(backup).
=back
=head1 Locks
Online migration and backups (vzdump) set a lock to prevent
unintentional action on such VMs. Sometimes you need remove such lock
manually (power failure).
qm unlock <vmid>
=head1 EXAMPLES
# create a new VM with 4 GB ide disk
qm create 300 -ide0 4 -vlan0 e1000 -cdrom proxmox-mailgateway_2.1.iso
# start the new VM
qm start 300
# send shutdown, then wait until VM is stopped
qm shutdown 300 && qm wait 300
# same as above, but only wait for 40 seconds
qm shutdown 300 && qm wait 300 40