]> git.proxmox.com Git - qemu-server.git/blobdiff - qm
cpuflags : remove enforce for cpumodel=host
[qemu-server.git] / qm
diff --git a/qm b/qm
index f77533c968f085136fad6db66dd7317e3fd573b2..b6617230a6d767cc95cc424d8ffd75d096400aa7 100755 (executable)
--- a/qm
+++ b/qm
@@ -1,6 +1,7 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl
 
 use strict;
+use warnings;
 use Getopt::Long;
 use Fcntl ':flock';
 use File::Path;
@@ -44,9 +45,10 @@ my $upid_exit = sub {
 my $nodename = PVE::INotify::nodename();
 
 sub run_vnc_proxy {
-    my ($vmid) = @_;
+    my ($path) = @_;
 
-    my $path = PVE::QemuServer::vnc_socket($vmid);
+    my $c;
+    while ( ++$c < 10 && !-e $path ) { sleep(1); }
 
     my $s = IO::Socket::UNIX->new(Peer => $path, Timeout => 120);
 
@@ -161,8 +163,17 @@ __PACKAGE__->register_method ({
        my ($param) = @_;
 
        my $vmid = $param->{vmid};
+       my $vnc_socket = PVE::QemuServer::vnc_socket($vmid);
 
-       run_vnc_proxy ($vmid);
+       if (my $ticket = $ENV{LC_PVE_TICKET}) {  # NOTE: ssh on debian only pass LC_* variables
+           PVE::QemuServer::vm_mon_cmd($vmid, "change", device => 'vnc', target => "unix:$vnc_socket,password");
+           PVE::QemuServer::vm_mon_cmd($vmid, "set_password", protocol => 'vnc', password => $ticket);
+           PVE::QemuServer::vm_mon_cmd($vmid, "expire_password", protocol => 'vnc', time => "+30");
+       } else {
+           PVE::QemuServer::vm_mon_cmd($vmid, "change", device => 'vnc', target => "unix:$vnc_socket,x509,password");
+       }
+
+       run_vnc_proxy($vnc_socket);
 
        return undef;
     }});
@@ -187,6 +198,7 @@ __PACKAGE__->register_method ({
        PVE::QemuServer::lock_config ($vmid, sub {
            my $conf = PVE::QemuServer::load_config($vmid);
            delete $conf->{lock};
+           delete $conf->{pending}->{lock} if $conf->{pending}; # just to be sure
            PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
        });
 
@@ -318,69 +330,60 @@ __PACKAGE__->register_method ({
     code => sub {
        my ($param) = @_;
 
-       my $cfg = PVE::Cluster::cfs_read_file("storage.cfg");
+       PVE::QemuServer::rescan($param->{vmid});
 
-       my $info = PVE::Storage::vdisk_list($cfg, undef, $param->{vmid});
+       return undef;
+    }});
 
-       my $volid_hash = {};
-       foreach my $storeid (keys %$info) {
-           foreach my $item (@{$info->{$storeid}}) {
-               next if !($item->{volid} && $item->{size});
-               $volid_hash->{$item->{volid}} = $item;
+__PACKAGE__->register_method ({
+    name => 'terminal', 
+    path => 'terminal', 
+    method => 'POST',
+    description => "Open a terminal using a serial device (The VM need to have a serial device configured, for example 'serial0: socket')",
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           vmid => get_standard_option('pve-vmid'),
+           iface => {
+               description => "Select the serial device. By default we simply use the first suitable device.",
+               type => 'string',
+               optional => 1,
+               enum => [qw(serial0 serial1 serial2 serial3)], 
            }
-       }
-
-       my $updatefn =  sub {
-           my ($vmid) = @_;
-
-           my $conf = PVE::QemuServer::load_config($vmid);
-           
-           PVE::QemuServer::check_lock($conf);
-
-           my $changes;
-
-           my $used = {};
+       },
+    },
+    returns => { type => 'null'},
+    code => sub {
+       my ($param) = @_;
 
-           # update size info
-           foreach my $opt (keys %$conf) {
-               if (PVE::QemuServer::valid_drivename($opt)) {
-                   my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
-                   my $volid = $drive->{file};
-                   next if !$volid;
+       my $vmid = $param->{vmid};
 
-                   $used->{$volid} = 1;
+       my $conf = PVE::QemuServer::load_config ($vmid); # check if VM exists
 
-                   next if PVE::QemuServer::drive_is_cdrom($drive);
-                   next if !$volid_hash->{$volid};
+       my $iface = $param->{iface};
 
-                   $drive->{size} = $volid_hash->{$volid}->{size};
-                   $changes = 1;
-                   $conf->{$opt} = PVE::QemuServer::print_drive($vmid, $drive);
+       if ($iface) { 
+           die "serial interface '$iface' is not configured\n" if !$conf->{$iface};
+           die "wrong serial type on interface '$iface'\n" if $conf->{$iface} ne 'socket';
+       } else {
+           foreach my $opt (qw(serial0 serial1 serial2 serial3)) {
+               if ($conf->{$opt} && ($conf->{$opt} eq 'socket')) {
+                   $iface = $opt;
+                   last;
                }
            }
+           die "unable to find a serial interface\n" if !$iface;
+       }
 
-           # add unused volumes
-           foreach my $storeid (keys %$info) {
-               foreach my $item (@{$info->{$storeid}}) {
-                   next if !($item->{volid} && $item->{vmid});
-                   next if $item->{vmid} ne $vmid;
-                   next if $used->{$item->{volid}};
-                   $changes = 1;
-                   PVE::QemuServer::add_unused_volume($conf, $item->{volid});
-               }
-           }
+       die "VM $vmid not running\n" if !PVE::QemuServer::check_running($vmid);
 
-           PVE::QemuServer::update_config_nolock($vmid, $conf, 1) if $changes;
-       };
+       my $socket = "/var/run/qemu-server/${vmid}.$iface";
 
-       if (defined($param->{vmid})) {
-           PVE::QemuServer::lock_config($param->{vmid}, $updatefn, $param->{vmid});
-       } else {
-           my $vmlist = PVE::QemuServer::config_list();
-           foreach my $vmid (keys %$vmlist) {
-               PVE::QemuServer::lock_config($vmid, $updatefn, $vmid);      
-           }
-       }
+       my $cmd = "socat UNIX-CONNECT:$socket STDIO,raw,echo=0,escape=0x0f";
+
+       print "starting serial terminal on interface $iface (press control-O to exit)\n";
+
+       system($cmd);
 
        return undef;
     }});
@@ -410,13 +413,17 @@ my $cmddef = {
 
     destroy => [ "PVE::API2::Qemu", 'destroy_vm', ['vmid'], { node => $nodename }, $upid_exit ],
 
+    clone => [ "PVE::API2::Qemu", 'clone_vm', ['vmid', 'newid'], { node => $nodename }, $upid_exit ],
+
     migrate => [ "PVE::API2::Qemu", 'migrate_vm', ['vmid', 'target'], { node => $nodename }, $upid_exit ],
 
     set => [ "PVE::API2::Qemu", 'update_vm', ['vmid'], { node => $nodename } ],
 
     resize => [ "PVE::API2::Qemu", 'resize_vm', ['vmid', 'disk', 'size'], { node => $nodename } ],
 
-    unlink => [ "PVE::API2::Qemu", 'unlink', ['vmid', 'idlist'], { node => $nodename } ],
+    move_disk => [ "PVE::API2::Qemu", 'move_vm_disk', ['vmid', 'disk', 'storage'], { node => $nodename }, $upid_exit ],
+
+    unlink => [ "PVE::API2::Qemu", 'unlink', ['vmid'], { node => $nodename } ],
 
     config => [ "PVE::API2::Qemu", 'vm_config', ['vmid'], 
                { node => $nodename }, sub {
@@ -431,6 +438,33 @@ my $cmddef = {
                    }
                }],
        
+    pending => [ "PVE::API2::Qemu", 'vm_pending', ['vmid'],
+               { node => $nodename }, sub {
+                   my $data = shift;
+                   foreach my $item (sort { $a->{key} cmp $b->{key}} @$data) {
+                       my $k = $item->{key};
+                       next if $k eq 'digest';
+                       my $v = $item->{value};
+                       my $p = $item->{pending};
+                       if ($k eq 'description') {
+                           $v = PVE::Tools::encode_text($v) if defined($v);
+                           $p = PVE::Tools::encode_text($p) if defined($p);
+                       }
+                       if (defined($v)) {
+                           if ($item->{delete}) {
+                               print "del $k: $v\n";
+                           } elsif (defined($p)) {
+                               print "cur $k: $v\n";
+                               print "new $k: $p\n";
+                           } else {
+                               print "cur $k: $v\n";
+                           }
+                       } elsif (defined($p)) {
+                           print "new $k: $p\n";
+                       }
+                   }
+               }],
+
     showcmd => [ __PACKAGE__, 'showcmd', ['vmid']],
 
     status => [ __PACKAGE__, 'status', ['vmid']],
@@ -441,6 +475,8 @@ my $cmddef = {
 
     rollback => [ "PVE::API2::Qemu", 'rollback', ['vmid', 'snapname'], { node => $nodename } , $upid_exit ],
 
+    template => [ "PVE::API2::Qemu", 'template', ['vmid'], { node => $nodename }],
+
     start => [ "PVE::API2::Qemu", 'vm_start', ['vmid'], { node => $nodename } , $upid_exit ],
 
     stop => [ "PVE::API2::Qemu", 'vm_stop', ['vmid'], { node => $nodename }, $upid_exit ],
@@ -466,6 +502,8 @@ my $cmddef = {
     monitor  => [ __PACKAGE__, 'monitor', ['vmid']],
 
     mtunnel => [ __PACKAGE__, 'mtunnel', []],  
+
+    terminal => [ __PACKAGE__, 'terminal', ['vmid']],
 };
 
 my $cmd = shift;