1 package PVE
::QemuServer
;
21 use Storable
qw(dclone);
22 use PVE
::Exception
qw(raise raise_param_exc);
24 use PVE
::Tools
qw(run_command lock_file file_read_firstline);
25 use PVE
::JSONSchema
qw(get_standard_option);
26 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
30 use PVE
::RPCEnvironment
;
31 use Time
::HiRes
qw(gettimeofday);
33 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
35 # Note about locking: we use flock on the config file protect
36 # against concurent actions.
37 # Aditionaly, we have a 'lock' setting in the config file. This
38 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
39 # allowed when such lock is set. But you can ignore this kind of
40 # lock with the --skiplock flag.
42 cfs_register_file
('/qemu-server/',
46 PVE
::JSONSchema
::register_standard_option
('skiplock', {
47 description
=> "Ignore locks - only root is allowed to use this option.",
52 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
53 description
=> "Some command save/restore state from this location.",
59 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
60 description
=> "The name of the snapshot.",
61 type
=> 'string', format
=> 'pve-configid',
65 #no warnings 'redefine';
67 unless(defined(&_VZSYSCALLS_H_
)) {
68 eval 'sub _VZSYSCALLS_H_ () {1;}' unless defined(&_VZSYSCALLS_H_
);
69 require 'sys/syscall.ph';
70 if(defined(&__x86_64__
)) {
71 eval 'sub __NR_fairsched_vcpus () {499;}' unless defined(&__NR_fairsched_vcpus
);
72 eval 'sub __NR_fairsched_mknod () {504;}' unless defined(&__NR_fairsched_mknod
);
73 eval 'sub __NR_fairsched_rmnod () {505;}' unless defined(&__NR_fairsched_rmnod
);
74 eval 'sub __NR_fairsched_chwt () {506;}' unless defined(&__NR_fairsched_chwt
);
75 eval 'sub __NR_fairsched_mvpr () {507;}' unless defined(&__NR_fairsched_mvpr
);
76 eval 'sub __NR_fairsched_rate () {508;}' unless defined(&__NR_fairsched_rate
);
77 eval 'sub __NR_setluid () {501;}' unless defined(&__NR_setluid
);
78 eval 'sub __NR_setublimit () {502;}' unless defined(&__NR_setublimit
);
80 elsif(defined( &__i386__
) ) {
81 eval 'sub __NR_fairsched_mknod () {500;}' unless defined(&__NR_fairsched_mknod
);
82 eval 'sub __NR_fairsched_rmnod () {501;}' unless defined(&__NR_fairsched_rmnod
);
83 eval 'sub __NR_fairsched_chwt () {502;}' unless defined(&__NR_fairsched_chwt
);
84 eval 'sub __NR_fairsched_mvpr () {503;}' unless defined(&__NR_fairsched_mvpr
);
85 eval 'sub __NR_fairsched_rate () {504;}' unless defined(&__NR_fairsched_rate
);
86 eval 'sub __NR_fairsched_vcpus () {505;}' unless defined(&__NR_fairsched_vcpus
);
87 eval 'sub __NR_setluid () {511;}' unless defined(&__NR_setluid
);
88 eval 'sub __NR_setublimit () {512;}' unless defined(&__NR_setublimit
);
90 die("no fairsched syscall for this arch");
92 require 'asm/ioctl.ph';
93 eval 'sub KVM_GET_API_VERSION () { &_IO(0xAE, 0x);}' unless defined(&KVM_GET_API_VERSION
);
97 my ($parent, $weight, $desired) = @_;
99 return syscall(&__NR_fairsched_mknod
, int($parent), int($weight), int($desired));
102 sub fairsched_rmnod
{
105 return syscall(&__NR_fairsched_rmnod
, int($id));
109 my ($pid, $newid) = @_;
111 return syscall(&__NR_fairsched_mvpr
, int($pid), int($newid));
114 sub fairsched_vcpus
{
115 my ($id, $vcpus) = @_;
117 return syscall(&__NR_fairsched_vcpus
, int($id), int($vcpus));
121 my ($id, $op, $rate) = @_;
123 return syscall(&__NR_fairsched_rate
, int($id), int($op), int($rate));
126 use constant FAIRSCHED_SET_RATE
=> 0;
127 use constant FAIRSCHED_DROP_RATE
=> 1;
128 use constant FAIRSCHED_GET_RATE
=> 2;
130 sub fairsched_cpulimit
{
131 my ($id, $limit) = @_;
133 my $cpulim1024 = int($limit * 1024 / 100);
134 my $op = $cpulim1024 ? FAIRSCHED_SET_RATE
: FAIRSCHED_DROP_RATE
;
136 return fairsched_rate
($id, $op, $cpulim1024);
139 my $nodename = PVE
::INotify
::nodename
();
141 mkdir "/etc/pve/nodes/$nodename";
142 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
145 my $var_run_tmpdir = "/var/run/qemu-server";
146 mkdir $var_run_tmpdir;
148 my $lock_dir = "/var/lock/qemu-server";
151 my $pcisysfs = "/sys/bus/pci";
157 description
=> "Specifies whether a VM will be started during system bootup.",
163 description
=> "Automatic restart after crash (currently ignored).",
169 description
=> "Allow hotplug for disk and network device",
175 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
181 description
=> "Lock/unlock the VM.",
182 enum
=> [qw(migrate backup snapshot rollback)],
187 description
=> "Limit of CPU usage in per cent. Note if the computer has 2 CPUs, it has total of 200% CPU time. Value '0' indicates no CPU limit.\n\nNOTE: This option is currently ignored.",
194 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
202 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
209 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
215 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
223 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
224 enum
=> PVE
::Tools
::kvmkeymaplist
(),
229 type
=> 'string', format
=> 'dns-name',
230 description
=> "Set a name for the VM. Only used on the configuration web interface.",
235 description
=> "scsi controller model",
236 enum
=> [qw(lsi virtio-scsi-pci megasas)],
242 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
247 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26)],
248 description
=> <<EODESC,
249 Used to enable special optimization/features for specific
252 other => unspecified OS
253 wxp => Microsoft Windows XP
254 w2k => Microsoft Windows 2000
255 w2k3 => Microsoft Windows 2003
256 w2k8 => Microsoft Windows 2008
257 wvista => Microsoft Windows Vista
258 win7 => Microsoft Windows 7
259 win8 => Microsoft Windows 8/2012
260 l24 => Linux 2.4 Kernel
261 l26 => Linux 2.6/3.X Kernel
263 other|l24|l26 ... no special behaviour
264 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
270 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
271 pattern
=> '[acdn]{1,4}',
276 type
=> 'string', format
=> 'pve-qm-bootdisk',
277 description
=> "Enable booting from specified disk.",
278 pattern
=> '(ide|sata|scsi|virtio)\d+',
283 description
=> "The number of CPUs. Please use option -sockets instead.",
290 description
=> "The number of CPU sockets.",
297 description
=> "The number of cores per socket.",
304 description
=> "Enable/disable ACPI.",
310 description
=> "Enable/disable Qemu GuestAgent.",
316 description
=> "Enable/disable KVM hardware virtualization.",
322 description
=> "Enable/disable time drift fix.",
328 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
333 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
338 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types",
339 enum
=> [qw(std cirrus vmware)],
343 type
=> 'string', format
=> 'pve-qm-watchdog',
344 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
345 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
350 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
351 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
352 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
357 type
=> 'string', format
=> 'pve-qm-startup',
358 typetext
=> '[[order=]\d+] [,up=\d+] [,down=\d+] ',
359 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.",
364 description
=> <<EODESCR,
365 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
367 args: -no-reboot -no-hpet
374 description
=> "Enable/disable the usb tablet device. 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 disabling this to save some context switches.",
379 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
383 migrate_downtime
=> {
386 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
392 type
=> 'string', format
=> 'pve-qm-drive',
393 typetext
=> 'volume',
394 description
=> "This is an alias for option -ide2",
398 description
=> "Emulated CPU type.",
400 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) ],
403 parent
=> get_standard_option
('pve-snapshot-name', {
405 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
409 description
=> "Timestamp for snapshots.",
415 type
=> 'string', format
=> 'pve-volume-id',
416 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
420 # what about other qemu settings ?
422 #machine => 'string',
435 ##soundhw => 'string',
437 while (my ($k, $v) = each %$confdesc) {
438 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
441 my $MAX_IDE_DISKS = 4;
442 my $MAX_SCSI_DISKS = 14;
443 my $MAX_VIRTIO_DISKS = 16;
444 my $MAX_SATA_DISKS = 6;
445 my $MAX_USB_DEVICES = 5;
447 my $MAX_UNUSED_DISKS = 8;
448 my $MAX_HOSTPCI_DEVICES = 2;
449 my $MAX_SERIAL_PORTS = 4;
450 my $MAX_PARALLEL_PORTS = 3;
452 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
453 'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
454 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
458 type
=> 'string', format
=> 'pve-qm-net',
459 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>][,tag=<vlanid>]",
460 description
=> <<EODESCR,
461 Specify network devices.
463 MODEL is one of: $nic_model_list_txt
465 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
466 automatically generated if not specified.
468 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
470 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
472 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
478 The DHCP server assign addresses to the guest starting from 10.0.2.15.
482 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
484 for (my $i = 0; $i < $MAX_NETS; $i++) {
485 $confdesc->{"net$i"} = $netdesc;
492 type
=> 'string', format
=> 'pve-qm-drive',
493 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
494 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
496 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
500 type
=> 'string', format
=> 'pve-qm-drive',
501 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
502 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
508 type
=> 'string', format
=> 'pve-qm-drive',
509 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
510 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
512 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
516 type
=> 'string', format
=> 'pve-qm-drive',
517 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
518 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
520 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
524 type
=> 'string', format
=> 'pve-qm-usb-device',
525 typetext
=> 'host=HOSTUSBDEVICE',
526 description
=> <<EODESCR,
527 Configure an USB device (n is 0 to 4). This can be used to
528 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
530 'bus-port(.port)*' (decimal numbers) or
531 'vendor_id:product_id' (hexadeciaml numbers)
533 You can use the 'lsusb -t' command to list existing usb devices.
535 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
539 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
543 type
=> 'string', format
=> 'pve-qm-hostpci',
544 typetext
=> "HOSTPCIDEVICE",
545 description
=> <<EODESCR,
546 Map host pci devices. HOSTPCIDEVICE syntax is:
548 'bus:dev.func' (hexadecimal numbers)
550 You can us the 'lspci' command to list existing pci devices.
552 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
554 Experimental: user reported problems with this option.
557 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
562 pattern
=> '/dev/ttyS\d+',
563 description
=> <<EODESCR,
564 Map host serial devices (n is 0 to 3).
566 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
568 Experimental: user reported problems with this option.
575 pattern
=> '/dev/parport\d+',
576 description
=> <<EODESCR,
577 Map host parallel devices (n is 0 to 2).
579 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
581 Experimental: user reported problems with this option.
585 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
586 $confdesc->{"parallel$i"} = $paralleldesc;
589 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
590 $confdesc->{"serial$i"} = $serialdesc;
593 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
594 $confdesc->{"hostpci$i"} = $hostpcidesc;
597 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
598 $drivename_hash->{"ide$i"} = 1;
599 $confdesc->{"ide$i"} = $idedesc;
602 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
603 $drivename_hash->{"sata$i"} = 1;
604 $confdesc->{"sata$i"} = $satadesc;
607 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
608 $drivename_hash->{"scsi$i"} = 1;
609 $confdesc->{"scsi$i"} = $scsidesc ;
612 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
613 $drivename_hash->{"virtio$i"} = 1;
614 $confdesc->{"virtio$i"} = $virtiodesc;
617 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
618 $confdesc->{"usb$i"} = $usbdesc;
623 type
=> 'string', format
=> 'pve-volume-id',
624 description
=> "Reference to unused volumes.",
627 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
628 $confdesc->{"unused$i"} = $unuseddesc;
631 my $kvm_api_version = 0;
635 return $kvm_api_version if $kvm_api_version;
637 my $fh = IO
::File-
>new("</dev/kvm") ||
640 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
641 $kvm_api_version = $v;
646 return $kvm_api_version;
649 my $kvm_user_version;
651 sub kvm_user_version
{
653 return $kvm_user_version if $kvm_user_version;
655 $kvm_user_version = 'unknown';
657 my $tmp = `kvm -help 2>/dev/null`;
659 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
660 $kvm_user_version = $2;
663 return $kvm_user_version;
667 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
670 # order is important - used to autoselect boot disk
671 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
672 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
673 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
674 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
677 sub valid_drivename
{
680 return defined($drivename_hash->{$dev});
685 return defined($confdesc->{$key});
689 return $nic_model_list;
692 sub os_list_description
{
697 w2k
=> 'Windows 2000',
698 w2k3
=>, 'Windows 2003',
699 w2k8
=> 'Windows 2008',
700 wvista
=> 'Windows Vista',
702 win8
=> 'Windows 8/2012',
712 return $cdrom_path if $cdrom_path;
714 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
715 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
716 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
720 my ($storecfg, $vmid, $cdrom) = @_;
722 if ($cdrom eq 'cdrom') {
723 return get_cdrom_path
();
724 } elsif ($cdrom eq 'none') {
726 } elsif ($cdrom =~ m
|^/|) {
729 return PVE
::Storage
::path
($storecfg, $cdrom);
733 # try to convert old style file names to volume IDs
734 sub filename_to_volume_id
{
735 my ($vmid, $file, $media) = @_;
737 if (!($file eq 'none' || $file eq 'cdrom' ||
738 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
740 return undef if $file =~ m
|/|;
742 if ($media && $media eq 'cdrom') {
743 $file = "local:iso/$file";
745 $file = "local:$vmid/$file";
752 sub verify_media_type
{
753 my ($opt, $vtype, $media) = @_;
758 if ($media eq 'disk') {
760 } elsif ($media eq 'cdrom') {
763 die "internal error";
766 return if ($vtype eq $etype);
768 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
771 sub cleanup_drive_path
{
772 my ($opt, $storecfg, $drive) = @_;
774 # try to convert filesystem paths to volume IDs
776 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
777 ($drive->{file
} !~ m
|^/dev/.+|) &&
778 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
779 ($drive->{file
} !~ m/^\d+$/)) {
780 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
781 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
782 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
783 verify_media_type
($opt, $vtype, $drive->{media
});
784 $drive->{file
} = $volid;
787 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
790 sub create_conf_nolock
{
791 my ($vmid, $settings) = @_;
793 my $filename = config_file
($vmid);
795 die "configuration file '$filename' already exists\n" if -f
$filename;
797 my $defaults = load_defaults
();
799 $settings->{name
} = "vm$vmid" if !$settings->{name
};
800 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
803 foreach my $opt (keys %$settings) {
804 next if !$confdesc->{$opt};
806 my $value = $settings->{$opt};
809 $data .= "$opt: $value\n";
812 PVE
::Tools
::file_set_contents
($filename, $data);
815 my $parse_size = sub {
818 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
819 my ($size, $unit) = ($1, $3);
822 $size = $size * 1024;
823 } elsif ($unit eq 'M') {
824 $size = $size * 1024 * 1024;
825 } elsif ($unit eq 'G') {
826 $size = $size * 1024 * 1024 * 1024;
832 my $format_size = sub {
837 my $kb = int($size/1024);
838 return $size if $kb*1024 != $size;
840 my $mb = int($kb/1024);
841 return "${kb}K" if $mb*1024 != $kb;
843 my $gb = int($mb/1024);
844 return "${mb}M" if $gb*1024 != $mb;
849 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
850 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
851 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
852 # [,aio=native|threads]
855 my ($key, $data) = @_;
859 # $key may be undefined - used to verify JSON parameters
860 if (!defined($key)) {
861 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
863 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
864 $res->{interface
} = $1;
870 foreach my $p (split (/,/, $data)) {
871 next if $p =~ m/^\s*$/;
873 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|bps_rd|mbps_rd|bps_wr|mbps_wr|iops|iops_rd|iops_wr|size)=(.+)$/) {
874 my ($k, $v) = ($1, $2);
876 $k = 'file' if $k eq 'volume';
878 return undef if defined $res->{$k};
880 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
881 return undef if !$v || $v !~ m/^\d+/;
883 $v = sprintf("%.3f", $v / (1024*1024));
887 if (!$res->{file
} && $p !~ m/=/) {
895 return undef if !$res->{file
};
897 return undef if $res->{cache
} &&
898 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
899 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
900 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
901 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
902 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
903 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
904 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
905 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qcow2|vmdk|cloop)$/;
906 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
907 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
908 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
909 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
912 return undef if $res->{mbps_rd
} && $res->{mbps
};
913 return undef if $res->{mbps_wr
} && $res->{mbps
};
915 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
916 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
917 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
919 return undef if $res->{iops_rd
} && $res->{iops
};
920 return undef if $res->{iops_wr
} && $res->{iops
};
921 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
922 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
923 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
927 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
930 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
931 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
932 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
933 return undef if $res->{interface
} eq 'virtio';
936 # rerror does not work with scsi drives
937 if ($res->{rerror
}) {
938 return undef if $res->{interface
} eq 'scsi';
944 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio iops iops_rd iops_wr);
947 my ($vmid, $drive) = @_;
950 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'backup') {
951 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
954 if ($drive->{size
}) {
955 $opts .= ",size=" . &$format_size($drive->{size
});
958 return "$drive->{file}$opts";
962 my($fh, $noerr) = @_;
965 my $SG_GET_VERSION_NUM = 0x2282;
967 my $versionbuf = "\x00" x
8;
968 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
970 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
973 my $version = unpack("I", $versionbuf);
974 if ($version < 30000) {
975 die "scsi generic interface too old\n" if !$noerr;
979 my $buf = "\x00" x
36;
980 my $sensebuf = "\x00" x
8;
981 my $cmd = pack("C x3 C x11", 0x12, 36);
983 # see /usr/include/scsi/sg.h
984 my $sg_io_hdr_t = "i i C C s I P P P I I i P C C C C S S i I I";
986 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
987 length($sensebuf), 0, length($buf), $buf,
988 $cmd, $sensebuf, 6000);
990 $ret = ioctl($fh, $SG_IO, $packet);
992 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
996 my @res = unpack($sg_io_hdr_t, $packet);
997 if ($res[17] || $res[18]) {
998 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1003 ($res->{device
}, $res->{removable
}, $res->{venodor
},
1004 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1012 my $fh = IO
::File-
>new("+<$path") || return undef;
1013 my $res = scsi_inquiry
($fh, 1);
1019 sub print_drivedevice_full
{
1020 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1025 if ($drive->{interface
} eq 'virtio') {
1026 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1027 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1028 } elsif ($drive->{interface
} eq 'scsi') {
1029 $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
1030 my $controller = int($drive->{index} / $maxdev);
1031 my $unit = $drive->{index} % $maxdev;
1032 my $devicetype = 'hd';
1034 if (drive_is_cdrom
($drive)) {
1037 if ($drive->{file
} =~ m
|^/|) {
1038 $path = $drive->{file
};
1040 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1043 if($path =~ m/^iscsi\:\/\
//){
1044 $devicetype = 'generic';
1047 $devicetype = 'block' if path_is_scsi
($path);
1051 if (!$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi'){
1052 $device = "scsi-$devicetype,bus=scsihw$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}" if !$conf->{scsihw
} || $conf->{scsihw
} eq 'lsi';
1054 $device = "scsi-$devicetype,bus=scsihw$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1057 } elsif ($drive->{interface
} eq 'ide'){
1059 my $controller = int($drive->{index} / $maxdev);
1060 my $unit = $drive->{index} % $maxdev;
1061 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1063 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1064 } elsif ($drive->{interface
} eq 'sata'){
1065 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1066 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1067 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1068 } elsif ($drive->{interface
} eq 'usb') {
1070 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1072 die "unsupported interface type";
1075 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1080 sub print_drive_full
{
1081 my ($storecfg, $vmid, $drive) = @_;
1084 foreach my $o (@qemu_drive_options) {
1085 next if $o eq 'bootindex';
1086 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1089 foreach my $o (qw(bps bps_rd bps_wr)) {
1090 my $v = $drive->{"m$o"};
1091 $opts .= ",$o=" . int($v*1024*1024) if $v;
1094 # use linux-aio by default (qemu default is threads)
1095 $opts .= ",aio=native" if !$drive->{aio
};
1098 my $volid = $drive->{file
};
1099 if (drive_is_cdrom
($drive)) {
1100 $path = get_iso_path
($storecfg, $vmid, $volid);
1102 if ($volid =~ m
|^/|) {
1105 $path = PVE
::Storage
::path
($storecfg, $volid);
1109 $opts .= ",cache=none" if !$drive->{cache
} && !drive_is_cdrom
($drive);
1111 my $pathinfo = $path ?
"file=$path," : '';
1113 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1116 sub print_netdevice_full
{
1117 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1119 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1121 my $device = $net->{model
};
1122 if ($net->{model
} eq 'virtio') {
1123 $device = 'virtio-net-pci';
1126 # qemu > 0.15 always try to boot from network - we disable that by
1127 # not loading the pxe rom file
1128 my $extra = ($bootorder !~ m/n/) ?
"romfile=," : '';
1129 my $pciaddr = print_pci_addr
("$netid", $bridges);
1130 my $tmpstr = "$device,${extra}mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1131 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1135 sub print_netdev_full
{
1136 my ($vmid, $conf, $net, $netid) = @_;
1139 if ($netid =~ m/^net(\d+)$/) {
1143 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1145 my $ifname = "tap${vmid}i$i";
1147 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1148 die "interface name '$ifname' is too long (max 15 character)\n"
1149 if length($ifname) >= 16;
1151 my $vhostparam = '';
1152 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1154 my $vmname = $conf->{name
} || "vm$vmid";
1156 if ($net->{bridge
}) {
1157 return "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge$vhostparam";
1159 return "type=user,id=$netid,hostname=$vmname";
1163 sub drive_is_cdrom
{
1166 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1173 return undef if !$value;
1177 if ($value =~ m/^[a-f0-9]{2}:[a-f0-9]{2}\.[a-f0-9]$/) {
1178 $res->{pciid
} = $value;
1186 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1192 foreach my $kvp (split(/,/, $data)) {
1194 if ($kvp =~ m/^(ne2k_pci|e1000|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1196 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1197 $res->{model
} = $model;
1198 $res->{macaddr
} = $mac;
1199 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1200 $res->{bridge
} = $1;
1201 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1203 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1211 return undef if !$res->{model
};
1219 my $res = "$net->{model}";
1220 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1221 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1222 $res .= ",rate=$net->{rate}" if $net->{rate
};
1223 $res .= ",tag=$net->{tag}" if $net->{tag
};
1228 sub add_random_macs
{
1229 my ($settings) = @_;
1231 foreach my $opt (keys %$settings) {
1232 next if $opt !~ m/^net(\d+)$/;
1233 my $net = parse_net
($settings->{$opt});
1235 $settings->{$opt} = print_net
($net);
1239 sub add_unused_volume
{
1240 my ($config, $volid) = @_;
1243 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1244 my $test = "unused$ind";
1245 if (my $vid = $config->{$test}) {
1246 return if $vid eq $volid; # do not add duplicates
1252 die "To many unused volume - please delete them first.\n" if !$key;
1254 $config->{$key} = $volid;
1259 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1260 sub verify_bootdisk
{
1261 my ($value, $noerr) = @_;
1263 return $value if valid_drivename
($value);
1265 return undef if $noerr;
1267 die "invalid boot disk '$value'\n";
1270 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1272 my ($value, $noerr) = @_;
1274 return $value if parse_net
($value);
1276 return undef if $noerr;
1278 die "unable to parse network options\n";
1281 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1283 my ($value, $noerr) = @_;
1285 return $value if parse_drive
(undef, $value);
1287 return undef if $noerr;
1289 die "unable to parse drive options\n";
1292 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1293 sub verify_hostpci
{
1294 my ($value, $noerr) = @_;
1296 return $value if parse_hostpci
($value);
1298 return undef if $noerr;
1300 die "unable to parse pci id\n";
1303 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1304 sub verify_watchdog
{
1305 my ($value, $noerr) = @_;
1307 return $value if parse_watchdog
($value);
1309 return undef if $noerr;
1311 die "unable to parse watchdog options\n";
1314 sub parse_watchdog
{
1317 return undef if !$value;
1321 foreach my $p (split(/,/, $value)) {
1322 next if $p =~ m/^\s*$/;
1324 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1326 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1327 $res->{action
} = $2;
1336 PVE
::JSONSchema
::register_format
('pve-qm-startup', \
&verify_startup
);
1337 sub verify_startup
{
1338 my ($value, $noerr) = @_;
1340 return $value if parse_startup
($value);
1342 return undef if $noerr;
1344 die "unable to parse startup options\n";
1350 return undef if !$value;
1354 foreach my $p (split(/,/, $value)) {
1355 next if $p =~ m/^\s*$/;
1357 if ($p =~ m/^(order=)?(\d+)$/) {
1359 } elsif ($p =~ m/^up=(\d+)$/) {
1361 } elsif ($p =~ m/^down=(\d+)$/) {
1371 sub parse_usb_device
{
1374 return undef if !$value;
1376 my @dl = split(/,/, $value);
1380 foreach my $v (@dl) {
1381 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1383 $res->{vendorid
} = $2;
1384 $res->{productid
} = $4;
1385 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1387 $res->{hostbus
} = $1;
1388 $res->{hostport
} = $2;
1393 return undef if !$found;
1398 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1399 sub verify_usb_device
{
1400 my ($value, $noerr) = @_;
1402 return $value if parse_usb_device
($value);
1404 return undef if $noerr;
1406 die "unable to parse usb device\n";
1409 # add JSON properties for create and set function
1410 sub json_config_properties
{
1413 foreach my $opt (keys %$confdesc) {
1414 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1415 $prop->{$opt} = $confdesc->{$opt};
1422 my ($key, $value) = @_;
1424 die "unknown setting '$key'\n" if !$confdesc->{$key};
1426 my $type = $confdesc->{$key}->{type
};
1428 if (!defined($value)) {
1429 die "got undefined value\n";
1432 if ($value =~ m/[\n\r]/) {
1433 die "property contains a line feed\n";
1436 if ($type eq 'boolean') {
1437 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1438 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1439 die "type check ('boolean') failed - got '$value'\n";
1440 } elsif ($type eq 'integer') {
1441 return int($1) if $value =~ m/^(\d+)$/;
1442 die "type check ('integer') failed - got '$value'\n";
1443 } elsif ($type eq 'number') {
1444 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1445 die "type check ('number') failed - got '$value'\n";
1446 } elsif ($type eq 'string') {
1447 if (my $fmt = $confdesc->{$key}->{format
}) {
1448 if ($fmt eq 'pve-qm-drive') {
1449 # special case - we need to pass $key to parse_drive()
1450 my $drive = parse_drive
($key, $value);
1451 return $value if $drive;
1452 die "unable to parse drive options\n";
1454 PVE
::JSONSchema
::check_format
($fmt, $value);
1457 $value =~ s/^\"(.*)\"$/$1/;
1460 die "internal error"
1464 sub lock_config_full
{
1465 my ($vmid, $timeout, $code, @param) = @_;
1467 my $filename = config_file_lock
($vmid);
1469 my $res = lock_file
($filename, $timeout, $code, @param);
1477 my ($vmid, $code, @param) = @_;
1479 return lock_config_full
($vmid, 10, $code, @param);
1482 sub cfs_config_path
{
1483 my ($vmid, $node) = @_;
1485 $node = $nodename if !$node;
1486 return "nodes/$node/qemu-server/$vmid.conf";
1489 sub check_iommu_support
{
1490 #fixme : need to check IOMMU support
1491 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1499 my ($vmid, $node) = @_;
1501 my $cfspath = cfs_config_path
($vmid, $node);
1502 return "/etc/pve/$cfspath";
1505 sub config_file_lock
{
1508 return "$lock_dir/lock-$vmid.conf";
1514 my $conf = config_file
($vmid);
1515 utime undef, undef, $conf;
1519 my ($storecfg, $vmid, $keep_empty_config) = @_;
1521 my $conffile = config_file
($vmid);
1523 my $conf = load_config
($vmid);
1527 # only remove disks owned by this VM
1528 foreach_drive
($conf, sub {
1529 my ($ds, $drive) = @_;
1531 return if drive_is_cdrom
($drive);
1533 my $volid = $drive->{file
};
1535 return if !$volid || $volid =~ m
|^/|;
1537 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1538 return if !$path || !$owner || ($owner != $vmid);
1540 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1543 if ($keep_empty_config) {
1544 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1549 # also remove unused disk
1551 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1554 PVE
::Storage
::foreach_volid
($dl, sub {
1555 my ($volid, $sid, $volname, $d) = @_;
1556 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1566 my ($vmid, $node) = @_;
1568 my $cfspath = cfs_config_path
($vmid, $node);
1570 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1572 die "no such VM ('$vmid')\n" if !defined($conf);
1577 sub parse_vm_config
{
1578 my ($filename, $raw) = @_;
1580 return undef if !defined($raw);
1583 digest
=> Digest
::SHA
::sha1_hex
($raw),
1587 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1588 || die "got strange filename '$filename'";
1595 my @lines = split(/\n/, $raw);
1596 foreach my $line (@lines) {
1597 next if $line =~ m/^\s*$/;
1599 if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1601 $conf->{description
} = $descr if $descr;
1603 $conf = $res->{snapshots
}->{$snapname} = {};
1607 if ($line =~ m/^\#(.*)\s*$/) {
1608 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1612 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1613 $descr .= PVE
::Tools
::decode_text
($2);
1614 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1615 $conf->{snapstate
} = $1;
1616 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1619 $conf->{$key} = $value;
1620 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1623 eval { $value = check_type
($key, $value); };
1625 warn "vm $vmid - unable to parse value of '$key' - $@";
1627 my $fmt = $confdesc->{$key}->{format
};
1628 if ($fmt && $fmt eq 'pve-qm-drive') {
1629 my $v = parse_drive
($key, $value);
1630 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1631 $v->{file
} = $volid;
1632 $value = print_drive
($vmid, $v);
1634 warn "vm $vmid - unable to parse value of '$key'\n";
1639 if ($key eq 'cdrom') {
1640 $conf->{ide2
} = $value;
1642 $conf->{$key} = $value;
1648 $conf->{description
} = $descr if $descr;
1650 delete $res->{snapstate
}; # just to be sure
1655 sub write_vm_config
{
1656 my ($filename, $conf) = @_;
1658 delete $conf->{snapstate
}; # just to be sure
1660 if ($conf->{cdrom
}) {
1661 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1662 $conf->{ide2
} = $conf->{cdrom
};
1663 delete $conf->{cdrom
};
1666 # we do not use 'smp' any longer
1667 if ($conf->{sockets
}) {
1668 delete $conf->{smp
};
1669 } elsif ($conf->{smp
}) {
1670 $conf->{sockets
} = $conf->{smp
};
1671 delete $conf->{cores
};
1672 delete $conf->{smp
};
1675 my $used_volids = {};
1677 my $cleanup_config = sub {
1680 foreach my $key (keys %$cref) {
1681 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1682 $key eq 'snapstate';
1683 my $value = $cref->{$key};
1684 eval { $value = check_type
($key, $value); };
1685 die "unable to parse value of '$key' - $@" if $@;
1687 $cref->{$key} = $value;
1689 if (valid_drivename
($key)) {
1690 my $drive = parse_drive
($key, $value);
1691 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
1696 &$cleanup_config($conf);
1697 foreach my $snapname (keys %{$conf->{snapshots
}}) {
1698 &$cleanup_config($conf->{snapshots
}->{$snapname});
1701 # remove 'unusedX' settings if we re-add a volume
1702 foreach my $key (keys %$conf) {
1703 my $value = $conf->{$key};
1704 if ($key =~ m/^unused/ && $used_volids->{$value}) {
1705 delete $conf->{$key};
1709 my $generate_raw_config = sub {
1714 # add description as comment to top of file
1715 my $descr = $conf->{description
} || '';
1716 foreach my $cl (split(/\n/, $descr)) {
1717 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
1720 foreach my $key (sort keys %$conf) {
1721 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots';
1722 $raw .= "$key: $conf->{$key}\n";
1727 my $raw = &$generate_raw_config($conf);
1728 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
1729 $raw .= "\n[$snapname]\n";
1730 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
1736 sub update_config_nolock
{
1737 my ($vmid, $conf, $skiplock) = @_;
1739 check_lock
($conf) if !$skiplock;
1741 my $cfspath = cfs_config_path
($vmid);
1743 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
1747 my ($vmid, $conf, $skiplock) = @_;
1749 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
1756 # we use static defaults from our JSON schema configuration
1757 foreach my $key (keys %$confdesc) {
1758 if (defined(my $default = $confdesc->{$key}->{default})) {
1759 $res->{$key} = $default;
1763 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1764 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
1770 my $vmlist = PVE
::Cluster
::get_vmlist
();
1772 return $res if !$vmlist || !$vmlist->{ids
};
1773 my $ids = $vmlist->{ids
};
1775 foreach my $vmid (keys %$ids) {
1776 my $d = $ids->{$vmid};
1777 next if !$d->{node
} || $d->{node
} ne $nodename;
1778 next if !$d->{type
} || $d->{type
} ne 'qemu';
1779 $res->{$vmid}->{exists} = 1;
1784 # test if VM uses local resources (to prevent migration)
1785 sub check_local_resources
{
1786 my ($conf, $noerr) = @_;
1790 $loc_res = 1 if $conf->{hostusb
}; # old syntax
1791 $loc_res = 1 if $conf->{hostpci
}; # old syntax
1793 foreach my $k (keys %$conf) {
1794 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
1797 die "VM uses local resources\n" if $loc_res && !$noerr;
1802 # check is used storages are available on all nodes (use by migrate)
1803 sub check_storage_availability
{
1804 my ($storecfg, $conf, $node) = @_;
1806 foreach_drive
($conf, sub {
1807 my ($ds, $drive) = @_;
1809 my $volid = $drive->{file
};
1812 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1815 # check if storage is available on both nodes
1816 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
1817 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
1824 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
1828 my ($pidfile, $pid) = @_;
1830 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
1834 return undef if !$line;
1835 my @param = split(/\0/, $line);
1837 my $cmd = $param[0];
1838 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
1840 for (my $i = 0; $i < scalar (@param); $i++) {
1843 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
1844 my $p = $param[$i+1];
1845 return 1 if $p && ($p eq $pidfile);
1854 my ($vmid, $nocheck, $node) = @_;
1856 my $filename = config_file
($vmid, $node);
1858 die "unable to find configuration file for VM $vmid - no such machine\n"
1859 if !$nocheck && ! -f
$filename;
1861 my $pidfile = pidfile_name
($vmid);
1863 if (my $fd = IO
::File-
>new("<$pidfile")) {
1868 my $mtime = $st->mtime;
1869 if ($mtime > time()) {
1870 warn "file '$filename' modified in future\n";
1873 if ($line =~ m/^(\d+)$/) {
1875 if (check_cmdline
($pidfile, $pid)) {
1876 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
1888 my $vzlist = config_list
();
1890 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
1892 while (defined(my $de = $fd->read)) {
1893 next if $de !~ m/^(\d+)\.pid$/;
1895 next if !defined($vzlist->{$vmid});
1896 if (my $pid = check_running
($vmid)) {
1897 $vzlist->{$vmid}->{pid
} = $pid;
1905 my ($storecfg, $conf) = @_;
1907 my $bootdisk = $conf->{bootdisk
};
1908 return undef if !$bootdisk;
1909 return undef if !valid_drivename
($bootdisk);
1911 return undef if !$conf->{$bootdisk};
1913 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
1914 return undef if !defined($drive);
1916 return undef if drive_is_cdrom
($drive);
1918 my $volid = $drive->{file
};
1919 return undef if !$volid;
1921 return $drive->{size
};
1924 my $last_proc_pid_stat;
1926 # get VM status information
1927 # This must be fast and should not block ($full == false)
1928 # We only query KVM using QMP if $full == true (this can be slow)
1930 my ($opt_vmid, $full) = @_;
1934 my $storecfg = PVE
::Storage
::config
();
1936 my $list = vzlist
();
1937 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
1939 my $cpucount = $cpuinfo->{cpus
} || 1;
1941 foreach my $vmid (keys %$list) {
1942 next if $opt_vmid && ($vmid ne $opt_vmid);
1944 my $cfspath = cfs_config_path
($vmid);
1945 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
1948 $d->{pid
} = $list->{$vmid}->{pid
};
1950 # fixme: better status?
1951 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
1953 my $size = disksize
($storecfg, $conf);
1954 if (defined($size)) {
1955 $d->{disk
} = 0; # no info available
1956 $d->{maxdisk
} = $size;
1962 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
1963 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
1965 $d->{name
} = $conf->{name
} || "VM $vmid";
1966 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
1968 if ($conf->{balloon
}) {
1969 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
1970 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
1981 $d->{diskwrite
} = 0;
1983 $d->{template
} = is_template
($conf);
1988 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
1989 foreach my $dev (keys %$netdev) {
1990 next if $dev !~ m/^tap([1-9]\d*)i/;
1992 my $d = $res->{$vmid};
1995 $d->{netout
} += $netdev->{$dev}->{receive
};
1996 $d->{netin
} += $netdev->{$dev}->{transmit
};
1999 my $ctime = gettimeofday
;
2001 foreach my $vmid (keys %$list) {
2003 my $d = $res->{$vmid};
2004 my $pid = $d->{pid
};
2007 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2008 next if !$pstat; # not running
2010 my $used = $pstat->{utime} + $pstat->{stime
};
2012 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2014 if ($pstat->{vsize
}) {
2015 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2018 my $old = $last_proc_pid_stat->{$pid};
2020 $last_proc_pid_stat->{$pid} = {
2028 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2030 if ($dtime > 1000) {
2031 my $dutime = $used - $old->{used
};
2033 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2034 $last_proc_pid_stat->{$pid} = {
2040 $d->{cpu
} = $old->{cpu
};
2044 return $res if !$full;
2046 my $qmpclient = PVE
::QMPClient-
>new();
2048 my $ballooncb = sub {
2049 my ($vmid, $resp) = @_;
2051 my $info = $resp->{'return'};
2052 return if !$info->{max_mem
};
2054 my $d = $res->{$vmid};
2056 # use memory assigned to VM
2057 $d->{maxmem
} = $info->{max_mem
};
2058 $d->{balloon
} = $info->{actual
};
2060 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2061 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2062 $d->{freemem
} = $info->{free_mem
};
2067 my $blockstatscb = sub {
2068 my ($vmid, $resp) = @_;
2069 my $data = $resp->{'return'} || [];
2070 my $totalrdbytes = 0;
2071 my $totalwrbytes = 0;
2072 for my $blockstat (@$data) {
2073 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2074 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2076 $res->{$vmid}->{diskread
} = $totalrdbytes;
2077 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2080 my $statuscb = sub {
2081 my ($vmid, $resp) = @_;
2083 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2084 # this fails if ballon driver is not loaded, so this must be
2085 # the last commnand (following command are aborted if this fails).
2086 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2088 my $status = 'unknown';
2089 if (!defined($status = $resp->{'return'}->{status
})) {
2090 warn "unable to get VM status\n";
2094 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2097 foreach my $vmid (keys %$list) {
2098 next if $opt_vmid && ($vmid ne $opt_vmid);
2099 next if !$res->{$vmid}->{pid
}; # not running
2100 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2103 $qmpclient->queue_execute();
2105 foreach my $vmid (keys %$list) {
2106 next if $opt_vmid && ($vmid ne $opt_vmid);
2107 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2114 my ($conf, $func) = @_;
2116 foreach my $ds (keys %$conf) {
2117 next if !valid_drivename
($ds);
2119 my $drive = parse_drive
($ds, $conf->{$ds});
2122 &$func($ds, $drive);
2127 my ($conf, $func) = @_;
2131 my $test_volid = sub {
2132 my ($volid, $is_cdrom) = @_;
2136 $volhash->{$volid} = $is_cdrom || 0;
2139 foreach_drive
($conf, sub {
2140 my ($ds, $drive) = @_;
2141 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2144 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2145 my $snap = $conf->{snapshots
}->{$snapname};
2146 &$test_volid($snap->{vmstate
}, 0);
2147 foreach_drive
($snap, sub {
2148 my ($ds, $drive) = @_;
2149 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2153 foreach my $volid (keys %$volhash) {
2154 &$func($volid, $volhash->{$volid});
2158 sub config_to_command
{
2159 my ($storecfg, $vmid, $conf, $defaults) = @_;
2162 my $globalFlags = [];
2163 my $machineFlags = [];
2168 my $kvmver = kvm_user_version
();
2169 my $vernum = 0; # unknown
2170 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2171 $vernum = $1*1000000+$2*1000;
2172 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2173 $vernum = $1*1000000+$2*1000+$3;
2176 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2178 my $have_ovz = -f
'/proc/vz/vestat';
2180 push @$cmd, '/usr/bin/kvm';
2182 push @$cmd, '-id', $vmid;
2186 my $qmpsocket = qmp_socket
($vmid);
2187 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2188 push @$cmd, '-mon', "chardev=qmp,mode=control";
2190 my $socket = vnc_socket
($vmid);
2191 push @$cmd, '-vnc', "unix:$socket,x509,password";
2193 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2195 push @$cmd, '-daemonize';
2197 $pciaddr = print_pci_addr
("piix3", $bridges);
2198 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2201 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2202 next if !$conf->{"usb$i"};
2205 # include usb device config
2206 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2208 # enable absolute mouse coordinates (needed by vnc)
2209 my $tablet = defined($conf->{tablet
}) ?
$conf->{tablet
} : $defaults->{tablet
};
2210 push @$devices, '-device', 'usb-tablet,id=tablet,bus=uhci.0,port=1' if $tablet;
2213 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2214 my $d = parse_hostpci
($conf->{"hostpci$i"});
2216 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2217 push @$devices, '-device', "pci-assign,host=$d->{pciid},id=hostpci$i$pciaddr";
2221 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2222 my $d = parse_usb_device
($conf->{"usb$i"});
2224 if ($d->{vendorid
} && $d->{productid
}) {
2225 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2226 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2227 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2232 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2233 if (my $path = $conf->{"serial$i"}) {
2234 die "no such serial device\n" if ! -c
$path;
2235 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2236 push @$devices, '-device', "isa-serial,chardev=serial$i";
2241 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2242 if (my $path = $conf->{"parallel$i"}) {
2243 die "no such parallel device\n" if ! -c
$path;
2244 push @$devices, '-chardev', "parport,id=parallel$i,path=$path";
2245 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2249 my $vmname = $conf->{name
} || "vm$vmid";
2251 push @$cmd, '-name', $vmname;
2254 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2255 $sockets = $conf->{sockets
} if $conf->{sockets
};
2257 my $cores = $conf->{cores
} || 1;
2259 push @$cmd, '-smp', "sockets=$sockets,cores=$cores";
2261 push @$cmd, '-cpu', $conf->{cpu
} if $conf->{cpu
};
2263 push @$cmd, '-nodefaults';
2265 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2267 my $bootindex_hash = {};
2269 foreach my $o (split(//, $bootorder)) {
2270 $bootindex_hash->{$o} = $i*100;
2274 push @$cmd, '-boot', "menu=on";
2276 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2278 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2280 my $vga = $conf->{vga
};
2282 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' || $conf->{ostype
} eq 'win7' || $conf->{ostype
} eq 'w2k8')) {
2289 push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
2292 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2294 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2295 my $useLocaltime = $conf->{localtime};
2297 if (my $ost = $conf->{ostype
}) {
2298 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26
2300 if ($ost =~ m/^w/) { # windows
2301 $useLocaltime = 1 if !defined($conf->{localtime});
2303 # use time drift fix when acpi is enabled
2304 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2305 $tdf = 1 if !defined($conf->{tdf
});
2309 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2311 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2312 push @$cmd, '-no-hpet';
2316 push @$rtcFlags, 'driftfix=slew' if $tdf;
2319 push @$machineFlags, 'accel=tcg';
2321 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2324 if ($conf->{startdate
}) {
2325 push @$rtcFlags, "base=$conf->{startdate}";
2326 } elsif ($useLocaltime) {
2327 push @$rtcFlags, 'base=localtime';
2330 push @$cmd, '-S' if $conf->{freeze
};
2332 # set keyboard layout
2333 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2334 push @$cmd, '-k', $kb if $kb;
2337 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2338 #push @$cmd, '-soundhw', 'es1370';
2339 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2341 if($conf->{agent
}) {
2342 my $qgasocket = qga_socket
($vmid);
2343 my $pciaddr = print_pci_addr
("qga0", $bridges);
2344 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2345 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2346 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
2349 # enable balloon by default, unless explicitly disabled
2350 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2351 $pciaddr = print_pci_addr
("balloon0", $bridges);
2352 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
2355 if ($conf->{watchdog
}) {
2356 my $wdopts = parse_watchdog
($conf->{watchdog
});
2357 $pciaddr = print_pci_addr
("watchdog", $bridges);
2358 my $watchdog = $wdopts->{model
} || 'i6300esb';
2359 push @$devices, '-device', "$watchdog$pciaddr";
2360 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
2364 my $scsicontroller = {};
2365 my $ahcicontroller = {};
2366 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
2368 foreach_drive
($conf, sub {
2369 my ($ds, $drive) = @_;
2371 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
2372 push @$vollist, $drive->{file
};
2375 $use_virtio = 1 if $ds =~ m/^virtio/;
2377 if (drive_is_cdrom
($drive)) {
2378 if ($bootindex_hash->{d
}) {
2379 $drive->{bootindex
} = $bootindex_hash->{d
};
2380 $bootindex_hash->{d
} += 1;
2383 if ($bootindex_hash->{c
}) {
2384 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
2385 $bootindex_hash->{c
} += 1;
2389 if ($drive->{interface
} eq 'scsi') {
2391 my $maxdev = ($scsihw ne 'lsi') ?
256 : 7;
2392 my $controller = int($drive->{index} / $maxdev);
2393 $pciaddr = print_pci_addr
("scsihw$controller", $bridges);
2394 push @$devices, '-device', "$scsihw,id=scsihw$controller$pciaddr" if !$scsicontroller->{$controller};
2395 $scsicontroller->{$controller}=1;
2398 if ($drive->{interface
} eq 'sata') {
2399 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
2400 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
2401 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
2402 $ahcicontroller->{$controller}=1;
2405 push @$devices, '-drive',print_drive_full
($storecfg, $vmid, $drive);
2406 push @$devices, '-device',print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
2409 push @$cmd, '-m', $conf->{memory
} || $defaults->{memory
};
2411 for (my $i = 0; $i < $MAX_NETS; $i++) {
2412 next if !$conf->{"net$i"};
2413 my $d = parse_net
($conf->{"net$i"});
2416 $use_virtio = 1 if $d->{model
} eq 'virtio';
2418 if ($bootindex_hash->{n
}) {
2419 $d->{bootindex
} = $bootindex_hash->{n
};
2420 $bootindex_hash->{n
} += 1;
2423 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
2424 push @$devices, '-netdev', $netdevfull;
2426 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
2427 push @$devices, '-device', $netdevicefull;
2431 while (my ($k, $v) = each %$bridges) {
2432 $pciaddr = print_pci_addr
("pci.$k");
2433 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
2437 # hack: virtio with fairsched is unreliable, so we do not use fairsched
2438 # when the VM uses virtio devices.
2439 if (!$use_virtio && $have_ovz) {
2441 my $cpuunits = defined($conf->{cpuunits
}) ?
2442 $conf->{cpuunits
} : $defaults->{cpuunits
};
2444 push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
2446 # fixme: cpulimit is currently ignored
2447 #push @$cmd, '-cpulimit', $conf->{cpulimit} if $conf->{cpulimit};
2451 if ($conf->{args
}) {
2452 my $aa = PVE
::Tools
::split_args
($conf->{args
});
2456 push @$cmd, @$devices;
2457 push @$cmd, '-rtc', join(',', @$rtcFlags)
2458 if scalar(@$rtcFlags);
2459 push @$cmd, '-machine', join(',', @$machineFlags)
2460 if scalar(@$machineFlags);
2461 push @$cmd, '-global', join(',', @$globalFlags)
2462 if scalar(@$globalFlags);
2464 return wantarray ?
($cmd, $vollist) : $cmd;
2469 return "${var_run_tmpdir}/$vmid.vnc";
2474 return "${var_run_tmpdir}/$vmid.qmp";
2479 return "${var_run_tmpdir}/$vmid.qga";
2484 return "${var_run_tmpdir}/$vmid.pid";
2487 sub next_migrate_port
{
2489 for (my $p = 60000; $p < 60010; $p++) {
2491 my $sock = IO
::Socket
::INET-
>new(Listen
=> 5,
2492 LocalAddr
=> 'localhost',
2503 die "unable to find free migration port";
2506 sub vm_devices_list
{
2509 my $res = vm_mon_cmd
($vmid, 'query-pci');
2512 foreach my $pcibus (@$res) {
2513 foreach my $device (@{$pcibus->{devices
}}) {
2514 next if !$device->{'qdev_id'};
2515 $devices->{$device->{'qdev_id'}} = $device;
2523 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
2525 return 1 if !check_running
($vmid);
2527 if ($deviceid eq 'tablet') {
2528 my $devicefull = "usb-tablet,id=tablet,bus=uhci.0,port=1";
2529 qemu_deviceadd
($vmid, $devicefull);
2533 return 1 if !$conf->{hotplug
};
2535 my $devices_list = vm_devices_list
($vmid);
2536 return 1 if defined($devices_list->{$deviceid});
2538 qemu_bridgeadd
($storecfg, $conf, $vmid, $deviceid); #add bridge if we need it for the device
2540 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2541 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2542 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2543 qemu_deviceadd
($vmid, $devicefull);
2544 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2545 qemu_drivedel
($vmid, $deviceid);
2550 if ($deviceid =~ m/^(scsihw)(\d+)$/) {
2551 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
2552 my $pciaddr = print_pci_addr
($deviceid);
2553 my $devicefull = "$scsihw,id=$deviceid$pciaddr";
2554 qemu_deviceadd
($vmid, $devicefull);
2555 return undef if(!qemu_deviceaddverify
($vmid, $deviceid));
2558 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2559 return 1 if ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi'); #virtio-scsi not yet support hotplug
2560 return undef if !qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
2561 return undef if !qemu_driveadd
($storecfg, $vmid, $device);
2562 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
2563 if(!qemu_deviceadd
($vmid, $devicefull)) {
2564 qemu_drivedel
($vmid, $deviceid);
2569 if ($deviceid =~ m/^(net)(\d+)$/) {
2570 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
2571 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
2572 qemu_deviceadd
($vmid, $netdevicefull);
2573 if(!qemu_deviceaddverify
($vmid, $deviceid)) {
2574 qemu_netdevdel
($vmid, $deviceid);
2579 if ($deviceid =~ m/^(pci\.)(\d+)$/) {
2581 my $pciaddr = print_pci_addr
($deviceid);
2582 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
2583 qemu_deviceadd
($vmid, $devicefull);
2584 return undef if !qemu_deviceaddverify
($vmid, $deviceid);
2590 sub vm_deviceunplug
{
2591 my ($vmid, $conf, $deviceid) = @_;
2593 return 1 if !check_running
($vmid);
2595 if ($deviceid eq 'tablet') {
2596 qemu_devicedel
($vmid, $deviceid);
2600 return 1 if !$conf->{hotplug
};
2602 my $devices_list = vm_devices_list
($vmid);
2603 return 1 if !defined($devices_list->{$deviceid});
2605 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
2607 if ($deviceid =~ m/^(virtio)(\d+)$/) {
2608 qemu_devicedel
($vmid, $deviceid);
2609 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2610 return undef if !qemu_drivedel
($vmid, $deviceid);
2613 if ($deviceid =~ m/^(lsi)(\d+)$/) {
2614 return undef if !qemu_devicedel
($vmid, $deviceid);
2617 if ($deviceid =~ m/^(scsi)(\d+)$/) {
2618 return undef if !qemu_devicedel
($vmid, $deviceid);
2619 return undef if !qemu_drivedel
($vmid, $deviceid);
2622 if ($deviceid =~ m/^(net)(\d+)$/) {
2623 qemu_devicedel
($vmid, $deviceid);
2624 return undef if !qemu_devicedelverify
($vmid, $deviceid);
2625 return undef if !qemu_netdevdel
($vmid, $deviceid);
2631 sub qemu_deviceadd
{
2632 my ($vmid, $devicefull) = @_;
2634 $devicefull = "driver=".$devicefull;
2635 my %options = split(/[=,]/, $devicefull);
2637 vm_mon_cmd
($vmid, "device_add" , %options);
2641 sub qemu_devicedel
{
2642 my($vmid, $deviceid) = @_;
2643 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
2648 my($storecfg, $vmid, $device) = @_;
2650 my $drive = print_drive_full
($storecfg, $vmid, $device);
2651 my $ret = vm_human_monitor_command
($vmid, "drive_add auto $drive");
2652 # If the command succeeds qemu prints: "OK"
2653 if ($ret !~ m/OK/s) {
2654 syslog
("err", "adding drive failed: $ret");
2661 my($vmid, $deviceid) = @_;
2663 my $ret = vm_human_monitor_command
($vmid, "drive_del drive-$deviceid");
2665 if ($ret =~ m/Device \'.*?\' not found/s) {
2666 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
2668 elsif ($ret ne "") {
2669 syslog
("err", "deleting drive $deviceid failed : $ret");
2675 sub qemu_deviceaddverify
{
2676 my ($vmid,$deviceid) = @_;
2678 for (my $i = 0; $i <= 5; $i++) {
2679 my $devices_list = vm_devices_list
($vmid);
2680 return 1 if defined($devices_list->{$deviceid});
2683 syslog
("err", "error on hotplug device $deviceid");
2688 sub qemu_devicedelverify
{
2689 my ($vmid,$deviceid) = @_;
2691 #need to verify the device is correctly remove as device_del is async and empty return is not reliable
2692 for (my $i = 0; $i <= 5; $i++) {
2693 my $devices_list = vm_devices_list
($vmid);
2694 return 1 if !defined($devices_list->{$deviceid});
2697 syslog
("err", "error on hot-unplugging device $deviceid");
2701 sub qemu_findorcreatescsihw
{
2702 my ($storecfg, $conf, $vmid, $device) = @_;
2704 my $maxdev = ($conf->{scsihw
} && $conf->{scsihw
} ne 'lsi') ?
256 : 7;
2705 my $controller = int($device->{index} / $maxdev);
2706 my $scsihwid="scsihw$controller";
2707 my $devices_list = vm_devices_list
($vmid);
2709 if(!defined($devices_list->{$scsihwid})) {
2710 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $scsihwid);
2715 sub qemu_bridgeadd
{
2716 my ($storecfg, $conf, $vmid, $device) = @_;
2719 my $bridgeid = undef;
2720 print_pci_addr
($device, $bridges);
2722 while (my ($k, $v) = each %$bridges) {
2725 return if $bridgeid < 1;
2726 my $bridge = "pci.$bridgeid";
2727 my $devices_list = vm_devices_list
($vmid);
2729 if(!defined($devices_list->{$bridge})) {
2730 return undef if !vm_deviceplug
($storecfg, $conf, $vmid, $bridge);
2735 sub qemu_netdevadd
{
2736 my ($vmid, $conf, $device, $deviceid) = @_;
2738 my $netdev = print_netdev_full
($vmid, $conf, $device, $deviceid);
2739 my %options = split(/[=,]/, $netdev);
2741 vm_mon_cmd
($vmid, "netdev_add", %options);
2745 sub qemu_netdevdel
{
2746 my ($vmid, $deviceid) = @_;
2748 vm_mon_cmd
($vmid, "netdev_del", id
=> $deviceid);
2752 sub qemu_block_set_io_throttle
{
2753 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
2755 return if !check_running
($vmid) ;
2758 $bps_rd = 0 if !$bps_rd;
2759 $bps_wr = 0 if !$bps_wr;
2760 $iops = 0 if !$iops;
2761 $iops_rd = 0 if !$iops_rd;
2762 $iops_wr = 0 if !$iops_wr;
2764 vm_mon_cmd
($vmid, "block_set_io_throttle", device
=> $deviceid, bps
=> int($bps), bps_rd
=> int($bps_rd), bps_wr
=> int($bps_wr), iops
=> int($iops), iops_rd
=> int($iops_rd), iops_wr
=> int($iops_wr));
2768 # old code, only used to shutdown old VM after update
2770 my ($fh, $timeout) = @_;
2772 my $sel = new IO
::Select
;
2779 while (scalar (@ready = $sel->can_read($timeout))) {
2781 if ($count = $fh->sysread($buf, 8192)) {
2782 if ($buf =~ /^(.*)\(qemu\) $/s) {
2789 if (!defined($count)) {
2796 die "monitor read timeout\n" if !scalar(@ready);
2801 # old code, only used to shutdown old VM after update
2802 sub vm_monitor_command
{
2803 my ($vmid, $cmdstr, $nocheck) = @_;
2808 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
2810 my $sname = "${var_run_tmpdir}/$vmid.mon";
2812 my $sock = IO
::Socket
::UNIX-
>new( Peer
=> $sname ) ||
2813 die "unable to connect to VM $vmid socket - $!\n";
2817 # hack: migrate sometime blocks the monitor (when migrate_downtime
2819 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2820 $timeout = 60*60; # 1 hour
2824 my $data = __read_avail
($sock, $timeout);
2826 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
2827 die "got unexpected qemu monitor banner\n";
2830 my $sel = new IO
::Select
;
2833 if (!scalar(my @ready = $sel->can_write($timeout))) {
2834 die "monitor write error - timeout";
2837 my $fullcmd = "$cmdstr\r";
2839 # syslog('info', "VM $vmid monitor command: $cmdstr");
2842 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
2843 die "monitor write error - $!";
2846 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
2850 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
2851 $timeout = 60*60; # 1 hour
2852 } elsif ($cmdstr =~ m/^(eject|change)/) {
2853 $timeout = 60; # note: cdrom mount command is slow
2855 if ($res = __read_avail
($sock, $timeout)) {
2857 my @lines = split("\r?\n", $res);
2859 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
2861 $res = join("\n", @lines);
2869 syslog
("err", "VM $vmid monitor command failed - $err");
2876 sub qemu_block_resize
{
2877 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
2879 my $running = check_running
($vmid);
2881 return if !PVE
::Storage
::volume_resize
($storecfg, $volid, $size, $running);
2883 return if !$running;
2885 vm_mon_cmd
($vmid, "block_resize", device
=> $deviceid, size
=> int($size));
2889 sub qemu_volume_snapshot
{
2890 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2892 my $running = check_running
($vmid);
2894 return if !PVE
::Storage
::volume_snapshot
($storecfg, $volid, $snap, $running);
2896 return if !$running;
2898 vm_mon_cmd
($vmid, "snapshot-drive", device
=> $deviceid, name
=> $snap);
2902 sub qemu_volume_snapshot_delete
{
2903 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
2905 my $running = check_running
($vmid);
2907 return if !PVE
::Storage
::volume_snapshot_delete
($storecfg, $volid, $snap, $running);
2909 return if !$running;
2911 vm_mon_cmd
($vmid, "delete-drive-snapshot", device
=> $deviceid, name
=> $snap);
2917 #need to impplement call to qemu-ga
2920 sub qga_unfreezefs
{
2923 #need to impplement call to qemu-ga
2927 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused) = @_;
2929 lock_config
($vmid, sub {
2930 my $conf = load_config
($vmid, $migratedfrom);
2932 die "you can't start a vm if it's a template\n" if is_template
($conf);
2934 check_lock
($conf) if !$skiplock;
2936 die "VM $vmid already running\n" if check_running
($vmid, undef, $migratedfrom);
2938 my $defaults = load_defaults
();
2940 # set environment variable useful inside network script
2941 $ENV{PVE_MIGRATED_FROM
} = $migratedfrom if $migratedfrom;
2943 my ($cmd, $vollist) = config_to_command
($storecfg, $vmid, $conf, $defaults);
2945 my $migrate_port = 0;
2948 if ($statefile eq 'tcp') {
2949 $migrate_port = next_migrate_port
();
2950 my $migrate_uri = "tcp:localhost:${migrate_port}";
2951 push @$cmd, '-incoming', $migrate_uri;
2954 push @$cmd, '-loadstate', $statefile;
2961 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2962 my $d = parse_hostpci
($conf->{"hostpci$i"});
2964 my $info = pci_device_info
("0000:$d->{pciid}");
2965 die "IOMMU not present\n" if !check_iommu_support
();
2966 die "no pci device info for device '$d->{pciid}'\n" if !$info;
2967 die "can't unbind pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub
($info);
2968 die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset
($info);
2971 PVE
::Storage
::activate_volumes
($storecfg, $vollist);
2973 eval { run_command
($cmd, timeout
=> $statefile ?
undef : 30,
2976 die "start failed: $err" if $err;
2978 print "migration listens on port $migrate_port\n" if $migrate_port;
2980 if ($statefile && $statefile ne 'tcp') {
2981 eval { vm_mon_cmd_nocheck
($vmid, "cont"); };
2986 my $capabilities = {};
2987 $capabilities->{capability
} = "xbzrle";
2988 $capabilities->{state} = JSON
::true
;
2989 eval { vm_mon_cmd_nocheck
($vmid, "migrate-set-capabilities", capabilities
=> [$capabilities]); };
2993 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
2994 vm_mon_cmd_nocheck
($vmid, "balloon", value
=> $conf->{balloon
}*1024*1024)
2995 if $conf->{balloon
};
2996 vm_mon_cmd_nocheck
($vmid, 'qom-set',
2997 path
=> "machine/peripheral/balloon0",
2998 property
=> "guest-stats-polling-interval",
3006 my ($vmid, $execute, %params) = @_;
3008 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3009 vm_qmp_command
($vmid, $cmd);
3012 sub vm_mon_cmd_nocheck
{
3013 my ($vmid, $execute, %params) = @_;
3015 my $cmd = { execute
=> $execute, arguments
=> \
%params };
3016 vm_qmp_command
($vmid, $cmd, 1);
3019 sub vm_qmp_command
{
3020 my ($vmid, $cmd, $nocheck) = @_;
3025 if ($cmd->{arguments
} && $cmd->{arguments
}->{timeout
}) {
3026 $timeout = $cmd->{arguments
}->{timeout
};
3027 delete $cmd->{arguments
}->{timeout
};
3031 die "VM $vmid not running\n" if !check_running
($vmid, $nocheck);
3032 my $sname = qmp_socket
($vmid);
3034 my $qmpclient = PVE
::QMPClient-
>new();
3036 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
3037 } elsif (-e
"${var_run_tmpdir}/$vmid.mon") {
3038 die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
3039 if scalar(%{$cmd->{arguments
}});
3040 vm_monitor_command
($vmid, $cmd->{execute
}, $nocheck);
3042 die "unable to open monitor socket\n";
3046 syslog
("err", "VM $vmid qmp command failed - $err");
3053 sub vm_human_monitor_command
{
3054 my ($vmid, $cmdline) = @_;
3059 execute
=> 'human-monitor-command',
3060 arguments
=> { 'command-line' => $cmdline},
3063 return vm_qmp_command
($vmid, $cmd);
3066 sub vm_commandline
{
3067 my ($storecfg, $vmid) = @_;
3069 my $conf = load_config
($vmid);
3071 my $defaults = load_defaults
();
3073 my $cmd = config_to_command
($storecfg, $vmid, $conf, $defaults);
3075 return join(' ', @$cmd);
3079 my ($vmid, $skiplock) = @_;
3081 lock_config
($vmid, sub {
3083 my $conf = load_config
($vmid);
3085 check_lock
($conf) if !$skiplock;
3087 vm_mon_cmd
($vmid, "system_reset");
3091 sub get_vm_volumes
{
3095 foreach_volid
($conf, sub {
3096 my ($volid, $is_cdrom) = @_;
3098 return if $volid =~ m
|^/|;
3100 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
3103 push @$vollist, $volid;
3109 sub vm_stop_cleanup
{
3110 my ($storecfg, $vmid, $conf, $keepActive) = @_;
3113 fairsched_rmnod
($vmid); # try to destroy group
3116 my $vollist = get_vm_volumes
($conf);
3117 PVE
::Storage
::deactivate_volumes
($storecfg, $vollist);
3120 foreach my $ext (qw(mon qmp pid vnc qga)) {
3121 unlink "/var/run/qemu-server/${vmid}.$ext";
3124 warn $@ if $@; # avoid errors - just warn
3127 # Note: use $nockeck to skip tests if VM configuration file exists.
3128 # We need that when migration VMs to other nodes (files already moved)
3129 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
3131 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
3133 $force = 1 if !defined($force) && !$shutdown;
3136 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
3137 kill 15, $pid if $pid;
3138 my $conf = load_config
($vmid, $migratedfrom);
3139 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive);
3143 lock_config
($vmid, sub {
3145 my $pid = check_running
($vmid, $nocheck);
3150 $conf = load_config
($vmid);
3151 check_lock
($conf) if !$skiplock;
3152 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
3153 my $opts = parse_startup
($conf->{startup
});
3154 $timeout = $opts->{down
} if $opts->{down
};
3158 $timeout = 60 if !defined($timeout);
3162 $nocheck ? vm_mon_cmd_nocheck
($vmid, "system_powerdown") : vm_mon_cmd
($vmid, "system_powerdown");
3165 $nocheck ? vm_mon_cmd_nocheck
($vmid, "quit") : vm_mon_cmd
($vmid, "quit");
3172 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3177 if ($count >= $timeout) {
3179 warn "VM still running - terminating now with SIGTERM\n";
3182 die "VM quit/powerdown failed - got timeout\n";
3185 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3190 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
3193 die "VM quit/powerdown failed\n";
3201 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
3206 if ($count >= $timeout) {
3207 warn "VM still running - terminating now with SIGKILL\n";
3212 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive) if $conf;
3217 my ($vmid, $skiplock) = @_;
3219 lock_config
($vmid, sub {
3221 my $conf = load_config
($vmid);
3223 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3225 vm_mon_cmd
($vmid, "stop");
3230 my ($vmid, $skiplock) = @_;
3232 lock_config
($vmid, sub {
3234 my $conf = load_config
($vmid);
3236 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
3238 vm_mon_cmd
($vmid, "cont");
3243 my ($vmid, $skiplock, $key) = @_;
3245 lock_config
($vmid, sub {
3247 my $conf = load_config
($vmid);
3249 # there is no qmp command, so we use the human monitor command
3250 vm_human_monitor_command
($vmid, "sendkey $key");
3255 my ($storecfg, $vmid, $skiplock) = @_;
3257 lock_config
($vmid, sub {
3259 my $conf = load_config
($vmid);
3261 check_lock
($conf) if !$skiplock;
3263 if (!check_running
($vmid)) {
3264 fairsched_rmnod
($vmid); # try to destroy group
3265 destroy_vm
($storecfg, $vmid);
3267 die "VM $vmid is running - destroy failed\n";
3275 my ($filename, $buf) = @_;
3277 my $fh = IO
::File-
>new($filename, "w");
3278 return undef if !$fh;
3280 my $res = print $fh $buf;
3287 sub pci_device_info
{
3292 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
3293 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
3295 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
3296 return undef if !defined($irq) || $irq !~ m/^\d+$/;
3298 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
3299 return undef if !defined($vendor) || $vendor !~ s/^0x//;
3301 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
3302 return undef if !defined($product) || $product !~ s/^0x//;
3307 product
=> $product,
3313 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
3322 my $name = $dev->{name
};
3324 my $fn = "$pcisysfs/devices/$name/reset";
3326 return file_write
($fn, "1");
3329 sub pci_dev_bind_to_stub
{
3332 my $name = $dev->{name
};
3334 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
3335 return 1 if -d
$testdir;
3337 my $data = "$dev->{vendor} $dev->{product}";
3338 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
3340 my $fn = "$pcisysfs/devices/$name/driver/unbind";
3341 if (!file_write
($fn, $name)) {
3342 return undef if -f
$fn;
3345 $fn = "$pcisysfs/drivers/pci-stub/bind";
3346 if (! -d
$testdir) {
3347 return undef if !file_write
($fn, $name);
3353 sub print_pci_addr
{
3354 my ($id, $bridges) = @_;
3358 piix3
=> { bus
=> 0, addr
=> 1 },
3359 #addr2 : first videocard
3360 balloon0
=> { bus
=> 0, addr
=> 3 },
3361 watchdog
=> { bus
=> 0, addr
=> 4 },
3362 scsihw0
=> { bus
=> 0, addr
=> 5 },
3363 scsihw1
=> { bus
=> 0, addr
=> 6 },
3364 ahci0
=> { bus
=> 0, addr
=> 7 },
3365 qga0
=> { bus
=> 0, addr
=> 8 },
3366 virtio0
=> { bus
=> 0, addr
=> 10 },
3367 virtio1
=> { bus
=> 0, addr
=> 11 },
3368 virtio2
=> { bus
=> 0, addr
=> 12 },
3369 virtio3
=> { bus
=> 0, addr
=> 13 },
3370 virtio4
=> { bus
=> 0, addr
=> 14 },
3371 virtio5
=> { bus
=> 0, addr
=> 15 },
3372 hostpci0
=> { bus
=> 0, addr
=> 16 },
3373 hostpci1
=> { bus
=> 0, addr
=> 17 },
3374 net0
=> { bus
=> 0, addr
=> 18 },
3375 net1
=> { bus
=> 0, addr
=> 19 },
3376 net2
=> { bus
=> 0, addr
=> 20 },
3377 net3
=> { bus
=> 0, addr
=> 21 },
3378 net4
=> { bus
=> 0, addr
=> 22 },
3379 net5
=> { bus
=> 0, addr
=> 23 },
3380 #addr29 : usb-host (pve-usb.cfg)
3381 'pci.1' => { bus
=> 0, addr
=> 30 },
3382 'pci.2' => { bus
=> 0, addr
=> 31 },
3383 'net6' => { bus
=> 1, addr
=> 1 },
3384 'net7' => { bus
=> 1, addr
=> 2 },
3385 'net8' => { bus
=> 1, addr
=> 3 },
3386 'net9' => { bus
=> 1, addr
=> 4 },
3387 'net10' => { bus
=> 1, addr
=> 5 },
3388 'net11' => { bus
=> 1, addr
=> 6 },
3389 'net12' => { bus
=> 1, addr
=> 7 },
3390 'net13' => { bus
=> 1, addr
=> 8 },
3391 'net14' => { bus
=> 1, addr
=> 9 },
3392 'net15' => { bus
=> 1, addr
=> 10 },
3393 'net16' => { bus
=> 1, addr
=> 11 },
3394 'net17' => { bus
=> 1, addr
=> 12 },
3395 'net18' => { bus
=> 1, addr
=> 13 },
3396 'net19' => { bus
=> 1, addr
=> 14 },
3397 'net20' => { bus
=> 1, addr
=> 15 },
3398 'net21' => { bus
=> 1, addr
=> 16 },
3399 'net22' => { bus
=> 1, addr
=> 17 },
3400 'net23' => { bus
=> 1, addr
=> 18 },
3401 'net24' => { bus
=> 1, addr
=> 19 },
3402 'net25' => { bus
=> 1, addr
=> 20 },
3403 'net26' => { bus
=> 1, addr
=> 21 },
3404 'net27' => { bus
=> 1, addr
=> 22 },
3405 'net28' => { bus
=> 1, addr
=> 23 },
3406 'net29' => { bus
=> 1, addr
=> 24 },
3407 'net30' => { bus
=> 1, addr
=> 25 },
3408 'net31' => { bus
=> 1, addr
=> 26 },
3409 'virtio6' => { bus
=> 2, addr
=> 1 },
3410 'virtio7' => { bus
=> 2, addr
=> 2 },
3411 'virtio8' => { bus
=> 2, addr
=> 3 },
3412 'virtio9' => { bus
=> 2, addr
=> 4 },
3413 'virtio10' => { bus
=> 2, addr
=> 5 },
3414 'virtio11' => { bus
=> 2, addr
=> 6 },
3415 'virtio12' => { bus
=> 2, addr
=> 7 },
3416 'virtio13' => { bus
=> 2, addr
=> 8 },
3417 'virtio14' => { bus
=> 2, addr
=> 9 },
3418 'virtio15' => { bus
=> 2, addr
=> 10 },
3421 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
3422 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
3423 my $bus = $devices->{$id}->{bus
};
3424 $res = ",bus=pci.$bus,addr=$addr";
3425 $bridges->{$bus} = 1 if $bridges;
3431 # vzdump restore implementaion
3433 sub tar_archive_read_firstfile
{
3434 my $archive = shift;
3436 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
3438 # try to detect archive type first
3439 my $pid = open (TMP
, "tar tf '$archive'|") ||
3440 die "unable to open file '$archive'\n";
3441 my $firstfile = <TMP
>;
3445 die "ERROR: archive contaions no data\n" if !$firstfile;
3451 sub tar_restore_cleanup
{
3452 my ($storecfg, $statfile) = @_;
3454 print STDERR
"starting cleanup\n";
3456 if (my $fd = IO
::File-
>new($statfile, "r")) {
3457 while (defined(my $line = <$fd>)) {
3458 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3461 if ($volid =~ m
|^/|) {
3462 unlink $volid || die 'unlink failed\n';
3464 PVE
::Storage
::vdisk_free
($storecfg, $volid);
3466 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3468 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3470 print STDERR
"unable to parse line in statfile - $line";
3477 sub restore_archive
{
3478 my ($archive, $vmid, $user, $opts) = @_;
3480 my $format = $opts->{format
};
3483 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
3484 $format = 'tar' if !$format;
3486 } elsif ($archive =~ m/\.tar$/) {
3487 $format = 'tar' if !$format;
3488 } elsif ($archive =~ m/.tar.lzo$/) {
3489 $format = 'tar' if !$format;
3491 } elsif ($archive =~ m/\.vma$/) {
3492 $format = 'vma' if !$format;
3493 } elsif ($archive =~ m/\.vma\.gz$/) {
3494 $format = 'vma' if !$format;
3496 } elsif ($archive =~ m/\.vma\.lzo$/) {
3497 $format = 'vma' if !$format;
3500 $format = 'vma' if !$format; # default
3503 # try to detect archive format
3504 if ($format eq 'tar') {
3505 return restore_tar_archive
($archive, $vmid, $user, $opts);
3507 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
3511 sub restore_update_config_line
{
3512 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
3514 return if $line =~ m/^\#qmdump\#/;
3515 return if $line =~ m/^\#vzdump\#/;
3516 return if $line =~ m/^lock:/;
3517 return if $line =~ m/^unused\d+:/;
3518 return if $line =~ m/^parent:/;
3520 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
3521 # try to convert old 1.X settings
3522 my ($id, $ind, $ethcfg) = ($1, $2, $3);
3523 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
3524 my ($model, $macaddr) = split(/\=/, $devconfig);
3525 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
3528 bridge
=> "vmbr$ind",
3529 macaddr
=> $macaddr,
3531 my $netstr = print_net
($net);
3533 print $outfd "net$cookie->{netcount}: $netstr\n";
3534 $cookie->{netcount
}++;
3536 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
3537 my ($id, $netstr) = ($1, $2);
3538 my $net = parse_net
($netstr);
3539 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
3540 $netstr = print_net
($net);
3541 print $outfd "$id: $netstr\n";
3542 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
3545 if ($line =~ m/backup=no/) {
3546 print $outfd "#$line";
3547 } elsif ($virtdev && $map->{$virtdev}) {
3548 my $di = parse_drive
($virtdev, $value);
3549 $di->{file
} = $map->{$virtdev};
3550 $value = print_drive
($vmid, $di);
3551 print $outfd "$virtdev: $value\n";
3561 my ($cfg, $vmid) = @_;
3563 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
3565 my $volid_hash = {};
3566 foreach my $storeid (keys %$info) {
3567 foreach my $item (@{$info->{$storeid}}) {
3568 next if !($item->{volid
} && $item->{size
});
3569 $volid_hash->{$item->{volid
}} = $item;
3576 sub update_disksize
{
3577 my ($vmid, $conf, $volid_hash) = @_;
3584 foreach my $opt (keys %$conf) {
3585 if (valid_drivename
($opt)) {
3586 my $drive = parse_drive
($opt, $conf->{$opt});
3587 my $volid = $drive->{file
};
3590 $used->{$volid} = 1;
3592 next if drive_is_cdrom
($drive);
3593 next if !$volid_hash->{$volid};
3595 $drive->{size
} = $volid_hash->{$volid}->{size
};
3597 $conf->{$opt} = print_drive
($vmid, $drive);
3601 foreach my $volid (sort keys %$volid_hash) {
3602 next if $volid =~ m/vm-$vmid-state-/;
3603 next if $used->{$volid};
3605 add_unused_volume
($conf, $volid);
3612 my ($vmid, $nolock) = @_;
3614 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
3616 my $volid_hash = scan_volids
($cfg, $vmid);
3618 my $updatefn = sub {
3621 my $conf = load_config
($vmid);
3625 my $changes = update_disksize
($vmid, $conf, $volid_hash);
3627 update_config_nolock
($vmid, $conf, 1) if $changes;
3630 if (defined($vmid)) {
3634 lock_config
($vmid, $updatefn, $vmid);
3637 my $vmlist = config_list
();
3638 foreach my $vmid (keys %$vmlist) {
3642 lock_config
($vmid, $updatefn, $vmid);
3648 sub restore_vma_archive
{
3649 my ($archive, $vmid, $user, $opts, $comp) = @_;
3651 my $input = $archive eq '-' ?
"<&STDIN" : undef;
3652 my $readfrom = $archive;
3657 my $qarchive = PVE
::Tools
::shellquote
($archive);
3658 if ($comp eq 'gzip') {
3659 $uncomp = "zcat $qarchive|";
3660 } elsif ($comp eq 'lzop') {
3661 $uncomp = "lzop -d -c $qarchive|";
3663 die "unknown compression method '$comp'\n";
3668 my $tmpdir = "/var/tmp/vzdumptmp$$";
3671 # disable interrupts (always do cleanups)
3672 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3673 warn "got interrupt - ignored\n";
3676 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
3677 POSIX
::mkfifo
($mapfifo, 0600);
3680 my $openfifo = sub {
3681 open($fifofh, '>', $mapfifo) || die $!;
3684 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
3691 my $rpcenv = PVE
::RPCEnvironment
::get
();
3693 my $conffile = config_file
($vmid);
3694 my $tmpfn = "$conffile.$$.tmp";
3696 # Note: $oldconf is undef if VM does not exists
3697 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
3699 my $print_devmap = sub {
3700 my $virtdev_hash = {};
3702 my $cfgfn = "$tmpdir/qemu-server.conf";
3704 # we can read the config - that is already extracted
3705 my $fh = IO
::File-
>new($cfgfn, "r") ||
3706 "unable to read qemu-server.conf - $!\n";
3708 while (defined(my $line = <$fh>)) {
3709 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
3710 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
3711 die "archive does not contain data for drive '$virtdev'\n"
3712 if !$devinfo->{$devname};
3713 if (defined($opts->{storage
})) {
3714 $storeid = $opts->{storage
} || 'local';
3715 } elsif (!$storeid) {
3718 $format = 'raw' if !$format;
3719 $devinfo->{$devname}->{devname
} = $devname;
3720 $devinfo->{$devname}->{virtdev
} = $virtdev;
3721 $devinfo->{$devname}->{format
} = $format;
3722 $devinfo->{$devname}->{storeid
} = $storeid;
3724 # check permission on storage
3725 my $pool = $opts->{pool
}; # todo: do we need that?
3726 if ($user ne 'root@pam') {
3727 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
3730 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
3734 foreach my $devname (keys %$devinfo) {
3735 die "found no device mapping information for device '$devname'\n"
3736 if !$devinfo->{$devname}->{virtdev
};
3739 my $cfg = cfs_read_file
('storage.cfg');
3741 # create empty/temp config
3743 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
3744 foreach_drive
($oldconf, sub {
3745 my ($ds, $drive) = @_;
3747 return if drive_is_cdrom
($drive);
3749 my $volid = $drive->{file
};
3751 return if !$volid || $volid =~ m
|^/|;
3753 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
3754 return if !$path || !$owner || ($owner != $vmid);
3756 # Note: only delete disk we want to restore
3757 # other volumes will become unused
3758 if ($virtdev_hash->{$ds}) {
3759 PVE
::Storage
::vdisk_free
($cfg, $volid);
3765 foreach my $virtdev (sort keys %$virtdev_hash) {
3766 my $d = $virtdev_hash->{$virtdev};
3767 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
3768 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
3769 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
3770 $d->{format
}, undef, $alloc_size);
3771 print STDERR
"new volume ID is '$volid'\n";
3772 $d->{volid
} = $volid;
3773 my $path = PVE
::Storage
::path
($cfg, $volid);
3775 my $write_zeros = 1;
3776 # fixme: what other storages types initialize volumes with zero?
3777 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' ||
3778 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
3782 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
3784 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
3785 $map->{$virtdev} = $volid;
3788 $fh->seek(0, 0) || die "seek failed - $!\n";
3790 my $outfd = new IO
::File
($tmpfn, "w") ||
3791 die "unable to write config for VM $vmid\n";
3793 my $cookie = { netcount
=> 0 };
3794 while (defined(my $line = <$fh>)) {
3795 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3804 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3805 die "interrupted by signal\n";
3807 local $SIG{ALRM
} = sub { die "got timeout\n"; };
3809 $oldtimeout = alarm($timeout);
3816 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
3817 my ($dev_id, $size, $devname) = ($1, $2, $3);
3818 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
3819 } elsif ($line =~ m/^CTIME: /) {
3821 print $fifofh "done\n";
3822 my $tmp = $oldtimeout || 0;
3823 $oldtimeout = undef;
3829 print "restore vma archive: $cmd\n";
3830 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
3834 alarm($oldtimeout) if $oldtimeout;
3842 my $cfg = cfs_read_file
('storage.cfg');
3843 foreach my $devname (keys %$devinfo) {
3844 my $volid = $devinfo->{$devname}->{volid
};
3847 if ($volid =~ m
|^/|) {
3848 unlink $volid || die 'unlink failed\n';
3850 PVE
::Storage
::vdisk_free
($cfg, $volid);
3852 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
3854 print STDERR
"unable to cleanup '$volid' - $@" if $@;
3861 rename($tmpfn, $conffile) ||
3862 die "unable to commit configuration file '$conffile'\n";
3864 PVE
::Cluster
::cfs_update
(); # make sure we read new file
3866 eval { rescan
($vmid, 1); };
3870 sub restore_tar_archive
{
3871 my ($archive, $vmid, $user, $opts) = @_;
3873 if ($archive ne '-') {
3874 my $firstfile = tar_archive_read_firstfile
($archive);
3875 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
3876 if $firstfile ne 'qemu-server.conf';
3879 my $storecfg = cfs_read_file
('storage.cfg');
3881 # destroy existing data - keep empty config
3882 my $vmcfgfn = PVE
::QemuServer
::config_file
($vmid);
3883 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
3885 my $tocmd = "/usr/lib/qemu-server/qmextract";
3887 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
3888 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
3889 $tocmd .= ' --prealloc' if $opts->{prealloc
};
3890 $tocmd .= ' --info' if $opts->{info
};
3892 # tar option "xf" does not autodetect compression when read from STDIN,
3893 # so we pipe to zcat
3894 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
3895 PVE
::Tools
::shellquote
("--to-command=$tocmd");
3897 my $tmpdir = "/var/tmp/vzdumptmp$$";
3900 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
3901 local $ENV{VZDUMP_VMID
} = $vmid;
3902 local $ENV{VZDUMP_USER
} = $user;
3904 my $conffile = config_file
($vmid);
3905 my $tmpfn = "$conffile.$$.tmp";
3907 # disable interrupts (always do cleanups)
3908 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
3909 print STDERR
"got interrupt - ignored\n";
3914 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
3915 die "interrupted by signal\n";
3918 if ($archive eq '-') {
3919 print "extracting archive from STDIN\n";
3920 run_command
($cmd, input
=> "<&STDIN");
3922 print "extracting archive '$archive'\n";
3926 return if $opts->{info
};
3930 my $statfile = "$tmpdir/qmrestore.stat";
3931 if (my $fd = IO
::File-
>new($statfile, "r")) {
3932 while (defined (my $line = <$fd>)) {
3933 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
3934 $map->{$1} = $2 if $1;
3936 print STDERR
"unable to parse line in statfile - $line\n";
3942 my $confsrc = "$tmpdir/qemu-server.conf";
3944 my $srcfd = new IO
::File
($confsrc, "r") ||
3945 die "unable to open file '$confsrc'\n";
3947 my $outfd = new IO
::File
($tmpfn, "w") ||
3948 die "unable to write config for VM $vmid\n";
3950 my $cookie = { netcount
=> 0 };
3951 while (defined (my $line = <$srcfd>)) {
3952 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
3964 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
3971 rename $tmpfn, $conffile ||
3972 die "unable to commit configuration file '$conffile'\n";
3974 PVE
::Cluster
::cfs_update
(); # make sure we read new file
3976 eval { rescan
($vmid, 1); };
3981 # Internal snapshots
3983 # NOTE: Snapshot create/delete involves several non-atomic
3984 # action, and can take a long time.
3985 # So we try to avoid locking the file and use 'lock' variable
3986 # inside the config file instead.
3988 my $snapshot_copy_config = sub {
3989 my ($source, $dest) = @_;
3991 foreach my $k (keys %$source) {
3992 next if $k eq 'snapshots';
3993 next if $k eq 'snapstate';
3994 next if $k eq 'snaptime';
3995 next if $k eq 'vmstate';
3996 next if $k eq 'lock';
3997 next if $k eq 'digest';
3998 next if $k eq 'description';
3999 next if $k =~ m/^unused\d+$/;
4001 $dest->{$k} = $source->{$k};
4005 my $snapshot_apply_config = sub {
4006 my ($conf, $snap) = @_;
4008 # copy snapshot list
4010 snapshots
=> $conf->{snapshots
},
4013 # keep description and list of unused disks
4014 foreach my $k (keys %$conf) {
4015 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
4016 $newconf->{$k} = $conf->{$k};
4019 &$snapshot_copy_config($snap, $newconf);
4024 sub foreach_writable_storage
{
4025 my ($conf, $func) = @_;
4029 foreach my $ds (keys %$conf) {
4030 next if !valid_drivename
($ds);
4032 my $drive = parse_drive
($ds, $conf->{$ds});
4034 next if drive_is_cdrom
($drive);
4036 my $volid = $drive->{file
};
4038 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
4039 $sidhash->{$sid} = $sid if $sid;
4042 foreach my $sid (sort keys %$sidhash) {
4047 my $alloc_vmstate_volid = sub {
4048 my ($storecfg, $vmid, $conf, $snapname) = @_;
4050 # Note: we try to be smart when selecting a $target storage
4054 # search shared storage first
4055 foreach_writable_storage
($conf, sub {
4057 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4058 return if !$scfg->{shared
};
4060 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
4064 # now search local storage
4065 foreach_writable_storage
($conf, sub {
4067 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
4068 return if $scfg->{shared
};
4070 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
4074 $target = 'local' if !$target;
4076 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
4077 # we abort live save after $conf->{memory}, so we need at max twice that space
4078 my $size = $conf->{memory
}*2 + $driver_state_size;
4080 my $name = "vm-$vmid-state-$snapname";
4081 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
4082 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
4083 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
4088 my $snapshot_prepare = sub {
4089 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
4093 my $updatefn = sub {
4095 my $conf = load_config
($vmid);
4097 die "you can't take a snapshot if it's a template\n"
4098 if is_template
($conf);
4102 $conf->{lock} = 'snapshot';
4104 die "snapshot name '$snapname' already used\n"
4105 if defined($conf->{snapshots
}->{$snapname});
4107 my $storecfg = PVE
::Storage
::config
();
4108 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
4110 $snap = $conf->{snapshots
}->{$snapname} = {};
4112 if ($save_vmstate && check_running
($vmid)) {
4113 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
4116 &$snapshot_copy_config($conf, $snap);
4118 $snap->{snapstate
} = "prepare";
4119 $snap->{snaptime
} = time();
4120 $snap->{description
} = $comment if $comment;
4122 update_config_nolock
($vmid, $conf, 1);
4125 lock_config
($vmid, $updatefn);
4130 my $snapshot_commit = sub {
4131 my ($vmid, $snapname) = @_;
4133 my $updatefn = sub {
4135 my $conf = load_config
($vmid);
4137 die "missing snapshot lock\n"
4138 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
4140 my $snap = $conf->{snapshots
}->{$snapname};
4142 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4144 die "wrong snapshot state\n"
4145 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
4147 delete $snap->{snapstate
};
4148 delete $conf->{lock};
4150 my $newconf = &$snapshot_apply_config($conf, $snap);
4152 $newconf->{parent
} = $snapname;
4154 update_config_nolock
($vmid, $newconf, 1);
4157 lock_config
($vmid, $updatefn);
4160 sub snapshot_rollback
{
4161 my ($vmid, $snapname) = @_;
4167 my $storecfg = PVE
::Storage
::config
();
4169 my $updatefn = sub {
4171 my $conf = load_config
($vmid);
4173 die "you can't rollback if vm is a template\n" if is_template
($conf);
4175 $snap = $conf->{snapshots
}->{$snapname};
4177 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4179 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
4180 if $snap->{snapstate
};
4184 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
4187 die "unable to rollback vm $vmid: vm is running\n"
4188 if check_running
($vmid);
4191 $conf->{lock} = 'rollback';
4193 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
4194 delete $conf->{lock};
4198 # copy snapshot config to current config
4199 $conf = &$snapshot_apply_config($conf, $snap);
4200 $conf->{parent
} = $snapname;
4203 update_config_nolock
($vmid, $conf, 1);
4205 if (!$prepare && $snap->{vmstate
}) {
4206 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4207 vm_start
($storecfg, $vmid, $statefile);
4211 lock_config
($vmid, $updatefn);
4213 foreach_drive
($snap, sub {
4214 my ($ds, $drive) = @_;
4216 return if drive_is_cdrom
($drive);
4218 my $volid = $drive->{file
};
4219 my $device = "drive-$ds";
4221 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
4225 lock_config
($vmid, $updatefn);
4228 my $savevm_wait = sub {
4232 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
4233 if (!$stat->{status
}) {
4234 die "savevm not active\n";
4235 } elsif ($stat->{status
} eq 'active') {
4238 } elsif ($stat->{status
} eq 'completed') {
4241 die "query-savevm returned status '$stat->{status}'\n";
4246 sub snapshot_create
{
4247 my ($vmid, $snapname, $save_vmstate, $freezefs, $comment) = @_;
4249 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
4251 $freezefs = $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
4255 my $running = check_running
($vmid);
4258 # create internal snapshots of all drives
4260 my $storecfg = PVE
::Storage
::config
();
4263 if ($snap->{vmstate
}) {
4264 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
4265 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
4266 &$savevm_wait($vmid);
4268 vm_mon_cmd
($vmid, "savevm-start");
4272 qga_freezefs
($vmid) if $running && $freezefs;
4274 foreach_drive
($snap, sub {
4275 my ($ds, $drive) = @_;
4277 return if drive_is_cdrom
($drive);
4279 my $volid = $drive->{file
};
4280 my $device = "drive-$ds";
4282 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
4283 $drivehash->{$ds} = 1;
4288 eval { gqa_unfreezefs
($vmid) if $running && $freezefs; };
4291 eval { vm_mon_cmd
($vmid, "savevm-end") if $running; };
4295 warn "snapshot create failed: starting cleanup\n";
4296 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
4301 &$snapshot_commit($vmid, $snapname);
4304 # Note: $drivehash is only set when called from snapshot_create.
4305 sub snapshot_delete
{
4306 my ($vmid, $snapname, $force, $drivehash) = @_;
4313 my $unlink_parent = sub {
4314 my ($confref, $new_parent) = @_;
4316 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
4318 $confref->{parent
} = $new_parent;
4320 delete $confref->{parent
};
4325 my $updatefn = sub {
4326 my ($remove_drive) = @_;
4328 my $conf = load_config
($vmid);
4332 die "you can't delete a snapshot if vm is a template\n"
4333 if is_template
($conf);
4336 $snap = $conf->{snapshots
}->{$snapname};
4338 die "snapshot '$snapname' does not exist\n" if !defined($snap);
4340 # remove parent refs
4341 &$unlink_parent($conf, $snap->{parent
});
4342 foreach my $sn (keys %{$conf->{snapshots
}}) {
4343 next if $sn eq $snapname;
4344 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
4347 if ($remove_drive) {
4348 if ($remove_drive eq 'vmstate') {
4349 delete $snap->{$remove_drive};
4351 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
4352 my $volid = $drive->{file
};
4353 delete $snap->{$remove_drive};
4354 add_unused_volume
($conf, $volid);
4359 $snap->{snapstate
} = 'delete';
4361 delete $conf->{snapshots
}->{$snapname};
4362 delete $conf->{lock} if $drivehash;
4363 foreach my $volid (@$unused) {
4364 add_unused_volume
($conf, $volid);
4368 update_config_nolock
($vmid, $conf, 1);
4371 lock_config
($vmid, $updatefn);
4373 # now remove vmstate file
4375 my $storecfg = PVE
::Storage
::config
();
4377 if ($snap->{vmstate
}) {
4378 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
4380 die $err if !$force;
4383 # save changes (remove vmstate from snapshot)
4384 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
4387 # now remove all internal snapshots
4388 foreach_drive
($snap, sub {
4389 my ($ds, $drive) = @_;
4391 return if drive_is_cdrom
($drive);
4393 my $volid = $drive->{file
};
4394 my $device = "drive-$ds";
4396 if (!$drivehash || $drivehash->{$ds}) {
4397 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
4399 die $err if !$force;
4404 # save changes (remove drive fron snapshot)
4405 lock_config
($vmid, $updatefn, $ds) if !$force;
4406 push @$unused, $volid;
4409 # now cleanup config
4411 lock_config
($vmid, $updatefn);
4415 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
4418 foreach_drive
($conf, sub {
4419 my ($ds, $drive) = @_;
4421 return if drive_is_cdrom
($drive);
4422 my $volid = $drive->{file
};
4423 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
4429 sub template_create
{
4430 my ($vmid, $conf, $disk) = @_;
4432 my $running = check_running
($vmid);
4433 die "you can't convert a vm to template if vm is running vm\n" if $running;
4435 my $storecfg = PVE
::Storage
::config
();
4438 foreach_drive
($conf, sub {
4439 my ($ds, $drive) = @_;
4441 return if drive_is_cdrom
($drive);
4442 return if $disk && $ds ne $disk;
4444 my $volid = $drive->{file
};
4445 die "volume '$volid' does not support template/clone\n"
4446 if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
4449 foreach_drive
($conf, sub {
4450 my ($ds, $drive) = @_;
4452 return if drive_is_cdrom
($drive);
4453 return if $disk && $ds ne $disk;
4455 my $volid = $drive->{file
};
4456 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
4457 $drive->{file
} = $voliddst;
4458 $conf->{$ds} = PVE
::QemuServer
::print_drive
($vmid, $drive);
4459 PVE
::QemuServer
::update_config_nolock
($vmid, $conf, 1);
4462 if($conf->{snapshots
}){
4463 delete $conf->{parent
};
4464 delete $conf->{snapshots
};
4465 PVE
::QemuServer
::update_config_nolock
($vmid, $conf, 1);
4466 #fixme : do we need to delete disks snapshots ?
4473 my $baseimagecount = 0;
4474 my $totalvolumecount = 0;
4475 my $storecfg = PVE
::Storage
::config
();
4477 foreach_drive
($conf, sub {
4478 my ($ds, $drive) = @_;
4479 return if drive_is_cdrom
($drive);
4480 $totalvolumecount++;
4481 my $volid = $drive->{file
};
4482 if (PVE
::Storage
::volume_is_base
($storecfg, $volid)){
4488 return 0 if $baseimagecount == 0;
4489 return 1 if $baseimagecount == $totalvolumecount; #full template
4490 return 2 if $baseimagecount < $totalvolumecount; #semi-template