]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/API2/Qemu.pm
allow to pass volume IDs in create_vm (restore)
[qemu-server.git] / PVE / API2 / Qemu.pm
index 46bbf52af70c4e7cd819f7cebc31e213d1f1edc2..cd63cfba4c07a3177259adad326a2d2517d4c627 100644 (file)
@@ -2,6 +2,7 @@ package PVE::API2::Qemu;
 
 use strict;
 use warnings;
+use Cwd 'abs_path';
 
 use PVE::Cluster;
 use PVE::SafeSyslog;
@@ -66,7 +67,7 @@ __PACKAGE__->register_method({
     name => 'create_vm', 
     path => '', 
     method => 'POST',
-    description => "Create new virtual machine.",
+    description => "Create or restore a virtual machine.",
     protected => 1,
     proxyto => 'node',
     parameters => {
@@ -75,6 +76,28 @@ __PACKAGE__->register_method({
            {
                node => get_standard_option('pve-node'),
                vmid => get_standard_option('pve-vmid'),
+               archive => {
+                   description => "The backup file.",
+                   type => 'string',
+                   optional => 1,
+                   maxLength => 255,
+               },
+               storage => get_standard_option('pve-storage-id', {
+                   description => "Default storage.",
+                   optional => 1,
+               }),
+               force => {
+                   optional => 1, 
+                   type => 'boolean',
+                   description => "Allow to overwrite existing VM.",
+                   requires => 'archive',
+               },
+               unique => {
+                   optional => 1, 
+                   type => 'boolean',
+                   description => "Assign a unique random ethernet address.",
+                   requires => 'archive',
+               },
            }),
     },
     returns => { 
@@ -89,30 +112,77 @@ __PACKAGE__->register_method({
 
        my $node = extract_param($param, 'node');
 
-       # fixme: fork worker?
-
        my $vmid = extract_param($param, 'vmid');
 
+       my $archive = extract_param($param, 'archive');
+
+       my $storage = extract_param($param, 'storage');
+
+       my $force = extract_param($param, 'force');
+
+       my $unique = extract_param($param, 'unique');
+
        my $filename = PVE::QemuServer::config_file($vmid);
-       # first test (befor locking)
-       die "unable to create vm $vmid: config file already exists\n" 
-           if -f $filename;
        
        my $storecfg = PVE::Storage::config(); 
 
-       &$resolve_cdrom_alias($param);
+       PVE::Cluster::check_cfs_quorum();
 
-       foreach my $opt (keys %$param) {
-           if (PVE::QemuServer::valid_drivename($opt)) {
-               my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
-               raise_param_exc({ $opt => "unable to parse drive options" }) if !$drive;
+       if (!$archive) { 
+           &$resolve_cdrom_alias($param);
 
-               PVE::QemuServer::cleanup_drive_path($opt, $storecfg, $drive);
-               $param->{$opt} = PVE::QemuServer::print_drive($vmid, $drive);
+           foreach my $opt (keys %$param) {
+               if (PVE::QemuServer::valid_drivename($opt)) {
+                   my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
+                   raise_param_exc({ $opt => "unable to parse drive options" }) if !$drive;
+                   
+                   PVE::QemuServer::cleanup_drive_path($opt, $storecfg, $drive);
+                   $param->{$opt} = PVE::QemuServer::print_drive($vmid, $drive);
+               }
            }
+
+           PVE::QemuServer::add_random_macs($param);
+       } else {
+           my $keystr = join(' ', keys %$param);
+           raise_param_exc({ archive => "option conflicts with other options ($keystr)"}) if $keystr;
+
+           if ($archive eq '-') {
+               die "pipe requires cli environment\n" 
+                   && $rpcenv->{type} ne 'cli';
+           } else {
+               if (PVE::Storage::parse_volume_id($archive, 1)) {
+                   $archive = PVE::Storage::path($storecfg, $archive);
+               } else {
+                   raise_param_exc({ archive => "Only root can pass arbitrary paths." }) 
+                       if $user ne 'root@pam';
+
+                   $archive = abs_path($archive);
+               }
+               die "can't find file '$archive'\n" if ! -f $archive;
+           } 
        }
 
-       PVE::QemuServer::add_random_macs($param);
+       my $restorefn = sub {
+
+           if (-f $filename) {
+               die "unable to restore vm $vmid: config file already exists\n" 
+                   if !$force;
+
+               die "unable to restore vm $vmid: vm is running\n" 
+                   if PVE::QemuServer::check_running($vmid);
+
+               # destroy existing data - keep empty config
+               PVE::QemuServer::destroy_vm($storecfg, $vmid, 1);
+           }
+
+           my $realcmd = sub {
+               PVE::QemuServer::restore_archive($archive, $vmid, { 
+                   storage => $storage,
+                   unique => $unique });
+           };
+
+           return $rpcenv->fork_worker('qmrestore', $vmid, $user, $realcmd);
+       };
 
        my $createfn = sub {
 
@@ -125,7 +195,7 @@ __PACKAGE__->register_method({
                my $vollist = [];
 
                eval {
-                   $vollist = PVE::QemuServer::create_disks($storecfg, $vmid, $param);
+                   $vollist = PVE::QemuServer::create_disks($storecfg, $vmid, $param, $storage);
 
                    # try to be smart about bootdisk
                    my @disks = PVE::QemuServer::disknames();
@@ -157,7 +227,7 @@ __PACKAGE__->register_method({
            return $rpcenv->fork_worker('qmcreate', $vmid, $user, $realcmd);
        };
 
-       return PVE::QemuServer::lock_config($vmid, $createfn);
+       return PVE::QemuServer::lock_config($vmid, $archive ? $restorefn : $createfn);
     }});
 
 __PACKAGE__->register_method({
@@ -460,7 +530,7 @@ __PACKAGE__->register_method({
                } 
                next if !defined($conf->{$opt});
                if (PVE::QemuServer::valid_drivename($opt)) {
-                   PVE::QemuServer::vm_devicedel($vmid,$opt);
+                   PVE::QemuServer::vm_devicedel($vmid, $conf, $opt);
                    my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
                    if (PVE::QemuServer::drive_is_cdrom($drive)) {
                        $cdchange->{$opt} = undef;
@@ -486,7 +556,7 @@ __PACKAGE__->register_method({
                $unset->{$opt} = 1;
            }
 
-           PVE::QemuServer::create_disks($storecfg, $vmid, $param);
+           PVE::QemuServer::create_disks($storecfg, $vmid, $param, $conf);
 
            PVE::QemuServer::change_config_nolock($vmid, $param, $unset, 1);