use Storable qw(dclone);
use PVE::Exception qw(raise raise_param_exc);
use PVE::Storage;
-use PVE::Tools qw(run_command lock_file file_read_firstline);
+use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline);
use PVE::JSONSchema qw(get_standard_option);
use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
use PVE::INotify;
typetext => '[[order=]\d+] [,up=\d+] [,down=\d+] ',
description => "Startup and shutdown behavior. Order is a non-negative number defining the general startup order. Shutdown in done with reverse ordering. Additionally you can set the 'up' or 'down' delay in seconds, which specifies a delay to wait before the next VM is started or stopped.",
},
+ template => {
+ optional => 1,
+ type => 'boolean',
+ description => "Enable/disable Template.",
+ default => 0,
+ },
args => {
optional => 1,
type => 'string',
description => "Emulated CPU type.",
type => 'string',
enum => [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
- default => 'qemu64',
+ default => 'kvm64',
},
parent => get_standard_option('pve-snapshot-name', {
optional => 1,
}
}
+ $opts .= ",cache=none" if !$drive->{cache} && !drive_is_cdrom($drive);
+
my $pathinfo = $path ? "file=$path," : '';
return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
my $model = lc($1);
- my $mac = uc($3) || PVE::Tools::random_ether_addr();
+ my $mac = defined($3) ? uc($3) : PVE::Tools::random_ether_addr();
$res->{model} = $model;
$res->{macaddr} = $mac;
} elsif ($kvp =~ m/^bridge=(\S+)$/) {
return $res;
}
+sub lock_config_shared {
+ my ($vmid, $timeout, $code, @param) = @_;
+
+ my $filename = config_file_lock($vmid);
+
+ my $res = lock_file_full($filename, $timeout, 1, $code, @param);
+
+ die $@ if $@;
+
+ return $res;
+}
+
sub lock_config {
my ($vmid, $code, @param) = @_;
die "can't unplug bootdisk" if $conf->{bootdisk} && $conf->{bootdisk} eq $deviceid;
if ($deviceid =~ m/^(virtio)(\d+)$/) {
- return undef if !qemu_drivedel($vmid, $deviceid);
qemu_devicedel($vmid, $deviceid);
return undef if !qemu_devicedelverify($vmid, $deviceid);
+ return undef if !qemu_drivedel($vmid, $deviceid);
}
if ($deviceid =~ m/^(lsi)(\d+)$/) {
}
if ($deviceid =~ m/^(net)(\d+)$/) {
- return undef if !qemu_netdevdel($vmid, $deviceid);
qemu_devicedel($vmid, $deviceid);
return undef if !qemu_devicedelverify($vmid, $deviceid);
+ return undef if !qemu_netdevdel($vmid, $deviceid);
}
return 1;
check_lock($conf);
- my $changes = update_disksize($vmid, $conf, $volid_hash);
+ my $vm_volids = {};
+ foreach my $volid (keys %$volid_hash) {
+ my $info = $volid_hash->{$volid};
+ $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
+ }
+
+ my $changes = update_disksize($vmid, $conf, $vm_volids);
update_config_nolock($vmid, $conf, 1) if $changes;
};
my $write_zeros = 1;
# fixme: what other storages types initialize volumes with zero?
- if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs') {
+ if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs' ||
+ $scfg->{type} eq 'sheepdog' || $scfg->{type} eq 'rbd') {
$write_zeros = 0;
}
sub template_create {
my ($vmid, $conf, $disk) = @_;
- my $running = check_running($vmid);
- die "you can't convert a vm to template if vm is running vm\n" if $running;
-
my $storecfg = PVE::Storage::config();
- my $i = 0;
foreach_drive($conf, sub {
my ($ds, $drive) = @_;
return if $disk && $ds ne $disk;
my $volid = $drive->{file};
- die "volume '$volid' does not support template/clone\n"
- if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
- });
-
- foreach_drive($conf, sub {
- my ($ds, $drive) = @_;
+ return if !PVE::Storage::volume_has_feature($storecfg, 'template', $volid);
- return if drive_is_cdrom($drive);
- return if $disk && $ds ne $disk;
-
- my $volid = $drive->{file};
my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
$drive->{file} = $voliddst;
$conf->{$ds} = PVE::QemuServer::print_drive($vmid, $drive);
PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
-
});
- if($conf->{snapshots}){
- delete $conf->{parent};
- delete $conf->{snapshots};
- PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
- #fixme : do we need to delete disks snapshots ?
- }
}
sub is_template {
my ($conf) = @_;
- my $baseimagecount = 0;
- my $totalvolumecount = 0;
- my $storecfg = PVE::Storage::config();
-
- foreach_drive($conf, sub {
- my ($ds, $drive) = @_;
- return if drive_is_cdrom($drive);
- $totalvolumecount++;
- my $volid = $drive->{file};
- if (PVE::Storage::volume_is_base($storecfg, $volid)){
- $baseimagecount++;
- }
-
- });
-
- return 0 if $baseimagecount == 0;
- return 1 if $baseimagecount == $totalvolumecount; #full template
- return 2 if $baseimagecount < $totalvolumecount; #semi-template
+ return 1 if defined $conf->{template} && $conf->{template} == 1;
}
1;