[pve-devel] r5166 - qemu-server/pve2

svn-commits at proxmox.com svn-commits at proxmox.com
Thu Sep 16 15:21:10 CEST 2010


Author: dietmar
Date: 2010-09-16 13:21:10 +0000 (Thu, 16 Sep 2010)
New Revision: 5166

Added:
   qemu-server/pve2/qm
   qemu-server/pve2/qm.old
Removed:
   qemu-server/pve2/nqm
   qemu-server/pve2/qm
Modified:
   qemu-server/pve2/ChangeLog
   qemu-server/pve2/Makefile
Log:
	* nqm: renamed to qm
	
	* qm: renamed to qm.old.



Modified: qemu-server/pve2/ChangeLog
===================================================================
--- qemu-server/pve2/ChangeLog	2010-09-16 13:17:19 UTC (rev 5165)
+++ qemu-server/pve2/ChangeLog	2010-09-16 13:21:10 UTC (rev 5166)
@@ -1,5 +1,9 @@
 2010-09-16  Proxmox Support Team  <support at proxmox.com>
 
+	* nqm: renamed to qm
+	
+	* qm: renamed to qm.old.
+	
 	* PVE/QemuServer.pm (disknames): removed - no longer needed
 	(parse_config): remove diskinfo
 	(config_to_command): also return volume ID list

Modified: qemu-server/pve2/Makefile
===================================================================
--- qemu-server/pve2/Makefile	2010-09-16 13:17:19 UTC (rev 5165)
+++ qemu-server/pve2/Makefile	2010-09-16 13:21:10 UTC (rev 5166)
@@ -76,7 +76,7 @@
 	rm -rf debian
 	mkdir debian
 	make DESTDIR=${CURDIR}/debian install
-	perl -I. ./nqm verifyapi
+	perl -I. ./qm verifyapi
 	install -d -m 0755 debian/DEBIAN
 	install -m 0644 control debian/DEBIAN
 	install -m 0755 postinst debian/DEBIAN

