]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/API2/Qemu.pm
template_create: check for 'clone' feature
[qemu-server.git] / PVE / API2 / Qemu.pm
index f4ae56662a10fd258c1fd91381e4bea24302dc43..924af264f47aa3ebd55682b223ccb09d0cc55287 100644 (file)
@@ -72,7 +72,8 @@ my $create_disks = sub {
        my $volid = $disk->{file};
 
        if (!$volid || $volid eq 'none' || $volid eq 'cdrom') {
-           $res->{$ds} = $settings->{$ds};
+           delete $disk->{size};
+           $res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
        } elsif ($volid =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
            my ($storeid, $size) = ($2 || $default_storage, $3);
            die "no storage ID specified (and no default storage)\n" if !$storeid;
@@ -147,7 +148,7 @@ my $check_vm_modify_config_perm = sub {
            $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.CPU']);
        } elsif ($opt eq 'boot' || $opt eq 'bootdisk') {
            $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Disk']);
-       } elsif ($opt eq 'memory' || $opt eq 'balloon') {
+       } elsif ($opt eq 'memory' || $opt eq 'balloon' || $opt eq 'shares') {
            $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Memory']);
        } elsif ($opt eq 'args' || $opt eq 'lock') {
            die "only root can set '$opt' config\n";
@@ -348,9 +349,6 @@ __PACKAGE__->register_method({
 
                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 {
@@ -829,6 +827,8 @@ __PACKAGE__->register_method({
 
        my $storecfg = PVE::Storage::config();
 
+       my $defaults = PVE::QemuServer::load_defaults();
+
        &$resolve_cdrom_alias($param);
 
        # now try to verify all parameters
@@ -875,6 +875,14 @@ __PACKAGE__->register_method({
 
            PVE::QemuServer::check_lock($conf) if !$skiplock;
 
+           if ($param->{memory} || defined($param->{balloon})) {
+               my $maxmem = $param->{memory} || $conf->{memory} || $defaults->{memory};
+               my $balloon = defined($param->{balloon}) ?  $param->{balloon} : $conf->{balloon};
+
+               die "balloon value too large (must be smaller than assigned memory)\n"
+                   if $balloon > $maxmem;
+           }
+
            PVE::Cluster::log_msg('info', $authuser, "update VM $vmid: " . join (' ', @paramarr));
 
            foreach my $opt (@delete) { # delete
@@ -882,6 +890,8 @@ __PACKAGE__->register_method({
                &$vmconfig_delete_option($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $force);
            }
 
+           my $running = PVE::QemuServer::check_running($vmid);
+
            foreach my $opt (keys %$param) { # add/change
 
                $conf = PVE::QemuServer::load_config($vmid); # update/reload
@@ -904,6 +914,14 @@ __PACKAGE__->register_method({
                    PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
                }
            }
+
+           # allow manual ballooning if shares is set to zero
+           if ($running && defined($param->{balloon}) && 
+               defined($conf->{shares}) && ($conf->{shares} == 0)) {
+               my $balloon = $param->{'balloon'} || $conf->{memory} || $defaults->{memory};
+               PVE::QemuServer::vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
+           }
+
        };
 
        PVE::QemuServer::lock_config($vmid, $updatefn);
@@ -1065,10 +1083,8 @@ __PACKAGE__->register_method({
            $remip = PVE::Cluster::remote_node_ip($node);
        }
 
-       # NOTE: kvm VNC traffic is already TLS encrypted,
-       # so we select the fastest chipher here (or 'none'?)
-       my $remcmd = $remip ? ['/usr/bin/ssh', '-T', '-o', 'BatchMode=yes',
-                              '-c', 'blowfish-cbc', $remip] : [];
+       # NOTE: kvm VNC traffic is already TLS encrypted
+       my $remcmd = $remip ? ['/usr/bin/ssh', '-T', '-o', 'BatchMode=yes', $remip] : [];
 
        my $timeout = 10;
 
@@ -1631,6 +1647,62 @@ __PACKAGE__->register_method({
        return;
     }});
 
+__PACKAGE__->register_method({
+    name => 'vm_feature',
+    path => '{vmid}/feature',
+    method => 'GET',
+    proxyto => 'node',
+    protected => 1, 
+    description => "Check if feature for virtual machine is available.",
+    permissions => {
+       check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
+    },
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           node => get_standard_option('pve-node'),
+           vmid => get_standard_option('pve-vmid'),
+            feature => {
+                description => "Feature to check.",
+                type => 'string',
+                enum => [ 'snapshot', 'clone' ],
+            },
+            snapname => get_standard_option('pve-snapshot-name', {
+                optional => 1,
+            }),
+       },
+
+    },
+    returns => {
+        type => 'boolean'
+    },
+    code => sub {
+       my ($param) = @_;
+
+       my $node = extract_param($param, 'node');
+
+       my $vmid = extract_param($param, 'vmid');
+
+       my $snapname = extract_param($param, 'snapname');
+
+       my $feature = extract_param($param, 'feature');
+
+       my $running = PVE::QemuServer::check_running($vmid);
+
+       my $conf = PVE::QemuServer::load_config($vmid);
+
+       if($snapname){
+           my $snap = $conf->{snapshots}->{$snapname};
+            die "snapshot '$snapname' does not exist\n" if !defined($snap);
+           $conf = $snap;
+       }
+       my $storecfg = PVE::Storage::config();
+
+       my $hasfeature = PVE::QemuServer::has_feature($feature, $conf, $storecfg, $snapname, $running);
+       my $res = $hasfeature ? 1 : 0 ;
+       return $res;
+    }});
+
 __PACKAGE__->register_method({
     name => 'migrate_vm',
     path => '{vmid}/migrate',
@@ -2226,4 +2298,63 @@ __PACKAGE__->register_method({
        return $rpcenv->fork_worker('qmdelsnapshot', $vmid, $authuser, $realcmd);
     }});
 
+__PACKAGE__->register_method({
+    name => 'template',
+    path => '{vmid}/template',
+    method => 'POST',
+    protected => 1,
+    proxyto => 'node',
+    description => "Create a Template.",
+    permissions => {
+       check => ['perm', '/vms/{vmid}', [ 'VM.Template' ]],
+    },
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           node => get_standard_option('pve-node'),
+           vmid => get_standard_option('pve-vmid'),
+           disk => {
+               optional => 1,
+               type => 'string',
+               description => "If you want to convert only 1 disk to base image.",
+               enum => [PVE::QemuServer::disknames()],
+           },
+
+       },
+    },
+    returns => { type => 'null'},
+    code => sub {
+       my ($param) = @_;
+
+       my $rpcenv = PVE::RPCEnvironment::get();
+
+       my $authuser = $rpcenv->get_user();
+
+       my $node = extract_param($param, 'node');
+
+       my $vmid = extract_param($param, 'vmid');
+
+       my $disk = extract_param($param, 'disk');
+
+       my $updatefn =  sub {
+
+           my $conf = PVE::QemuServer::load_config($vmid);
+
+           PVE::QemuServer::check_lock($conf);
+
+           die "you can't convert a template to a template" if PVE::QemuServer::is_template($conf) && !$disk;
+           my $realcmd = sub {
+               PVE::QemuServer::template_create($vmid, $conf, $disk);
+           };
+           return $rpcenv->fork_worker('qmtemplate', $vmid, $authuser, $realcmd);
+
+           PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+       };
+
+       PVE::QemuServer::lock_config($vmid, $updatefn);
+       return undef;
+    }});
+
+
+
 1;