1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
33 use File
::Copy
qw(copy);
35 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
37 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
39 # Note about locking: we use flock on the config file protect
40 # against concurent actions.
41 # Aditionaly, we have a 'lock' setting in the config file. This
42 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
43 # allowed when such lock is set. But you can ignore this kind of
44 # lock with the --skiplock flag.
46 cfs_register_file
('/qemu-server/',
50 PVE
::JSONSchema
::register_standard_option
('skiplock', {
51 description
=> "Ignore locks - only root is allowed to use this option.",
56 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
57 description
=> "Some command save/restore state from this location.",
63 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
64 description
=> "The name of the snapshot.",
65 type
=> 'string', format
=> 'pve-configid',
69 #no warnings 'redefine';
72 my ($controller, $vmid, $option, $value) = @_;
74 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
75 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
79 my $nodename = PVE
::INotify
::nodename
();
81 mkdir "/etc/pve/nodes/$nodename";
82 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
85 my $var_run_tmpdir = "/var/run/qemu-server";
86 mkdir $var_run_tmpdir;
88 my $lock_dir = "/var/lock/qemu-server";
91 my $pcisysfs = "/sys/bus/pci";
95 description
=> "Emulated CPU type.",
97 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Haswell-noTSX Broadwell Broadwell-noTSX Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
102 description
=> "Do not identify as a KVM virtual machine.",
113 description
=> "Specifies whether a VM will be started during system bootup.",
119 description
=> "Automatic restart after crash (currently ignored).",
124 type
=> 'string', format
=> 'pve-hotplug-features',
125 description
=> "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
126 default => 'network,disk,usb',
131 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
137 description
=> "Lock/unlock the VM.",
138 enum
=> [qw(migrate backup snapshot rollback)],
143 description
=> "Limit of CPU usage. Note if the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
151 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.",
159 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
166 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
172 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",
180 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
181 enum
=> PVE
::Tools
::kvmkeymaplist
(),
186 type
=> 'string', format
=> 'dns-name',
187 description
=> "Set a name for the VM. Only used on the configuration web interface.",
192 description
=> "scsi controller model",
193 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
199 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
204 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
205 description
=> <<EODESC,
206 Used to enable special optimization/features for specific
209 other => unspecified OS
210 wxp => Microsoft Windows XP
211 w2k => Microsoft Windows 2000
212 w2k3 => Microsoft Windows 2003
213 w2k8 => Microsoft Windows 2008
214 wvista => Microsoft Windows Vista
215 win7 => Microsoft Windows 7
216 win8 => Microsoft Windows 8/2012
217 l24 => Linux 2.4 Kernel
218 l26 => Linux 2.6/3.X Kernel
219 solaris => solaris/opensolaris/openindiania kernel
221 other|l24|l26|solaris ... no special behaviour
222 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
228 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
229 pattern
=> '[acdn]{1,4}',
234 type
=> 'string', format
=> 'pve-qm-bootdisk',
235 description
=> "Enable booting from specified disk.",
236 pattern
=> '(ide|sata|scsi|virtio)\d+',
241 description
=> "The number of CPUs. Please use option -sockets instead.",
248 description
=> "The number of CPU sockets.",
255 description
=> "The number of cores per socket.",
262 description
=> "Enable/disable Numa.",
268 description
=> "Number of hotplugged vcpus.",
275 description
=> "Enable/disable ACPI.",
281 description
=> "Enable/disable Qemu GuestAgent.",
287 description
=> "Enable/disable KVM hardware virtualization.",
293 description
=> "Enable/disable time drift fix.",
299 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
304 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
309 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. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
310 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
314 type
=> 'string', format
=> 'pve-qm-watchdog',
315 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
316 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)",
321 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
322 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'.",
323 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
326 startup
=> get_standard_option
('pve-startup-order'),
330 description
=> "Enable/disable Template.",
336 description
=> <<EODESCR,
337 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
339 args: -no-reboot -no-hpet
346 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. 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. This is turned of by default if you use spice (vga=qxl).",
351 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
355 migrate_downtime
=> {
358 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
364 type
=> 'string', format
=> 'pve-qm-drive',
365 typetext
=> 'volume',
366 description
=> "This is an alias for option -ide2",
370 description
=> "Emulated CPU type.",
374 parent
=> get_standard_option
('pve-snapshot-name', {
376 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
380 description
=> "Timestamp for snapshots.",
386 type
=> 'string', format
=> 'pve-volume-id',
387 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
390 description
=> "Specific the Qemu machine type.",
392 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
397 description
=> "Specify SMBIOS type 1 fields.",
398 type
=> 'string', format
=> 'pve-qm-smbios1',
405 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
411 enum
=> [ qw(seabios ovmf) ],
412 description
=> "Select BIOS implementation.",
413 default => 'seabios',
417 # what about other qemu settings ?
419 #machine => 'string',
432 ##soundhw => 'string',
434 while (my ($k, $v) = each %$confdesc) {
435 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
438 my $MAX_IDE_DISKS = 4;
439 my $MAX_SCSI_DISKS = 14;
440 my $MAX_VIRTIO_DISKS = 16;
441 my $MAX_SATA_DISKS = 6;
442 my $MAX_USB_DEVICES = 5;
444 my $MAX_UNUSED_DISKS = 8;
445 my $MAX_HOSTPCI_DEVICES = 4;
446 my $MAX_SERIAL_PORTS = 4;
447 my $MAX_PARALLEL_PORTS = 3;
449 my $MAX_MEM = 4194304;
450 my $STATICMEM = 1024;
454 type
=> 'string', format
=> 'pve-qm-numanode',
455 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
456 description
=> "numa topology",
458 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
460 for (my $i = 0; $i < $MAX_NUMA; $i++) {
461 $confdesc->{"numa$i"} = $numadesc;
464 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
465 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
466 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
467 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
471 type
=> 'string', format
=> 'pve-qm-net',
472 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,trunks=<vlanid[;vlanid]>][,firewall=0|1],link_down=0|1]",
473 description
=> <<EODESCR,
474 Specify network devices.
476 MODEL is one of: $nic_model_list_txt
478 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
479 automatically generated if not specified.
481 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
483 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'.
485 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
491 The DHCP server assign addresses to the guest starting from 10.0.2.15.
495 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
497 for (my $i = 0; $i < $MAX_NETS; $i++) {
498 $confdesc->{"net$i"} = $netdesc;
503 my %drivedesc_base = (
504 volume
=> { alias
=> 'file' },
506 type
=> 'pve-volume-id',
508 format_description
=> 'volume',
509 description
=> "The drive's backing volume.",
513 format_description
=> 'cdrom|disk',
514 enum
=> [qw(cdrom disk)],
515 description
=> "The drive's media type.",
521 format_description
=> 'count',
522 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
527 format_description
=> 'count',
528 description
=> "Force the drive's physical geometry to have a specific head count.",
533 format_description
=> 'count',
534 description
=> "Force the drive's physical geometry to have a specific sector count.",
539 format_description
=> 'none|lba|auto',
540 enum
=> [qw(none lba auto)],
541 description
=> "Force disk geometry bios translation mode.",
546 format_description
=> 'on|off',
547 description
=> "Whether the drive should be included when making snapshots.",
552 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
553 enum
=> [qw(none writethrough writeback unsafe directsync)],
554 description
=> "The drive's cache mode",
559 format_description
=> 'drive format',
560 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
561 description
=> "The drive's backing file's data format.",
566 format
=> 'disk-size',
567 description
=> "Disk size. This is purely informational and has no effect.",
572 format_description
=> 'on|off',
573 description
=> "Whether the drive should be included when making backups.",
578 format_description
=> 'enospc|ignore|report|stop',
579 enum
=> [qw(enospc ignore report stop)],
580 description
=> 'Write error action.',
585 format_description
=> 'native|threads',
586 enum
=> [qw(native threads)],
587 description
=> 'AIO type to use.',
592 format_description
=> 'ignore|on',
593 enum
=> [qw(ignore on)],
594 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
599 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
604 format_description
=> 'serial',
605 description
=> "The drive's reported serial number.",
613 format_description
=> 'ignore|report|stop',
614 enum
=> [qw(ignore report stop)],
615 description
=> 'Read error action.',
620 my %iothread_fmt = ( iothread
=> {
622 format_description
=> 'off|on',
623 description
=> "Whether to use iothreads for this drive",
630 format_description
=> 'model',
631 description
=> "The drive's reported model name.",
639 format_description
=> 'nbqueues',
640 description
=> "Number of queues.",
646 my $add_throttle_desc = sub {
647 my ($key, $type, $what, $size, $longsize) = @_;
648 $drivedesc_base{$key} = {
650 format_description
=> $size,
651 description
=> "Maximum $what speed in $longsize per second.",
655 # throughput: (leaky bucket)
656 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
657 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
658 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
659 $add_throttle_desc->('mbps', 'float', 'r/w speed', 'mbps', 'megabytes');
660 $add_throttle_desc->('mbps_rd', 'float', 'read speed', 'mbps', 'megabytes');
661 $add_throttle_desc->('mbps_wr', 'float', 'write speed', 'mbps', 'megabytes');
662 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
663 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
664 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
666 # pools: (pool of IO before throttling starts taking effect)
667 $add_throttle_desc->('mbps_max', 'float', 'unthrottled r/w pool', 'mbps', 'megabytes');
668 $add_throttle_desc->('mbps_rd_max', 'float', 'unthrottled read pool', 'mbps', 'megabytes');
669 $add_throttle_desc->('mbps_wr_max', 'float', 'unthrottled write pool', 'mbps', 'megabytes');
670 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
671 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
672 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
682 type
=> 'string', format
=> $ide_fmt,
683 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
685 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
694 type
=> 'string', format
=> $scsi_fmt,
695 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
697 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
705 type
=> 'string', format
=> $sata_fmt,
706 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
708 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
717 type
=> 'string', format
=> $virtio_fmt,
718 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
720 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
733 type
=> 'string', format
=> 'pve-qm-usb-device',
734 format_description
=> 'HOSTUSBDEVICE|spice',
735 description
=> 'The Host USB device or port or the value spice',
740 format_description
=> 'yes|no',
741 description
=> 'Specifies whether if given host option is a USB3 device or port',
747 type
=> 'string', format
=> $usbformat,
748 description
=> <<EODESCR,
749 Configure an USB device (n is 0 to 4). This can be used to
750 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
752 'bus-port(.port)*' (decimal numbers) or
753 'vendor_id:product_id' (hexadeciaml numbers) or
756 You can use the 'lsusb -t' command to list existing usb devices.
758 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
760 The value 'spice' can be used to add a usb redirection devices for spice.
762 The 'usb3' option determines whether the device is a USB3 device or not (this does currently not work reliably with spice redirection and is then ignored).
766 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
770 type
=> 'string', format
=> 'pve-qm-hostpci',
771 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
772 description
=> <<EODESCR,
773 Map host pci devices. HOSTPCIDEVICE syntax is:
775 'bus:dev.func' (hexadecimal numbers)
777 You can us the 'lspci' command to list existing pci devices.
779 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
781 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
783 Experimental: user reported problems with this option.
786 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
791 pattern
=> '(/dev/.+|socket)',
792 description
=> <<EODESCR,
793 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
795 Note: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
797 Experimental: user reported problems with this option.
804 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
805 description
=> <<EODESCR,
806 Map host parallel devices (n is 0 to 2).
808 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
810 Experimental: user reported problems with this option.
814 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
815 $confdesc->{"parallel$i"} = $paralleldesc;
818 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
819 $confdesc->{"serial$i"} = $serialdesc;
822 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
823 $confdesc->{"hostpci$i"} = $hostpcidesc;
826 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
827 $drivename_hash->{"ide$i"} = 1;
828 $confdesc->{"ide$i"} = $idedesc;
831 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
832 $drivename_hash->{"sata$i"} = 1;
833 $confdesc->{"sata$i"} = $satadesc;
836 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
837 $drivename_hash->{"scsi$i"} = 1;
838 $confdesc->{"scsi$i"} = $scsidesc ;
841 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
842 $drivename_hash->{"virtio$i"} = 1;
843 $confdesc->{"virtio$i"} = $virtiodesc;
846 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
847 $confdesc->{"usb$i"} = $usbdesc;
852 type
=> 'string', format
=> 'pve-volume-id',
853 description
=> "Reference to unused volumes.",
856 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
857 $confdesc->{"unused$i"} = $unuseddesc;
860 my $kvm_api_version = 0;
864 return $kvm_api_version if $kvm_api_version;
866 my $fh = IO
::File-
>new("</dev/kvm") ||
869 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
870 $kvm_api_version = $v;
875 return $kvm_api_version;
878 my $kvm_user_version;
880 sub kvm_user_version
{
882 return $kvm_user_version if $kvm_user_version;
884 $kvm_user_version = 'unknown';
888 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
889 $kvm_user_version = $2;
893 eval { run_command
("kvm -version", outfunc
=> $code); };
896 return $kvm_user_version;
900 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
902 sub valid_drive_names
{
903 # order is important - used to autoselect boot disk
904 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
905 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
906 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
907 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
910 sub is_valid_drivename
{
913 return defined($drivename_hash->{$dev});
918 return defined($confdesc->{$key});
922 return $nic_model_list;
925 sub os_list_description
{
930 w2k
=> 'Windows 2000',
931 w2k3
=>, 'Windows 2003',
932 w2k8
=> 'Windows 2008',
933 wvista
=> 'Windows Vista',
935 win8
=> 'Windows 8/2012',
945 return $cdrom_path if $cdrom_path;
947 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
948 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
949 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
953 my ($storecfg, $vmid, $cdrom) = @_;
955 if ($cdrom eq 'cdrom') {
956 return get_cdrom_path
();
957 } elsif ($cdrom eq 'none') {
959 } elsif ($cdrom =~ m
|^/|) {
962 return PVE
::Storage
::path
($storecfg, $cdrom);
966 # try to convert old style file names to volume IDs
967 sub filename_to_volume_id
{
968 my ($vmid, $file, $media) = @_;
970 if (!($file eq 'none' || $file eq 'cdrom' ||
971 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
973 return undef if $file =~ m
|/|;
975 if ($media && $media eq 'cdrom') {
976 $file = "local:iso/$file";
978 $file = "local:$vmid/$file";
985 sub verify_media_type
{
986 my ($opt, $vtype, $media) = @_;
991 if ($media eq 'disk') {
993 } elsif ($media eq 'cdrom') {
996 die "internal error";
999 return if ($vtype eq $etype);
1001 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1004 sub cleanup_drive_path
{
1005 my ($opt, $storecfg, $drive) = @_;
1007 # try to convert filesystem paths to volume IDs
1009 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1010 ($drive->{file
} !~ m
|^/dev/.+|) &&
1011 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1012 ($drive->{file
} !~ m/^\d+$/)) {
1013 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1014 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1015 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1016 verify_media_type
($opt, $vtype, $drive->{media
});
1017 $drive->{file
} = $volid;
1020 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1023 sub parse_hotplug_features
{
1028 return $res if $data eq '0';
1030 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1032 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1033 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1036 warn "ignoring unknown hotplug feature '$feature'\n";
1042 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1043 sub pve_verify_hotplug_features
{
1044 my ($value, $noerr) = @_;
1046 return $value if parse_hotplug_features
($value);
1048 return undef if $noerr;
1050 die "unable to parse hotplug option\n";
1053 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1054 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1055 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1056 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1057 # [,iothread=on][,serial=serial][,model=model]
1060 my ($key, $data) = @_;
1062 my ($interface, $index);
1064 if ($key =~ m/^([^\d]+)(\d+)$/) {
1071 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1072 : $confdesc->{$key}->{format
};
1074 warn "invalid drive key: $key\n";
1077 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1078 return undef if !$res;
1079 $res->{interface
} = $interface;
1080 $res->{index} = $index;
1083 foreach my $opt (qw(bps bps_rd bps_wr)) {
1084 if (my $bps = defined(delete $res->{$opt})) {
1085 if (defined($res->{"m$opt"})) {
1086 warn "both $opt and m$opt specified\n";
1090 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1093 return undef if $error;
1095 return undef if $res->{mbps_rd
} && $res->{mbps
};
1096 return undef if $res->{mbps_wr
} && $res->{mbps
};
1097 return undef if $res->{iops_rd
} && $res->{iops
};
1098 return undef if $res->{iops_wr
} && $res->{iops
};
1100 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1101 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1102 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1103 return undef if $res->{interface
} eq 'virtio';
1106 if (my $size = $res->{size
}) {
1107 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1114 my ($vmid, $drive) = @_;
1115 my $data = { %$drive };
1116 delete $data->{$_} for qw(index interface);
1117 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1121 my($fh, $noerr) = @_;
1124 my $SG_GET_VERSION_NUM = 0x2282;
1126 my $versionbuf = "\x00" x
8;
1127 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1129 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1132 my $version = unpack("I", $versionbuf);
1133 if ($version < 30000) {
1134 die "scsi generic interface too old\n" if !$noerr;
1138 my $buf = "\x00" x
36;
1139 my $sensebuf = "\x00" x
8;
1140 my $cmd = pack("C x3 C x1", 0x12, 36);
1142 # see /usr/include/scsi/sg.h
1143 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";
1145 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1146 length($sensebuf), 0, length($buf), $buf,
1147 $cmd, $sensebuf, 6000);
1149 $ret = ioctl($fh, $SG_IO, $packet);
1151 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1155 my @res = unpack($sg_io_hdr_t, $packet);
1156 if ($res[17] || $res[18]) {
1157 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1162 (my $byte0, my $byte1, $res->{vendor
},
1163 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1165 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1166 $res->{type
} = $byte0 & 31;
1174 my $fh = IO
::File-
>new("+<$path") || return undef;
1175 my $res = scsi_inquiry
($fh, 1);
1181 sub machine_type_is_q35
{
1184 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1187 sub print_tabletdevice_full
{
1190 my $q35 = machine_type_is_q35
($conf);
1192 # we use uhci for old VMs because tablet driver was buggy in older qemu
1193 my $usbbus = $q35 ?
"ehci" : "uhci";
1195 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1198 sub print_drivedevice_full
{
1199 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1204 if ($drive->{interface
} eq 'virtio') {
1205 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1206 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1207 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1208 } elsif ($drive->{interface
} eq 'scsi') {
1210 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1211 my $unit = $drive->{index} % $maxdev;
1212 my $devicetype = 'hd';
1214 if (drive_is_cdrom
($drive)) {
1217 if ($drive->{file
} =~ m
|^/|) {
1218 $path = $drive->{file
};
1219 if (my $info = path_is_scsi
($path)) {
1220 if ($info->{type
} == 0) {
1221 $devicetype = 'block';
1222 } elsif ($info->{type
} == 1) { # tape
1223 $devicetype = 'generic';
1227 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1230 if($path =~ m/^iscsi\:\/\
//){
1231 $devicetype = 'generic';
1235 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1236 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1238 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,channel=0,scsi-id=0,lun=$drive->{index},drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1241 } elsif ($drive->{interface
} eq 'ide'){
1243 my $controller = int($drive->{index} / $maxdev);
1244 my $unit = $drive->{index} % $maxdev;
1245 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1247 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1248 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1249 $device .= ",model=$model";
1251 } elsif ($drive->{interface
} eq 'sata'){
1252 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1253 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1254 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1255 } elsif ($drive->{interface
} eq 'usb') {
1257 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1259 die "unsupported interface type";
1262 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1267 sub get_initiator_name
{
1270 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1271 while (defined(my $line = <$fh>)) {
1272 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1281 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max serial);
1282 sub print_drive_full
{
1283 my ($storecfg, $vmid, $drive) = @_;
1286 my $volid = $drive->{file
};
1289 if (drive_is_cdrom
($drive)) {
1290 $path = get_iso_path
($storecfg, $vmid, $volid);
1292 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1294 $path = PVE
::Storage
::path
($storecfg, $volid);
1295 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1296 $format = qemu_img_format
($scfg, $volname);
1304 foreach my $o (@qemu_drive_options) {
1305 next if $o eq 'bootindex';
1306 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1309 $opts .= ",format=$format" if $format && !$drive->{format
};
1311 foreach my $o (qw(bps bps_rd bps_wr)) {
1312 my $v = $drive->{"m$o"};
1313 $opts .= ",$o=" . int($v*1024*1024) if $v;
1316 my $cache_direct = 0;
1318 if (my $cache = $drive->{cache
}) {
1319 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1320 } elsif (!drive_is_cdrom
($drive)) {
1321 $opts .= ",cache=none";
1325 # aio native works only with O_DIRECT
1326 if (!$drive->{aio
}) {
1328 $opts .= ",aio=native";
1330 $opts .= ",aio=threads";
1334 if (!drive_is_cdrom
($drive)) {
1336 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1337 $detectzeroes = 'off';
1338 } elsif ($drive->{discard
}) {
1339 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1341 # This used to be our default with discard not being specified:
1342 $detectzeroes = 'on';
1344 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1347 my $pathinfo = $path ?
"file=$path," : '';
1349 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1352 sub print_netdevice_full
{
1353 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1355 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1357 my $device = $net->{model
};
1358 if ($net->{model
} eq 'virtio') {
1359 $device = 'virtio-net-pci';
1362 my $pciaddr = print_pci_addr
("$netid", $bridges);
1363 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1364 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1365 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1366 my $vectors = $net->{queues
} * 2 + 2;
1367 $tmpstr .= ",vectors=$vectors,mq=on";
1369 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1371 if ($use_old_bios_files) {
1373 if ($device eq 'virtio-net-pci') {
1374 $romfile = 'pxe-virtio.rom';
1375 } elsif ($device eq 'e1000') {
1376 $romfile = 'pxe-e1000.rom';
1377 } elsif ($device eq 'ne2k') {
1378 $romfile = 'pxe-ne2k_pci.rom';
1379 } elsif ($device eq 'pcnet') {
1380 $romfile = 'pxe-pcnet.rom';
1381 } elsif ($device eq 'rtl8139') {
1382 $romfile = 'pxe-rtl8139.rom';
1384 $tmpstr .= ",romfile=$romfile" if $romfile;
1390 sub print_netdev_full
{
1391 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1394 if ($netid =~ m/^net(\d+)$/) {
1398 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1400 my $ifname = "tap${vmid}i$i";
1402 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1403 die "interface name '$ifname' is too long (max 15 character)\n"
1404 if length($ifname) >= 16;
1406 my $vhostparam = '';
1407 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1409 my $vmname = $conf->{name
} || "vm$vmid";
1412 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1414 if ($net->{bridge
}) {
1415 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1417 $netdev = "type=user,id=$netid,hostname=$vmname";
1420 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1425 sub drive_is_cdrom
{
1428 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1437 foreach my $kvp (split(/,/, $data)) {
1439 if ($kvp =~ m/^memory=(\S+)$/) {
1440 $res->{memory
} = $1;
1441 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1442 $res->{policy
} = $1;
1443 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1444 $res->{cpus
}->{start
} = $1;
1445 $res->{cpus
}->{end
} = $3;
1446 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1447 $res->{hostnodes
}->{start
} = $1;
1448 $res->{hostnodes
}->{end
} = $3;
1460 return undef if !$value;
1463 my @list = split(/,/, $value);
1467 foreach my $kv (@list) {
1469 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1472 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1475 my $pcidevices = lspci
($2);
1476 $res->{pciid
} = $pcidevices->{$2};
1478 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1479 $res->{rombar
} = $1;
1480 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1481 $res->{'x-vga'} = $1;
1482 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1483 $res->{pcie
} = 1 if $1 == 1;
1485 warn "unknown hostpci setting '$kv'\n";
1489 return undef if !$found;
1494 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1500 foreach my $kvp (split(/,/, $data)) {
1502 if ($kvp =~ m/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1504 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1505 $res->{model
} = $model;
1506 $res->{macaddr
} = $mac;
1507 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1508 $res->{bridge
} = $1;
1509 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1510 $res->{queues
} = $1;
1511 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1513 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1515 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1516 $res->{trunks
} = $1;
1517 } elsif ($kvp =~ m/^firewall=([01])$/) {
1518 $res->{firewall
} = $1;
1519 } elsif ($kvp =~ m/^link_down=([01])$/) {
1520 $res->{link_down
} = $1;
1527 return undef if !$res->{model
};
1535 my $res = "$net->{model}";
1536 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1537 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1538 $res .= ",rate=$net->{rate}" if $net->{rate
};
1539 $res .= ",tag=$net->{tag}" if $net->{tag
};
1540 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1541 $res .= ",firewall=1" if $net->{firewall
};
1542 $res .= ",link_down=1" if $net->{link_down
};
1543 $res .= ",queues=$net->{queues}" if $net->{queues
};
1548 sub add_random_macs
{
1549 my ($settings) = @_;
1551 foreach my $opt (keys %$settings) {
1552 next if $opt !~ m/^net(\d+)$/;
1553 my $net = parse_net
($settings->{$opt});
1555 $settings->{$opt} = print_net
($net);
1559 sub add_unused_volume
{
1560 my ($config, $volid) = @_;
1563 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1564 my $test = "unused$ind";
1565 if (my $vid = $config->{$test}) {
1566 return if $vid eq $volid; # do not add duplicates
1572 die "To many unused volume - please delete them first.\n" if !$key;
1574 $config->{$key} = $volid;
1579 sub vm_is_volid_owner
{
1580 my ($storecfg, $vmid, $volid) = @_;
1582 if ($volid !~ m
|^/|) {
1584 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1585 if ($owner && ($owner == $vmid)) {
1593 sub split_flagged_list
{
1594 my $text = shift || '';
1595 $text =~ s/[,;]/ /g;
1597 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1600 sub join_flagged_list
{
1601 my ($how, $lst) = @_;
1602 join $how, map { $lst->{$_} . $_ } keys %$lst;
1605 sub vmconfig_delete_pending_option
{
1606 my ($conf, $key, $force) = @_;
1608 delete $conf->{pending
}->{$key};
1609 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1610 $pending_delete_hash->{$key} = $force ?
'!' : '';
1611 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1614 sub vmconfig_undelete_pending_option
{
1615 my ($conf, $key) = @_;
1617 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1618 delete $pending_delete_hash->{$key};
1620 if (%$pending_delete_hash) {
1621 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1623 delete $conf->{pending
}->{delete};
1627 sub vmconfig_register_unused_drive
{
1628 my ($storecfg, $vmid, $conf, $drive) = @_;
1630 if (!drive_is_cdrom
($drive)) {
1631 my $volid = $drive->{file
};
1632 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1633 add_unused_volume
($conf, $volid, $vmid);
1638 sub vmconfig_cleanup_pending
{
1641 # remove pending changes when nothing changed
1643 foreach my $opt (keys %{$conf->{pending
}}) {
1644 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1646 delete $conf->{pending
}->{$opt};
1650 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1651 my $pending_delete_hash = {};
1652 while (my ($opt, $force) = each %$current_delete_hash) {
1653 if (defined($conf->{$opt})) {
1654 $pending_delete_hash->{$opt} = $force;
1660 if (%$pending_delete_hash) {
1661 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1663 delete $conf->{pending
}->{delete};
1669 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1670 my $smbios1_desc = {
1673 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1674 format_description
=> 'UUID',
1680 format_description
=> 'str',
1686 format_description
=> 'str',
1692 format_description
=> 'name',
1698 format_description
=> 'name',
1704 format_description
=> 'str',
1710 format_description
=> 'str',
1718 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_desc, $data) };
1725 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_desc);
1728 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_desc);
1730 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1731 sub verify_bootdisk
{
1732 my ($value, $noerr) = @_;
1734 return $value if is_valid_drivename
($value);
1736 return undef if $noerr;
1738 die "invalid boot disk '$value'\n";
1741 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1743 my ($value, $noerr) = @_;
1745 return $value if parse_numa
($value);
1747 return undef if $noerr;
1749 die "unable to parse numa options\n";
1752 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1754 my ($value, $noerr) = @_;
1756 return $value if parse_net
($value);
1758 return undef if $noerr;
1760 die "unable to parse network options\n";
1763 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1764 sub verify_hostpci
{
1765 my ($value, $noerr) = @_;
1767 return $value if parse_hostpci
($value);
1769 return undef if $noerr;
1771 die "unable to parse pci id\n";
1774 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1775 sub verify_watchdog
{
1776 my ($value, $noerr) = @_;
1778 return $value if parse_watchdog
($value);
1780 return undef if $noerr;
1782 die "unable to parse watchdog options\n";
1785 sub parse_watchdog
{
1788 return undef if !$value;
1792 foreach my $p (split(/,/, $value)) {
1793 next if $p =~ m/^\s*$/;
1795 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1797 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1798 $res->{action
} = $2;
1807 sub parse_usb_device
{
1810 return undef if !$value;
1813 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1814 $res->{vendorid
} = $2;
1815 $res->{productid
} = $4;
1816 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1817 $res->{hostbus
} = $1;
1818 $res->{hostport
} = $2;
1819 } elsif ($value =~ m/^spice$/i) {
1828 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1829 sub verify_usb_device
{
1830 my ($value, $noerr) = @_;
1832 return $value if parse_usb_device
($value);
1834 return undef if $noerr;
1836 die "unable to parse usb device\n";
1839 # add JSON properties for create and set function
1840 sub json_config_properties
{
1843 foreach my $opt (keys %$confdesc) {
1844 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1845 $prop->{$opt} = $confdesc->{$opt};
1852 my ($key, $value) = @_;
1854 die "unknown setting '$key'\n" if !$confdesc->{$key};
1856 my $type = $confdesc->{$key}->{type
};
1858 if (!defined($value)) {
1859 die "got undefined value\n";
1862 if ($value =~ m/[\n\r]/) {
1863 die "property contains a line feed\n";
1866 if ($type eq 'boolean') {
1867 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1868 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1869 die "type check ('boolean') failed - got '$value'\n";
1870 } elsif ($type eq 'integer') {
1871 return int($1) if $value =~ m/^(\d+)$/;
1872 die "type check ('integer') failed - got '$value'\n";
1873 } elsif ($type eq 'number') {
1874 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1875 die "type check ('number') failed - got '$value'\n";
1876 } elsif ($type eq 'string') {
1877 if (my $fmt = $confdesc->{$key}->{format
}) {
1878 if ($fmt eq 'pve-qm-drive') {
1879 # special case - we need to pass $key to parse_drive()
1880 my $drive = parse_drive
($key, $value);
1881 return $value if $drive;
1882 die "unable to parse drive options\n";
1884 PVE
::JSONSchema
::check_format
($fmt, $value);
1887 $value =~ s/^\"(.*)\"$/$1/;
1890 die "internal error"
1894 sub lock_config_full
{
1895 my ($vmid, $timeout, $code, @param) = @_;
1897 my $filename = config_file_lock
($vmid);
1899 my $res = lock_file
($filename, $timeout, $code, @param);
1906 sub lock_config_mode
{
1907 my ($vmid, $timeout, $shared, $code, @param) = @_;
1909 my $filename = config_file_lock
($vmid);
1911 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1919 my ($vmid, $code, @param) = @_;
1921 return lock_config_full
($vmid, 10, $code, @param);
1924 sub cfs_config_path
{
1925 my ($vmid, $node) = @_;
1927 $node = $nodename if !$node;
1928 return "nodes/$node/qemu-server/$vmid.conf";
1931 sub check_iommu_support
{
1932 #fixme : need to check IOMMU support
1933 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1941 my ($vmid, $node) = @_;
1943 my $cfspath = cfs_config_path
($vmid, $node);
1944 return "/etc/pve/$cfspath";
1947 sub config_file_lock
{
1950 return "$lock_dir/lock-$vmid.conf";
1956 my $conf = config_file
($vmid);
1957 utime undef, undef, $conf;
1961 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1963 my $conffile = config_file
($vmid);
1965 my $conf = load_config
($vmid);
1967 check_lock
($conf) if !$skiplock;
1969 # only remove disks owned by this VM
1970 foreach_drive
($conf, sub {
1971 my ($ds, $drive) = @_;
1973 return if drive_is_cdrom
($drive);
1975 my $volid = $drive->{file
};
1977 return if !$volid || $volid =~ m
|^/|;
1979 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1980 return if !$path || !$owner || ($owner != $vmid);
1982 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1985 if ($keep_empty_config) {
1986 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1991 # also remove unused disk
1993 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1996 PVE
::Storage
::foreach_volid
($dl, sub {
1997 my ($volid, $sid, $volname, $d) = @_;
1998 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2008 my ($vmid, $node) = @_;
2010 my $cfspath = cfs_config_path
($vmid, $node);
2012 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
2014 die "no such VM ('$vmid')\n" if !defined($conf);
2019 sub parse_vm_config
{
2020 my ($filename, $raw) = @_;
2022 return undef if !defined($raw);
2025 digest
=> Digest
::SHA
::sha1_hex
($raw),
2030 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2031 || die "got strange filename '$filename'";
2039 my @lines = split(/\n/, $raw);
2040 foreach my $line (@lines) {
2041 next if $line =~ m/^\s*$/;
2043 if ($line =~ m/^\[PENDING\]\s*$/i) {
2044 $section = 'pending';
2045 if (defined($descr)) {
2047 $conf->{description
} = $descr;
2050 $conf = $res->{$section} = {};
2053 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2055 if (defined($descr)) {
2057 $conf->{description
} = $descr;
2060 $conf = $res->{snapshots
}->{$section} = {};
2064 if ($line =~ m/^\#(.*)\s*$/) {
2065 $descr = '' if !defined($descr);
2066 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2070 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2071 $descr = '' if !defined($descr);
2072 $descr .= PVE
::Tools
::decode_text
($2);
2073 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2074 $conf->{snapstate
} = $1;
2075 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2078 $conf->{$key} = $value;
2079 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2081 if ($section eq 'pending') {
2082 $conf->{delete} = $value; # we parse this later
2084 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2086 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2089 eval { $value = check_type
($key, $value); };
2091 warn "vm $vmid - unable to parse value of '$key' - $@";
2093 my $fmt = $confdesc->{$key}->{format
};
2094 if ($fmt && $fmt eq 'pve-qm-drive') {
2095 my $v = parse_drive
($key, $value);
2096 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2097 $v->{file
} = $volid;
2098 $value = print_drive
($vmid, $v);
2100 warn "vm $vmid - unable to parse value of '$key'\n";
2105 if ($key eq 'cdrom') {
2106 $conf->{ide2
} = $value;
2108 $conf->{$key} = $value;
2114 if (defined($descr)) {
2116 $conf->{description
} = $descr;
2118 delete $res->{snapstate
}; # just to be sure
2123 sub write_vm_config
{
2124 my ($filename, $conf) = @_;
2126 delete $conf->{snapstate
}; # just to be sure
2128 if ($conf->{cdrom
}) {
2129 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2130 $conf->{ide2
} = $conf->{cdrom
};
2131 delete $conf->{cdrom
};
2134 # we do not use 'smp' any longer
2135 if ($conf->{sockets
}) {
2136 delete $conf->{smp
};
2137 } elsif ($conf->{smp
}) {
2138 $conf->{sockets
} = $conf->{smp
};
2139 delete $conf->{cores
};
2140 delete $conf->{smp
};
2143 my $used_volids = {};
2145 my $cleanup_config = sub {
2146 my ($cref, $pending, $snapname) = @_;
2148 foreach my $key (keys %$cref) {
2149 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2150 $key eq 'snapstate' || $key eq 'pending';
2151 my $value = $cref->{$key};
2152 if ($key eq 'delete') {
2153 die "propertry 'delete' is only allowed in [PENDING]\n"
2155 # fixme: check syntax?
2158 eval { $value = check_type
($key, $value); };
2159 die "unable to parse value of '$key' - $@" if $@;
2161 $cref->{$key} = $value;
2163 if (!$snapname && is_valid_drivename
($key)) {
2164 my $drive = parse_drive
($key, $value);
2165 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2170 &$cleanup_config($conf);
2172 &$cleanup_config($conf->{pending
}, 1);
2174 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2175 die "internal error" if $snapname eq 'pending';
2176 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2179 # remove 'unusedX' settings if we re-add a volume
2180 foreach my $key (keys %$conf) {
2181 my $value = $conf->{$key};
2182 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2183 delete $conf->{$key};
2187 my $generate_raw_config = sub {
2188 my ($conf, $pending) = @_;
2192 # add description as comment to top of file
2193 if (defined(my $descr = $conf->{description
})) {
2195 foreach my $cl (split(/\n/, $descr)) {
2196 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2199 $raw .= "#\n" if $pending;
2203 foreach my $key (sort keys %$conf) {
2204 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2205 $raw .= "$key: $conf->{$key}\n";
2210 my $raw = &$generate_raw_config($conf);
2212 if (scalar(keys %{$conf->{pending
}})){
2213 $raw .= "\n[PENDING]\n";
2214 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2217 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2218 $raw .= "\n[$snapname]\n";
2219 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2226 my ($vmid, $conf) = @_;
2228 my $cfspath = cfs_config_path
($vmid);
2230 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2237 # we use static defaults from our JSON schema configuration
2238 foreach my $key (keys %$confdesc) {
2239 if (defined(my $default = $confdesc->{$key}->{default})) {
2240 $res->{$key} = $default;
2244 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2245 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2251 my $vmlist = PVE
::Cluster
::get_vmlist
();
2253 return $res if !$vmlist || !$vmlist->{ids
};
2254 my $ids = $vmlist->{ids
};
2256 foreach my $vmid (keys %$ids) {
2257 my $d = $ids->{$vmid};
2258 next if !$d->{node
} || $d->{node
} ne $nodename;
2259 next if !$d->{type
} || $d->{type
} ne 'qemu';
2260 $res->{$vmid}->{exists} = 1;
2265 # test if VM uses local resources (to prevent migration)
2266 sub check_local_resources
{
2267 my ($conf, $noerr) = @_;
2271 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2272 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2274 foreach my $k (keys %$conf) {
2275 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2276 # sockets are safe: they will recreated be on the target side post-migrate
2277 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2278 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2281 die "VM uses local resources\n" if $loc_res && !$noerr;
2286 # check if used storages are available on all nodes (use by migrate)
2287 sub check_storage_availability
{
2288 my ($storecfg, $conf, $node) = @_;
2290 foreach_drive
($conf, sub {
2291 my ($ds, $drive) = @_;
2293 my $volid = $drive->{file
};
2296 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2299 # check if storage is available on both nodes
2300 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2301 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2305 # list nodes where all VM images are available (used by has_feature API)
2307 my ($conf, $storecfg) = @_;
2309 my $nodelist = PVE
::Cluster
::get_nodelist
();
2310 my $nodehash = { map { $_ => 1 } @$nodelist };
2311 my $nodename = PVE
::INotify
::nodename
();
2313 foreach_drive
($conf, sub {
2314 my ($ds, $drive) = @_;
2316 my $volid = $drive->{file
};
2319 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2321 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2322 if ($scfg->{disable
}) {
2324 } elsif (my $avail = $scfg->{nodes
}) {
2325 foreach my $node (keys %$nodehash) {
2326 delete $nodehash->{$node} if !$avail->{$node};
2328 } elsif (!$scfg->{shared
}) {
2329 foreach my $node (keys %$nodehash) {
2330 delete $nodehash->{$node} if $node ne $nodename
2342 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2346 my ($pidfile, $pid) = @_;
2348 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2352 return undef if !$line;
2353 my @param = split(/\0/, $line);
2355 my $cmd = $param[0];
2356 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2358 for (my $i = 0; $i < scalar (@param); $i++) {
2361 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2362 my $p = $param[$i+1];
2363 return 1 if $p && ($p eq $pidfile);
2372 my ($vmid, $nocheck, $node) = @_;
2374 my $filename = config_file
($vmid, $node);
2376 die "unable to find configuration file for VM $vmid - no such machine\n"
2377 if !$nocheck && ! -f
$filename;
2379 my $pidfile = pidfile_name
($vmid);
2381 if (my $fd = IO
::File-
>new("<$pidfile")) {
2386 my $mtime = $st->mtime;
2387 if ($mtime > time()) {
2388 warn "file '$filename' modified in future\n";
2391 if ($line =~ m/^(\d+)$/) {
2393 if (check_cmdline
($pidfile, $pid)) {
2394 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2406 my $vzlist = config_list
();
2408 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2410 while (defined(my $de = $fd->read)) {
2411 next if $de !~ m/^(\d+)\.pid$/;
2413 next if !defined($vzlist->{$vmid});
2414 if (my $pid = check_running
($vmid)) {
2415 $vzlist->{$vmid}->{pid
} = $pid;
2423 my ($storecfg, $conf) = @_;
2425 my $bootdisk = $conf->{bootdisk
};
2426 return undef if !$bootdisk;
2427 return undef if !is_valid_drivename
($bootdisk);
2429 return undef if !$conf->{$bootdisk};
2431 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2432 return undef if !defined($drive);
2434 return undef if drive_is_cdrom
($drive);
2436 my $volid = $drive->{file
};
2437 return undef if !$volid;
2439 return $drive->{size
};
2442 my $last_proc_pid_stat;
2444 # get VM status information
2445 # This must be fast and should not block ($full == false)
2446 # We only query KVM using QMP if $full == true (this can be slow)
2448 my ($opt_vmid, $full) = @_;
2452 my $storecfg = PVE
::Storage
::config
();
2454 my $list = vzlist
();
2455 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2457 my $cpucount = $cpuinfo->{cpus
} || 1;
2459 foreach my $vmid (keys %$list) {
2460 next if $opt_vmid && ($vmid ne $opt_vmid);
2462 my $cfspath = cfs_config_path
($vmid);
2463 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2466 $d->{pid
} = $list->{$vmid}->{pid
};
2468 # fixme: better status?
2469 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2471 my $size = disksize
($storecfg, $conf);
2472 if (defined($size)) {
2473 $d->{disk
} = 0; # no info available
2474 $d->{maxdisk
} = $size;
2480 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2481 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2482 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2484 $d->{name
} = $conf->{name
} || "VM $vmid";
2485 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2487 if ($conf->{balloon
}) {
2488 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2489 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2500 $d->{diskwrite
} = 0;
2502 $d->{template
} = is_template
($conf);
2507 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2508 foreach my $dev (keys %$netdev) {
2509 next if $dev !~ m/^tap([1-9]\d*)i/;
2511 my $d = $res->{$vmid};
2514 $d->{netout
} += $netdev->{$dev}->{receive
};
2515 $d->{netin
} += $netdev->{$dev}->{transmit
};
2518 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2519 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2524 my $ctime = gettimeofday
;
2526 foreach my $vmid (keys %$list) {
2528 my $d = $res->{$vmid};
2529 my $pid = $d->{pid
};
2532 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2533 next if !$pstat; # not running
2535 my $used = $pstat->{utime} + $pstat->{stime
};
2537 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2539 if ($pstat->{vsize
}) {
2540 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2543 my $old = $last_proc_pid_stat->{$pid};
2545 $last_proc_pid_stat->{$pid} = {
2553 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2555 if ($dtime > 1000) {
2556 my $dutime = $used - $old->{used
};
2558 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2559 $last_proc_pid_stat->{$pid} = {
2565 $d->{cpu
} = $old->{cpu
};
2569 return $res if !$full;
2571 my $qmpclient = PVE
::QMPClient-
>new();
2573 my $ballooncb = sub {
2574 my ($vmid, $resp) = @_;
2576 my $info = $resp->{'return'};
2577 return if !$info->{max_mem
};
2579 my $d = $res->{$vmid};
2581 # use memory assigned to VM
2582 $d->{maxmem
} = $info->{max_mem
};
2583 $d->{balloon
} = $info->{actual
};
2585 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2586 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2587 $d->{freemem
} = $info->{free_mem
};
2590 $d->{ballooninfo
} = $info;
2593 my $blockstatscb = sub {
2594 my ($vmid, $resp) = @_;
2595 my $data = $resp->{'return'} || [];
2596 my $totalrdbytes = 0;
2597 my $totalwrbytes = 0;
2599 for my $blockstat (@$data) {
2600 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2601 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2603 $blockstat->{device
} =~ s/drive-//;
2604 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2606 $res->{$vmid}->{diskread
} = $totalrdbytes;
2607 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2610 my $statuscb = sub {
2611 my ($vmid, $resp) = @_;
2613 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2614 # this fails if ballon driver is not loaded, so this must be
2615 # the last commnand (following command are aborted if this fails).
2616 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2618 my $status = 'unknown';
2619 if (!defined($status = $resp->{'return'}->{status
})) {
2620 warn "unable to get VM status\n";
2624 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2627 foreach my $vmid (keys %$list) {
2628 next if $opt_vmid && ($vmid ne $opt_vmid);
2629 next if !$res->{$vmid}->{pid
}; # not running
2630 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2633 $qmpclient->queue_execute(undef, 1);
2635 foreach my $vmid (keys %$list) {
2636 next if $opt_vmid && ($vmid ne $opt_vmid);
2637 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2644 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2647 my $current_size = 1024;
2648 my $dimm_size = 512;
2649 return if $current_size == $memory;
2651 for (my $j = 0; $j < 8; $j++) {
2652 for (my $i = 0; $i < 32; $i++) {
2653 my $name = "dimm${dimm_id}";
2655 my $numanode = $i % $sockets;
2656 $current_size += $dimm_size;
2657 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2658 return $current_size if $current_size >= $memory;
2664 sub foreach_reverse_dimm
{
2665 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2668 my $current_size = 4177920;
2669 my $dimm_size = 65536;
2670 return if $current_size == $memory;
2672 for (my $j = 0; $j < 8; $j++) {
2673 for (my $i = 0; $i < 32; $i++) {
2674 my $name = "dimm${dimm_id}";
2676 my $numanode = $i % $sockets;
2677 $current_size -= $dimm_size;
2678 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2679 return $current_size if $current_size <= $memory;
2686 my ($conf, $func) = @_;
2688 foreach my $ds (valid_drive_names
()) {
2689 next if !defined($conf->{$ds});
2691 my $drive = parse_drive
($ds, $conf->{$ds});
2694 &$func($ds, $drive);
2699 my ($conf, $func) = @_;
2703 my $test_volid = sub {
2704 my ($volid, $is_cdrom) = @_;
2708 $volhash->{$volid} = $is_cdrom || 0;
2711 foreach_drive
($conf, sub {
2712 my ($ds, $drive) = @_;
2713 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2716 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2717 my $snap = $conf->{snapshots
}->{$snapname};
2718 &$test_volid($snap->{vmstate
}, 0);
2719 foreach_drive
($snap, sub {
2720 my ($ds, $drive) = @_;
2721 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2725 foreach my $volid (keys %$volhash) {
2726 &$func($volid, $volhash->{$volid});
2730 sub vga_conf_has_spice
{
2733 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2738 sub config_to_command
{
2739 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2742 my $globalFlags = [];
2743 my $machineFlags = [];
2749 my $kvmver = kvm_user_version
();
2750 my $vernum = 0; # unknown
2751 my $ostype = $conf->{ostype
};
2752 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2753 $vernum = $1*1000000+$2*1000;
2754 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2755 $vernum = $1*1000000+$2*1000+$3;
2758 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2760 my $have_ovz = -f
'/proc/vz/vestat';
2762 my $q35 = machine_type_is_q35
($conf);
2763 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2764 my $machine_type = $forcemachine || $conf->{machine
};
2765 my $use_old_bios_files = undef;
2766 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2768 my $cpuunits = defined($conf->{cpuunits
}) ?
2769 $conf->{cpuunits
} : $defaults->{cpuunits
};
2771 push @$cmd, '/usr/bin/systemd-run';
2772 push @$cmd, '--scope';
2773 push @$cmd, '--slice', "qemu";
2774 push @$cmd, '--unit', $vmid;
2775 # set KillMode=none, so that systemd don't kill those scopes
2776 # at shutdown (pve-manager service should stop the VMs instead)
2777 push @$cmd, '-p', "KillMode=none";
2778 push @$cmd, '-p', "CPUShares=$cpuunits";
2779 if ($conf->{cpulimit
}) {
2780 my $cpulimit = int($conf->{cpulimit
} * 100);
2781 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2784 push @$cmd, '/usr/bin/kvm';
2786 push @$cmd, '-id', $vmid;
2790 my $qmpsocket = qmp_socket
($vmid);
2791 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2792 push @$cmd, '-mon', "chardev=qmp,mode=control";
2795 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2797 push @$cmd, '-daemonize';
2799 if ($conf->{smbios1
}) {
2800 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2803 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2804 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2805 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2806 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2807 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2808 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2809 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2813 # the q35 chipset support native usb2, so we enable usb controller
2814 # by default for this machine type
2815 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2817 $pciaddr = print_pci_addr
("piix3", $bridges);
2818 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2821 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2822 next if !$conf->{"usb$i"};
2823 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2824 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2827 # include usb device config
2828 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2831 # add usb3 controller if needed
2834 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2835 next if !$conf->{"usb$i"};
2836 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2837 next if !$d || !$d->{usb3
};
2841 $pciaddr = print_pci_addr
("xhci", $bridges);
2842 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2844 my $vga = $conf->{vga
};
2846 my $qxlnum = vga_conf_has_spice
($vga);
2847 $vga = 'qxl' if $qxlnum;
2850 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2851 $conf->{ostype
} eq 'win7' ||
2852 $conf->{ostype
} eq 'w2k8')) {
2859 # enable absolute mouse coordinates (needed by vnc)
2861 if (defined($conf->{tablet
})) {
2862 $tablet = $conf->{tablet
};
2864 $tablet = $defaults->{tablet
};
2865 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2866 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2869 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2873 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2874 my $d = parse_hostpci
($conf->{"hostpci$i"});
2877 my $pcie = $d->{pcie
};
2879 die "q35 machine model is not enabled" if !$q35;
2880 $pciaddr = print_pcie_addr
("hostpci$i");
2882 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2885 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2886 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2887 if ($xvga && $xvga ne '') {
2890 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2891 push @$cpuFlags , 'hv_vendor_id=proxmox';
2893 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2897 my $pcidevices = $d->{pciid
};
2898 my $multifunction = 1 if @$pcidevices > 1;
2901 foreach my $pcidevice (@$pcidevices) {
2903 my $id = "hostpci$i";
2904 $id .= ".$j" if $multifunction;
2905 my $addr = $pciaddr;
2906 $addr .= ".$j" if $multifunction;
2907 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2910 $devicestr .= "$rombar$xvga";
2911 $devicestr .= ",multifunction=on" if $multifunction;
2914 push @$devices, '-device', $devicestr;
2920 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2921 next if !$conf->{"usb$i"};
2922 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2925 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2927 if (defined($d->{usb3
}) && $d->{usb3
}) {
2928 $usbbus = ',bus=xhci.0';
2931 if (defined($d->{host
})) {
2932 $d = parse_usb_device
($d->{host
});
2933 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2934 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2935 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2936 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2937 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2938 # usb redir support for spice, currently no usb3
2939 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2940 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2946 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2947 if (my $path = $conf->{"serial$i"}) {
2948 if ($path eq 'socket') {
2949 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2950 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2951 push @$devices, '-device', "isa-serial,chardev=serial$i";
2953 die "no such serial device\n" if ! -c
$path;
2954 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2955 push @$devices, '-device', "isa-serial,chardev=serial$i";
2961 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2962 if (my $path = $conf->{"parallel$i"}) {
2963 die "no such parallel device\n" if ! -c
$path;
2964 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2965 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2966 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2970 my $vmname = $conf->{name
} || "vm$vmid";
2972 push @$cmd, '-name', $vmname;
2975 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2976 $sockets = $conf->{sockets
} if $conf->{sockets
};
2978 my $cores = $conf->{cores
} || 1;
2980 my $maxcpus = $sockets * $cores;
2982 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2984 my $allowed_vcpus = $cpuinfo->{cpus
};
2986 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2987 if ($allowed_vcpus < $maxcpus);
2989 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2991 push @$cmd, '-nodefaults';
2993 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2995 my $bootindex_hash = {};
2997 foreach my $o (split(//, $bootorder)) {
2998 $bootindex_hash->{$o} = $i*100;
3002 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
3004 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3006 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3008 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3010 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3011 my $socket = vnc_socket
($vmid);
3012 push @$cmd, '-vnc', "unix:$socket,x509,password";
3014 push @$cmd, '-nographic';
3018 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3020 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3021 my $useLocaltime = $conf->{localtime};
3024 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3026 if ($ostype =~ m/^w/) { # windows
3027 $useLocaltime = 1 if !defined($conf->{localtime});
3029 # use time drift fix when acpi is enabled
3030 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3031 $tdf = 1 if !defined($conf->{tdf
});
3035 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3036 $ostype eq 'wvista') {
3037 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3038 push @$cmd, '-no-hpet';
3039 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3040 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3041 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3042 push @$cpuFlags , 'hv_time' if !$nokvm;
3045 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3049 if ($ostype eq 'win7' || $ostype eq 'win8') {
3050 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3054 push @$rtcFlags, 'driftfix=slew' if $tdf;
3057 push @$machineFlags, 'accel=tcg';
3059 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3062 if ($machine_type) {
3063 push @$machineFlags, "type=${machine_type}";
3066 if ($conf->{startdate
}) {
3067 push @$rtcFlags, "base=$conf->{startdate}";
3068 } elsif ($useLocaltime) {
3069 push @$rtcFlags, 'base=localtime';
3072 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3073 if (my $cputype = $conf->{cpu
}) {
3074 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpudesc, $cputype)
3075 or die "Cannot parse cpu description: $cputype\n";
3076 $cpu = $cpuconf->{cputype
};
3077 $kvm_off = 1 if $cpuconf->{hidden
};
3080 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3082 push @$cpuFlags , '-x2apic'
3083 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3085 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3087 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3089 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3091 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3092 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3095 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3097 push @$cpuFlags, 'kvm=off' if $kvm_off;
3099 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3101 push @$cmd, '-cpu', $cpu;
3103 my $memory = $conf->{memory
} || $defaults->{memory
};
3104 my $static_memory = 0;
3105 my $dimm_memory = 0;
3107 if ($hotplug_features->{memory
}) {
3108 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3109 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3110 $static_memory = $STATICMEM;
3111 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3112 $dimm_memory = $memory - $static_memory;
3113 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3117 $static_memory = $memory;
3118 push @$cmd, '-m', $static_memory;
3121 if ($conf->{numa
}) {
3123 my $numa_totalmemory = undef;
3124 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3125 next if !$conf->{"numa$i"};
3126 my $numa = parse_numa
($conf->{"numa$i"});
3129 die "missing numa node$i memory value\n" if !$numa->{memory
};
3130 my $numa_memory = $numa->{memory
};
3131 $numa_totalmemory += $numa_memory;
3132 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3135 my $cpus_start = $numa->{cpus
}->{start
};
3136 die "missing numa node$i cpus\n" if !defined($cpus_start);
3137 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3138 my $cpus = $cpus_start;
3139 if (defined($cpus_end)) {
3140 $cpus .= "-$cpus_end";
3141 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3145 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3146 if (defined($hostnodes_start)) {
3147 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3148 my $hostnodes = $hostnodes_start;
3149 if (defined($hostnodes_end)) {
3150 $hostnodes .= "-$hostnodes_end";
3151 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3154 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3155 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3156 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3160 my $policy = $numa->{policy
};
3161 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3162 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3165 push @$cmd, '-object', $numa_object;
3166 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3169 die "total memory for NUMA nodes must be equal to vm static memory\n"
3170 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3172 #if no custom tology, we split memory and cores across numa nodes
3173 if(!$numa_totalmemory) {
3175 my $numa_memory = ($static_memory / $sockets) . "M";
3177 for (my $i = 0; $i < $sockets; $i++) {
3179 my $cpustart = ($cores * $i);
3180 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3181 my $cpus = $cpustart;
3182 $cpus .= "-$cpuend" if $cpuend;
3184 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3185 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3190 if ($hotplug_features->{memory
}) {
3191 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3192 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3193 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3194 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3196 #if dimm_memory is not aligned to dimm map
3197 if($current_size > $memory) {
3198 $conf->{memory
} = $current_size;
3199 write_config
($vmid, $conf);
3204 push @$cmd, '-S' if $conf->{freeze
};
3206 # set keyboard layout
3207 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3208 push @$cmd, '-k', $kb if $kb;
3211 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3212 #push @$cmd, '-soundhw', 'es1370';
3213 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3215 if($conf->{agent
}) {
3216 my $qgasocket = qmp_socket
($vmid, 1);
3217 my $pciaddr = print_pci_addr
("qga0", $bridges);
3218 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3219 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3220 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3227 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3228 for(my $i = 1; $i < $qxlnum; $i++){
3229 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3230 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3233 # assume other OS works like Linux
3234 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3235 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3239 my $pciaddr = print_pci_addr
("spice", $bridges);
3241 my $nodename = PVE
::INotify
::nodename
();
3242 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3243 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3245 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3247 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3248 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3249 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3252 # enable balloon by default, unless explicitly disabled
3253 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3254 $pciaddr = print_pci_addr
("balloon0", $bridges);
3255 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3258 if ($conf->{watchdog
}) {
3259 my $wdopts = parse_watchdog
($conf->{watchdog
});
3260 $pciaddr = print_pci_addr
("watchdog", $bridges);
3261 my $watchdog = $wdopts->{model
} || 'i6300esb';
3262 push @$devices, '-device', "$watchdog$pciaddr";
3263 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3267 my $scsicontroller = {};
3268 my $ahcicontroller = {};
3269 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3271 # Add iscsi initiator name if available
3272 if (my $initiator = get_initiator_name
()) {
3273 push @$devices, '-iscsi', "initiator-name=$initiator";
3276 foreach_drive
($conf, sub {
3277 my ($ds, $drive) = @_;
3279 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3280 push @$vollist, $drive->{file
};
3283 $use_virtio = 1 if $ds =~ m/^virtio/;
3285 if (drive_is_cdrom
($drive)) {
3286 if ($bootindex_hash->{d
}) {
3287 $drive->{bootindex
} = $bootindex_hash->{d
};
3288 $bootindex_hash->{d
} += 1;
3291 if ($bootindex_hash->{c
}) {
3292 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3293 $bootindex_hash->{c
} += 1;
3297 if($drive->{interface
} eq 'virtio'){
3298 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3301 if ($drive->{interface
} eq 'scsi') {
3303 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3305 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3306 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3309 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3310 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3311 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3315 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3316 $queues = ",num_queues=$drive->{queues}";
3319 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3320 $scsicontroller->{$controller}=1;
3323 if ($drive->{interface
} eq 'sata') {
3324 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3325 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3326 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3327 $ahcicontroller->{$controller}=1;
3330 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3331 push @$devices, '-drive',$drive_cmd;
3332 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3335 for (my $i = 0; $i < $MAX_NETS; $i++) {
3336 next if !$conf->{"net$i"};
3337 my $d = parse_net
($conf->{"net$i"});
3340 $use_virtio = 1 if $d->{model
} eq 'virtio';
3342 if ($bootindex_hash->{n
}) {
3343 $d->{bootindex
} = $bootindex_hash->{n
};
3344 $bootindex_hash->{n
} += 1;
3347 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3348 push @$devices, '-netdev', $netdevfull;
3350 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3351 push @$devices, '-device', $netdevicefull;
3356 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3361 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3363 while (my ($k, $v) = each %$bridges) {
3364 $pciaddr = print_pci_addr
("pci.$k");
3365 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3370 if ($conf->{args
}) {
3371 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3375 push @$cmd, @$devices;
3376 push @$cmd, '-rtc', join(',', @$rtcFlags)
3377 if scalar(@$rtcFlags);
3378 push @$cmd, '-machine', join(',', @$machineFlags)
3379 if scalar(@$machineFlags);
3380 push @$cmd, '-global', join(',', @$globalFlags)
3381 if scalar(@$globalFlags);
3383 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3388 return "${var_run_tmpdir}/$vmid.vnc";
3394 my $res = vm_mon_cmd
($vmid, 'query-spice');
3396 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3400 my ($vmid, $qga) = @_;
3401 my $sockettype = $qga ?
'qga' : 'qmp';
3402 return "${var_run_tmpdir}/$vmid.$sockettype";
3407 return "${var_run_tmpdir}/$vmid.pid";
3410 sub vm_devices_list
{
3413 my $res = vm_mon_cmd
($vmid, 'query-pci');
3415 foreach my $pcibus (@$res) {
3416 foreach my $device (@{$pcibus->{devices
}}) {
3417 next if !$device->{'qdev_id'};
3418 if ($device->{'pci_bridge'}) {
3419 $devices->{$device->{'qdev_id'}} = 1;
3420 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3421 next if !$bridge_device->{'qdev_id'};
3422 $devices->{$bridge_device->{'qdev_id'}} = 1;
3423 $devices->{$device->{'qdev_id'}}++;
3426 $devices->{$device->{'qdev_id'}} = 1;
3431 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3432 foreach my $block (@$resblock) {
3433 if($block->{device
} =~ m/^drive-(\S+)/){
3438 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3439 foreach my $mice (@$resmice) {
3440 if ($mice->{name
} eq 'QEMU HID Tablet') {
3441 $devices->{tablet
} = 1;
3450 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3452 my $q35 = machine_type_is_q35
($conf);
3454 my $devices_list = vm_devices_list
($vmid);
3455 return 1 if defined($devices_list->{$deviceid});
3457 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3459 if ($deviceid eq 'tablet') {
3461 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3463 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3465 qemu_iothread_add
($vmid, $deviceid, $device);
3467 qemu_driveadd
($storecfg, $vmid, $device);
3468 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3470 qemu_deviceadd
($vmid, $devicefull);
3471 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3473 eval { qemu_drivedel
($vmid, $deviceid); };
3478 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3481 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3482 my $pciaddr = print_pci_addr
($deviceid);
3483 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3485 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3487 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3488 qemu_iothread_add
($vmid, $deviceid, $device);
3489 $devicefull .= ",iothread=iothread-$deviceid";
3492 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3493 $devicefull .= ",num_queues=$device->{queues}";
3496 qemu_deviceadd
($vmid, $devicefull);
3497 qemu_deviceaddverify
($vmid, $deviceid);
3499 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3501 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3502 qemu_driveadd
($storecfg, $vmid, $device);
3504 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3505 eval { qemu_deviceadd
($vmid, $devicefull); };
3507 eval { qemu_drivedel
($vmid, $deviceid); };
3512 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3514 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3516 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3517 my $use_old_bios_files = undef;
3518 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3520 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3521 qemu_deviceadd
($vmid, $netdevicefull);
3522 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3524 eval { qemu_netdevdel
($vmid, $deviceid); };
3529 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3532 my $pciaddr = print_pci_addr
($deviceid);
3533 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3535 qemu_deviceadd
($vmid, $devicefull);
3536 qemu_deviceaddverify
($vmid, $deviceid);
3539 die "can't hotplug device '$deviceid'\n";
3545 # fixme: this should raise exceptions on error!
3546 sub vm_deviceunplug
{
3547 my ($vmid, $conf, $deviceid) = @_;
3549 my $devices_list = vm_devices_list
($vmid);
3550 return 1 if !defined($devices_list->{$deviceid});
3552 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3554 if ($deviceid eq 'tablet') {
3556 qemu_devicedel
($vmid, $deviceid);
3558 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3560 qemu_devicedel
($vmid, $deviceid);
3561 qemu_devicedelverify
($vmid, $deviceid);
3562 qemu_drivedel
($vmid, $deviceid);
3563 qemu_iothread_del
($conf, $vmid, $deviceid);
3565 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3567 qemu_devicedel
($vmid, $deviceid);
3568 qemu_devicedelverify
($vmid, $deviceid);
3569 qemu_iothread_del
($conf, $vmid, $deviceid);
3571 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3573 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3574 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3575 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3577 qemu_devicedel
($vmid, $deviceid);
3578 qemu_drivedel
($vmid, $deviceid);
3579 qemu_deletescsihw
($conf, $vmid, $deviceid);
3581 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3583 qemu_devicedel
($vmid, $deviceid);
3584 qemu_devicedelverify
($vmid, $deviceid);
3585 qemu_netdevdel
($vmid, $deviceid);
3588 die "can't unplug device '$deviceid'\n";
3594 sub qemu_deviceadd
{
3595 my ($vmid, $devicefull) = @_;
3597 $devicefull = "driver=".$devicefull;
3598 my %options = split(/[=,]/, $devicefull);
3600 vm_mon_cmd
($vmid, "device_add" , %options);
3603 sub qemu_devicedel
{
3604 my ($vmid, $deviceid) = @_;
3606 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3609 sub qemu_iothread_add
{
3610 my($vmid, $deviceid, $device) = @_;
3612 if ($device->{iothread
}) {
3613 my $iothreads = vm_iothreads_list
($vmid);
3614 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3618 sub qemu_iothread_del
{
3619 my($conf, $vmid, $deviceid) = @_;
3621 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3622 if ($device->{iothread
}) {
3623 my $iothreads = vm_iothreads_list
($vmid);
3624 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3628 sub qemu_objectadd
{
3629 my($vmid, $objectid, $qomtype) = @_;
3631 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3636 sub qemu_objectdel
{
3637 my($vmid, $objectid) = @_;
3639 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3645 my ($storecfg, $vmid, $device) = @_;
3647 my $drive = print_drive_full
($storecfg, $vmid, $device);
3648 $drive =~ s/\\/\\\\/g;
3649 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3651 # If the command succeeds qemu prints: "OK
"
3652 return 1 if $ret =~ m/OK/s;
3654 die "adding drive failed
: $ret\n";
3658 my($vmid, $deviceid) = @_;
3660 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3663 return 1 if $ret eq "";
3665 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3666 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3668 die "deleting drive
$deviceid failed
: $ret\n";
3671 sub qemu_deviceaddverify {
3672 my ($vmid, $deviceid) = @_;
3674 for (my $i = 0; $i <= 5; $i++) {
3675 my $devices_list = vm_devices_list($vmid);
3676 return 1 if defined($devices_list->{$deviceid});
3680 die "error on hotplug device
'$deviceid'\n";
3684 sub qemu_devicedelverify {
3685 my ($vmid, $deviceid) = @_;
3687 # need to verify that the device is correctly removed as device_del
3688 # is async and empty return is not reliable
3690 for (my $i = 0; $i <= 5; $i++) {
3691 my $devices_list = vm_devices_list($vmid);
3692 return 1 if !defined($devices_list->{$deviceid});
3696 die "error on hot-unplugging device
'$deviceid'\n";
3699 sub qemu_findorcreatescsihw {
3700 my ($storecfg, $conf, $vmid, $device) = @_;
3702 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3704 my $scsihwid="$controller_prefix$controller";
3705 my $devices_list = vm_devices_list($vmid);
3707 if(!defined($devices_list->{$scsihwid})) {
3708 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3714 sub qemu_deletescsihw {
3715 my ($conf, $vmid, $opt) = @_;
3717 my $device = parse_drive($opt, $conf->{$opt});
3719 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3720 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3724 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3726 my $devices_list = vm_devices_list($vmid);
3727 foreach my $opt (keys %{$devices_list}) {
3728 if (PVE::QemuServer::is_valid_drivename($opt)) {
3729 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3730 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3736 my $scsihwid="scsihw
$controller";
3738 vm_deviceunplug($vmid, $conf, $scsihwid);
3743 sub qemu_add_pci_bridge {
3744 my ($storecfg, $conf, $vmid, $device) = @_;
3750 print_pci_addr($device, $bridges);
3752 while (my ($k, $v) = each %$bridges) {
3755 return 1 if !defined($bridgeid) || $bridgeid < 1;
3757 my $bridge = "pci
.$bridgeid";
3758 my $devices_list = vm_devices_list($vmid);
3760 if (!defined($devices_list->{$bridge})) {
3761 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3767 sub qemu_set_link_status {
3768 my ($vmid, $device, $up) = @_;
3770 vm_mon_cmd($vmid, "set_link
", name => $device,
3771 up => $up ? JSON::true : JSON::false);
3774 sub qemu_netdevadd {
3775 my ($vmid, $conf, $device, $deviceid) = @_;
3777 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3778 my %options = split(/[=,]/, $netdev);
3780 vm_mon_cmd($vmid, "netdev_add
", %options);
3784 sub qemu_netdevdel {
3785 my ($vmid, $deviceid) = @_;
3787 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3790 sub qemu_cpu_hotplug {
3791 my ($vmid, $conf, $vcpus) = @_;
3794 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3795 $sockets = $conf->{sockets} if $conf->{sockets};
3796 my $cores = $conf->{cores} || 1;
3797 my $maxcpus = $sockets * $cores;
3799 $vcpus = $maxcpus if !$vcpus;
3801 die "you can
't add more vcpus than maxcpus\n"
3802 if $vcpus > $maxcpus;
3804 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3805 die "online cpu unplug is not yet possible\n"
3806 if $vcpus < $currentvcpus;
3808 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3809 die "vcpus in running vm is different than configuration\n"
3810 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3812 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3813 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3817 sub qemu_memory_hotplug {
3818 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3820 return $value if !check_running($vmid);
3822 my $memory = $conf->{memory} || $defaults->{memory};
3823 $value = $defaults->{memory} if !$value;
3824 return $value if $value == $memory;
3826 my $static_memory = $STATICMEM;
3827 my $dimm_memory = $memory - $static_memory;
3829 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3830 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3834 $sockets = $conf->{sockets} if $conf->{sockets};
3836 if($value > $memory) {
3838 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3839 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3841 return if $current_size <= $conf->{memory};
3843 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3845 eval { qemu_objectdel($vmid, "mem-
$name"); };
3849 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3851 eval { qemu_objectdel($vmid, "mem-
$name"); };
3854 #update conf after each succesful module hotplug
3855 $conf->{memory} = $current_size;
3856 write_config($vmid, $conf);
3861 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3862 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3864 return if $current_size >= $conf->{memory};
3865 print "try to unplug memory dimm
$name\n";
3869 eval { qemu_devicedel($vmid, $name) };
3871 my $dimm_list = qemu_dimm_list($vmid);
3872 last if !$dimm_list->{$name};
3873 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3877 #update conf after each succesful module unplug
3878 $conf->{memory} = $current_size;
3880 eval { qemu_objectdel($vmid, "mem-
$name"); };
3881 write_config($vmid, $conf);
3886 sub qemu_dimm_list {
3889 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3892 foreach my $dimm (@$dimmarray) {
3894 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3895 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3896 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3897 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3898 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3903 sub qemu_block_set_io_throttle {
3904 my ($vmid, $deviceid,
3905 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3906 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3908 return if !check_running($vmid) ;
3910 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3912 bps_rd => int($bps_rd),
3913 bps_wr => int($bps_wr),
3915 iops_rd => int($iops_rd),
3916 iops_wr => int($iops_wr),
3917 bps_max => int($bps_max),
3918 bps_rd_max => int($bps_rd_max),
3919 bps_wr_max => int($bps_wr_max),
3920 iops_max => int($iops_max),
3921 iops_rd_max => int($iops_rd_max),
3922 iops_wr_max => int($iops_wr_max)
3927 # old code, only used to shutdown old VM after update
3929 my ($fh, $timeout) = @_;
3931 my $sel = new IO::Select;
3938 while (scalar (@ready = $sel->can_read($timeout))) {
3940 if ($count = $fh->sysread($buf, 8192)) {
3941 if ($buf =~ /^(.*)\(qemu\) $/s) {
3948 if (!defined($count)) {
3955 die "monitor
read timeout
\n" if !scalar(@ready);
3960 # old code, only used to shutdown old VM after update
3961 sub vm_monitor_command {
3962 my ($vmid, $cmdstr, $nocheck) = @_;
3967 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3969 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3971 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3972 die "unable to
connect to VM
$vmid socket - $!\n";
3976 # hack: migrate sometime blocks the monitor (when migrate_downtime
3978 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3979 $timeout = 60*60; # 1 hour
3983 my $data = __read_avail($sock, $timeout);
3985 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3986 die "got unexpected qemu monitor banner
\n";
3989 my $sel = new IO::Select;
3992 if (!scalar(my @ready = $sel->can_write($timeout))) {
3993 die "monitor
write error
- timeout
";
3996 my $fullcmd = "$cmdstr\r";
3998 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
4001 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4002 die "monitor
write error
- $!";
4005 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
4009 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4010 $timeout = 60*60; # 1 hour
4011 } elsif ($cmdstr =~ m/^(eject|change)/) {
4012 $timeout = 60; # note: cdrom mount command is slow
4014 if ($res = __read_avail($sock, $timeout)) {
4016 my @lines = split("\r?
\n", $res);
4018 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4020 $res = join("\n", @lines);
4028 syslog("err
", "VM
$vmid monitor command failed
- $err");
4035 sub qemu_block_resize {
4036 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4038 my $running = check_running($vmid);
4040 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4042 return if !$running;
4044 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4048 sub qemu_volume_snapshot {
4049 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4051 my $running = check_running($vmid);
4053 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4054 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4056 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4060 sub qemu_volume_snapshot_delete {
4061 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4063 my $running = check_running($vmid);
4065 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4067 return if !$running;
4069 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4072 sub set_migration_caps {
4078 "auto-converge
" => 1,
4080 "x-rdma-pin-all
" => 0,
4085 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4087 for my $supported_capability (@$supported_capabilities) {
4089 capability => $supported_capability->{capability},
4090 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4094 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4097 my $fast_plug_option = {
4106 # hotplug changes in [PENDING]
4107 # $selection hash can be used to only apply specified options, for
4108 # example: { cores => 1 } (only apply changed 'cores')
4109 # $errors ref is used to return error messages
4110 sub vmconfig_hotplug_pending {
4111 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4113 my $defaults = load_defaults();
4115 # commit values which do not have any impact on running VM first
4116 # Note: those option cannot raise errors, we we do not care about
4117 # $selection and always apply them.
4119 my $add_error = sub {
4120 my ($opt, $msg) = @_;
4121 $errors->{$opt} = "hotplug problem
- $msg";
4125 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4126 if ($fast_plug_option->{$opt}) {
4127 $conf->{$opt} = $conf->{pending}->{$opt};
4128 delete $conf->{pending}->{$opt};
4134 write_config($vmid, $conf);
4135 $conf = load_config($vmid); # update/reload
4138 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4140 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4141 while (my ($opt, $force) = each %$pending_delete_hash) {
4142 next if $selection && !$selection->{$opt};
4144 if ($opt eq 'hotplug') {
4145 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4146 } elsif ($opt eq 'tablet') {
4147 die "skip
\n" if !$hotplug_features->{usb};
4148 if ($defaults->{tablet}) {
4149 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4151 vm_deviceunplug($vmid, $conf, $opt);
4153 } elsif ($opt eq 'vcpus') {
4154 die "skip
\n" if !$hotplug_features->{cpu};
4155 qemu_cpu_hotplug($vmid, $conf, undef);
4156 } elsif ($opt eq 'balloon') {
4157 # enable balloon device is not hotpluggable
4158 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4159 } elsif ($fast_plug_option->{$opt}) {
4161 } elsif ($opt =~ m/^net(\d+)$/) {
4162 die "skip
\n" if !$hotplug_features->{network};
4163 vm_deviceunplug($vmid, $conf, $opt);
4164 } elsif (is_valid_drivename($opt)) {
4165 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4166 vm_deviceunplug($vmid, $conf, $opt);
4167 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4168 } elsif ($opt =~ m/^memory$/) {
4169 die "skip
\n" if !$hotplug_features->{memory};
4170 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4171 } elsif ($opt eq 'cpuunits') {
4172 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4173 } elsif ($opt eq 'cpulimit') {
4174 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4180 &$add_error($opt, $err) if $err ne "skip
\n";
4182 # save new config if hotplug was successful
4183 delete $conf->{$opt};
4184 vmconfig_undelete_pending_option($conf, $opt);
4185 write_config($vmid, $conf);
4186 $conf = load_config($vmid); # update/reload
4190 foreach my $opt (keys %{$conf->{pending}}) {
4191 next if $selection && !$selection->{$opt};
4192 my $value = $conf->{pending}->{$opt};
4194 if ($opt eq 'hotplug') {
4195 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4196 } elsif ($opt eq 'tablet') {
4197 die "skip
\n" if !$hotplug_features->{usb};
4199 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4200 } elsif ($value == 0) {
4201 vm_deviceunplug($vmid, $conf, $opt);
4203 } elsif ($opt eq 'vcpus') {
4204 die "skip
\n" if !$hotplug_features->{cpu};
4205 qemu_cpu_hotplug($vmid, $conf, $value);
4206 } elsif ($opt eq 'balloon') {
4207 # enable/disable balloning device is not hotpluggable
4208 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4209 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4210 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4212 # allow manual ballooning if shares is set to zero
4213 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4214 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4215 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4217 } elsif ($opt =~ m/^net(\d+)$/) {
4218 # some changes can be done without hotplug
4219 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4220 $vmid, $opt, $value);
4221 } elsif (is_valid_drivename($opt)) {
4222 # some changes can be done without hotplug
4223 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4224 $vmid, $opt, $value, 1);
4225 } elsif ($opt =~ m/^memory$/) { #dimms
4226 die "skip
\n" if !$hotplug_features->{memory};
4227 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4228 } elsif ($opt eq 'cpuunits') {
4229 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4230 } elsif ($opt eq 'cpulimit') {
4231 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4232 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4234 die "skip
\n"; # skip non-hot-pluggable options
4238 &$add_error($opt, $err) if $err ne "skip
\n";
4240 # save new config if hotplug was successful
4241 $conf->{$opt} = $value;
4242 delete $conf->{pending}->{$opt};
4243 write_config($vmid, $conf);
4244 $conf = load_config($vmid); # update/reload
4249 sub try_deallocate_drive {
4250 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4252 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4253 my $volid = $drive->{file};
4254 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4255 my $sid = PVE::Storage::parse_volume_id($volid);
4256 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4258 # check if the disk is really unused
4259 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4260 if is_volume_in_use($storecfg, $conf, $key, $volid);
4261 PVE::Storage::vdisk_free($storecfg, $volid);
4264 # If vm is not owner of this disk remove from config
4272 sub vmconfig_delete_or_detach_drive {
4273 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4275 my $drive = parse_drive($opt, $conf->{$opt});
4277 my $rpcenv = PVE::RPCEnvironment::get();
4278 my $authuser = $rpcenv->get_user();
4281 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4282 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4284 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4288 sub vmconfig_apply_pending {
4289 my ($vmid, $conf, $storecfg) = @_;
4293 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4294 while (my ($opt, $force) = each %$pending_delete_hash) {
4295 die "internal error
" if $opt =~ m/^unused/;
4296 $conf = load_config($vmid); # update/reload
4297 if (!defined($conf->{$opt})) {
4298 vmconfig_undelete_pending_option($conf, $opt);
4299 write_config($vmid, $conf);
4300 } elsif (is_valid_drivename($opt)) {
4301 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4302 vmconfig_undelete_pending_option($conf, $opt);
4303 delete $conf->{$opt};
4304 write_config($vmid, $conf);
4306 vmconfig_undelete_pending_option($conf, $opt);
4307 delete $conf->{$opt};
4308 write_config($vmid, $conf);
4312 $conf = load_config($vmid); # update/reload
4314 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4315 $conf = load_config($vmid); # update/reload
4317 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4318 # skip if nothing changed
4319 } elsif (is_valid_drivename($opt)) {
4320 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4321 if defined($conf->{$opt});
4322 $conf->{$opt} = $conf->{pending}->{$opt};
4324 $conf->{$opt} = $conf->{pending}->{$opt};
4327 delete $conf->{pending}->{$opt};
4328 write_config($vmid, $conf);
4332 my $safe_num_ne = sub {
4335 return 0 if !defined($a) && !defined($b);
4336 return 1 if !defined($a);
4337 return 1 if !defined($b);
4342 my $safe_string_ne = sub {
4345 return 0 if !defined($a) && !defined($b);
4346 return 1 if !defined($a);
4347 return 1 if !defined($b);
4352 sub vmconfig_update_net {
4353 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4355 my $newnet = parse_net($value);
4357 if ($conf->{$opt}) {
4358 my $oldnet = parse_net($conf->{$opt});
4360 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4361 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4362 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4363 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4365 # for non online change, we try to hot-unplug
4366 die "skip
\n" if !$hotplug;
4367 vm_deviceunplug($vmid, $conf, $opt);
4370 die "internal error
" if $opt !~ m/net(\d+)/;
4371 my $iface = "tap
${vmid
}i
$1";
4373 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4374 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4377 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4378 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4379 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4380 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4381 PVE::Network::tap_unplug($iface);
4382 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks});
4385 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4386 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4394 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4400 sub vmconfig_update_disk {
4401 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4403 # fixme: do we need force?
4405 my $drive = parse_drive($opt, $value);
4407 if ($conf->{$opt}) {
4409 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4411 my $media = $drive->{media} || 'disk';
4412 my $oldmedia = $old_drive->{media} || 'disk';
4413 die "unable to change media type
\n" if $media ne $oldmedia;
4415 if (!drive_is_cdrom($old_drive)) {
4417 if ($drive->{file} ne $old_drive->{file}) {
4419 die "skip
\n" if !$hotplug;
4421 # unplug and register as unused
4422 vm_deviceunplug($vmid, $conf, $opt);
4423 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4426 # update existing disk
4428 # skip non hotpluggable value
4429 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4430 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4431 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4432 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4437 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4438 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4439 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4440 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4441 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4442 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4443 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4444 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4445 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4446 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4447 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4448 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4450 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4451 ($drive->{mbps} || 0)*1024*1024,
4452 ($drive->{mbps_rd} || 0)*1024*1024,
4453 ($drive->{mbps_wr} || 0)*1024*1024,
4454 $drive->{iops} || 0,
4455 $drive->{iops_rd} || 0,
4456 $drive->{iops_wr} || 0,
4457 ($drive->{mbps_max} || 0)*1024*1024,
4458 ($drive->{mbps_rd_max} || 0)*1024*1024,
4459 ($drive->{mbps_wr_max} || 0)*1024*1024,
4460 $drive->{iops_max} || 0,
4461 $drive->{iops_rd_max} || 0,
4462 $drive->{iops_wr_max} || 0);
4471 if ($drive->{file} eq 'none') {
4472 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4474 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4475 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4476 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4484 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4486 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4487 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4491 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4492 $forcemachine, $spice_ticket) = @_;
4494 lock_config($vmid, sub {
4495 my $conf = load_config($vmid, $migratedfrom);
4497 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4499 check_lock($conf) if !$skiplock;
4501 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4503 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4504 vmconfig_apply_pending($vmid, $conf, $storecfg);
4505 $conf = load_config($vmid); # update/reload
4508 my $defaults = load_defaults();
4510 # set environment variable useful inside network script
4511 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4513 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4515 my $migrate_port = 0;
4518 if ($statefile eq 'tcp') {
4519 my $localip = "localhost
";
4520 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4521 my $nodename = PVE::INotify::nodename();
4522 if ($datacenterconf->{migration_unsecure}) {
4523 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4524 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4526 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4527 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4528 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4529 push @$cmd, '-incoming', $migrate_uri;
4532 push @$cmd, '-loadstate', $statefile;
4539 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4540 my $d = parse_hostpci($conf->{"hostpci
$i"});
4542 my $pcidevices = $d->{pciid};
4543 foreach my $pcidevice (@$pcidevices) {
4544 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4546 my $info = pci_device_info("0000:$pciid");
4547 die "IOMMU
not present
\n" if !check_iommu_support();
4548 die "no pci device info
for device
'$pciid'\n" if !$info;
4549 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4550 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4554 PVE::Storage::activate_volumes($storecfg, $vollist);
4556 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4560 # deactivate volumes if start fails
4561 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4562 die "start failed
: $err";
4565 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4567 if ($statefile && $statefile ne 'tcp') {
4568 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4572 if ($migratedfrom) {
4575 set_migration_caps($vmid);
4580 print "spice listens on port
$spice_port\n";
4581 if ($spice_ticket) {
4582 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4583 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4589 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4590 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4591 if $conf->{balloon};
4594 foreach my $opt (keys %$conf) {
4595 next if $opt !~ m/^net\d+$/;
4596 my $nicconf = parse_net($conf->{$opt});
4597 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4601 vm_mon_cmd_nocheck($vmid, 'qom-set',
4602 path => "machine
/peripheral/balloon0
",
4603 property => "guest-stats-polling-interval
",
4604 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4610 my ($vmid, $execute, %params) = @_;
4612 my $cmd = { execute => $execute, arguments => \%params };
4613 vm_qmp_command($vmid, $cmd);
4616 sub vm_mon_cmd_nocheck {
4617 my ($vmid, $execute, %params) = @_;
4619 my $cmd = { execute => $execute, arguments => \%params };
4620 vm_qmp_command($vmid, $cmd, 1);
4623 sub vm_qmp_command {
4624 my ($vmid, $cmd, $nocheck) = @_;
4629 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4630 $timeout = $cmd->{arguments}->{timeout};
4631 delete $cmd->{arguments}->{timeout};
4635 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4636 my $sname = qmp_socket($vmid);
4637 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4638 my $qmpclient = PVE::QMPClient->new();
4640 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4641 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4642 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4643 if scalar(%{$cmd->{arguments}});
4644 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4646 die "unable to open monitor socket\n";
4650 syslog("err", "VM $vmid qmp command failed - $err");
4657 sub vm_human_monitor_command {
4658 my ($vmid, $cmdline) = @_;
4663 execute => 'human-monitor-command
',
4664 arguments => { 'command-line
' => $cmdline},
4667 return vm_qmp_command($vmid, $cmd);
4670 sub vm_commandline {
4671 my ($storecfg, $vmid) = @_;
4673 my $conf = load_config($vmid);
4675 my $defaults = load_defaults();
4677 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4679 return join(' ', @$cmd);
4683 my ($vmid, $skiplock) = @_;
4685 lock_config($vmid, sub {
4687 my $conf = load_config($vmid);
4689 check_lock($conf) if !$skiplock;
4691 vm_mon_cmd($vmid, "system_reset");
4695 sub get_vm_volumes {
4699 foreach_volid($conf, sub {
4700 my ($volid, $is_cdrom) = @_;
4702 return if $volid =~ m|^/|;
4704 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4707 push @$vollist, $volid;
4713 sub vm_stop_cleanup {
4714 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4719 my $vollist = get_vm_volumes($conf);
4720 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4723 foreach my $ext (qw(mon qmp pid vnc qga)) {
4724 unlink "/var/run/qemu-server/${vmid}.$ext";
4727 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4729 warn $@ if $@; # avoid errors - just warn
4732 # Note: use $nockeck to skip tests if VM configuration file exists.
4733 # We need that when migration VMs to other nodes (files already moved)
4734 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4736 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4738 $force = 1 if !defined($force) && !$shutdown;
4741 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4742 kill 15, $pid if $pid;
4743 my $conf = load_config
($vmid, $migratedfrom);
4744 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4748 lock_config
($vmid, sub {
4750 my $pid = check_running
($vmid, $nocheck);
4755 $conf = load_config
($vmid);
4756 check_lock
($conf) if !$skiplock;
4757 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4758 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4759 $timeout = $opts->{down
} if $opts->{down
};
4763 $timeout = 60 if !defined($timeout);
4767 if (defined($conf) && $conf->{agent
}) {
4768 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4770 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4773 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4780 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4785 if ($count >= $timeout) {
4787 warn "VM still running - terminating now with SIGTERM\n";
4790 die "VM quit/powerdown failed - got timeout\n";
4793 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4798 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4801 die "VM quit/powerdown failed\n";
4809 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4814 if ($count >= $timeout) {
4815 warn "VM still running - terminating now with SIGKILL\n";
4820 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4825 my ($vmid, $skiplock) = @_;
4827 lock_config
($vmid, sub {
4829 my $conf = load_config
($vmid);
4831 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4833 vm_mon_cmd
($vmid, "stop");
4838 my ($vmid, $skiplock, $nocheck) = @_;
4840 lock_config
($vmid, sub {
4844 my $conf = load_config
($vmid);
4846 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4848 vm_mon_cmd
($vmid, "cont");
4851 vm_mon_cmd_nocheck
($vmid, "cont");
4857 my ($vmid, $skiplock, $key) = @_;
4859 lock_config
($vmid, sub {
4861 my $conf = load_config
($vmid);
4863 # there is no qmp command, so we use the human monitor command
4864 vm_human_monitor_command
($vmid, "sendkey $key");
4869 my ($storecfg, $vmid, $skiplock) = @_;
4871 lock_config
($vmid, sub {
4873 my $conf = load_config
($vmid);
4875 if (!check_running
($vmid)) {
4876 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4878 die "VM $vmid is running - destroy failed\n";
4886 my ($filename, $buf) = @_;
4888 my $fh = IO
::File-
>new($filename, "w");
4889 return undef if !$fh;
4891 my $res = print $fh $buf;
4898 sub pci_device_info
{
4903 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4904 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4906 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4907 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4909 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4910 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4912 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4913 return undef if !defined($product) || $product !~ s/^0x//;
4918 product
=> $product,
4924 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4933 my $name = $dev->{name
};
4935 my $fn = "$pcisysfs/devices/$name/reset";
4937 return file_write
($fn, "1");
4940 sub pci_dev_bind_to_vfio
{
4943 my $name = $dev->{name
};
4945 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4947 if (!-d
$vfio_basedir) {
4948 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4950 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4952 my $testdir = "$vfio_basedir/$name";
4953 return 1 if -d
$testdir;
4955 my $data = "$dev->{vendor} $dev->{product}";
4956 return undef if !file_write
("$vfio_basedir/new_id", $data);
4958 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4959 if (!file_write
($fn, $name)) {
4960 return undef if -f
$fn;
4963 $fn = "$vfio_basedir/bind";
4964 if (! -d
$testdir) {
4965 return undef if !file_write
($fn, $name);
4971 sub pci_dev_group_bind_to_vfio
{
4974 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4976 if (!-d
$vfio_basedir) {
4977 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4979 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4981 # get IOMMU group devices
4982 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4983 my @devs = grep /^0000:/, readdir($D);
4986 foreach my $pciid (@devs) {
4987 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4989 # pci bridges, switches or root ports are not supported
4990 # they have a pci_bus subdirectory so skip them
4991 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4993 my $info = pci_device_info
($1);
4994 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5000 sub print_pci_addr
{
5001 my ($id, $bridges) = @_;
5005 piix3
=> { bus
=> 0, addr
=> 1 },
5006 #addr2 : first videocard
5007 balloon0
=> { bus
=> 0, addr
=> 3 },
5008 watchdog
=> { bus
=> 0, addr
=> 4 },
5009 scsihw0
=> { bus
=> 0, addr
=> 5 },
5010 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
5011 scsihw1
=> { bus
=> 0, addr
=> 6 },
5012 ahci0
=> { bus
=> 0, addr
=> 7 },
5013 qga0
=> { bus
=> 0, addr
=> 8 },
5014 spice
=> { bus
=> 0, addr
=> 9 },
5015 virtio0
=> { bus
=> 0, addr
=> 10 },
5016 virtio1
=> { bus
=> 0, addr
=> 11 },
5017 virtio2
=> { bus
=> 0, addr
=> 12 },
5018 virtio3
=> { bus
=> 0, addr
=> 13 },
5019 virtio4
=> { bus
=> 0, addr
=> 14 },
5020 virtio5
=> { bus
=> 0, addr
=> 15 },
5021 hostpci0
=> { bus
=> 0, addr
=> 16 },
5022 hostpci1
=> { bus
=> 0, addr
=> 17 },
5023 net0
=> { bus
=> 0, addr
=> 18 },
5024 net1
=> { bus
=> 0, addr
=> 19 },
5025 net2
=> { bus
=> 0, addr
=> 20 },
5026 net3
=> { bus
=> 0, addr
=> 21 },
5027 net4
=> { bus
=> 0, addr
=> 22 },
5028 net5
=> { bus
=> 0, addr
=> 23 },
5029 vga1
=> { bus
=> 0, addr
=> 24 },
5030 vga2
=> { bus
=> 0, addr
=> 25 },
5031 vga3
=> { bus
=> 0, addr
=> 26 },
5032 hostpci2
=> { bus
=> 0, addr
=> 27 },
5033 hostpci3
=> { bus
=> 0, addr
=> 28 },
5034 #addr29 : usb-host (pve-usb.cfg)
5035 'pci.1' => { bus
=> 0, addr
=> 30 },
5036 'pci.2' => { bus
=> 0, addr
=> 31 },
5037 'net6' => { bus
=> 1, addr
=> 1 },
5038 'net7' => { bus
=> 1, addr
=> 2 },
5039 'net8' => { bus
=> 1, addr
=> 3 },
5040 'net9' => { bus
=> 1, addr
=> 4 },
5041 'net10' => { bus
=> 1, addr
=> 5 },
5042 'net11' => { bus
=> 1, addr
=> 6 },
5043 'net12' => { bus
=> 1, addr
=> 7 },
5044 'net13' => { bus
=> 1, addr
=> 8 },
5045 'net14' => { bus
=> 1, addr
=> 9 },
5046 'net15' => { bus
=> 1, addr
=> 10 },
5047 'net16' => { bus
=> 1, addr
=> 11 },
5048 'net17' => { bus
=> 1, addr
=> 12 },
5049 'net18' => { bus
=> 1, addr
=> 13 },
5050 'net19' => { bus
=> 1, addr
=> 14 },
5051 'net20' => { bus
=> 1, addr
=> 15 },
5052 'net21' => { bus
=> 1, addr
=> 16 },
5053 'net22' => { bus
=> 1, addr
=> 17 },
5054 'net23' => { bus
=> 1, addr
=> 18 },
5055 'net24' => { bus
=> 1, addr
=> 19 },
5056 'net25' => { bus
=> 1, addr
=> 20 },
5057 'net26' => { bus
=> 1, addr
=> 21 },
5058 'net27' => { bus
=> 1, addr
=> 22 },
5059 'net28' => { bus
=> 1, addr
=> 23 },
5060 'net29' => { bus
=> 1, addr
=> 24 },
5061 'net30' => { bus
=> 1, addr
=> 25 },
5062 'net31' => { bus
=> 1, addr
=> 26 },
5063 'xhci' => { bus
=> 1, addr
=> 27 },
5064 'virtio6' => { bus
=> 2, addr
=> 1 },
5065 'virtio7' => { bus
=> 2, addr
=> 2 },
5066 'virtio8' => { bus
=> 2, addr
=> 3 },
5067 'virtio9' => { bus
=> 2, addr
=> 4 },
5068 'virtio10' => { bus
=> 2, addr
=> 5 },
5069 'virtio11' => { bus
=> 2, addr
=> 6 },
5070 'virtio12' => { bus
=> 2, addr
=> 7 },
5071 'virtio13' => { bus
=> 2, addr
=> 8 },
5072 'virtio14' => { bus
=> 2, addr
=> 9 },
5073 'virtio15' => { bus
=> 2, addr
=> 10 },
5074 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5075 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5076 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5077 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5078 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5079 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5080 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5081 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5082 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5083 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5084 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5085 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5086 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5087 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5088 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5089 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5090 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5091 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5092 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5093 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5094 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5095 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5096 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5097 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5098 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5099 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5100 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5101 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5102 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5103 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5104 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5108 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5109 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5110 my $bus = $devices->{$id}->{bus
};
5111 $res = ",bus=pci.$bus,addr=$addr";
5112 $bridges->{$bus} = 1 if $bridges;
5118 sub print_pcie_addr
{
5123 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5124 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5125 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5126 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5129 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5130 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5131 my $bus = $devices->{$id}->{bus
};
5132 $res = ",bus=$bus,addr=$addr";
5138 # vzdump restore implementaion
5140 sub tar_archive_read_firstfile
{
5141 my $archive = shift;
5143 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5145 # try to detect archive type first
5146 my $pid = open (TMP
, "tar tf '$archive'|") ||
5147 die "unable to open file '$archive'\n";
5148 my $firstfile = <TMP
>;
5152 die "ERROR: archive contaions no data\n" if !$firstfile;
5158 sub tar_restore_cleanup
{
5159 my ($storecfg, $statfile) = @_;
5161 print STDERR
"starting cleanup\n";
5163 if (my $fd = IO
::File-
>new($statfile, "r")) {
5164 while (defined(my $line = <$fd>)) {
5165 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5168 if ($volid =~ m
|^/|) {
5169 unlink $volid || die 'unlink failed\n';
5171 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5173 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5175 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5177 print STDERR
"unable to parse line in statfile - $line";
5184 sub restore_archive
{
5185 my ($archive, $vmid, $user, $opts) = @_;
5187 my $format = $opts->{format
};
5190 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5191 $format = 'tar' if !$format;
5193 } elsif ($archive =~ m/\.tar$/) {
5194 $format = 'tar' if !$format;
5195 } elsif ($archive =~ m/.tar.lzo$/) {
5196 $format = 'tar' if !$format;
5198 } elsif ($archive =~ m/\.vma$/) {
5199 $format = 'vma' if !$format;
5200 } elsif ($archive =~ m/\.vma\.gz$/) {
5201 $format = 'vma' if !$format;
5203 } elsif ($archive =~ m/\.vma\.lzo$/) {
5204 $format = 'vma' if !$format;
5207 $format = 'vma' if !$format; # default
5210 # try to detect archive format
5211 if ($format eq 'tar') {
5212 return restore_tar_archive
($archive, $vmid, $user, $opts);
5214 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5218 sub restore_update_config_line
{
5219 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5221 return if $line =~ m/^\#qmdump\#/;
5222 return if $line =~ m/^\#vzdump\#/;
5223 return if $line =~ m/^lock:/;
5224 return if $line =~ m/^unused\d+:/;
5225 return if $line =~ m/^parent:/;
5226 return if $line =~ m/^template:/; # restored VM is never a template
5228 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5229 # try to convert old 1.X settings
5230 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5231 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5232 my ($model, $macaddr) = split(/\=/, $devconfig);
5233 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5236 bridge
=> "vmbr$ind",
5237 macaddr
=> $macaddr,
5239 my $netstr = print_net
($net);
5241 print $outfd "net$cookie->{netcount}: $netstr\n";
5242 $cookie->{netcount
}++;
5244 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5245 my ($id, $netstr) = ($1, $2);
5246 my $net = parse_net
($netstr);
5247 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5248 $netstr = print_net
($net);
5249 print $outfd "$id: $netstr\n";
5250 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5253 my $di = parse_drive
($virtdev, $value);
5254 if (defined($di->{backup
}) && !$di->{backup
}) {
5255 print $outfd "#$line";
5256 } elsif ($map->{$virtdev}) {
5257 delete $di->{format
}; # format can change on restore
5258 $di->{file
} = $map->{$virtdev};
5259 $value = print_drive
($vmid, $di);
5260 print $outfd "$virtdev: $value\n";
5270 my ($cfg, $vmid) = @_;
5272 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5274 my $volid_hash = {};
5275 foreach my $storeid (keys %$info) {
5276 foreach my $item (@{$info->{$storeid}}) {
5277 next if !($item->{volid
} && $item->{size
});
5278 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5279 $volid_hash->{$item->{volid
}} = $item;
5286 sub is_volume_in_use
{
5287 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5289 my $path = PVE
::Storage
::path
($storecfg, $volid);
5291 my $scan_config = sub {
5292 my ($cref, $snapname) = @_;
5294 foreach my $key (keys %$cref) {
5295 my $value = $cref->{$key};
5296 if (is_valid_drivename
($key)) {
5297 next if $skip_drive && $key eq $skip_drive;
5298 my $drive = parse_drive
($key, $value);
5299 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5300 return 1 if $volid eq $drive->{file
};
5301 if ($drive->{file
} =~ m!^/!) {
5302 return 1 if $drive->{file
} eq $path;
5304 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5306 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5308 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5316 return 1 if &$scan_config($conf);
5320 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5321 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5327 sub update_disksize
{
5328 my ($vmid, $conf, $volid_hash) = @_;
5334 # Note: it is allowed to define multiple storages with same path (alias), so
5335 # we need to check both 'volid' and real 'path' (two different volid can point
5336 # to the same path).
5341 foreach my $opt (keys %$conf) {
5342 if (is_valid_drivename
($opt)) {
5343 my $drive = parse_drive
($opt, $conf->{$opt});
5344 my $volid = $drive->{file
};
5347 $used->{$volid} = 1;
5348 if ($volid_hash->{$volid} &&
5349 (my $path = $volid_hash->{$volid}->{path
})) {
5350 $usedpath->{$path} = 1;
5353 next if drive_is_cdrom
($drive);
5354 next if !$volid_hash->{$volid};
5356 $drive->{size
} = $volid_hash->{$volid}->{size
};
5357 my $new = print_drive
($vmid, $drive);
5358 if ($new ne $conf->{$opt}) {
5360 $conf->{$opt} = $new;
5365 # remove 'unusedX' entry if volume is used
5366 foreach my $opt (keys %$conf) {
5367 next if $opt !~ m/^unused\d+$/;
5368 my $volid = $conf->{$opt};
5369 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5370 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5372 delete $conf->{$opt};
5376 foreach my $volid (sort keys %$volid_hash) {
5377 next if $volid =~ m/vm-$vmid-state-/;
5378 next if $used->{$volid};
5379 my $path = $volid_hash->{$volid}->{path
};
5380 next if !$path; # just to be sure
5381 next if $usedpath->{$path};
5383 add_unused_volume
($conf, $volid);
5384 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5391 my ($vmid, $nolock) = @_;
5393 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5395 my $volid_hash = scan_volids
($cfg, $vmid);
5397 my $updatefn = sub {
5400 my $conf = load_config
($vmid);
5405 foreach my $volid (keys %$volid_hash) {
5406 my $info = $volid_hash->{$volid};
5407 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5410 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5412 write_config
($vmid, $conf) if $changes;
5415 if (defined($vmid)) {
5419 lock_config
($vmid, $updatefn, $vmid);
5422 my $vmlist = config_list
();
5423 foreach my $vmid (keys %$vmlist) {
5427 lock_config
($vmid, $updatefn, $vmid);
5433 sub restore_vma_archive
{
5434 my ($archive, $vmid, $user, $opts, $comp) = @_;
5436 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5437 my $readfrom = $archive;
5442 my $qarchive = PVE
::Tools
::shellquote
($archive);
5443 if ($comp eq 'gzip') {
5444 $uncomp = "zcat $qarchive|";
5445 } elsif ($comp eq 'lzop') {
5446 $uncomp = "lzop -d -c $qarchive|";
5448 die "unknown compression method '$comp'\n";
5453 my $tmpdir = "/var/tmp/vzdumptmp$$";
5456 # disable interrupts (always do cleanups)
5457 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5458 warn "got interrupt - ignored\n";
5461 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5462 POSIX
::mkfifo
($mapfifo, 0600);
5465 my $openfifo = sub {
5466 open($fifofh, '>', $mapfifo) || die $!;
5469 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5476 my $rpcenv = PVE
::RPCEnvironment
::get
();
5478 my $conffile = config_file
($vmid);
5479 my $tmpfn = "$conffile.$$.tmp";
5481 # Note: $oldconf is undef if VM does not exists
5482 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5484 my $print_devmap = sub {
5485 my $virtdev_hash = {};
5487 my $cfgfn = "$tmpdir/qemu-server.conf";
5489 # we can read the config - that is already extracted
5490 my $fh = IO
::File-
>new($cfgfn, "r") ||
5491 "unable to read qemu-server.conf - $!\n";
5493 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5495 my $pve_firewall_dir = '/etc/pve/firewall';
5496 mkdir $pve_firewall_dir; # make sure the dir exists
5497 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5500 while (defined(my $line = <$fh>)) {
5501 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5502 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5503 die "archive does not contain data for drive '$virtdev'\n"
5504 if !$devinfo->{$devname};
5505 if (defined($opts->{storage
})) {
5506 $storeid = $opts->{storage
} || 'local';
5507 } elsif (!$storeid) {
5510 $format = 'raw' if !$format;
5511 $devinfo->{$devname}->{devname
} = $devname;
5512 $devinfo->{$devname}->{virtdev
} = $virtdev;
5513 $devinfo->{$devname}->{format
} = $format;
5514 $devinfo->{$devname}->{storeid
} = $storeid;
5516 # check permission on storage
5517 my $pool = $opts->{pool
}; # todo: do we need that?
5518 if ($user ne 'root@pam') {
5519 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5522 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5526 foreach my $devname (keys %$devinfo) {
5527 die "found no device mapping information for device '$devname'\n"
5528 if !$devinfo->{$devname}->{virtdev
};
5531 my $cfg = cfs_read_file
('storage.cfg');
5533 # create empty/temp config
5535 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5536 foreach_drive
($oldconf, sub {
5537 my ($ds, $drive) = @_;
5539 return if drive_is_cdrom
($drive);
5541 my $volid = $drive->{file
};
5543 return if !$volid || $volid =~ m
|^/|;
5545 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5546 return if !$path || !$owner || ($owner != $vmid);
5548 # Note: only delete disk we want to restore
5549 # other volumes will become unused
5550 if ($virtdev_hash->{$ds}) {
5551 PVE
::Storage
::vdisk_free
($cfg, $volid);
5555 # delete vmstate files
5556 # since after the restore we have no snapshots anymore
5557 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5558 my $snap = $oldconf->{snapshots
}->{$snapname};
5559 if ($snap->{vmstate
}) {
5560 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5569 foreach my $virtdev (sort keys %$virtdev_hash) {
5570 my $d = $virtdev_hash->{$virtdev};
5571 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5572 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5574 # test if requested format is supported
5575 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5576 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5577 $d->{format
} = $defFormat if !$supported;
5579 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5580 $d->{format
}, undef, $alloc_size);
5581 print STDERR
"new volume ID is '$volid'\n";
5582 $d->{volid
} = $volid;
5583 my $path = PVE
::Storage
::path
($cfg, $volid);
5585 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5587 my $write_zeros = 1;
5588 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5592 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5594 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5595 $map->{$virtdev} = $volid;
5598 $fh->seek(0, 0) || die "seek failed - $!\n";
5600 my $outfd = new IO
::File
($tmpfn, "w") ||
5601 die "unable to write config for VM $vmid\n";
5603 my $cookie = { netcount
=> 0 };
5604 while (defined(my $line = <$fh>)) {
5605 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5614 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5615 die "interrupted by signal\n";
5617 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5619 $oldtimeout = alarm($timeout);
5626 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5627 my ($dev_id, $size, $devname) = ($1, $2, $3);
5628 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5629 } elsif ($line =~ m/^CTIME: /) {
5630 # we correctly received the vma config, so we can disable
5631 # the timeout now for disk allocation (set to 10 minutes, so
5632 # that we always timeout if something goes wrong)
5635 print $fifofh "done\n";
5636 my $tmp = $oldtimeout || 0;
5637 $oldtimeout = undef;
5643 print "restore vma archive: $cmd\n";
5644 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5648 alarm($oldtimeout) if $oldtimeout;
5651 foreach my $devname (keys %$devinfo) {
5652 my $volid = $devinfo->{$devname}->{volid
};
5653 push @$vollist, $volid if $volid;
5656 my $cfg = cfs_read_file
('storage.cfg');
5657 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5665 foreach my $devname (keys %$devinfo) {
5666 my $volid = $devinfo->{$devname}->{volid
};
5669 if ($volid =~ m
|^/|) {
5670 unlink $volid || die 'unlink failed\n';
5672 PVE
::Storage
::vdisk_free
($cfg, $volid);
5674 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5676 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5683 rename($tmpfn, $conffile) ||
5684 die "unable to commit configuration file '$conffile'\n";
5686 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5688 eval { rescan
($vmid, 1); };
5692 sub restore_tar_archive
{
5693 my ($archive, $vmid, $user, $opts) = @_;
5695 if ($archive ne '-') {
5696 my $firstfile = tar_archive_read_firstfile
($archive);
5697 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5698 if $firstfile ne 'qemu-server.conf';
5701 my $storecfg = cfs_read_file
('storage.cfg');
5703 # destroy existing data - keep empty config
5704 my $vmcfgfn = config_file
($vmid);
5705 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5707 my $tocmd = "/usr/lib/qemu-server/qmextract";
5709 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5710 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5711 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5712 $tocmd .= ' --info' if $opts->{info
};
5714 # tar option "xf" does not autodetect compression when read from STDIN,
5715 # so we pipe to zcat
5716 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5717 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5719 my $tmpdir = "/var/tmp/vzdumptmp$$";
5722 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5723 local $ENV{VZDUMP_VMID
} = $vmid;
5724 local $ENV{VZDUMP_USER
} = $user;
5726 my $conffile = config_file
($vmid);
5727 my $tmpfn = "$conffile.$$.tmp";
5729 # disable interrupts (always do cleanups)
5730 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5731 print STDERR
"got interrupt - ignored\n";
5736 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5737 die "interrupted by signal\n";
5740 if ($archive eq '-') {
5741 print "extracting archive from STDIN\n";
5742 run_command
($cmd, input
=> "<&STDIN");
5744 print "extracting archive '$archive'\n";
5748 return if $opts->{info
};
5752 my $statfile = "$tmpdir/qmrestore.stat";
5753 if (my $fd = IO
::File-
>new($statfile, "r")) {
5754 while (defined (my $line = <$fd>)) {
5755 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5756 $map->{$1} = $2 if $1;
5758 print STDERR
"unable to parse line in statfile - $line\n";
5764 my $confsrc = "$tmpdir/qemu-server.conf";
5766 my $srcfd = new IO
::File
($confsrc, "r") ||
5767 die "unable to open file '$confsrc'\n";
5769 my $outfd = new IO
::File
($tmpfn, "w") ||
5770 die "unable to write config for VM $vmid\n";
5772 my $cookie = { netcount
=> 0 };
5773 while (defined (my $line = <$srcfd>)) {
5774 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5786 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5793 rename $tmpfn, $conffile ||
5794 die "unable to commit configuration file '$conffile'\n";
5796 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5798 eval { rescan
($vmid, 1); };
5803 # Internal snapshots
5805 # NOTE: Snapshot create/delete involves several non-atomic
5806 # action, and can take a long time.
5807 # So we try to avoid locking the file and use 'lock' variable
5808 # inside the config file instead.
5810 my $snapshot_copy_config = sub {
5811 my ($source, $dest) = @_;
5813 foreach my $k (keys %$source) {
5814 next if $k eq 'snapshots';
5815 next if $k eq 'snapstate';
5816 next if $k eq 'snaptime';
5817 next if $k eq 'vmstate';
5818 next if $k eq 'lock';
5819 next if $k eq 'digest';
5820 next if $k eq 'description';
5821 next if $k =~ m/^unused\d+$/;
5823 $dest->{$k} = $source->{$k};
5827 my $snapshot_apply_config = sub {
5828 my ($conf, $snap) = @_;
5830 # copy snapshot list
5832 snapshots
=> $conf->{snapshots
},
5835 # keep description and list of unused disks
5836 foreach my $k (keys %$conf) {
5837 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5838 $newconf->{$k} = $conf->{$k};
5841 &$snapshot_copy_config($snap, $newconf);
5846 sub foreach_writable_storage
{
5847 my ($conf, $func) = @_;
5851 foreach my $ds (keys %$conf) {
5852 next if !is_valid_drivename
($ds);
5854 my $drive = parse_drive
($ds, $conf->{$ds});
5856 next if drive_is_cdrom
($drive);
5858 my $volid = $drive->{file
};
5860 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5861 $sidhash->{$sid} = $sid if $sid;
5864 foreach my $sid (sort keys %$sidhash) {
5869 my $alloc_vmstate_volid = sub {
5870 my ($storecfg, $vmid, $conf, $snapname) = @_;
5872 # Note: we try to be smart when selecting a $target storage
5876 # search shared storage first
5877 foreach_writable_storage
($conf, sub {
5879 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5880 return if !$scfg->{shared
};
5882 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5886 # now search local storage
5887 foreach_writable_storage
($conf, sub {
5889 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5890 return if $scfg->{shared
};
5892 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5896 $target = 'local' if !$target;
5898 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5899 # we abort live save after $conf->{memory}, so we need at max twice that space
5900 my $size = $conf->{memory
}*2 + $driver_state_size;
5902 my $name = "vm-$vmid-state-$snapname";
5903 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5904 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5905 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5910 sub snapshot_save_vmstate
{
5911 my ($vmid, $conf, $snapname, $storecfg) = @_;
5913 my $snap = $conf->{snapshots
}->{$snapname};
5915 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5916 # always overwrite machine if we save vmstate. This makes sure we
5917 # can restore it later using correct machine type
5918 $snap->{machine
} = get_current_qemu_machine
($vmid);
5921 sub snapshot_prepare
{
5922 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5926 my $updatefn = sub {
5928 my $conf = load_config
($vmid);
5930 die "you can't take a snapshot if it's a template\n"
5931 if is_template
($conf);
5935 $conf->{lock} = 'snapshot';
5937 die "snapshot name '$snapname' already used\n"
5938 if defined($conf->{snapshots
}->{$snapname});
5940 my $storecfg = PVE
::Storage
::config
();
5941 die "snapshot feature is not available\n"
5942 if !has_feature
('snapshot', $conf, $storecfg, undef, undef, $snapname eq 'vzdump');
5944 $snap = $conf->{snapshots
}->{$snapname} = {};
5946 if ($save_vmstate && check_running
($vmid)) {
5947 snapshot_save_vmstate
($vmid, $conf, $snapname, $storecfg);
5950 &$snapshot_copy_config($conf, $snap);
5952 $snap->{snapstate
} = "prepare";
5953 $snap->{snaptime
} = time();
5954 $snap->{description
} = $comment if $comment;
5956 write_config
($vmid, $conf);
5959 lock_config
($vmid, $updatefn);
5964 sub snapshot_commit
{
5965 my ($vmid, $snapname) = @_;
5967 my $updatefn = sub {
5969 my $conf = load_config
($vmid);
5971 die "missing snapshot lock\n"
5972 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5974 my $snap = $conf->{snapshots
}->{$snapname};
5976 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5978 die "wrong snapshot state\n"
5979 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5981 delete $snap->{snapstate
};
5982 delete $conf->{lock};
5984 $conf->{parent
} = $snapname;
5986 write_config
($vmid, $conf);
5989 lock_config
($vmid, $updatefn);
5992 sub snapshot_rollback
{
5993 my ($vmid, $snapname) = @_;
5997 my $storecfg = PVE
::Storage
::config
();
5999 my $conf = load_config
($vmid);
6001 my $get_snapshot_config = sub {
6003 die "you can't rollback if vm is a template\n" if is_template
($conf);
6005 my $res = $conf->{snapshots
}->{$snapname};
6007 die "snapshot '$snapname' does not exist\n" if !defined($res);
6012 my $snap = &$get_snapshot_config();
6014 foreach_drive
($snap, sub {
6015 my ($ds, $drive) = @_;
6017 return if drive_is_cdrom
($drive);
6019 my $volid = $drive->{file
};
6021 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
6024 my $updatefn = sub {
6026 $conf = load_config
($vmid);
6028 $snap = &$get_snapshot_config();
6030 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
6031 if $snap->{snapstate
};
6035 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
6038 die "unable to rollback vm $vmid: vm is running\n"
6039 if check_running
($vmid);
6042 $conf->{lock} = 'rollback';
6044 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
6045 delete $conf->{lock};
6051 my $has_machine_config = defined($conf->{machine
});
6053 # copy snapshot config to current config
6054 $conf = &$snapshot_apply_config($conf, $snap);
6055 $conf->{parent
} = $snapname;
6057 # Note: old code did not store 'machine', so we try to be smart
6058 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
6059 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
6060 # we remove the 'machine' configuration if not explicitly specified
6061 # in the original config.
6062 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
6065 write_config
($vmid, $conf);
6067 if (!$prepare && $snap->{vmstate
}) {
6068 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6069 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
6073 lock_config
($vmid, $updatefn);
6075 foreach_drive
($snap, sub {
6076 my ($ds, $drive) = @_;
6078 return if drive_is_cdrom
($drive);
6080 my $volid = $drive->{file
};
6081 my $device = "drive-$ds";
6083 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
6087 lock_config
($vmid, $updatefn);
6090 my $savevm_wait = sub {
6094 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6095 if (!$stat->{status
}) {
6096 die "savevm not active\n";
6097 } elsif ($stat->{status
} eq 'active') {
6100 } elsif ($stat->{status
} eq 'completed') {
6103 die "query-savevm returned status '$stat->{status}'\n";
6108 sub do_snapshots_with_qemu
{
6109 my ($storecfg, $volid) = @_;
6111 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
6113 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
6114 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
6118 if ($volid =~ m/\.(qcow2|qed)$/){
6125 sub qga_check_running
{
6128 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
6130 warn "Qemu Guest Agent are not running - $@";
6136 sub check_freeze_needed
{
6137 my ($vmid, $config, $save_vmstate) = @_;
6139 my $running = check_running
($vmid);
6140 if ($save_vmstate) {
6141 return ($running, $running && $config->{agent
} && qga_check_running
($vmid));
6143 return ($running, 0);
6147 sub snapshot_create
{
6148 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
6150 my $snap = snapshot_prepare
($vmid, $snapname, $save_vmstate, $comment);
6152 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
6154 my $config = load_config
($vmid);
6156 my ($running, $freezefs) = check_freeze_needed
($vmid, $config, $snap->{vmstate
});
6162 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6163 warn "guest-fsfreeze-freeze problems - $@" if $@;
6166 # create internal snapshots of all drives
6168 my $storecfg = PVE
::Storage
::config
();
6171 if ($snap->{vmstate
}) {
6172 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6173 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
6174 &$savevm_wait($vmid);
6176 vm_mon_cmd
($vmid, "savevm-start");
6180 foreach_drive
($snap, sub {
6181 my ($ds, $drive) = @_;
6183 return if drive_is_cdrom
($drive);
6185 my $volid = $drive->{file
};
6186 my $device = "drive-$ds";
6188 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
6189 $drivehash->{$ds} = 1;
6195 eval { vm_mon_cmd
($vmid, "savevm-end") };
6199 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6200 warn "guest-fsfreeze-thaw problems - $@" if $@;
6203 # savevm-end is async, we need to wait
6205 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6206 if (!$stat->{bytes
}) {
6209 print "savevm not yet finished\n";
6217 warn "snapshot create failed: starting cleanup\n";
6218 eval { snapshot_delete
($vmid, $snapname, 1, $drivehash); };
6223 snapshot_commit
($vmid, $snapname);
6226 # Note: $drivehash is only set when called from snapshot_create.
6227 sub snapshot_delete
{
6228 my ($vmid, $snapname, $force, $drivehash) = @_;
6235 my $unlink_parent = sub {
6236 my ($confref, $new_parent) = @_;
6238 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6240 $confref->{parent
} = $new_parent;
6242 delete $confref->{parent
};
6247 my $updatefn = sub {
6248 my ($remove_drive) = @_;
6250 my $conf = load_config
($vmid);
6254 die "you can't delete a snapshot if vm is a template\n"
6255 if is_template
($conf);
6258 $snap = $conf->{snapshots
}->{$snapname};
6260 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6262 # remove parent refs
6264 &$unlink_parent($conf, $snap->{parent
});
6265 foreach my $sn (keys %{$conf->{snapshots
}}) {
6266 next if $sn eq $snapname;
6267 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6271 if ($remove_drive) {
6272 if ($remove_drive eq 'vmstate') {
6273 delete $snap->{$remove_drive};
6275 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6276 my $volid = $drive->{file
};
6277 delete $snap->{$remove_drive};
6278 add_unused_volume
($conf, $volid);
6283 $snap->{snapstate
} = 'delete';
6285 delete $conf->{snapshots
}->{$snapname};
6286 delete $conf->{lock} if $drivehash;
6287 foreach my $volid (@$unused) {
6288 add_unused_volume
($conf, $volid);
6292 write_config
($vmid, $conf);
6295 lock_config
($vmid, $updatefn);
6297 # now remove vmstate file
6299 my $storecfg = PVE
::Storage
::config
();
6301 if ($snap->{vmstate
}) {
6302 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6304 die $err if !$force;
6307 # save changes (remove vmstate from snapshot)
6308 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6311 # now remove all internal snapshots
6312 foreach_drive
($snap, sub {
6313 my ($ds, $drive) = @_;
6315 return if drive_is_cdrom
($drive);
6317 my $volid = $drive->{file
};
6318 my $device = "drive-$ds";
6320 if (!$drivehash || $drivehash->{$ds}) {
6321 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6323 die $err if !$force;
6328 # save changes (remove drive fron snapshot)
6329 lock_config
($vmid, $updatefn, $ds) if !$force;
6330 push @$unused, $volid;
6333 # now cleanup config
6335 lock_config
($vmid, $updatefn);
6339 my ($feature, $conf, $storecfg, $snapname, $running, $backup_only) = @_;
6342 foreach_drive
($conf, sub {
6343 my ($ds, $drive) = @_;
6345 return if drive_is_cdrom
($drive);
6346 return if $backup_only && !$drive->{backup
};
6347 my $volid = $drive->{file
};
6348 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6351 return $err ?
0 : 1;
6354 sub template_create
{
6355 my ($vmid, $conf, $disk) = @_;
6357 my $storecfg = PVE
::Storage
::config
();
6359 foreach_drive
($conf, sub {
6360 my ($ds, $drive) = @_;
6362 return if drive_is_cdrom
($drive);
6363 return if $disk && $ds ne $disk;
6365 my $volid = $drive->{file
};
6366 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6368 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6369 $drive->{file
} = $voliddst;
6370 $conf->{$ds} = print_drive
($vmid, $drive);
6371 write_config
($vmid, $conf);
6378 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6381 sub qemu_img_convert
{
6382 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6384 my $storecfg = PVE
::Storage
::config
();
6385 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6386 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6388 if ($src_storeid && $dst_storeid) {
6390 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6392 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6393 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6395 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6396 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6398 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6399 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6402 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6403 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6404 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6408 if($line =~ m/\((\S+)\/100\
%\)/){
6410 my $transferred = int($size * $percent / 100);
6411 my $remaining = $size - $transferred;
6413 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6418 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6420 die "copy failed: $err" if $err;
6424 sub qemu_img_format
{
6425 my ($scfg, $volname) = @_;
6427 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6434 sub qemu_drive_mirror
{
6435 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6437 my $storecfg = PVE
::Storage
::config
();
6438 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6440 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6442 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6444 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6446 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6447 $opts->{format
} = $format if $format;
6449 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6452 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6454 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6455 my $stat = @$stats[0];
6456 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6457 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6459 my $busy = $stat->{busy
};
6460 my $ready = $stat->{ready
};
6462 if (my $total = $stat->{len
}) {
6463 my $transferred = $stat->{offset
} || 0;
6464 my $remaining = $total - $transferred;
6465 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6467 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6471 if ($stat->{ready
} eq 'true') {
6473 last if $vmiddst != $vmid;
6475 # try to switch the disk if source and destination are on the same guest
6476 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6478 die $@ if $@ !~ m/cannot be completed/;
6487 my $cancel_job = sub {
6488 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6490 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6491 my $stat = @$stats[0];
6498 eval { &$cancel_job(); };
6499 die "mirroring error: $err";
6502 if ($vmiddst != $vmid) {
6503 # if we clone a disk for a new target vm, we don't switch the disk
6504 &$cancel_job(); # so we call block-job-cancel
6509 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6510 $newvmid, $storage, $format, $full, $newvollist) = @_;
6515 print "create linked clone of drive $drivename ($drive->{file})\n";
6516 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6517 push @$newvollist, $newvolid;
6519 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6520 $storeid = $storage if $storage;
6522 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6524 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6525 $format = qemu_img_format
($scfg, $volname);
6528 # test if requested format is supported - else use default
6529 my $supported = grep { $_ eq $format } @$validFormats;
6530 $format = $defFormat if !$supported;
6532 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6534 print "create full clone of drive $drivename ($drive->{file})\n";
6535 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6536 push @$newvollist, $newvolid;
6538 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6540 if (!$running || $snapname) {
6541 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6543 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6547 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6550 $disk->{format
} = undef;
6551 $disk->{file
} = $newvolid;
6552 $disk->{size
} = $size;
6557 # this only works if VM is running
6558 sub get_current_qemu_machine
{
6561 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6562 my $res = vm_qmp_command
($vmid, $cmd);
6564 my ($current, $default);
6565 foreach my $e (@$res) {
6566 $default = $e->{name
} if $e->{'is-default'};
6567 $current = $e->{name
} if $e->{'is-current'};
6570 # fallback to the default machine if current is not supported by qemu
6571 return $current || $default || 'pc';
6574 sub qemu_machine_feature_enabled
{
6575 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6580 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6582 $current_major = $3;
6583 $current_minor = $4;
6585 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6587 $current_major = $1;
6588 $current_minor = $2;
6591 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6596 sub qemu_machine_pxe
{
6597 my ($vmid, $conf, $machine) = @_;
6599 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6601 foreach my $opt (keys %$conf) {
6602 next if $opt !~ m/^net(\d+)$/;
6603 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6605 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6606 return $machine.".pxe" if $romfile =~ m/pxe/;
6613 sub qemu_use_old_bios_files
{
6614 my ($machine_type) = @_;
6616 return if !$machine_type;
6618 my $use_old_bios_files = undef;
6620 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6622 $use_old_bios_files = 1;
6624 my $kvmver = kvm_user_version
();
6625 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6626 # load new efi bios files on migration. So this hack is required to allow
6627 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6628 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6629 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6632 return ($use_old_bios_files, $machine_type);
6639 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6640 my (undef, $id, $function) = @_;
6641 my $res = { id
=> $id, function
=> $function};
6642 push @{$devices->{$id}}, $res;
6648 sub vm_iothreads_list
{
6651 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6654 foreach my $iothread (@$res) {
6655 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6662 my ($conf, $drive) = @_;
6666 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6668 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6674 my $controller = int($drive->{index} / $maxdev);
6675 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6677 return ($maxdev, $controller, $controller_prefix);
6680 # bash completion helper
6682 sub complete_backup_archives
{
6683 my ($cmdname, $pname, $cvalue) = @_;
6685 my $cfg = PVE
::Storage
::config
();
6689 if ($cvalue =~ m/^([^:]+):/) {
6693 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6696 foreach my $id (keys %$data) {
6697 foreach my $item (@{$data->{$id}}) {
6698 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6699 push @$res, $item->{volid
} if defined($item->{volid
});
6706 my $complete_vmid_full = sub {
6709 my $idlist = vmstatus
();
6713 foreach my $id (keys %$idlist) {
6714 my $d = $idlist->{$id};
6715 if (defined($running)) {
6716 next if $d->{template
};
6717 next if $running && $d->{status
} ne 'running';
6718 next if !$running && $d->{status
} eq 'running';
6727 return &$complete_vmid_full();
6730 sub complete_vmid_stopped
{
6731 return &$complete_vmid_full(0);
6734 sub complete_vmid_running
{
6735 return &$complete_vmid_full(1);
6738 sub complete_storage
{
6740 my $cfg = PVE
::Storage
::config
();
6741 my $ids = $cfg->{ids
};
6744 foreach my $sid (keys %$ids) {
6745 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6746 next if !$ids->{$sid}->{content
}->{images
};