Deleted: qemu-server/pve2/nqm
===================================================================
--- qemu-server/pve2/nqm	2010-09-16 13:17:19 UTC (rev 5165)
+++ qemu-server/pve2/nqm	2010-09-16 13:21:10 UTC (rev 5166)
@@ -1,447 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use Getopt::Long;
-use Fcntl ':flock';
-use File::Path;
-use IO::Socket::UNIX;
-use IO::Select;
-
-use PVE::INotify qw(read_file);
-use PVE::RPCEnvironment;
-use PVE::QemuServer;
-use PVE::API2::Qemu::Config;
-use PVE::API2::Qemu::Status;
-use PVE::JSONSchema qw(get_standard_option);
-use Term::ReadLine;
-
-use PVE::CLIHandler;
-
-use base qw(PVE::CLIHandler);
-
-$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
-
-die "please run as root\n" if $> != 0;
-
-PVE::INotify::inotify_init();
-
-my $rpcenv = PVE::RPCEnvironment->init('cli');
-
-$rpcenv->set_language($ENV{LANG});
-
-$rpcenv->set_user('root'); 
-
-my $hostname = $rpcenv->get_hostname();
-
-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);
-}
-
-__PACKAGE__->register_method ({
-    name => 'showcmd', 
-    path => 'showcmd', 
-    method => 'GET',
-    description => "Show command line which is used to start the VM (debug info).",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {
-	    vmid => get_standard_option('pve-vmid'),
-	},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	my $storecfg = read_file('storagecfg');
-	print PVE::QemuServer::vm_commandline ($storecfg, $param->{vmid}) . "\n";
-
-	return undef;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'status', 
-    path => 'status', 
-    method => 'GET',
-    description => "Show VM status.",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {
-	    vmid => get_standard_option('pve-vmid'),
-	},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	my $status = 'unknown';
-
-	eval { 
-	    if (PVE::QemuServer::check_running($param->{vmid})) {
-		$status = 'running';
-	    } else {
-		$status = 'stopped';
-	    }
-	};
-
-	print "$status\n";
-
-	return undef;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'vncticket', 
-    path => 'vncticket', 
-    method => 'PUT',
-    description => "Create and set a VNC authentication ticket.",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {
-	    vmid => get_standard_option('pve-vmid'),
-	},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	my $vmid = $param->{vmid};
-
-	my $ticket = PVE::QemuServer::vm_vncticket ($vmid);
-	print "TICKET:$ticket\n";
-
-	return undef;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'vncproxy', 
-    path => 'vncproxy', 
-    method => 'PUT',
-    description => "Proxy VM VNC traffic to stdin/stdout",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {
-	    vmid => get_standard_option('pve-vmid'),
-	    ticket => get_standard_option('pve-vncticket', { optional => 1 }), 
-	},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	my $vmid = $param->{vmid};
-	my $ticket = $param->{ticket};
-
-	if ($ticket) {
-	    PVE::QemuServer::vm_vncticket ($vmid, $ticket);
-	}
-
-	run_vnc_proxy ($vmid, $ticket);
-
-	return undef;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'unlock', 
-    path => 'unlock', 
-    method => 'PUT',
-    description => "Unlock the VM.",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {
-	    vmid => get_standard_option('pve-vmid'),
-	},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	my $vmid = $param->{vmid};
-
-	PVE::QemuServer::lock_config ($vmid, sub {
-	    PVE::QemuServer::change_config_nolock  ($vmid, {}, { lock => 1 }, 1);
-	});
-
-	return undef;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'mtunnel', 
-    path => 'mtunnel', 
-    method => 'POST',
-    description => "Used by vzmigrate - do not use manually.",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	print "tunnel online\n";
-	*STDOUT->flush();
-
-	while (my $line = <>) {
-	    chomp $line;
-	    last if $line =~ m/^quit$/;
-	}
-
-	return undef;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'startall', 
-    path => 'startall', 
-    method => 'POST',
-    description => "Start all virtual machines (when onboot=1).",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	my $vzlist = PVE::QemuServer::vzlist();
-	my $storecfg = read_file('storagecfg');
-
-	foreach my $vmid (keys %$vzlist) {
-	    next if $vzlist->{$vmid}->{pid}; # already running
-
-	    eval {
-		my $conf = PVE::QemuServer::load_config ($vmid);
-		if ($conf->{onboot}) {
-		    print STDERR "Starting Qemu VM $vmid\n";
-		    vm_start ($storecfg, $vmid);
-		}
-	    };
-	    print STDERR $@ if $@;
-	}
-
-	return undef;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'stopall', 
-    path => 'stopall', 
-    method => 'POST',
-    description => "Stop all virtual machines.",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {
-	    timeout => {
-		description => "Timeout in seconds. Default is to wait 3 minutes.",
-		type => 'integer',
-		minimum => 1,
-		optional => 1,
-	    }
-	},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	my $timeout = $param->{timeout};
-
-	PVE::QemuServer::vm_stopall($timeout);
-
-	return undef;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'wait', 
-    path => 'wait', 
-    method => 'GET',
-    description => "Wait until the VM is stopped.",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {
-	    vmid => get_standard_option('pve-vmid'),
-	    timeout => {
-		description => "Timeout in seconds. Default is to wait forever.",
-		type => 'integer',
-		minimum => 1,
-		optional => 1,
-	    }
-	},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	my $vmid = $param->{vmid};
-	my $timeout = $param->{timeout};
-
-	my $pid = PVE::QemuServer::check_running ($vmid);
-	return if !$pid;
-
-	print "waiting until VM $vmid stopps (PID $pid)\n";
-
-	my $count = 0;
-	while ((!$timeout || ($count < $timeout)) && PVE::QemuServer::check_running ($vmid)) {
-	    $count++;
-	    sleep 1;
-	}
-
-	die "wait failed - got timeout\n" if PVE::QemuServer::check_running ($vmid);
-
-	return undef;
-    }});
-
-__PACKAGE__->register_method ({
-    name => 'monitor', 
-    path => 'monitor', 
-    method => 'POST',
-    description => "Enter Qemu Monitor interface.",
-    parameters => {
-    	additionalProperties => 0,
-	properties => {
-	    vmid => get_standard_option('pve-vmid'),
-	},
-    },
-    returns => { type => 'null'},
-    code => sub {
-	my ($param) = @_;
-
-	my $vmid = $param->{vmid};
-
-	my $conf = PVE::QemuServer::load_config ($vmid); # check if VM exists
-
-	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*$/;
-
-	    last if $input =~ m/^\s*q(uit)?\s*$/;
-
-	    eval {
-		print PVE::QemuServer::vm_monitor_command ($vmid, $input);
-	    };
-	    print "ERROR: $@" if $@;
-	}
-
-	return undef;
-
-    }});
-
-# fixme: unlink
-
-my $cmddef = {
-    list => [ "PVE::API2::Qemu::Config", 'vmlist', [],
-	     { node => $hostname }, sub {
-		 my $vmlist = shift;
-
-		 exit 0 if (!scalar(@$vmlist));
-
-		 printf "%10s %-20s %-10s %-10s %12s %-10s\n", 
-		 qw(VMID NAME STATUS MEM(MB) BOOTDISK(GB) PID);
-
-		 foreach my $rec (sort { $a->{vmid} <=> $b->{vmid} } @$vmlist) {
-		     printf "%10s %-20s %-10s %-10s %12.2f %-10s\n", $rec->{vmid}, $rec->{name}, 
-		     $rec->{status}, $rec->{maxmem}, $rec->{maxdisk}||0, $rec->{pid}||0;
-		 }
-
-		 
-	      } ],
-
-    create => [ "PVE::API2::Qemu::Config", 'create_vm', ['vmid'], { node => $hostname } ],
-
-    destroy => [ "PVE::API2::Qemu::Config", 'destroy_vm', ['vmid'], { node => $hostname } ],
-
-    set => [ "PVE::API2::Qemu::Config", 'update_vm', ['vmid'], { node => $hostname } ],
-
-    config => [ "PVE::API2::Qemu::Config", 'vm_config', ['vmid'], 
-		{ node => $hostname }, sub {
-		    my $config = shift;
-		    foreach my $k (sort (keys %$config)) {
-			my $v = $config->{$k};
-			print "$k: $v\n";
-		    }
-		}],
-	
-    showcmd => [ __PACKAGE__, 'showcmd', ['vmid']],
-
-    status => [ __PACKAGE__, 'status', ['vmid']],
-
-    vncticket => [ __PACKAGE__, 'vncticket', ['vmid']],
-
-    vncproxy => [ __PACKAGE__, 'vncproxy', ['vmid', 'ticket']],
-
-    wait => [ __PACKAGE__, 'wait', ['vmid']],
-
-    unlock => [ __PACKAGE__, 'unlock', ['vmid']],
-
-    monitor  => [ __PACKAGE__, 'monitor', ['vmid']],
-
-    startall => [ __PACKAGE__, 'startall', []],
-
-    stopall => [ __PACKAGE__, 'stopall', []],
-
-    mtunnel => [ __PACKAGE__, 'mtunnel', []],
-
-
-    start => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
-	       { node => $hostname, command => 'start' } ],
-    stop => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
-	      { node => $hostname, command => 'stop' } ],
-    reset => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
-	       { node => $hostname, command => 'reset' } ],
-    suspend => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
-		 { node => $hostname, command => 'suspend' } ],
-    resume => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
-		{ node => $hostname, command => 'resume' } ],
-    cad => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
-	     { node => $hostname, command => 'cad' } ],
-	
-};
-
-my $cmd = shift;
-
-if ($cmd && $cmd eq 'verifyapi') {
-    PVE::RESTHandler::validate_method_schemas();
-    exit 0;
-}
-
-PVE::CLIHandler::handle_cmd($cmddef, "qm", $cmd, \@ARGV);
-
-exit 0;

Deleted: qemu-server/pve2/qm
===================================================================
--- qemu-server/pve2/qm	2010-09-16 13:17:19 UTC (rev 5165)
+++ qemu-server/pve2/qm	2010-09-16 13:21:10 UTC (rev 5166)
@@ -1,1073 +0,0 @@
-#!/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
-
-
-
-
-
-
-

Copied: qemu-server/pve2/qm (from rev 5165, qemu-server/pve2/nqm)
===================================================================
--- qemu-server/pve2/qm	                        (rev 0)
+++ qemu-server/pve2/qm	2010-09-16 13:21:10 UTC (rev 5166)
@@ -0,0 +1,447 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Getopt::Long;
+use Fcntl ':flock';
+use File::Path;
+use IO::Socket::UNIX;
+use IO::Select;
+
+use PVE::INotify qw(read_file);
+use PVE::RPCEnvironment;
+use PVE::QemuServer;
+use PVE::API2::Qemu::Config;
+use PVE::API2::Qemu::Status;
+use PVE::JSONSchema qw(get_standard_option);
+use Term::ReadLine;
+
+use PVE::CLIHandler;
+
+use base qw(PVE::CLIHandler);
+
+$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
+
+die "please run as root\n" if $> != 0;
+
+PVE::INotify::inotify_init();
+
+my $rpcenv = PVE::RPCEnvironment->init('cli');
+
+$rpcenv->set_language($ENV{LANG});
+
+$rpcenv->set_user('root'); 
+
+my $hostname = $rpcenv->get_hostname();
+
+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);
+}
+
+__PACKAGE__->register_method ({
+    name => 'showcmd', 
+    path => 'showcmd', 
+    method => 'GET',
+    description => "Show command line which is used to start the VM (debug info).",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {
+	    vmid => get_standard_option('pve-vmid'),
+	},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	my $storecfg = read_file('storagecfg');
+	print PVE::QemuServer::vm_commandline ($storecfg, $param->{vmid}) . "\n";
+
+	return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'status', 
+    path => 'status', 
+    method => 'GET',
+    description => "Show VM status.",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {
+	    vmid => get_standard_option('pve-vmid'),
+	},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	my $status = 'unknown';
+
+	eval { 
+	    if (PVE::QemuServer::check_running($param->{vmid})) {
+		$status = 'running';
+	    } else {
+		$status = 'stopped';
+	    }
+	};
+
+	print "$status\n";
+
+	return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'vncticket', 
+    path => 'vncticket', 
+    method => 'PUT',
+    description => "Create and set a VNC authentication ticket.",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {
+	    vmid => get_standard_option('pve-vmid'),
+	},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	my $vmid = $param->{vmid};
+
+	my $ticket = PVE::QemuServer::vm_vncticket ($vmid);
+	print "TICKET:$ticket\n";
+
+	return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'vncproxy', 
+    path => 'vncproxy', 
+    method => 'PUT',
+    description => "Proxy VM VNC traffic to stdin/stdout",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {
+	    vmid => get_standard_option('pve-vmid'),
+	    ticket => get_standard_option('pve-vncticket', { optional => 1 }), 
+	},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	my $vmid = $param->{vmid};
+	my $ticket = $param->{ticket};
+
+	if ($ticket) {
+	    PVE::QemuServer::vm_vncticket ($vmid, $ticket);
+	}
+
+	run_vnc_proxy ($vmid, $ticket);
+
+	return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'unlock', 
+    path => 'unlock', 
+    method => 'PUT',
+    description => "Unlock the VM.",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {
+	    vmid => get_standard_option('pve-vmid'),
+	},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	my $vmid = $param->{vmid};
+
+	PVE::QemuServer::lock_config ($vmid, sub {
+	    PVE::QemuServer::change_config_nolock  ($vmid, {}, { lock => 1 }, 1);
+	});
+
+	return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'mtunnel', 
+    path => 'mtunnel', 
+    method => 'POST',
+    description => "Used by vzmigrate - do not use manually.",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	print "tunnel online\n";
+	*STDOUT->flush();
+
+	while (my $line = <>) {
+	    chomp $line;
+	    last if $line =~ m/^quit$/;
+	}
+
+	return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'startall', 
+    path => 'startall', 
+    method => 'POST',
+    description => "Start all virtual machines (when onboot=1).",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	my $vzlist = PVE::QemuServer::vzlist();
+	my $storecfg = read_file('storagecfg');
+
+	foreach my $vmid (keys %$vzlist) {
+	    next if $vzlist->{$vmid}->{pid}; # already running
+
+	    eval {
+		my $conf = PVE::QemuServer::load_config ($vmid);
+		if ($conf->{onboot}) {
+		    print STDERR "Starting Qemu VM $vmid\n";
+		    vm_start ($storecfg, $vmid);
+		}
+	    };
+	    print STDERR $@ if $@;
+	}
+
+	return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'stopall', 
+    path => 'stopall', 
+    method => 'POST',
+    description => "Stop all virtual machines.",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {
+	    timeout => {
+		description => "Timeout in seconds. Default is to wait 3 minutes.",
+		type => 'integer',
+		minimum => 1,
+		optional => 1,
+	    }
+	},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	my $timeout = $param->{timeout};
+
+	PVE::QemuServer::vm_stopall($timeout);
+
+	return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'wait', 
+    path => 'wait', 
+    method => 'GET',
+    description => "Wait until the VM is stopped.",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {
+	    vmid => get_standard_option('pve-vmid'),
+	    timeout => {
+		description => "Timeout in seconds. Default is to wait forever.",
+		type => 'integer',
+		minimum => 1,
+		optional => 1,
+	    }
+	},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	my $vmid = $param->{vmid};
+	my $timeout = $param->{timeout};
+
+	my $pid = PVE::QemuServer::check_running ($vmid);
+	return if !$pid;
+
+	print "waiting until VM $vmid stopps (PID $pid)\n";
+
+	my $count = 0;
+	while ((!$timeout || ($count < $timeout)) && PVE::QemuServer::check_running ($vmid)) {
+	    $count++;
+	    sleep 1;
+	}
+
+	die "wait failed - got timeout\n" if PVE::QemuServer::check_running ($vmid);
+
+	return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'monitor', 
+    path => 'monitor', 
+    method => 'POST',
+    description => "Enter Qemu Monitor interface.",
+    parameters => {
+    	additionalProperties => 0,
+	properties => {
+	    vmid => get_standard_option('pve-vmid'),
+	},
+    },
+    returns => { type => 'null'},
+    code => sub {
+	my ($param) = @_;
+
+	my $vmid = $param->{vmid};
+
+	my $conf = PVE::QemuServer::load_config ($vmid); # check if VM exists
+
+	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*$/;
+
+	    last if $input =~ m/^\s*q(uit)?\s*$/;
+
+	    eval {
+		print PVE::QemuServer::vm_monitor_command ($vmid, $input);
+	    };
+	    print "ERROR: $@" if $@;
+	}
+
+	return undef;
+
+    }});
+
+# fixme: unlink
+
+my $cmddef = {
+    list => [ "PVE::API2::Qemu::Config", 'vmlist', [],
+	     { node => $hostname }, sub {
+		 my $vmlist = shift;
+
+		 exit 0 if (!scalar(@$vmlist));
+
+		 printf "%10s %-20s %-10s %-10s %12s %-10s\n", 
+		 qw(VMID NAME STATUS MEM(MB) BOOTDISK(GB) PID);
+
+		 foreach my $rec (sort { $a->{vmid} <=> $b->{vmid} } @$vmlist) {
+		     printf "%10s %-20s %-10s %-10s %12.2f %-10s\n", $rec->{vmid}, $rec->{name}, 
+		     $rec->{status}, $rec->{maxmem}, $rec->{maxdisk}||0, $rec->{pid}||0;
+		 }
+
+		 
+	      } ],
+
+    create => [ "PVE::API2::Qemu::Config", 'create_vm', ['vmid'], { node => $hostname } ],
+
+    destroy => [ "PVE::API2::Qemu::Config", 'destroy_vm', ['vmid'], { node => $hostname } ],
+
+    set => [ "PVE::API2::Qemu::Config", 'update_vm', ['vmid'], { node => $hostname } ],
+
+    config => [ "PVE::API2::Qemu::Config", 'vm_config', ['vmid'], 
+		{ node => $hostname }, sub {
+		    my $config = shift;
+		    foreach my $k (sort (keys %$config)) {
+			my $v = $config->{$k};
+			print "$k: $v\n";
+		    }
+		}],
+	
+    showcmd => [ __PACKAGE__, 'showcmd', ['vmid']],
+
+    status => [ __PACKAGE__, 'status', ['vmid']],
+
+    vncticket => [ __PACKAGE__, 'vncticket', ['vmid']],
+
+    vncproxy => [ __PACKAGE__, 'vncproxy', ['vmid', 'ticket']],
+
+    wait => [ __PACKAGE__, 'wait', ['vmid']],
+
+    unlock => [ __PACKAGE__, 'unlock', ['vmid']],
+
+    monitor  => [ __PACKAGE__, 'monitor', ['vmid']],
+
+    startall => [ __PACKAGE__, 'startall', []],
+
+    stopall => [ __PACKAGE__, 'stopall', []],
+
+    mtunnel => [ __PACKAGE__, 'mtunnel', []],
+
+
+    start => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
+	       { node => $hostname, command => 'start' } ],
+    stop => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
+	      { node => $hostname, command => 'stop' } ],
+    reset => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
+	       { node => $hostname, command => 'reset' } ],
+    suspend => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
+		 { node => $hostname, command => 'suspend' } ],
+    resume => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
+		{ node => $hostname, command => 'resume' } ],
+    cad => [ "PVE::API2::Qemu::Status", 'vm_command', ['vmid'], 
+	     { node => $hostname, command => 'cad' } ],
+	
+};
+
+my $cmd = shift;
+
+if ($cmd && $cmd eq 'verifyapi') {
+    PVE::RESTHandler::validate_method_schemas();
+    exit 0;
+}
+
+PVE::CLIHandler::handle_cmd($cmddef, "qm", $cmd, \@ARGV);
+
+exit 0;

Copied: qemu-server/pve2/qm.old (from rev 5165, qemu-server/pve2/qm)
===================================================================
--- qemu-server/pve2/qm.old	                        (rev 0)
+++ qemu-server/pve2/qm.old	2010-09-16 13:21:10 UTC (rev 5166)
@@ -0,0 +1,1073 @@
+#!/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
+
+
+
+
+
+
+




More information about the pve-devel mailing list