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);
32 use PVE
::RPCEnvironment
;
33 use Time
::HiRes
qw(gettimeofday);
34 use File
::Copy
qw(copy);
37 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
39 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
41 # Note about locking: we use flock on the config file protect
42 # against concurent actions.
43 # Aditionaly, we have a 'lock' setting in the config file. This
44 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
45 # allowed when such lock is set. But you can ignore this kind of
46 # lock with the --skiplock flag.
48 cfs_register_file
('/qemu-server/',
52 PVE
::JSONSchema
::register_standard_option
('skiplock', {
53 description
=> "Ignore locks - only root is allowed to use this option.",
58 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
59 description
=> "Some command save/restore state from this location.",
65 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
66 description
=> "The name of the snapshot.",
67 type
=> 'string', format
=> 'pve-configid',
71 #no warnings 'redefine';
74 my ($controller, $vmid, $option, $value) = @_;
76 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
77 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
81 my $nodename = PVE
::INotify
::nodename
();
83 mkdir "/etc/pve/nodes/$nodename";
84 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
87 my $var_run_tmpdir = "/var/run/qemu-server";
88 mkdir $var_run_tmpdir;
90 my $lock_dir = "/var/lock/qemu-server";
93 my $pcisysfs = "/sys/bus/pci";
97 description
=> "Emulated CPU type.",
99 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) ],
100 format_description
=> 'cputype',
105 description
=> "Do not identify as a KVM virtual machine.",
116 description
=> "Specifies whether a VM will be started during system bootup.",
122 description
=> "Automatic restart after crash (currently ignored).",
127 type
=> 'string', format
=> 'pve-hotplug-features',
128 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'.",
129 default => 'network,disk,usb',
134 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
140 description
=> "Lock/unlock the VM.",
141 enum
=> [qw(migrate backup snapshot rollback)],
146 description
=> "Limit of CPU usage.\n\nNOTE: If the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
154 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.",
162 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
169 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
175 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",
183 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
184 enum
=> PVE
::Tools
::kvmkeymaplist
(),
189 type
=> 'string', format
=> 'dns-name',
190 description
=> "Set a name for the VM. Only used on the configuration web interface.",
195 description
=> "scsi controller model",
196 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
202 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
207 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
208 description
=> <<EODESC,
209 Used to enable special optimization/features for specific
212 other => unspecified OS
213 wxp => Microsoft Windows XP
214 w2k => Microsoft Windows 2000
215 w2k3 => Microsoft Windows 2003
216 w2k8 => Microsoft Windows 2008
217 wvista => Microsoft Windows Vista
218 win7 => Microsoft Windows 7
219 win8 => Microsoft Windows 8/2012
220 l24 => Linux 2.4 Kernel
221 l26 => Linux 2.6/3.X Kernel
222 solaris => solaris/opensolaris/openindiania kernel
224 other|l24|l26|solaris ... no special behaviour
225 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
231 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
232 pattern
=> '[acdn]{1,4}',
237 type
=> 'string', format
=> 'pve-qm-bootdisk',
238 description
=> "Enable booting from specified disk.",
239 pattern
=> '(ide|sata|scsi|virtio)\d+',
244 description
=> "The number of CPUs. Please use option -sockets instead.",
251 description
=> "The number of CPU sockets.",
258 description
=> "The number of cores per socket.",
265 description
=> "Enable/disable NUMA.",
271 description
=> "Number of hotplugged vcpus.",
278 description
=> "Enable/disable ACPI.",
284 description
=> "Enable/disable Qemu GuestAgent.",
290 description
=> "Enable/disable KVM hardware virtualization.",
296 description
=> "Enable/disable time drift fix.",
302 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
307 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
312 description
=> "Select the VGA type. If you want to use high resolution" .
313 " modes (>= 1280x1024x16) then you should use the options " .
314 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
315 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
316 "display sever. For win* OS you can select how many independent " .
317 "displays you want, Linux guests can add displays them self. " .
318 "You can also run without any graphic card, using a serial device" .
320 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
324 type
=> 'string', format
=> 'pve-qm-watchdog',
325 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
326 description
=> "Create a virtual hardware watchdog device. Once enabled" .
327 " (by a guest action), the watchdog must be periodically polled " .
328 "by an agent inside the guest or else the watchdog will reset " .
329 "the guest (or execute the respective action specified)",
334 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
335 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'.",
336 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
339 startup
=> get_standard_option
('pve-startup-order'),
343 description
=> "Enable/disable Template.",
349 description
=> <<EODESCR,
350 NOTE: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
352 args: -no-reboot -no-hpet
359 description
=> "Enable/disable the USB tablet device. This device is " .
360 "usually needed to allow absolute mouse positioning with VNC. " .
361 "Else the mouse runs out of sync with normal VNC clients. " .
362 "If you're running lots of console-only guests on one host, " .
363 "you may consider disabling this to save some context switches. " .
364 "This is turned off by default if you use spice (-vga=qxl).",
369 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
373 migrate_downtime
=> {
376 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
382 type
=> 'string', format
=> 'pve-qm-drive',
383 typetext
=> 'volume',
384 description
=> "This is an alias for option -ide2",
388 description
=> "Emulated CPU type.",
392 parent
=> get_standard_option
('pve-snapshot-name', {
394 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
398 description
=> "Timestamp for snapshots.",
404 type
=> 'string', format
=> 'pve-volume-id',
405 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
408 description
=> "Specific the Qemu machine type.",
410 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
415 description
=> "Specify SMBIOS type 1 fields.",
416 type
=> 'string', format
=> 'pve-qm-smbios1',
423 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
429 enum
=> [ qw(seabios ovmf) ],
430 description
=> "Select BIOS implementation.",
431 default => 'seabios',
435 # what about other qemu settings ?
437 #machine => 'string',
450 ##soundhw => 'string',
452 while (my ($k, $v) = each %$confdesc) {
453 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
456 my $MAX_IDE_DISKS = 4;
457 my $MAX_SCSI_DISKS = 14;
458 my $MAX_VIRTIO_DISKS = 16;
459 my $MAX_SATA_DISKS = 6;
460 my $MAX_USB_DEVICES = 5;
462 my $MAX_UNUSED_DISKS = 8;
463 my $MAX_HOSTPCI_DEVICES = 4;
464 my $MAX_SERIAL_PORTS = 4;
465 my $MAX_PARALLEL_PORTS = 3;
467 my $MAX_MEM = 4194304;
468 my $STATICMEM = 1024;
472 type
=> 'string', format
=> 'pve-qm-numanode',
473 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
474 description
=> "numa topology",
476 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
478 for (my $i = 0; $i < $MAX_NUMA; $i++) {
479 $confdesc->{"numa$i"} = $numadesc;
482 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
483 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
484 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
485 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
489 type
=> 'string', format
=> 'pve-qm-net',
490 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]",
491 description
=> <<EODESCR,
492 Specify network devices.
494 MODEL is one of: $nic_model_list_txt
496 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
497 automatically generated if not specified.
499 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
501 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'.
503 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
509 The DHCP server assign addresses to the guest starting from 10.0.2.15.
513 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
515 for (my $i = 0; $i < $MAX_NETS; $i++) {
516 $confdesc->{"net$i"} = $netdesc;
521 my %drivedesc_base = (
522 volume
=> { alias
=> 'file' },
525 format
=> 'pve-volume-id',
527 format_description
=> 'volume',
528 description
=> "The drive's backing volume.",
532 format_description
=> 'cdrom|disk',
533 enum
=> [qw(cdrom disk)],
534 description
=> "The drive's media type.",
540 format_description
=> 'count',
541 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
546 format_description
=> 'count',
547 description
=> "Force the drive's physical geometry to have a specific head count.",
552 format_description
=> 'count',
553 description
=> "Force the drive's physical geometry to have a specific sector count.",
558 format_description
=> 'none|lba|auto',
559 enum
=> [qw(none lba auto)],
560 description
=> "Force disk geometry bios translation mode.",
565 format_description
=> 'on|off',
566 description
=> "Whether the drive should be included when making snapshots.",
571 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
572 enum
=> [qw(none writethrough writeback unsafe directsync)],
573 description
=> "The drive's cache mode",
578 format_description
=> 'drive format',
579 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
580 description
=> "The drive's backing file's data format.",
585 format
=> 'disk-size',
586 description
=> "Disk size. This is purely informational and has no effect.",
591 format_description
=> 'on|off',
592 description
=> "Whether the drive should be included when making backups.",
597 format_description
=> 'enospc|ignore|report|stop',
598 enum
=> [qw(enospc ignore report stop)],
599 description
=> 'Write error action.',
604 format_description
=> 'native|threads',
605 enum
=> [qw(native threads)],
606 description
=> 'AIO type to use.',
611 format_description
=> 'ignore|on',
612 enum
=> [qw(ignore on)],
613 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
618 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
623 format
=> 'urlencoded',
624 format_description
=> 'serial',
625 maxLength
=> 20*3, # *3 since it's %xx url enoded
626 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
634 format_description
=> 'ignore|report|stop',
635 enum
=> [qw(ignore report stop)],
636 description
=> 'Read error action.',
641 my %iothread_fmt = ( iothread
=> {
643 format_description
=> 'off|on',
644 description
=> "Whether to use iothreads for this drive",
651 format
=> 'urlencoded',
652 format_description
=> 'model',
653 maxLength
=> 40*3, # *3 since it's %xx url enoded
654 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
662 format_description
=> 'nbqueues',
663 description
=> "Number of queues.",
669 my $add_throttle_desc = sub {
670 my ($key, $type, $what, $size, $longsize) = @_;
671 $drivedesc_base{$key} = {
673 format_description
=> $size,
674 description
=> "Maximum $what speed in $longsize per second.",
678 # throughput: (leaky bucket)
679 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
680 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
681 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
682 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
683 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
684 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
685 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
686 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
687 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
689 # pools: (pool of IO before throttling starts taking effect)
690 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
691 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
692 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
693 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
694 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
695 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
705 type
=> 'string', format
=> $ide_fmt,
706 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
708 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
717 type
=> 'string', format
=> $scsi_fmt,
718 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
720 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
728 type
=> 'string', format
=> $sata_fmt,
729 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
731 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
740 type
=> 'string', format
=> $virtio_fmt,
741 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
743 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
756 type
=> 'string', format
=> 'pve-qm-usb-device',
757 format_description
=> 'HOSTUSBDEVICE|spice',
758 description
=> 'The Host USB device or port or the value spice',
763 format_description
=> 'yes|no',
764 description
=> 'Specifies whether if given host option is a USB3 device or port',
770 type
=> 'string', format
=> $usb_fmt,
771 description
=> <<EODESCR,
772 Configure an USB device (n is 0 to 4). This can be used to
773 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
775 'bus-port(.port)*' (decimal numbers) or
776 'vendor_id:product_id' (hexadeciaml numbers) or
779 You can use the 'lsusb -t' command to list existing usb devices.
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 The value 'spice' can be used to add a usb redirection devices for spice.
785 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).
789 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
793 type
=> 'string', format
=> 'pve-qm-hostpci',
794 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
795 description
=> <<EODESCR,
796 Map host pci devices. HOSTPCIDEVICE syntax is:
798 'bus:dev.func' (hexadecimal numbers)
800 You can us the 'lspci' command to list existing pci devices.
802 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
804 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
806 Experimental: user reported problems with this option.
809 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
814 pattern
=> '(/dev/.+|socket)',
815 description
=> <<EODESCR,
816 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).
818 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
820 Experimental: user reported problems with this option.
827 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
828 description
=> <<EODESCR,
829 Map host parallel devices (n is 0 to 2).
831 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
833 Experimental: user reported problems with this option.
837 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
838 $confdesc->{"parallel$i"} = $paralleldesc;
841 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
842 $confdesc->{"serial$i"} = $serialdesc;
845 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
846 $confdesc->{"hostpci$i"} = $hostpcidesc;
849 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
850 $drivename_hash->{"ide$i"} = 1;
851 $confdesc->{"ide$i"} = $idedesc;
854 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
855 $drivename_hash->{"sata$i"} = 1;
856 $confdesc->{"sata$i"} = $satadesc;
859 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
860 $drivename_hash->{"scsi$i"} = 1;
861 $confdesc->{"scsi$i"} = $scsidesc ;
864 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
865 $drivename_hash->{"virtio$i"} = 1;
866 $confdesc->{"virtio$i"} = $virtiodesc;
869 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
870 $confdesc->{"usb$i"} = $usbdesc;
875 type
=> 'string', format
=> 'pve-volume-id',
876 description
=> "Reference to unused volumes.",
879 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
880 $confdesc->{"unused$i"} = $unuseddesc;
883 my $kvm_api_version = 0;
887 return $kvm_api_version if $kvm_api_version;
889 my $fh = IO
::File-
>new("</dev/kvm") ||
892 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
893 $kvm_api_version = $v;
898 return $kvm_api_version;
901 my $kvm_user_version;
903 sub kvm_user_version
{
905 return $kvm_user_version if $kvm_user_version;
907 $kvm_user_version = 'unknown';
911 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
912 $kvm_user_version = $2;
916 eval { run_command
("kvm -version", outfunc
=> $code); };
919 return $kvm_user_version;
923 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
925 sub valid_drive_names
{
926 # order is important - used to autoselect boot disk
927 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
928 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
929 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
930 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
933 sub is_valid_drivename
{
936 return defined($drivename_hash->{$dev});
941 return defined($confdesc->{$key});
945 return $nic_model_list;
948 sub os_list_description
{
953 w2k
=> 'Windows 2000',
954 w2k3
=>, 'Windows 2003',
955 w2k8
=> 'Windows 2008',
956 wvista
=> 'Windows Vista',
958 win8
=> 'Windows 8/2012',
968 return $cdrom_path if $cdrom_path;
970 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
971 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
972 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
976 my ($storecfg, $vmid, $cdrom) = @_;
978 if ($cdrom eq 'cdrom') {
979 return get_cdrom_path
();
980 } elsif ($cdrom eq 'none') {
982 } elsif ($cdrom =~ m
|^/|) {
985 return PVE
::Storage
::path
($storecfg, $cdrom);
989 # try to convert old style file names to volume IDs
990 sub filename_to_volume_id
{
991 my ($vmid, $file, $media) = @_;
993 if (!($file eq 'none' || $file eq 'cdrom' ||
994 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
996 return undef if $file =~ m
|/|;
998 if ($media && $media eq 'cdrom') {
999 $file = "local:iso/$file";
1001 $file = "local:$vmid/$file";
1008 sub verify_media_type
{
1009 my ($opt, $vtype, $media) = @_;
1014 if ($media eq 'disk') {
1016 } elsif ($media eq 'cdrom') {
1019 die "internal error";
1022 return if ($vtype eq $etype);
1024 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1027 sub cleanup_drive_path
{
1028 my ($opt, $storecfg, $drive) = @_;
1030 # try to convert filesystem paths to volume IDs
1032 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1033 ($drive->{file
} !~ m
|^/dev/.+|) &&
1034 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1035 ($drive->{file
} !~ m/^\d+$/)) {
1036 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1037 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1038 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1039 verify_media_type
($opt, $vtype, $drive->{media
});
1040 $drive->{file
} = $volid;
1043 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1046 sub parse_hotplug_features
{
1051 return $res if $data eq '0';
1053 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1055 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1056 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1059 warn "ignoring unknown hotplug feature '$feature'\n";
1065 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1066 sub pve_verify_hotplug_features
{
1067 my ($value, $noerr) = @_;
1069 return $value if parse_hotplug_features
($value);
1071 return undef if $noerr;
1073 die "unable to parse hotplug option\n";
1076 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1077 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1078 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1079 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1080 # [,iothread=on][,serial=serial][,model=model]
1083 my ($key, $data) = @_;
1085 my ($interface, $index);
1087 if ($key =~ m/^([^\d]+)(\d+)$/) {
1094 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1095 : $confdesc->{$key}->{format
};
1097 warn "invalid drive key: $key\n";
1100 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1101 return undef if !$res;
1102 $res->{interface
} = $interface;
1103 $res->{index} = $index;
1106 foreach my $opt (qw(bps bps_rd bps_wr)) {
1107 if (my $bps = defined(delete $res->{$opt})) {
1108 if (defined($res->{"m$opt"})) {
1109 warn "both $opt and m$opt specified\n";
1113 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1116 return undef if $error;
1118 return undef if $res->{mbps_rd
} && $res->{mbps
};
1119 return undef if $res->{mbps_wr
} && $res->{mbps
};
1120 return undef if $res->{iops_rd
} && $res->{iops
};
1121 return undef if $res->{iops_wr
} && $res->{iops
};
1123 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1124 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1125 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1126 return undef if $res->{interface
} eq 'virtio';
1129 if (my $size = $res->{size
}) {
1130 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1137 my ($vmid, $drive) = @_;
1138 my $data = { %$drive };
1139 delete $data->{$_} for qw(index interface);
1140 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1144 my($fh, $noerr) = @_;
1147 my $SG_GET_VERSION_NUM = 0x2282;
1149 my $versionbuf = "\x00" x
8;
1150 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1152 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1155 my $version = unpack("I", $versionbuf);
1156 if ($version < 30000) {
1157 die "scsi generic interface too old\n" if !$noerr;
1161 my $buf = "\x00" x
36;
1162 my $sensebuf = "\x00" x
8;
1163 my $cmd = pack("C x3 C x1", 0x12, 36);
1165 # see /usr/include/scsi/sg.h
1166 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";
1168 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1169 length($sensebuf), 0, length($buf), $buf,
1170 $cmd, $sensebuf, 6000);
1172 $ret = ioctl($fh, $SG_IO, $packet);
1174 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1178 my @res = unpack($sg_io_hdr_t, $packet);
1179 if ($res[17] || $res[18]) {
1180 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1185 (my $byte0, my $byte1, $res->{vendor
},
1186 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1188 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1189 $res->{type
} = $byte0 & 31;
1197 my $fh = IO
::File-
>new("+<$path") || return undef;
1198 my $res = scsi_inquiry
($fh, 1);
1204 sub machine_type_is_q35
{
1207 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1210 sub print_tabletdevice_full
{
1213 my $q35 = machine_type_is_q35
($conf);
1215 # we use uhci for old VMs because tablet driver was buggy in older qemu
1216 my $usbbus = $q35 ?
"ehci" : "uhci";
1218 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1221 sub print_drivedevice_full
{
1222 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1227 if ($drive->{interface
} eq 'virtio') {
1228 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1229 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1230 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1231 } elsif ($drive->{interface
} eq 'scsi') {
1233 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1234 my $unit = $drive->{index} % $maxdev;
1235 my $devicetype = 'hd';
1237 if (drive_is_cdrom
($drive)) {
1240 if ($drive->{file
} =~ m
|^/|) {
1241 $path = $drive->{file
};
1242 if (my $info = path_is_scsi
($path)) {
1243 if ($info->{type
} == 0) {
1244 $devicetype = 'block';
1245 } elsif ($info->{type
} == 1) { # tape
1246 $devicetype = 'generic';
1250 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1253 if($path =~ m/^iscsi\:\/\
//){
1254 $devicetype = 'generic';
1258 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1259 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1261 $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}";
1264 } elsif ($drive->{interface
} eq 'ide'){
1266 my $controller = int($drive->{index} / $maxdev);
1267 my $unit = $drive->{index} % $maxdev;
1268 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1270 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1271 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1272 $model = URI
::Escape
::uri_unescape
($model);
1273 $device .= ",model=$model";
1275 } elsif ($drive->{interface
} eq 'sata'){
1276 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1277 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1278 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1279 } elsif ($drive->{interface
} eq 'usb') {
1281 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1283 die "unsupported interface type";
1286 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1291 sub get_initiator_name
{
1294 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1295 while (defined(my $line = <$fh>)) {
1296 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1305 sub print_drive_full
{
1306 my ($storecfg, $vmid, $drive) = @_;
1309 my $volid = $drive->{file
};
1312 if (drive_is_cdrom
($drive)) {
1313 $path = get_iso_path
($storecfg, $vmid, $volid);
1315 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1317 $path = PVE
::Storage
::path
($storecfg, $volid);
1318 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1319 $format = qemu_img_format
($scfg, $volname);
1327 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);
1328 foreach my $o (@qemu_drive_options) {
1329 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1331 if (my $serial = $drive->{serial
}) {
1332 $serial = URI
::Escape
::uri_unescape
($serial);
1333 $opts .= ",serial=$serial";
1336 $opts .= ",format=$format" if $format && !$drive->{format
};
1338 foreach my $o (qw(bps bps_rd bps_wr)) {
1339 my $v = $drive->{"m$o"};
1340 $opts .= ",$o=" . int($v*1024*1024) if $v;
1343 my $cache_direct = 0;
1345 if (my $cache = $drive->{cache
}) {
1346 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1347 } elsif (!drive_is_cdrom
($drive)) {
1348 $opts .= ",cache=none";
1352 # aio native works only with O_DIRECT
1353 if (!$drive->{aio
}) {
1355 $opts .= ",aio=native";
1357 $opts .= ",aio=threads";
1361 if (!drive_is_cdrom
($drive)) {
1363 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1364 $detectzeroes = 'off';
1365 } elsif ($drive->{discard
}) {
1366 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1368 # This used to be our default with discard not being specified:
1369 $detectzeroes = 'on';
1371 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1374 my $pathinfo = $path ?
"file=$path," : '';
1376 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1379 sub print_netdevice_full
{
1380 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1382 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1384 my $device = $net->{model
};
1385 if ($net->{model
} eq 'virtio') {
1386 $device = 'virtio-net-pci';
1389 my $pciaddr = print_pci_addr
("$netid", $bridges);
1390 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1391 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1392 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1393 my $vectors = $net->{queues
} * 2 + 2;
1394 $tmpstr .= ",vectors=$vectors,mq=on";
1396 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1398 if ($use_old_bios_files) {
1400 if ($device eq 'virtio-net-pci') {
1401 $romfile = 'pxe-virtio.rom';
1402 } elsif ($device eq 'e1000') {
1403 $romfile = 'pxe-e1000.rom';
1404 } elsif ($device eq 'ne2k') {
1405 $romfile = 'pxe-ne2k_pci.rom';
1406 } elsif ($device eq 'pcnet') {
1407 $romfile = 'pxe-pcnet.rom';
1408 } elsif ($device eq 'rtl8139') {
1409 $romfile = 'pxe-rtl8139.rom';
1411 $tmpstr .= ",romfile=$romfile" if $romfile;
1417 sub print_netdev_full
{
1418 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1421 if ($netid =~ m/^net(\d+)$/) {
1425 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1427 my $ifname = "tap${vmid}i$i";
1429 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1430 die "interface name '$ifname' is too long (max 15 character)\n"
1431 if length($ifname) >= 16;
1433 my $vhostparam = '';
1434 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1436 my $vmname = $conf->{name
} || "vm$vmid";
1439 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1441 if ($net->{bridge
}) {
1442 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1444 $netdev = "type=user,id=$netid,hostname=$vmname";
1447 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1452 sub drive_is_cdrom
{
1455 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1464 foreach my $kvp (split(/,/, $data)) {
1466 if ($kvp =~ m/^memory=(\S+)$/) {
1467 $res->{memory
} = $1;
1468 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1469 $res->{policy
} = $1;
1470 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1471 $res->{cpus
}->{start
} = $1;
1472 $res->{cpus
}->{end
} = $3;
1473 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1474 $res->{hostnodes
}->{start
} = $1;
1475 $res->{hostnodes
}->{end
} = $3;
1487 return undef if !$value;
1490 my @list = split(/,/, $value);
1494 foreach my $kv (@list) {
1496 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1499 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1502 my $pcidevices = lspci
($2);
1503 $res->{pciid
} = $pcidevices->{$2};
1505 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1506 $res->{rombar
} = $1;
1507 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1508 $res->{'x-vga'} = $1;
1509 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1510 $res->{pcie
} = 1 if $1 == 1;
1512 warn "unknown hostpci setting '$kv'\n";
1516 return undef if !$found;
1521 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1527 foreach my $kvp (split(/,/, $data)) {
1529 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) {
1531 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1532 $res->{model
} = $model;
1533 $res->{macaddr
} = $mac;
1534 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1535 $res->{bridge
} = $1;
1536 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1537 $res->{queues
} = $1;
1538 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1540 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1542 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1543 $res->{trunks
} = $1;
1544 } elsif ($kvp =~ m/^firewall=([01])$/) {
1545 $res->{firewall
} = $1;
1546 } elsif ($kvp =~ m/^link_down=([01])$/) {
1547 $res->{link_down
} = $1;
1554 return undef if !$res->{model
};
1562 my $res = "$net->{model}";
1563 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1564 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1565 $res .= ",rate=$net->{rate}" if $net->{rate
};
1566 $res .= ",tag=$net->{tag}" if $net->{tag
};
1567 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1568 $res .= ",firewall=1" if $net->{firewall
};
1569 $res .= ",link_down=1" if $net->{link_down
};
1570 $res .= ",queues=$net->{queues}" if $net->{queues
};
1575 sub add_random_macs
{
1576 my ($settings) = @_;
1578 foreach my $opt (keys %$settings) {
1579 next if $opt !~ m/^net(\d+)$/;
1580 my $net = parse_net
($settings->{$opt});
1582 $settings->{$opt} = print_net
($net);
1586 sub vm_is_volid_owner
{
1587 my ($storecfg, $vmid, $volid) = @_;
1589 if ($volid !~ m
|^/|) {
1591 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1592 if ($owner && ($owner == $vmid)) {
1600 sub split_flagged_list
{
1601 my $text = shift || '';
1602 $text =~ s/[,;]/ /g;
1604 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1607 sub join_flagged_list
{
1608 my ($how, $lst) = @_;
1609 join $how, map { $lst->{$_} . $_ } keys %$lst;
1612 sub vmconfig_delete_pending_option
{
1613 my ($conf, $key, $force) = @_;
1615 delete $conf->{pending
}->{$key};
1616 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1617 $pending_delete_hash->{$key} = $force ?
'!' : '';
1618 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1621 sub vmconfig_undelete_pending_option
{
1622 my ($conf, $key) = @_;
1624 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1625 delete $pending_delete_hash->{$key};
1627 if (%$pending_delete_hash) {
1628 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1630 delete $conf->{pending
}->{delete};
1634 sub vmconfig_register_unused_drive
{
1635 my ($storecfg, $vmid, $conf, $drive) = @_;
1637 if (!drive_is_cdrom
($drive)) {
1638 my $volid = $drive->{file
};
1639 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1640 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1645 sub vmconfig_cleanup_pending
{
1648 # remove pending changes when nothing changed
1650 foreach my $opt (keys %{$conf->{pending
}}) {
1651 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1653 delete $conf->{pending
}->{$opt};
1657 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1658 my $pending_delete_hash = {};
1659 while (my ($opt, $force) = each %$current_delete_hash) {
1660 if (defined($conf->{$opt})) {
1661 $pending_delete_hash->{$opt} = $force;
1667 if (%$pending_delete_hash) {
1668 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1670 delete $conf->{pending
}->{delete};
1676 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1680 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1681 format_description
=> 'UUID',
1687 format_description
=> 'str',
1693 format_description
=> 'str',
1699 format_description
=> 'name',
1705 format_description
=> 'name',
1711 format_description
=> 'str',
1717 format_description
=> 'str',
1725 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1732 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1735 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1737 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1738 sub verify_bootdisk
{
1739 my ($value, $noerr) = @_;
1741 return $value if is_valid_drivename
($value);
1743 return undef if $noerr;
1745 die "invalid boot disk '$value'\n";
1748 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1750 my ($value, $noerr) = @_;
1752 return $value if parse_numa
($value);
1754 return undef if $noerr;
1756 die "unable to parse numa options\n";
1759 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1761 my ($value, $noerr) = @_;
1763 return $value if parse_net
($value);
1765 return undef if $noerr;
1767 die "unable to parse network options\n";
1770 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1771 sub verify_hostpci
{
1772 my ($value, $noerr) = @_;
1774 return $value if parse_hostpci
($value);
1776 return undef if $noerr;
1778 die "unable to parse pci id\n";
1781 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1782 sub verify_watchdog
{
1783 my ($value, $noerr) = @_;
1785 return $value if parse_watchdog
($value);
1787 return undef if $noerr;
1789 die "unable to parse watchdog options\n";
1792 sub parse_watchdog
{
1795 return undef if !$value;
1799 foreach my $p (split(/,/, $value)) {
1800 next if $p =~ m/^\s*$/;
1802 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1804 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1805 $res->{action
} = $2;
1814 sub parse_usb_device
{
1817 return undef if !$value;
1820 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1821 $res->{vendorid
} = $2;
1822 $res->{productid
} = $4;
1823 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1824 $res->{hostbus
} = $1;
1825 $res->{hostport
} = $2;
1826 } elsif ($value =~ m/^spice$/i) {
1835 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1836 sub verify_usb_device
{
1837 my ($value, $noerr) = @_;
1839 return $value if parse_usb_device
($value);
1841 return undef if $noerr;
1843 die "unable to parse usb device\n";
1846 # add JSON properties for create and set function
1847 sub json_config_properties
{
1850 foreach my $opt (keys %$confdesc) {
1851 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1852 $prop->{$opt} = $confdesc->{$opt};
1859 my ($key, $value) = @_;
1861 die "unknown setting '$key'\n" if !$confdesc->{$key};
1863 my $type = $confdesc->{$key}->{type
};
1865 if (!defined($value)) {
1866 die "got undefined value\n";
1869 if ($value =~ m/[\n\r]/) {
1870 die "property contains a line feed\n";
1873 if ($type eq 'boolean') {
1874 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1875 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1876 die "type check ('boolean') failed - got '$value'\n";
1877 } elsif ($type eq 'integer') {
1878 return int($1) if $value =~ m/^(\d+)$/;
1879 die "type check ('integer') failed - got '$value'\n";
1880 } elsif ($type eq 'number') {
1881 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1882 die "type check ('number') failed - got '$value'\n";
1883 } elsif ($type eq 'string') {
1884 if (my $fmt = $confdesc->{$key}->{format
}) {
1885 if ($fmt eq 'pve-qm-drive') {
1886 # special case - we need to pass $key to parse_drive()
1887 my $drive = parse_drive
($key, $value);
1888 return $value if $drive;
1889 die "unable to parse drive options\n";
1891 PVE
::JSONSchema
::check_format
($fmt, $value);
1894 $value =~ s/^\"(.*)\"$/$1/;
1897 die "internal error"
1901 sub check_iommu_support
{
1902 #fixme : need to check IOMMU support
1903 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1913 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1914 utime undef, undef, $conf;
1918 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1920 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1922 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1924 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1926 # only remove disks owned by this VM
1927 foreach_drive
($conf, sub {
1928 my ($ds, $drive) = @_;
1930 return if drive_is_cdrom
($drive);
1932 my $volid = $drive->{file
};
1934 return if !$volid || $volid =~ m
|^/|;
1936 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1937 return if !$path || !$owner || ($owner != $vmid);
1939 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1942 if ($keep_empty_config) {
1943 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1948 # also remove unused disk
1950 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1953 PVE
::Storage
::foreach_volid
($dl, sub {
1954 my ($volid, $sid, $volname, $d) = @_;
1955 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1964 sub parse_vm_config
{
1965 my ($filename, $raw) = @_;
1967 return undef if !defined($raw);
1970 digest
=> Digest
::SHA
::sha1_hex
($raw),
1975 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1976 || die "got strange filename '$filename'";
1984 my @lines = split(/\n/, $raw);
1985 foreach my $line (@lines) {
1986 next if $line =~ m/^\s*$/;
1988 if ($line =~ m/^\[PENDING\]\s*$/i) {
1989 $section = 'pending';
1990 if (defined($descr)) {
1992 $conf->{description
} = $descr;
1995 $conf = $res->{$section} = {};
1998 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2000 if (defined($descr)) {
2002 $conf->{description
} = $descr;
2005 $conf = $res->{snapshots
}->{$section} = {};
2009 if ($line =~ m/^\#(.*)\s*$/) {
2010 $descr = '' if !defined($descr);
2011 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2015 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2016 $descr = '' if !defined($descr);
2017 $descr .= PVE
::Tools
::decode_text
($2);
2018 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2019 $conf->{snapstate
} = $1;
2020 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2023 $conf->{$key} = $value;
2024 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2026 if ($section eq 'pending') {
2027 $conf->{delete} = $value; # we parse this later
2029 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2031 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2034 eval { $value = check_type
($key, $value); };
2036 warn "vm $vmid - unable to parse value of '$key' - $@";
2038 my $fmt = $confdesc->{$key}->{format
};
2039 if ($fmt && $fmt eq 'pve-qm-drive') {
2040 my $v = parse_drive
($key, $value);
2041 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2042 $v->{file
} = $volid;
2043 $value = print_drive
($vmid, $v);
2045 warn "vm $vmid - unable to parse value of '$key'\n";
2050 if ($key eq 'cdrom') {
2051 $conf->{ide2
} = $value;
2053 $conf->{$key} = $value;
2059 if (defined($descr)) {
2061 $conf->{description
} = $descr;
2063 delete $res->{snapstate
}; # just to be sure
2068 sub write_vm_config
{
2069 my ($filename, $conf) = @_;
2071 delete $conf->{snapstate
}; # just to be sure
2073 if ($conf->{cdrom
}) {
2074 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2075 $conf->{ide2
} = $conf->{cdrom
};
2076 delete $conf->{cdrom
};
2079 # we do not use 'smp' any longer
2080 if ($conf->{sockets
}) {
2081 delete $conf->{smp
};
2082 } elsif ($conf->{smp
}) {
2083 $conf->{sockets
} = $conf->{smp
};
2084 delete $conf->{cores
};
2085 delete $conf->{smp
};
2088 my $used_volids = {};
2090 my $cleanup_config = sub {
2091 my ($cref, $pending, $snapname) = @_;
2093 foreach my $key (keys %$cref) {
2094 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2095 $key eq 'snapstate' || $key eq 'pending';
2096 my $value = $cref->{$key};
2097 if ($key eq 'delete') {
2098 die "propertry 'delete' is only allowed in [PENDING]\n"
2100 # fixme: check syntax?
2103 eval { $value = check_type
($key, $value); };
2104 die "unable to parse value of '$key' - $@" if $@;
2106 $cref->{$key} = $value;
2108 if (!$snapname && is_valid_drivename
($key)) {
2109 my $drive = parse_drive
($key, $value);
2110 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2115 &$cleanup_config($conf);
2117 &$cleanup_config($conf->{pending
}, 1);
2119 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2120 die "internal error" if $snapname eq 'pending';
2121 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2124 # remove 'unusedX' settings if we re-add a volume
2125 foreach my $key (keys %$conf) {
2126 my $value = $conf->{$key};
2127 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2128 delete $conf->{$key};
2132 my $generate_raw_config = sub {
2133 my ($conf, $pending) = @_;
2137 # add description as comment to top of file
2138 if (defined(my $descr = $conf->{description
})) {
2140 foreach my $cl (split(/\n/, $descr)) {
2141 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2144 $raw .= "#\n" if $pending;
2148 foreach my $key (sort keys %$conf) {
2149 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2150 $raw .= "$key: $conf->{$key}\n";
2155 my $raw = &$generate_raw_config($conf);
2157 if (scalar(keys %{$conf->{pending
}})){
2158 $raw .= "\n[PENDING]\n";
2159 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2162 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2163 $raw .= "\n[$snapname]\n";
2164 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2174 # we use static defaults from our JSON schema configuration
2175 foreach my $key (keys %$confdesc) {
2176 if (defined(my $default = $confdesc->{$key}->{default})) {
2177 $res->{$key} = $default;
2181 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2182 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2188 my $vmlist = PVE
::Cluster
::get_vmlist
();
2190 return $res if !$vmlist || !$vmlist->{ids
};
2191 my $ids = $vmlist->{ids
};
2193 foreach my $vmid (keys %$ids) {
2194 my $d = $ids->{$vmid};
2195 next if !$d->{node
} || $d->{node
} ne $nodename;
2196 next if !$d->{type
} || $d->{type
} ne 'qemu';
2197 $res->{$vmid}->{exists} = 1;
2202 # test if VM uses local resources (to prevent migration)
2203 sub check_local_resources
{
2204 my ($conf, $noerr) = @_;
2208 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2209 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2211 foreach my $k (keys %$conf) {
2212 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2213 # sockets are safe: they will recreated be on the target side post-migrate
2214 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2215 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2218 die "VM uses local resources\n" if $loc_res && !$noerr;
2223 # check if used storages are available on all nodes (use by migrate)
2224 sub check_storage_availability
{
2225 my ($storecfg, $conf, $node) = @_;
2227 foreach_drive
($conf, sub {
2228 my ($ds, $drive) = @_;
2230 my $volid = $drive->{file
};
2233 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2236 # check if storage is available on both nodes
2237 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2238 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2242 # list nodes where all VM images are available (used by has_feature API)
2244 my ($conf, $storecfg) = @_;
2246 my $nodelist = PVE
::Cluster
::get_nodelist
();
2247 my $nodehash = { map { $_ => 1 } @$nodelist };
2248 my $nodename = PVE
::INotify
::nodename
();
2250 foreach_drive
($conf, sub {
2251 my ($ds, $drive) = @_;
2253 my $volid = $drive->{file
};
2256 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2258 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2259 if ($scfg->{disable
}) {
2261 } elsif (my $avail = $scfg->{nodes
}) {
2262 foreach my $node (keys %$nodehash) {
2263 delete $nodehash->{$node} if !$avail->{$node};
2265 } elsif (!$scfg->{shared
}) {
2266 foreach my $node (keys %$nodehash) {
2267 delete $nodehash->{$node} if $node ne $nodename
2277 my ($pidfile, $pid) = @_;
2279 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2283 return undef if !$line;
2284 my @param = split(/\0/, $line);
2286 my $cmd = $param[0];
2287 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2289 for (my $i = 0; $i < scalar (@param); $i++) {
2292 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2293 my $p = $param[$i+1];
2294 return 1 if $p && ($p eq $pidfile);
2303 my ($vmid, $nocheck, $node) = @_;
2305 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2307 die "unable to find configuration file for VM $vmid - no such machine\n"
2308 if !$nocheck && ! -f
$filename;
2310 my $pidfile = pidfile_name
($vmid);
2312 if (my $fd = IO
::File-
>new("<$pidfile")) {
2317 my $mtime = $st->mtime;
2318 if ($mtime > time()) {
2319 warn "file '$filename' modified in future\n";
2322 if ($line =~ m/^(\d+)$/) {
2324 if (check_cmdline
($pidfile, $pid)) {
2325 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2337 my $vzlist = config_list
();
2339 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2341 while (defined(my $de = $fd->read)) {
2342 next if $de !~ m/^(\d+)\.pid$/;
2344 next if !defined($vzlist->{$vmid});
2345 if (my $pid = check_running
($vmid)) {
2346 $vzlist->{$vmid}->{pid
} = $pid;
2354 my ($storecfg, $conf) = @_;
2356 my $bootdisk = $conf->{bootdisk
};
2357 return undef if !$bootdisk;
2358 return undef if !is_valid_drivename
($bootdisk);
2360 return undef if !$conf->{$bootdisk};
2362 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2363 return undef if !defined($drive);
2365 return undef if drive_is_cdrom
($drive);
2367 my $volid = $drive->{file
};
2368 return undef if !$volid;
2370 return $drive->{size
};
2373 my $last_proc_pid_stat;
2375 # get VM status information
2376 # This must be fast and should not block ($full == false)
2377 # We only query KVM using QMP if $full == true (this can be slow)
2379 my ($opt_vmid, $full) = @_;
2383 my $storecfg = PVE
::Storage
::config
();
2385 my $list = vzlist
();
2386 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2388 my $cpucount = $cpuinfo->{cpus
} || 1;
2390 foreach my $vmid (keys %$list) {
2391 next if $opt_vmid && ($vmid ne $opt_vmid);
2393 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2394 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2397 $d->{pid
} = $list->{$vmid}->{pid
};
2399 # fixme: better status?
2400 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2402 my $size = disksize
($storecfg, $conf);
2403 if (defined($size)) {
2404 $d->{disk
} = 0; # no info available
2405 $d->{maxdisk
} = $size;
2411 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2412 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2413 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2415 $d->{name
} = $conf->{name
} || "VM $vmid";
2416 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2418 if ($conf->{balloon
}) {
2419 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2420 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2431 $d->{diskwrite
} = 0;
2433 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2438 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2439 foreach my $dev (keys %$netdev) {
2440 next if $dev !~ m/^tap([1-9]\d*)i/;
2442 my $d = $res->{$vmid};
2445 $d->{netout
} += $netdev->{$dev}->{receive
};
2446 $d->{netin
} += $netdev->{$dev}->{transmit
};
2449 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2450 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2455 my $ctime = gettimeofday
;
2457 foreach my $vmid (keys %$list) {
2459 my $d = $res->{$vmid};
2460 my $pid = $d->{pid
};
2463 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2464 next if !$pstat; # not running
2466 my $used = $pstat->{utime} + $pstat->{stime
};
2468 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2470 if ($pstat->{vsize
}) {
2471 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2474 my $old = $last_proc_pid_stat->{$pid};
2476 $last_proc_pid_stat->{$pid} = {
2484 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2486 if ($dtime > 1000) {
2487 my $dutime = $used - $old->{used
};
2489 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2490 $last_proc_pid_stat->{$pid} = {
2496 $d->{cpu
} = $old->{cpu
};
2500 return $res if !$full;
2502 my $qmpclient = PVE
::QMPClient-
>new();
2504 my $ballooncb = sub {
2505 my ($vmid, $resp) = @_;
2507 my $info = $resp->{'return'};
2508 return if !$info->{max_mem
};
2510 my $d = $res->{$vmid};
2512 # use memory assigned to VM
2513 $d->{maxmem
} = $info->{max_mem
};
2514 $d->{balloon
} = $info->{actual
};
2516 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2517 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2518 $d->{freemem
} = $info->{free_mem
};
2521 $d->{ballooninfo
} = $info;
2524 my $blockstatscb = sub {
2525 my ($vmid, $resp) = @_;
2526 my $data = $resp->{'return'} || [];
2527 my $totalrdbytes = 0;
2528 my $totalwrbytes = 0;
2530 for my $blockstat (@$data) {
2531 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2532 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2534 $blockstat->{device
} =~ s/drive-//;
2535 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2537 $res->{$vmid}->{diskread
} = $totalrdbytes;
2538 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2541 my $statuscb = sub {
2542 my ($vmid, $resp) = @_;
2544 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2545 # this fails if ballon driver is not loaded, so this must be
2546 # the last commnand (following command are aborted if this fails).
2547 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2549 my $status = 'unknown';
2550 if (!defined($status = $resp->{'return'}->{status
})) {
2551 warn "unable to get VM status\n";
2555 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2558 foreach my $vmid (keys %$list) {
2559 next if $opt_vmid && ($vmid ne $opt_vmid);
2560 next if !$res->{$vmid}->{pid
}; # not running
2561 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2564 $qmpclient->queue_execute(undef, 1);
2566 foreach my $vmid (keys %$list) {
2567 next if $opt_vmid && ($vmid ne $opt_vmid);
2568 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2575 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2578 my $current_size = 1024;
2579 my $dimm_size = 512;
2580 return if $current_size == $memory;
2582 for (my $j = 0; $j < 8; $j++) {
2583 for (my $i = 0; $i < 32; $i++) {
2584 my $name = "dimm${dimm_id}";
2586 my $numanode = $i % $sockets;
2587 $current_size += $dimm_size;
2588 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2589 return $current_size if $current_size >= $memory;
2595 sub foreach_reverse_dimm
{
2596 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2599 my $current_size = 4177920;
2600 my $dimm_size = 65536;
2601 return if $current_size == $memory;
2603 for (my $j = 0; $j < 8; $j++) {
2604 for (my $i = 0; $i < 32; $i++) {
2605 my $name = "dimm${dimm_id}";
2607 my $numanode = $i % $sockets;
2608 $current_size -= $dimm_size;
2609 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2610 return $current_size if $current_size <= $memory;
2617 my ($conf, $func) = @_;
2619 foreach my $ds (valid_drive_names
()) {
2620 next if !defined($conf->{$ds});
2622 my $drive = parse_drive
($ds, $conf->{$ds});
2625 &$func($ds, $drive);
2630 my ($conf, $func) = @_;
2634 my $test_volid = sub {
2635 my ($volid, $is_cdrom) = @_;
2639 $volhash->{$volid} = $is_cdrom || 0;
2642 foreach_drive
($conf, sub {
2643 my ($ds, $drive) = @_;
2644 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2647 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2648 my $snap = $conf->{snapshots
}->{$snapname};
2649 &$test_volid($snap->{vmstate
}, 0);
2650 foreach_drive
($snap, sub {
2651 my ($ds, $drive) = @_;
2652 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2656 foreach my $volid (keys %$volhash) {
2657 &$func($volid, $volhash->{$volid});
2661 sub vga_conf_has_spice
{
2664 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2669 sub config_to_command
{
2670 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2673 my $globalFlags = [];
2674 my $machineFlags = [];
2680 my $kvmver = kvm_user_version
();
2681 my $vernum = 0; # unknown
2682 my $ostype = $conf->{ostype
};
2683 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2684 $vernum = $1*1000000+$2*1000;
2685 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2686 $vernum = $1*1000000+$2*1000+$3;
2689 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2691 my $have_ovz = -f
'/proc/vz/vestat';
2693 my $q35 = machine_type_is_q35
($conf);
2694 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2695 my $machine_type = $forcemachine || $conf->{machine
};
2696 my $use_old_bios_files = undef;
2697 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2699 my $cpuunits = defined($conf->{cpuunits
}) ?
2700 $conf->{cpuunits
} : $defaults->{cpuunits
};
2702 push @$cmd, '/usr/bin/systemd-run';
2703 push @$cmd, '--scope';
2704 push @$cmd, '--slice', "qemu";
2705 push @$cmd, '--unit', $vmid;
2706 # set KillMode=none, so that systemd don't kill those scopes
2707 # at shutdown (pve-manager service should stop the VMs instead)
2708 push @$cmd, '-p', "KillMode=none";
2709 push @$cmd, '-p', "CPUShares=$cpuunits";
2710 if ($conf->{cpulimit
}) {
2711 my $cpulimit = int($conf->{cpulimit
} * 100);
2712 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2715 push @$cmd, '/usr/bin/kvm';
2717 push @$cmd, '-id', $vmid;
2721 my $qmpsocket = qmp_socket
($vmid);
2722 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2723 push @$cmd, '-mon', "chardev=qmp,mode=control";
2726 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2728 push @$cmd, '-daemonize';
2730 if ($conf->{smbios1
}) {
2731 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2734 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2735 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2736 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2737 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2738 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2739 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2740 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2744 # the q35 chipset support native usb2, so we enable usb controller
2745 # by default for this machine type
2746 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2748 $pciaddr = print_pci_addr
("piix3", $bridges);
2749 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2752 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2753 next if !$conf->{"usb$i"};
2754 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2755 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2758 # include usb device config
2759 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2762 # add usb3 controller if needed
2765 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2766 next if !$conf->{"usb$i"};
2767 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2768 next if !$d || !$d->{usb3
};
2772 $pciaddr = print_pci_addr
("xhci", $bridges);
2773 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2775 my $vga = $conf->{vga
};
2777 my $qxlnum = vga_conf_has_spice
($vga);
2778 $vga = 'qxl' if $qxlnum;
2781 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2782 $conf->{ostype
} eq 'win7' ||
2783 $conf->{ostype
} eq 'w2k8')) {
2790 # enable absolute mouse coordinates (needed by vnc)
2792 if (defined($conf->{tablet
})) {
2793 $tablet = $conf->{tablet
};
2795 $tablet = $defaults->{tablet
};
2796 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2797 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2800 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2804 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2805 my $d = parse_hostpci
($conf->{"hostpci$i"});
2808 my $pcie = $d->{pcie
};
2810 die "q35 machine model is not enabled" if !$q35;
2811 $pciaddr = print_pcie_addr
("hostpci$i");
2813 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2816 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2817 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2818 if ($xvga && $xvga ne '') {
2821 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2822 push @$cpuFlags , 'hv_vendor_id=proxmox';
2824 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2828 my $pcidevices = $d->{pciid
};
2829 my $multifunction = 1 if @$pcidevices > 1;
2832 foreach my $pcidevice (@$pcidevices) {
2834 my $id = "hostpci$i";
2835 $id .= ".$j" if $multifunction;
2836 my $addr = $pciaddr;
2837 $addr .= ".$j" if $multifunction;
2838 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2841 $devicestr .= "$rombar$xvga";
2842 $devicestr .= ",multifunction=on" if $multifunction;
2845 push @$devices, '-device', $devicestr;
2851 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2852 next if !$conf->{"usb$i"};
2853 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2856 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2858 if (defined($d->{usb3
}) && $d->{usb3
}) {
2859 $usbbus = ',bus=xhci.0';
2862 if (defined($d->{host
})) {
2863 $d = parse_usb_device
($d->{host
});
2864 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2865 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2866 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2867 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2868 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2869 # usb redir support for spice, currently no usb3
2870 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2871 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2877 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2878 if (my $path = $conf->{"serial$i"}) {
2879 if ($path eq 'socket') {
2880 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2881 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2882 push @$devices, '-device', "isa-serial,chardev=serial$i";
2884 die "no such serial device\n" if ! -c
$path;
2885 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2886 push @$devices, '-device', "isa-serial,chardev=serial$i";
2892 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2893 if (my $path = $conf->{"parallel$i"}) {
2894 die "no such parallel device\n" if ! -c
$path;
2895 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2896 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2897 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2901 my $vmname = $conf->{name
} || "vm$vmid";
2903 push @$cmd, '-name', $vmname;
2906 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2907 $sockets = $conf->{sockets
} if $conf->{sockets
};
2909 my $cores = $conf->{cores
} || 1;
2911 my $maxcpus = $sockets * $cores;
2913 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2915 my $allowed_vcpus = $cpuinfo->{cpus
};
2917 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2918 if ($allowed_vcpus < $maxcpus);
2920 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2922 push @$cmd, '-nodefaults';
2924 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2926 my $bootindex_hash = {};
2928 foreach my $o (split(//, $bootorder)) {
2929 $bootindex_hash->{$o} = $i*100;
2933 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2935 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2937 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2939 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2941 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2942 my $socket = vnc_socket
($vmid);
2943 push @$cmd, '-vnc', "unix:$socket,x509,password";
2945 push @$cmd, '-nographic';
2949 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2951 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2952 my $useLocaltime = $conf->{localtime};
2955 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2957 if ($ostype =~ m/^w/) { # windows
2958 $useLocaltime = 1 if !defined($conf->{localtime});
2960 # use time drift fix when acpi is enabled
2961 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2962 $tdf = 1 if !defined($conf->{tdf
});
2966 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2967 $ostype eq 'wvista') {
2968 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2969 push @$cmd, '-no-hpet';
2970 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2971 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2972 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2973 push @$cpuFlags , 'hv_time' if !$nokvm;
2976 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2980 if ($ostype eq 'win7' || $ostype eq 'win8') {
2981 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2985 push @$rtcFlags, 'driftfix=slew' if $tdf;
2988 push @$machineFlags, 'accel=tcg';
2990 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2993 if ($machine_type) {
2994 push @$machineFlags, "type=${machine_type}";
2997 if ($conf->{startdate
}) {
2998 push @$rtcFlags, "base=$conf->{startdate}";
2999 } elsif ($useLocaltime) {
3000 push @$rtcFlags, 'base=localtime';
3003 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3004 if (my $cputype = $conf->{cpu
}) {
3005 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3006 or die "Cannot parse cpu description: $cputype\n";
3007 $cpu = $cpuconf->{cputype
};
3008 $kvm_off = 1 if $cpuconf->{hidden
};
3011 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3013 push @$cpuFlags , '-x2apic'
3014 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3016 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3018 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3020 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3022 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3023 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3026 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3028 push @$cpuFlags, 'kvm=off' if $kvm_off;
3030 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3032 push @$cmd, '-cpu', $cpu;
3034 my $memory = $conf->{memory
} || $defaults->{memory
};
3035 my $static_memory = 0;
3036 my $dimm_memory = 0;
3038 if ($hotplug_features->{memory
}) {
3039 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3040 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3041 $static_memory = $STATICMEM;
3042 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3043 $dimm_memory = $memory - $static_memory;
3044 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3048 $static_memory = $memory;
3049 push @$cmd, '-m', $static_memory;
3052 if ($conf->{numa
}) {
3054 my $numa_totalmemory = undef;
3055 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3056 next if !$conf->{"numa$i"};
3057 my $numa = parse_numa
($conf->{"numa$i"});
3060 die "missing numa node$i memory value\n" if !$numa->{memory
};
3061 my $numa_memory = $numa->{memory
};
3062 $numa_totalmemory += $numa_memory;
3063 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3066 my $cpus_start = $numa->{cpus
}->{start
};
3067 die "missing numa node$i cpus\n" if !defined($cpus_start);
3068 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3069 my $cpus = $cpus_start;
3070 if (defined($cpus_end)) {
3071 $cpus .= "-$cpus_end";
3072 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3076 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3077 if (defined($hostnodes_start)) {
3078 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3079 my $hostnodes = $hostnodes_start;
3080 if (defined($hostnodes_end)) {
3081 $hostnodes .= "-$hostnodes_end";
3082 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3085 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3086 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3087 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3091 my $policy = $numa->{policy
};
3092 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3093 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3096 push @$cmd, '-object', $numa_object;
3097 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3100 die "total memory for NUMA nodes must be equal to vm static memory\n"
3101 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3103 #if no custom tology, we split memory and cores across numa nodes
3104 if(!$numa_totalmemory) {
3106 my $numa_memory = ($static_memory / $sockets) . "M";
3108 for (my $i = 0; $i < $sockets; $i++) {
3110 my $cpustart = ($cores * $i);
3111 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3112 my $cpus = $cpustart;
3113 $cpus .= "-$cpuend" if $cpuend;
3115 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3116 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3121 if ($hotplug_features->{memory
}) {
3122 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3123 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3124 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3125 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3127 #if dimm_memory is not aligned to dimm map
3128 if($current_size > $memory) {
3129 $conf->{memory
} = $current_size;
3130 PVE
::QemuConfig-
>write_config($vmid, $conf);
3135 push @$cmd, '-S' if $conf->{freeze
};
3137 # set keyboard layout
3138 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3139 push @$cmd, '-k', $kb if $kb;
3142 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3143 #push @$cmd, '-soundhw', 'es1370';
3144 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3146 if($conf->{agent
}) {
3147 my $qgasocket = qmp_socket
($vmid, 1);
3148 my $pciaddr = print_pci_addr
("qga0", $bridges);
3149 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3150 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3151 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3158 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3159 for(my $i = 1; $i < $qxlnum; $i++){
3160 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3161 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3164 # assume other OS works like Linux
3165 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3166 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3170 my $pciaddr = print_pci_addr
("spice", $bridges);
3172 my $nodename = PVE
::INotify
::nodename
();
3173 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3174 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3176 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3178 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3179 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3180 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3183 # enable balloon by default, unless explicitly disabled
3184 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3185 $pciaddr = print_pci_addr
("balloon0", $bridges);
3186 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3189 if ($conf->{watchdog
}) {
3190 my $wdopts = parse_watchdog
($conf->{watchdog
});
3191 $pciaddr = print_pci_addr
("watchdog", $bridges);
3192 my $watchdog = $wdopts->{model
} || 'i6300esb';
3193 push @$devices, '-device', "$watchdog$pciaddr";
3194 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3198 my $scsicontroller = {};
3199 my $ahcicontroller = {};
3200 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3202 # Add iscsi initiator name if available
3203 if (my $initiator = get_initiator_name
()) {
3204 push @$devices, '-iscsi', "initiator-name=$initiator";
3207 foreach_drive
($conf, sub {
3208 my ($ds, $drive) = @_;
3210 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3211 push @$vollist, $drive->{file
};
3214 $use_virtio = 1 if $ds =~ m/^virtio/;
3216 if (drive_is_cdrom
($drive)) {
3217 if ($bootindex_hash->{d
}) {
3218 $drive->{bootindex
} = $bootindex_hash->{d
};
3219 $bootindex_hash->{d
} += 1;
3222 if ($bootindex_hash->{c
}) {
3223 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3224 $bootindex_hash->{c
} += 1;
3228 if($drive->{interface
} eq 'virtio'){
3229 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3232 if ($drive->{interface
} eq 'scsi') {
3234 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3236 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3237 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3240 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3241 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3242 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3246 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3247 $queues = ",num_queues=$drive->{queues}";
3250 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3251 $scsicontroller->{$controller}=1;
3254 if ($drive->{interface
} eq 'sata') {
3255 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3256 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3257 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3258 $ahcicontroller->{$controller}=1;
3261 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3262 push @$devices, '-drive',$drive_cmd;
3263 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3266 for (my $i = 0; $i < $MAX_NETS; $i++) {
3267 next if !$conf->{"net$i"};
3268 my $d = parse_net
($conf->{"net$i"});
3271 $use_virtio = 1 if $d->{model
} eq 'virtio';
3273 if ($bootindex_hash->{n
}) {
3274 $d->{bootindex
} = $bootindex_hash->{n
};
3275 $bootindex_hash->{n
} += 1;
3278 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3279 push @$devices, '-netdev', $netdevfull;
3281 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3282 push @$devices, '-device', $netdevicefull;
3287 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3292 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3294 while (my ($k, $v) = each %$bridges) {
3295 $pciaddr = print_pci_addr
("pci.$k");
3296 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3301 if ($conf->{args
}) {
3302 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3306 push @$cmd, @$devices;
3307 push @$cmd, '-rtc', join(',', @$rtcFlags)
3308 if scalar(@$rtcFlags);
3309 push @$cmd, '-machine', join(',', @$machineFlags)
3310 if scalar(@$machineFlags);
3311 push @$cmd, '-global', join(',', @$globalFlags)
3312 if scalar(@$globalFlags);
3314 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3319 return "${var_run_tmpdir}/$vmid.vnc";
3325 my $res = vm_mon_cmd
($vmid, 'query-spice');
3327 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3331 my ($vmid, $qga) = @_;
3332 my $sockettype = $qga ?
'qga' : 'qmp';
3333 return "${var_run_tmpdir}/$vmid.$sockettype";
3338 return "${var_run_tmpdir}/$vmid.pid";
3341 sub vm_devices_list
{
3344 my $res = vm_mon_cmd
($vmid, 'query-pci');
3346 foreach my $pcibus (@$res) {
3347 foreach my $device (@{$pcibus->{devices
}}) {
3348 next if !$device->{'qdev_id'};
3349 if ($device->{'pci_bridge'}) {
3350 $devices->{$device->{'qdev_id'}} = 1;
3351 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3352 next if !$bridge_device->{'qdev_id'};
3353 $devices->{$bridge_device->{'qdev_id'}} = 1;
3354 $devices->{$device->{'qdev_id'}}++;
3357 $devices->{$device->{'qdev_id'}} = 1;
3362 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3363 foreach my $block (@$resblock) {
3364 if($block->{device
} =~ m/^drive-(\S+)/){
3369 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3370 foreach my $mice (@$resmice) {
3371 if ($mice->{name
} eq 'QEMU HID Tablet') {
3372 $devices->{tablet
} = 1;
3381 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3383 my $q35 = machine_type_is_q35
($conf);
3385 my $devices_list = vm_devices_list
($vmid);
3386 return 1 if defined($devices_list->{$deviceid});
3388 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3390 if ($deviceid eq 'tablet') {
3392 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3394 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3396 qemu_iothread_add
($vmid, $deviceid, $device);
3398 qemu_driveadd
($storecfg, $vmid, $device);
3399 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3401 qemu_deviceadd
($vmid, $devicefull);
3402 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3404 eval { qemu_drivedel
($vmid, $deviceid); };
3409 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3412 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3413 my $pciaddr = print_pci_addr
($deviceid);
3414 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3416 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3418 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3419 qemu_iothread_add
($vmid, $deviceid, $device);
3420 $devicefull .= ",iothread=iothread-$deviceid";
3423 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3424 $devicefull .= ",num_queues=$device->{queues}";
3427 qemu_deviceadd
($vmid, $devicefull);
3428 qemu_deviceaddverify
($vmid, $deviceid);
3430 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3432 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3433 qemu_driveadd
($storecfg, $vmid, $device);
3435 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3436 eval { qemu_deviceadd
($vmid, $devicefull); };
3438 eval { qemu_drivedel
($vmid, $deviceid); };
3443 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3445 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3447 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3448 my $use_old_bios_files = undef;
3449 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3451 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3452 qemu_deviceadd
($vmid, $netdevicefull);
3453 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3455 eval { qemu_netdevdel
($vmid, $deviceid); };
3460 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3463 my $pciaddr = print_pci_addr
($deviceid);
3464 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3466 qemu_deviceadd
($vmid, $devicefull);
3467 qemu_deviceaddverify
($vmid, $deviceid);
3470 die "can't hotplug device '$deviceid'\n";
3476 # fixme: this should raise exceptions on error!
3477 sub vm_deviceunplug
{
3478 my ($vmid, $conf, $deviceid) = @_;
3480 my $devices_list = vm_devices_list
($vmid);
3481 return 1 if !defined($devices_list->{$deviceid});
3483 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3485 if ($deviceid eq 'tablet') {
3487 qemu_devicedel
($vmid, $deviceid);
3489 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3491 qemu_devicedel
($vmid, $deviceid);
3492 qemu_devicedelverify
($vmid, $deviceid);
3493 qemu_drivedel
($vmid, $deviceid);
3494 qemu_iothread_del
($conf, $vmid, $deviceid);
3496 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3498 qemu_devicedel
($vmid, $deviceid);
3499 qemu_devicedelverify
($vmid, $deviceid);
3500 qemu_iothread_del
($conf, $vmid, $deviceid);
3502 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3504 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3505 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3506 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3508 qemu_devicedel
($vmid, $deviceid);
3509 qemu_drivedel
($vmid, $deviceid);
3510 qemu_deletescsihw
($conf, $vmid, $deviceid);
3512 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3514 qemu_devicedel
($vmid, $deviceid);
3515 qemu_devicedelverify
($vmid, $deviceid);
3516 qemu_netdevdel
($vmid, $deviceid);
3519 die "can't unplug device '$deviceid'\n";
3525 sub qemu_deviceadd
{
3526 my ($vmid, $devicefull) = @_;
3528 $devicefull = "driver=".$devicefull;
3529 my %options = split(/[=,]/, $devicefull);
3531 vm_mon_cmd
($vmid, "device_add" , %options);
3534 sub qemu_devicedel
{
3535 my ($vmid, $deviceid) = @_;
3537 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3540 sub qemu_iothread_add
{
3541 my($vmid, $deviceid, $device) = @_;
3543 if ($device->{iothread
}) {
3544 my $iothreads = vm_iothreads_list
($vmid);
3545 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3549 sub qemu_iothread_del
{
3550 my($conf, $vmid, $deviceid) = @_;
3552 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3553 if ($device->{iothread
}) {
3554 my $iothreads = vm_iothreads_list
($vmid);
3555 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3559 sub qemu_objectadd
{
3560 my($vmid, $objectid, $qomtype) = @_;
3562 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3567 sub qemu_objectdel
{
3568 my($vmid, $objectid) = @_;
3570 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3576 my ($storecfg, $vmid, $device) = @_;
3578 my $drive = print_drive_full
($storecfg, $vmid, $device);
3579 $drive =~ s/\\/\\\\/g;
3580 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3582 # If the command succeeds qemu prints: "OK
"
3583 return 1 if $ret =~ m/OK/s;
3585 die "adding drive failed
: $ret\n";
3589 my($vmid, $deviceid) = @_;
3591 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3594 return 1 if $ret eq "";
3596 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3597 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3599 die "deleting drive
$deviceid failed
: $ret\n";
3602 sub qemu_deviceaddverify {
3603 my ($vmid, $deviceid) = @_;
3605 for (my $i = 0; $i <= 5; $i++) {
3606 my $devices_list = vm_devices_list($vmid);
3607 return 1 if defined($devices_list->{$deviceid});
3611 die "error on hotplug device
'$deviceid'\n";
3615 sub qemu_devicedelverify {
3616 my ($vmid, $deviceid) = @_;
3618 # need to verify that the device is correctly removed as device_del
3619 # is async and empty return is not reliable
3621 for (my $i = 0; $i <= 5; $i++) {
3622 my $devices_list = vm_devices_list($vmid);
3623 return 1 if !defined($devices_list->{$deviceid});
3627 die "error on hot-unplugging device
'$deviceid'\n";
3630 sub qemu_findorcreatescsihw {
3631 my ($storecfg, $conf, $vmid, $device) = @_;
3633 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3635 my $scsihwid="$controller_prefix$controller";
3636 my $devices_list = vm_devices_list($vmid);
3638 if(!defined($devices_list->{$scsihwid})) {
3639 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3645 sub qemu_deletescsihw {
3646 my ($conf, $vmid, $opt) = @_;
3648 my $device = parse_drive($opt, $conf->{$opt});
3650 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3651 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3655 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3657 my $devices_list = vm_devices_list($vmid);
3658 foreach my $opt (keys %{$devices_list}) {
3659 if (PVE::QemuServer::is_valid_drivename($opt)) {
3660 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3661 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3667 my $scsihwid="scsihw
$controller";
3669 vm_deviceunplug($vmid, $conf, $scsihwid);
3674 sub qemu_add_pci_bridge {
3675 my ($storecfg, $conf, $vmid, $device) = @_;
3681 print_pci_addr($device, $bridges);
3683 while (my ($k, $v) = each %$bridges) {
3686 return 1 if !defined($bridgeid) || $bridgeid < 1;
3688 my $bridge = "pci
.$bridgeid";
3689 my $devices_list = vm_devices_list($vmid);
3691 if (!defined($devices_list->{$bridge})) {
3692 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3698 sub qemu_set_link_status {
3699 my ($vmid, $device, $up) = @_;
3701 vm_mon_cmd($vmid, "set_link
", name => $device,
3702 up => $up ? JSON::true : JSON::false);
3705 sub qemu_netdevadd {
3706 my ($vmid, $conf, $device, $deviceid) = @_;
3708 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3709 my %options = split(/[=,]/, $netdev);
3711 vm_mon_cmd($vmid, "netdev_add
", %options);
3715 sub qemu_netdevdel {
3716 my ($vmid, $deviceid) = @_;
3718 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3721 sub qemu_cpu_hotplug {
3722 my ($vmid, $conf, $vcpus) = @_;
3725 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3726 $sockets = $conf->{sockets} if $conf->{sockets};
3727 my $cores = $conf->{cores} || 1;
3728 my $maxcpus = $sockets * $cores;
3730 $vcpus = $maxcpus if !$vcpus;
3732 die "you can
't add more vcpus than maxcpus\n"
3733 if $vcpus > $maxcpus;
3735 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3736 die "online cpu unplug is not yet possible\n"
3737 if $vcpus < $currentvcpus;
3739 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3740 die "vcpus in running vm is different than configuration\n"
3741 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3743 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3744 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3748 sub qemu_memory_hotplug {
3749 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3751 return $value if !check_running($vmid);
3753 my $memory = $conf->{memory} || $defaults->{memory};
3754 $value = $defaults->{memory} if !$value;
3755 return $value if $value == $memory;
3757 my $static_memory = $STATICMEM;
3758 my $dimm_memory = $memory - $static_memory;
3760 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3761 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3765 $sockets = $conf->{sockets} if $conf->{sockets};
3767 if($value > $memory) {
3769 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3770 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3772 return if $current_size <= $conf->{memory};
3774 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3776 eval { qemu_objectdel($vmid, "mem-
$name"); };
3780 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3782 eval { qemu_objectdel($vmid, "mem-
$name"); };
3785 #update conf after each succesful module hotplug
3786 $conf->{memory} = $current_size;
3787 PVE::QemuConfig->write_config($vmid, $conf);
3792 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3793 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3795 return if $current_size >= $conf->{memory};
3796 print "try to unplug memory dimm
$name\n";
3800 eval { qemu_devicedel($vmid, $name) };
3802 my $dimm_list = qemu_dimm_list($vmid);
3803 last if !$dimm_list->{$name};
3804 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3808 #update conf after each succesful module unplug
3809 $conf->{memory} = $current_size;
3811 eval { qemu_objectdel($vmid, "mem-
$name"); };
3812 PVE::QemuConfig->write_config($vmid, $conf);
3817 sub qemu_dimm_list {
3820 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3823 foreach my $dimm (@$dimmarray) {
3825 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3826 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3827 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3828 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3829 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3834 sub qemu_block_set_io_throttle {
3835 my ($vmid, $deviceid,
3836 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3837 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3839 return if !check_running($vmid) ;
3841 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3843 bps_rd => int($bps_rd),
3844 bps_wr => int($bps_wr),
3846 iops_rd => int($iops_rd),
3847 iops_wr => int($iops_wr),
3848 bps_max => int($bps_max),
3849 bps_rd_max => int($bps_rd_max),
3850 bps_wr_max => int($bps_wr_max),
3851 iops_max => int($iops_max),
3852 iops_rd_max => int($iops_rd_max),
3853 iops_wr_max => int($iops_wr_max)
3858 # old code, only used to shutdown old VM after update
3860 my ($fh, $timeout) = @_;
3862 my $sel = new IO::Select;
3869 while (scalar (@ready = $sel->can_read($timeout))) {
3871 if ($count = $fh->sysread($buf, 8192)) {
3872 if ($buf =~ /^(.*)\(qemu\) $/s) {
3879 if (!defined($count)) {
3886 die "monitor
read timeout
\n" if !scalar(@ready);
3891 # old code, only used to shutdown old VM after update
3892 sub vm_monitor_command {
3893 my ($vmid, $cmdstr, $nocheck) = @_;
3898 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3900 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3902 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3903 die "unable to
connect to VM
$vmid socket - $!\n";
3907 # hack: migrate sometime blocks the monitor (when migrate_downtime
3909 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3910 $timeout = 60*60; # 1 hour
3914 my $data = __read_avail($sock, $timeout);
3916 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3917 die "got unexpected qemu monitor banner
\n";
3920 my $sel = new IO::Select;
3923 if (!scalar(my @ready = $sel->can_write($timeout))) {
3924 die "monitor
write error
- timeout
";
3927 my $fullcmd = "$cmdstr\r";
3929 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3932 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3933 die "monitor
write error
- $!";
3936 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3940 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3941 $timeout = 60*60; # 1 hour
3942 } elsif ($cmdstr =~ m/^(eject|change)/) {
3943 $timeout = 60; # note: cdrom mount command is slow
3945 if ($res = __read_avail($sock, $timeout)) {
3947 my @lines = split("\r?
\n", $res);
3949 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3951 $res = join("\n", @lines);
3959 syslog("err
", "VM
$vmid monitor command failed
- $err");
3966 sub qemu_block_resize {
3967 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3969 my $running = check_running($vmid);
3971 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3973 return if !$running;
3975 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3979 sub qemu_volume_snapshot {
3980 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3982 my $running = check_running($vmid);
3984 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3985 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3987 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3991 sub qemu_volume_snapshot_delete {
3992 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3994 my $running = check_running($vmid);
3996 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3998 return if !$running;
4000 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4003 sub set_migration_caps {
4009 "auto-converge
" => 1,
4011 "x-rdma-pin-all
" => 0,
4016 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4018 for my $supported_capability (@$supported_capabilities) {
4020 capability => $supported_capability->{capability},
4021 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4025 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4028 my $fast_plug_option = {
4037 # hotplug changes in [PENDING]
4038 # $selection hash can be used to only apply specified options, for
4039 # example: { cores => 1 } (only apply changed 'cores')
4040 # $errors ref is used to return error messages
4041 sub vmconfig_hotplug_pending {
4042 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4044 my $defaults = load_defaults();
4046 # commit values which do not have any impact on running VM first
4047 # Note: those option cannot raise errors, we we do not care about
4048 # $selection and always apply them.
4050 my $add_error = sub {
4051 my ($opt, $msg) = @_;
4052 $errors->{$opt} = "hotplug problem
- $msg";
4056 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4057 if ($fast_plug_option->{$opt}) {
4058 $conf->{$opt} = $conf->{pending}->{$opt};
4059 delete $conf->{pending}->{$opt};
4065 PVE::QemuConfig->write_config($vmid, $conf);
4066 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4069 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4071 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4072 while (my ($opt, $force) = each %$pending_delete_hash) {
4073 next if $selection && !$selection->{$opt};
4075 if ($opt eq 'hotplug') {
4076 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4077 } elsif ($opt eq 'tablet') {
4078 die "skip
\n" if !$hotplug_features->{usb};
4079 if ($defaults->{tablet}) {
4080 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4082 vm_deviceunplug($vmid, $conf, $opt);
4084 } elsif ($opt eq 'vcpus') {
4085 die "skip
\n" if !$hotplug_features->{cpu};
4086 qemu_cpu_hotplug($vmid, $conf, undef);
4087 } elsif ($opt eq 'balloon') {
4088 # enable balloon device is not hotpluggable
4089 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4090 } elsif ($fast_plug_option->{$opt}) {
4092 } elsif ($opt =~ m/^net(\d+)$/) {
4093 die "skip
\n" if !$hotplug_features->{network};
4094 vm_deviceunplug($vmid, $conf, $opt);
4095 } elsif (is_valid_drivename($opt)) {
4096 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4097 vm_deviceunplug($vmid, $conf, $opt);
4098 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4099 } elsif ($opt =~ m/^memory$/) {
4100 die "skip
\n" if !$hotplug_features->{memory};
4101 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4102 } elsif ($opt eq 'cpuunits') {
4103 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4104 } elsif ($opt eq 'cpulimit') {
4105 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4111 &$add_error($opt, $err) if $err ne "skip
\n";
4113 # save new config if hotplug was successful
4114 delete $conf->{$opt};
4115 vmconfig_undelete_pending_option($conf, $opt);
4116 PVE::QemuConfig->write_config($vmid, $conf);
4117 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4121 foreach my $opt (keys %{$conf->{pending}}) {
4122 next if $selection && !$selection->{$opt};
4123 my $value = $conf->{pending}->{$opt};
4125 if ($opt eq 'hotplug') {
4126 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4127 } elsif ($opt eq 'tablet') {
4128 die "skip
\n" if !$hotplug_features->{usb};
4130 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4131 } elsif ($value == 0) {
4132 vm_deviceunplug($vmid, $conf, $opt);
4134 } elsif ($opt eq 'vcpus') {
4135 die "skip
\n" if !$hotplug_features->{cpu};
4136 qemu_cpu_hotplug($vmid, $conf, $value);
4137 } elsif ($opt eq 'balloon') {
4138 # enable/disable balloning device is not hotpluggable
4139 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4140 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4141 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4143 # allow manual ballooning if shares is set to zero
4144 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4145 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4146 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4148 } elsif ($opt =~ m/^net(\d+)$/) {
4149 # some changes can be done without hotplug
4150 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4151 $vmid, $opt, $value);
4152 } elsif (is_valid_drivename($opt)) {
4153 # some changes can be done without hotplug
4154 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4155 $vmid, $opt, $value, 1);
4156 } elsif ($opt =~ m/^memory$/) { #dimms
4157 die "skip
\n" if !$hotplug_features->{memory};
4158 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4159 } elsif ($opt eq 'cpuunits') {
4160 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4161 } elsif ($opt eq 'cpulimit') {
4162 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4163 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4165 die "skip
\n"; # skip non-hot-pluggable options
4169 &$add_error($opt, $err) if $err ne "skip
\n";
4171 # save new config if hotplug was successful
4172 $conf->{$opt} = $value;
4173 delete $conf->{pending}->{$opt};
4174 PVE::QemuConfig->write_config($vmid, $conf);
4175 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4180 sub try_deallocate_drive {
4181 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4183 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4184 my $volid = $drive->{file};
4185 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4186 my $sid = PVE::Storage::parse_volume_id($volid);
4187 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4189 # check if the disk is really unused
4190 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4191 if is_volume_in_use($storecfg, $conf, $key, $volid);
4192 PVE::Storage::vdisk_free($storecfg, $volid);
4195 # If vm is not owner of this disk remove from config
4203 sub vmconfig_delete_or_detach_drive {
4204 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4206 my $drive = parse_drive($opt, $conf->{$opt});
4208 my $rpcenv = PVE::RPCEnvironment::get();
4209 my $authuser = $rpcenv->get_user();
4212 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4213 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4215 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4219 sub vmconfig_apply_pending {
4220 my ($vmid, $conf, $storecfg) = @_;
4224 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4225 while (my ($opt, $force) = each %$pending_delete_hash) {
4226 die "internal error
" if $opt =~ m/^unused/;
4227 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4228 if (!defined($conf->{$opt})) {
4229 vmconfig_undelete_pending_option($conf, $opt);
4230 PVE::QemuConfig->write_config($vmid, $conf);
4231 } elsif (is_valid_drivename($opt)) {
4232 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4233 vmconfig_undelete_pending_option($conf, $opt);
4234 delete $conf->{$opt};
4235 PVE::QemuConfig->write_config($vmid, $conf);
4237 vmconfig_undelete_pending_option($conf, $opt);
4238 delete $conf->{$opt};
4239 PVE::QemuConfig->write_config($vmid, $conf);
4243 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4245 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4246 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4248 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4249 # skip if nothing changed
4250 } elsif (is_valid_drivename($opt)) {
4251 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4252 if defined($conf->{$opt});
4253 $conf->{$opt} = $conf->{pending}->{$opt};
4255 $conf->{$opt} = $conf->{pending}->{$opt};
4258 delete $conf->{pending}->{$opt};
4259 PVE::QemuConfig->write_config($vmid, $conf);
4263 my $safe_num_ne = sub {
4266 return 0 if !defined($a) && !defined($b);
4267 return 1 if !defined($a);
4268 return 1 if !defined($b);
4273 my $safe_string_ne = sub {
4276 return 0 if !defined($a) && !defined($b);
4277 return 1 if !defined($a);
4278 return 1 if !defined($b);
4283 sub vmconfig_update_net {
4284 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4286 my $newnet = parse_net($value);
4288 if ($conf->{$opt}) {
4289 my $oldnet = parse_net($conf->{$opt});
4291 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4292 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4293 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4294 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4296 # for non online change, we try to hot-unplug
4297 die "skip
\n" if !$hotplug;
4298 vm_deviceunplug($vmid, $conf, $opt);
4301 die "internal error
" if $opt !~ m/net(\d+)/;
4302 my $iface = "tap
${vmid
}i
$1";
4304 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4305 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4306 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4307 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4308 PVE::Network::tap_unplug($iface);
4309 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4310 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4311 # Rate can be applied on its own but any change above needs to
4312 # include the rate in tap_plug since OVS resets everything.
4313 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4316 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4317 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4325 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4331 sub vmconfig_update_disk {
4332 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4334 # fixme: do we need force?
4336 my $drive = parse_drive($opt, $value);
4338 if ($conf->{$opt}) {
4340 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4342 my $media = $drive->{media} || 'disk';
4343 my $oldmedia = $old_drive->{media} || 'disk';
4344 die "unable to change media type
\n" if $media ne $oldmedia;
4346 if (!drive_is_cdrom($old_drive)) {
4348 if ($drive->{file} ne $old_drive->{file}) {
4350 die "skip
\n" if !$hotplug;
4352 # unplug and register as unused
4353 vm_deviceunplug($vmid, $conf, $opt);
4354 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4357 # update existing disk
4359 # skip non hotpluggable value
4360 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4361 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4362 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4363 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4368 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4369 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4370 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4371 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4372 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4373 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4374 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4375 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4376 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4377 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4378 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4379 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4381 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4382 ($drive->{mbps} || 0)*1024*1024,
4383 ($drive->{mbps_rd} || 0)*1024*1024,
4384 ($drive->{mbps_wr} || 0)*1024*1024,
4385 $drive->{iops} || 0,
4386 $drive->{iops_rd} || 0,
4387 $drive->{iops_wr} || 0,
4388 ($drive->{mbps_max} || 0)*1024*1024,
4389 ($drive->{mbps_rd_max} || 0)*1024*1024,
4390 ($drive->{mbps_wr_max} || 0)*1024*1024,
4391 $drive->{iops_max} || 0,
4392 $drive->{iops_rd_max} || 0,
4393 $drive->{iops_wr_max} || 0);
4402 if ($drive->{file} eq 'none') {
4403 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4405 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4406 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4407 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4415 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4417 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4418 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4422 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4423 $forcemachine, $spice_ticket) = @_;
4425 PVE::QemuConfig->lock_config($vmid, sub {
4426 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4428 die "you can
't start a vm if it's a template
\n" if PVE::QemuConfig->is_template($conf);
4430 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4432 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4434 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4435 vmconfig_apply_pending($vmid, $conf, $storecfg);
4436 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4439 my $defaults = load_defaults();
4441 # set environment variable useful inside network script
4442 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4444 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4446 my $migrate_port = 0;
4449 if ($statefile eq 'tcp') {
4450 my $localip = "localhost
";
4451 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4452 my $nodename = PVE::INotify::nodename();
4453 if ($datacenterconf->{migration_unsecure}) {
4454 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4455 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4457 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4458 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4459 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4460 push @$cmd, '-incoming', $migrate_uri;
4463 push @$cmd, '-loadstate', $statefile;
4470 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4471 my $d = parse_hostpci($conf->{"hostpci
$i"});
4473 my $pcidevices = $d->{pciid};
4474 foreach my $pcidevice (@$pcidevices) {
4475 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4477 my $info = pci_device_info("0000:$pciid");
4478 die "IOMMU
not present
\n" if !check_iommu_support();
4479 die "no pci device info
for device
'$pciid'\n" if !$info;
4480 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4481 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4485 PVE::Storage::activate_volumes($storecfg, $vollist);
4487 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4491 # deactivate volumes if start fails
4492 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4493 die "start failed
: $err";
4496 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4498 if ($statefile && $statefile ne 'tcp') {
4499 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4503 if ($migratedfrom) {
4506 set_migration_caps($vmid);
4511 print "spice listens on port
$spice_port\n";
4512 if ($spice_ticket) {
4513 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4514 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4520 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4521 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4522 if $conf->{balloon};
4525 foreach my $opt (keys %$conf) {
4526 next if $opt !~ m/^net\d+$/;
4527 my $nicconf = parse_net($conf->{$opt});
4528 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4532 vm_mon_cmd_nocheck($vmid, 'qom-set',
4533 path => "machine
/peripheral/balloon0
",
4534 property => "guest-stats-polling-interval
",
4535 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4541 my ($vmid, $execute, %params) = @_;
4543 my $cmd = { execute => $execute, arguments => \%params };
4544 vm_qmp_command($vmid, $cmd);
4547 sub vm_mon_cmd_nocheck {
4548 my ($vmid, $execute, %params) = @_;
4550 my $cmd = { execute => $execute, arguments => \%params };
4551 vm_qmp_command($vmid, $cmd, 1);
4554 sub vm_qmp_command {
4555 my ($vmid, $cmd, $nocheck) = @_;
4560 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4561 $timeout = $cmd->{arguments}->{timeout};
4562 delete $cmd->{arguments}->{timeout};
4566 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4567 my $sname = qmp_socket($vmid);
4568 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4569 my $qmpclient = PVE::QMPClient->new();
4571 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4572 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4573 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4574 if scalar(%{$cmd->{arguments}});
4575 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4577 die "unable to open monitor socket\n";
4581 syslog("err", "VM $vmid qmp command failed - $err");
4588 sub vm_human_monitor_command {
4589 my ($vmid, $cmdline) = @_;
4594 execute => 'human-monitor-command
',
4595 arguments => { 'command-line
' => $cmdline},
4598 return vm_qmp_command($vmid, $cmd);
4601 sub vm_commandline {
4602 my ($storecfg, $vmid) = @_;
4604 my $conf = PVE::QemuConfig->load_config($vmid);
4606 my $defaults = load_defaults();
4608 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4610 return join(' ', @$cmd);
4614 my ($vmid, $skiplock) = @_;
4616 PVE::QemuConfig->lock_config($vmid, sub {
4618 my $conf = PVE::QemuConfig->load_config($vmid);
4620 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4622 vm_mon_cmd($vmid, "system_reset");
4626 sub get_vm_volumes {
4630 foreach_volid($conf, sub {
4631 my ($volid, $is_cdrom) = @_;
4633 return if $volid =~ m|^/|;
4635 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4638 push @$vollist, $volid;
4644 sub vm_stop_cleanup {
4645 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4650 my $vollist = get_vm_volumes($conf);
4651 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4654 foreach my $ext (qw(mon qmp pid vnc qga)) {
4655 unlink "/var/run/qemu-server/${vmid}.$ext";
4658 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4660 warn $@ if $@; # avoid errors - just warn
4663 # Note: use $nockeck to skip tests if VM configuration file exists.
4664 # We need that when migration VMs to other nodes (files already moved)
4665 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4667 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4669 $force = 1 if !defined($force) && !$shutdown;
4672 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4673 kill 15, $pid if $pid;
4674 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4675 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4679 PVE
::QemuConfig-
>lock_config($vmid, sub {
4681 my $pid = check_running
($vmid, $nocheck);
4686 $conf = PVE
::QemuConfig-
>load_config($vmid);
4687 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4688 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4689 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4690 $timeout = $opts->{down
} if $opts->{down
};
4694 $timeout = 60 if !defined($timeout);
4698 if (defined($conf) && $conf->{agent
}) {
4699 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4701 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4704 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4711 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4716 if ($count >= $timeout) {
4718 warn "VM still running - terminating now with SIGTERM\n";
4721 die "VM quit/powerdown failed - got timeout\n";
4724 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4729 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4732 die "VM quit/powerdown failed\n";
4740 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4745 if ($count >= $timeout) {
4746 warn "VM still running - terminating now with SIGKILL\n";
4751 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4756 my ($vmid, $skiplock) = @_;
4758 PVE
::QemuConfig-
>lock_config($vmid, sub {
4760 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4762 PVE
::QemuConfig-
>check_lock($conf)
4763 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4765 vm_mon_cmd
($vmid, "stop");
4770 my ($vmid, $skiplock, $nocheck) = @_;
4772 PVE
::QemuConfig-
>lock_config($vmid, sub {
4776 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4778 PVE
::QemuConfig-
>check_lock($conf)
4779 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4781 vm_mon_cmd
($vmid, "cont");
4784 vm_mon_cmd_nocheck
($vmid, "cont");
4790 my ($vmid, $skiplock, $key) = @_;
4792 PVE
::QemuConfig-
>lock_config($vmid, sub {
4794 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4796 # there is no qmp command, so we use the human monitor command
4797 vm_human_monitor_command
($vmid, "sendkey $key");
4802 my ($storecfg, $vmid, $skiplock) = @_;
4804 PVE
::QemuConfig-
>lock_config($vmid, sub {
4806 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4808 if (!check_running
($vmid)) {
4809 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4811 die "VM $vmid is running - destroy failed\n";
4819 my ($filename, $buf) = @_;
4821 my $fh = IO
::File-
>new($filename, "w");
4822 return undef if !$fh;
4824 my $res = print $fh $buf;
4831 sub pci_device_info
{
4836 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4837 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4839 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4840 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4842 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4843 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4845 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4846 return undef if !defined($product) || $product !~ s/^0x//;
4851 product
=> $product,
4857 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4866 my $name = $dev->{name
};
4868 my $fn = "$pcisysfs/devices/$name/reset";
4870 return file_write
($fn, "1");
4873 sub pci_dev_bind_to_vfio
{
4876 my $name = $dev->{name
};
4878 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4880 if (!-d
$vfio_basedir) {
4881 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4883 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4885 my $testdir = "$vfio_basedir/$name";
4886 return 1 if -d
$testdir;
4888 my $data = "$dev->{vendor} $dev->{product}";
4889 return undef if !file_write
("$vfio_basedir/new_id", $data);
4891 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4892 if (!file_write
($fn, $name)) {
4893 return undef if -f
$fn;
4896 $fn = "$vfio_basedir/bind";
4897 if (! -d
$testdir) {
4898 return undef if !file_write
($fn, $name);
4904 sub pci_dev_group_bind_to_vfio
{
4907 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4909 if (!-d
$vfio_basedir) {
4910 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4912 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4914 # get IOMMU group devices
4915 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4916 my @devs = grep /^0000:/, readdir($D);
4919 foreach my $pciid (@devs) {
4920 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4922 # pci bridges, switches or root ports are not supported
4923 # they have a pci_bus subdirectory so skip them
4924 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4926 my $info = pci_device_info
($1);
4927 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4933 sub print_pci_addr
{
4934 my ($id, $bridges) = @_;
4938 piix3
=> { bus
=> 0, addr
=> 1 },
4939 #addr2 : first videocard
4940 balloon0
=> { bus
=> 0, addr
=> 3 },
4941 watchdog
=> { bus
=> 0, addr
=> 4 },
4942 scsihw0
=> { bus
=> 0, addr
=> 5 },
4943 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4944 scsihw1
=> { bus
=> 0, addr
=> 6 },
4945 ahci0
=> { bus
=> 0, addr
=> 7 },
4946 qga0
=> { bus
=> 0, addr
=> 8 },
4947 spice
=> { bus
=> 0, addr
=> 9 },
4948 virtio0
=> { bus
=> 0, addr
=> 10 },
4949 virtio1
=> { bus
=> 0, addr
=> 11 },
4950 virtio2
=> { bus
=> 0, addr
=> 12 },
4951 virtio3
=> { bus
=> 0, addr
=> 13 },
4952 virtio4
=> { bus
=> 0, addr
=> 14 },
4953 virtio5
=> { bus
=> 0, addr
=> 15 },
4954 hostpci0
=> { bus
=> 0, addr
=> 16 },
4955 hostpci1
=> { bus
=> 0, addr
=> 17 },
4956 net0
=> { bus
=> 0, addr
=> 18 },
4957 net1
=> { bus
=> 0, addr
=> 19 },
4958 net2
=> { bus
=> 0, addr
=> 20 },
4959 net3
=> { bus
=> 0, addr
=> 21 },
4960 net4
=> { bus
=> 0, addr
=> 22 },
4961 net5
=> { bus
=> 0, addr
=> 23 },
4962 vga1
=> { bus
=> 0, addr
=> 24 },
4963 vga2
=> { bus
=> 0, addr
=> 25 },
4964 vga3
=> { bus
=> 0, addr
=> 26 },
4965 hostpci2
=> { bus
=> 0, addr
=> 27 },
4966 hostpci3
=> { bus
=> 0, addr
=> 28 },
4967 #addr29 : usb-host (pve-usb.cfg)
4968 'pci.1' => { bus
=> 0, addr
=> 30 },
4969 'pci.2' => { bus
=> 0, addr
=> 31 },
4970 'net6' => { bus
=> 1, addr
=> 1 },
4971 'net7' => { bus
=> 1, addr
=> 2 },
4972 'net8' => { bus
=> 1, addr
=> 3 },
4973 'net9' => { bus
=> 1, addr
=> 4 },
4974 'net10' => { bus
=> 1, addr
=> 5 },
4975 'net11' => { bus
=> 1, addr
=> 6 },
4976 'net12' => { bus
=> 1, addr
=> 7 },
4977 'net13' => { bus
=> 1, addr
=> 8 },
4978 'net14' => { bus
=> 1, addr
=> 9 },
4979 'net15' => { bus
=> 1, addr
=> 10 },
4980 'net16' => { bus
=> 1, addr
=> 11 },
4981 'net17' => { bus
=> 1, addr
=> 12 },
4982 'net18' => { bus
=> 1, addr
=> 13 },
4983 'net19' => { bus
=> 1, addr
=> 14 },
4984 'net20' => { bus
=> 1, addr
=> 15 },
4985 'net21' => { bus
=> 1, addr
=> 16 },
4986 'net22' => { bus
=> 1, addr
=> 17 },
4987 'net23' => { bus
=> 1, addr
=> 18 },
4988 'net24' => { bus
=> 1, addr
=> 19 },
4989 'net25' => { bus
=> 1, addr
=> 20 },
4990 'net26' => { bus
=> 1, addr
=> 21 },
4991 'net27' => { bus
=> 1, addr
=> 22 },
4992 'net28' => { bus
=> 1, addr
=> 23 },
4993 'net29' => { bus
=> 1, addr
=> 24 },
4994 'net30' => { bus
=> 1, addr
=> 25 },
4995 'net31' => { bus
=> 1, addr
=> 26 },
4996 'xhci' => { bus
=> 1, addr
=> 27 },
4997 'virtio6' => { bus
=> 2, addr
=> 1 },
4998 'virtio7' => { bus
=> 2, addr
=> 2 },
4999 'virtio8' => { bus
=> 2, addr
=> 3 },
5000 'virtio9' => { bus
=> 2, addr
=> 4 },
5001 'virtio10' => { bus
=> 2, addr
=> 5 },
5002 'virtio11' => { bus
=> 2, addr
=> 6 },
5003 'virtio12' => { bus
=> 2, addr
=> 7 },
5004 'virtio13' => { bus
=> 2, addr
=> 8 },
5005 'virtio14' => { bus
=> 2, addr
=> 9 },
5006 'virtio15' => { bus
=> 2, addr
=> 10 },
5007 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5008 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5009 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5010 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5011 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5012 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5013 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5014 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5015 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5016 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5017 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5018 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5019 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5020 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5021 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5022 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5023 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5024 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5025 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5026 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5027 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5028 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5029 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5030 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5031 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5032 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5033 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5034 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5035 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5036 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5037 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5041 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5042 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5043 my $bus = $devices->{$id}->{bus
};
5044 $res = ",bus=pci.$bus,addr=$addr";
5045 $bridges->{$bus} = 1 if $bridges;
5051 sub print_pcie_addr
{
5056 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5057 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5058 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5059 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5062 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5063 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5064 my $bus = $devices->{$id}->{bus
};
5065 $res = ",bus=$bus,addr=$addr";
5071 # vzdump restore implementaion
5073 sub tar_archive_read_firstfile
{
5074 my $archive = shift;
5076 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5078 # try to detect archive type first
5079 my $pid = open (TMP
, "tar tf '$archive'|") ||
5080 die "unable to open file '$archive'\n";
5081 my $firstfile = <TMP
>;
5085 die "ERROR: archive contaions no data\n" if !$firstfile;
5091 sub tar_restore_cleanup
{
5092 my ($storecfg, $statfile) = @_;
5094 print STDERR
"starting cleanup\n";
5096 if (my $fd = IO
::File-
>new($statfile, "r")) {
5097 while (defined(my $line = <$fd>)) {
5098 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5101 if ($volid =~ m
|^/|) {
5102 unlink $volid || die 'unlink failed\n';
5104 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5106 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5108 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5110 print STDERR
"unable to parse line in statfile - $line";
5117 sub restore_archive
{
5118 my ($archive, $vmid, $user, $opts) = @_;
5120 my $format = $opts->{format
};
5123 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5124 $format = 'tar' if !$format;
5126 } elsif ($archive =~ m/\.tar$/) {
5127 $format = 'tar' if !$format;
5128 } elsif ($archive =~ m/.tar.lzo$/) {
5129 $format = 'tar' if !$format;
5131 } elsif ($archive =~ m/\.vma$/) {
5132 $format = 'vma' if !$format;
5133 } elsif ($archive =~ m/\.vma\.gz$/) {
5134 $format = 'vma' if !$format;
5136 } elsif ($archive =~ m/\.vma\.lzo$/) {
5137 $format = 'vma' if !$format;
5140 $format = 'vma' if !$format; # default
5143 # try to detect archive format
5144 if ($format eq 'tar') {
5145 return restore_tar_archive
($archive, $vmid, $user, $opts);
5147 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5151 sub restore_update_config_line
{
5152 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5154 return if $line =~ m/^\#qmdump\#/;
5155 return if $line =~ m/^\#vzdump\#/;
5156 return if $line =~ m/^lock:/;
5157 return if $line =~ m/^unused\d+:/;
5158 return if $line =~ m/^parent:/;
5159 return if $line =~ m/^template:/; # restored VM is never a template
5161 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5162 # try to convert old 1.X settings
5163 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5164 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5165 my ($model, $macaddr) = split(/\=/, $devconfig);
5166 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5169 bridge
=> "vmbr$ind",
5170 macaddr
=> $macaddr,
5172 my $netstr = print_net
($net);
5174 print $outfd "net$cookie->{netcount}: $netstr\n";
5175 $cookie->{netcount
}++;
5177 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5178 my ($id, $netstr) = ($1, $2);
5179 my $net = parse_net
($netstr);
5180 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5181 $netstr = print_net
($net);
5182 print $outfd "$id: $netstr\n";
5183 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5186 my $di = parse_drive
($virtdev, $value);
5187 if (defined($di->{backup
}) && !$di->{backup
}) {
5188 print $outfd "#$line";
5189 } elsif ($map->{$virtdev}) {
5190 delete $di->{format
}; # format can change on restore
5191 $di->{file
} = $map->{$virtdev};
5192 $value = print_drive
($vmid, $di);
5193 print $outfd "$virtdev: $value\n";
5203 my ($cfg, $vmid) = @_;
5205 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5207 my $volid_hash = {};
5208 foreach my $storeid (keys %$info) {
5209 foreach my $item (@{$info->{$storeid}}) {
5210 next if !($item->{volid
} && $item->{size
});
5211 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5212 $volid_hash->{$item->{volid
}} = $item;
5219 sub is_volume_in_use
{
5220 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5222 my $path = PVE
::Storage
::path
($storecfg, $volid);
5224 my $scan_config = sub {
5225 my ($cref, $snapname) = @_;
5227 foreach my $key (keys %$cref) {
5228 my $value = $cref->{$key};
5229 if (is_valid_drivename
($key)) {
5230 next if $skip_drive && $key eq $skip_drive;
5231 my $drive = parse_drive
($key, $value);
5232 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5233 return 1 if $volid eq $drive->{file
};
5234 if ($drive->{file
} =~ m!^/!) {
5235 return 1 if $drive->{file
} eq $path;
5237 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5239 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5241 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5249 return 1 if &$scan_config($conf);
5253 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5254 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5260 sub update_disksize
{
5261 my ($vmid, $conf, $volid_hash) = @_;
5267 # Note: it is allowed to define multiple storages with same path (alias), so
5268 # we need to check both 'volid' and real 'path' (two different volid can point
5269 # to the same path).
5274 foreach my $opt (keys %$conf) {
5275 if (is_valid_drivename
($opt)) {
5276 my $drive = parse_drive
($opt, $conf->{$opt});
5277 my $volid = $drive->{file
};
5280 $used->{$volid} = 1;
5281 if ($volid_hash->{$volid} &&
5282 (my $path = $volid_hash->{$volid}->{path
})) {
5283 $usedpath->{$path} = 1;
5286 next if drive_is_cdrom
($drive);
5287 next if !$volid_hash->{$volid};
5289 $drive->{size
} = $volid_hash->{$volid}->{size
};
5290 my $new = print_drive
($vmid, $drive);
5291 if ($new ne $conf->{$opt}) {
5293 $conf->{$opt} = $new;
5298 # remove 'unusedX' entry if volume is used
5299 foreach my $opt (keys %$conf) {
5300 next if $opt !~ m/^unused\d+$/;
5301 my $volid = $conf->{$opt};
5302 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5303 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5305 delete $conf->{$opt};
5309 foreach my $volid (sort keys %$volid_hash) {
5310 next if $volid =~ m/vm-$vmid-state-/;
5311 next if $used->{$volid};
5312 my $path = $volid_hash->{$volid}->{path
};
5313 next if !$path; # just to be sure
5314 next if $usedpath->{$path};
5316 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5317 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5324 my ($vmid, $nolock) = @_;
5326 my $cfg = PVE
::Storage
::config
();
5328 my $volid_hash = scan_volids
($cfg, $vmid);
5330 my $updatefn = sub {
5333 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5335 PVE
::QemuConfig-
>check_lock($conf);
5338 foreach my $volid (keys %$volid_hash) {
5339 my $info = $volid_hash->{$volid};
5340 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5343 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5345 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5348 if (defined($vmid)) {
5352 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5355 my $vmlist = config_list
();
5356 foreach my $vmid (keys %$vmlist) {
5360 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5366 sub restore_vma_archive
{
5367 my ($archive, $vmid, $user, $opts, $comp) = @_;
5369 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5370 my $readfrom = $archive;
5375 my $qarchive = PVE
::Tools
::shellquote
($archive);
5376 if ($comp eq 'gzip') {
5377 $uncomp = "zcat $qarchive|";
5378 } elsif ($comp eq 'lzop') {
5379 $uncomp = "lzop -d -c $qarchive|";
5381 die "unknown compression method '$comp'\n";
5386 my $tmpdir = "/var/tmp/vzdumptmp$$";
5389 # disable interrupts (always do cleanups)
5390 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5391 warn "got interrupt - ignored\n";
5394 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5395 POSIX
::mkfifo
($mapfifo, 0600);
5398 my $openfifo = sub {
5399 open($fifofh, '>', $mapfifo) || die $!;
5402 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5409 my $rpcenv = PVE
::RPCEnvironment
::get
();
5411 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5412 my $tmpfn = "$conffile.$$.tmp";
5414 # Note: $oldconf is undef if VM does not exists
5415 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5416 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5418 my $print_devmap = sub {
5419 my $virtdev_hash = {};
5421 my $cfgfn = "$tmpdir/qemu-server.conf";
5423 # we can read the config - that is already extracted
5424 my $fh = IO
::File-
>new($cfgfn, "r") ||
5425 "unable to read qemu-server.conf - $!\n";
5427 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5429 my $pve_firewall_dir = '/etc/pve/firewall';
5430 mkdir $pve_firewall_dir; # make sure the dir exists
5431 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5434 while (defined(my $line = <$fh>)) {
5435 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5436 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5437 die "archive does not contain data for drive '$virtdev'\n"
5438 if !$devinfo->{$devname};
5439 if (defined($opts->{storage
})) {
5440 $storeid = $opts->{storage
} || 'local';
5441 } elsif (!$storeid) {
5444 $format = 'raw' if !$format;
5445 $devinfo->{$devname}->{devname
} = $devname;
5446 $devinfo->{$devname}->{virtdev
} = $virtdev;
5447 $devinfo->{$devname}->{format
} = $format;
5448 $devinfo->{$devname}->{storeid
} = $storeid;
5450 # check permission on storage
5451 my $pool = $opts->{pool
}; # todo: do we need that?
5452 if ($user ne 'root@pam') {
5453 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5456 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5460 foreach my $devname (keys %$devinfo) {
5461 die "found no device mapping information for device '$devname'\n"
5462 if !$devinfo->{$devname}->{virtdev
};
5465 my $cfg = PVE
::Storage
::config
();
5467 # create empty/temp config
5469 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5470 foreach_drive
($oldconf, sub {
5471 my ($ds, $drive) = @_;
5473 return if drive_is_cdrom
($drive);
5475 my $volid = $drive->{file
};
5477 return if !$volid || $volid =~ m
|^/|;
5479 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5480 return if !$path || !$owner || ($owner != $vmid);
5482 # Note: only delete disk we want to restore
5483 # other volumes will become unused
5484 if ($virtdev_hash->{$ds}) {
5485 PVE
::Storage
::vdisk_free
($cfg, $volid);
5489 # delete vmstate files
5490 # since after the restore we have no snapshots anymore
5491 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5492 my $snap = $oldconf->{snapshots
}->{$snapname};
5493 if ($snap->{vmstate
}) {
5494 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5503 foreach my $virtdev (sort keys %$virtdev_hash) {
5504 my $d = $virtdev_hash->{$virtdev};
5505 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5506 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5508 # test if requested format is supported
5509 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5510 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5511 $d->{format
} = $defFormat if !$supported;
5513 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5514 $d->{format
}, undef, $alloc_size);
5515 print STDERR
"new volume ID is '$volid'\n";
5516 $d->{volid
} = $volid;
5517 my $path = PVE
::Storage
::path
($cfg, $volid);
5519 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5521 my $write_zeros = 1;
5522 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5526 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5528 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5529 $map->{$virtdev} = $volid;
5532 $fh->seek(0, 0) || die "seek failed - $!\n";
5534 my $outfd = new IO
::File
($tmpfn, "w") ||
5535 die "unable to write config for VM $vmid\n";
5537 my $cookie = { netcount
=> 0 };
5538 while (defined(my $line = <$fh>)) {
5539 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5548 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5549 die "interrupted by signal\n";
5551 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5553 $oldtimeout = alarm($timeout);
5560 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5561 my ($dev_id, $size, $devname) = ($1, $2, $3);
5562 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5563 } elsif ($line =~ m/^CTIME: /) {
5564 # we correctly received the vma config, so we can disable
5565 # the timeout now for disk allocation (set to 10 minutes, so
5566 # that we always timeout if something goes wrong)
5569 print $fifofh "done\n";
5570 my $tmp = $oldtimeout || 0;
5571 $oldtimeout = undef;
5577 print "restore vma archive: $cmd\n";
5578 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5582 alarm($oldtimeout) if $oldtimeout;
5585 foreach my $devname (keys %$devinfo) {
5586 my $volid = $devinfo->{$devname}->{volid
};
5587 push @$vollist, $volid if $volid;
5590 my $cfg = PVE
::Storage
::config
();
5591 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5599 foreach my $devname (keys %$devinfo) {
5600 my $volid = $devinfo->{$devname}->{volid
};
5603 if ($volid =~ m
|^/|) {
5604 unlink $volid || die 'unlink failed\n';
5606 PVE
::Storage
::vdisk_free
($cfg, $volid);
5608 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5610 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5617 rename($tmpfn, $conffile) ||
5618 die "unable to commit configuration file '$conffile'\n";
5620 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5622 eval { rescan
($vmid, 1); };
5626 sub restore_tar_archive
{
5627 my ($archive, $vmid, $user, $opts) = @_;
5629 if ($archive ne '-') {
5630 my $firstfile = tar_archive_read_firstfile
($archive);
5631 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5632 if $firstfile ne 'qemu-server.conf';
5635 my $storecfg = PVE
::Storage
::config
();
5637 # destroy existing data - keep empty config
5638 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5639 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5641 my $tocmd = "/usr/lib/qemu-server/qmextract";
5643 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5644 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5645 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5646 $tocmd .= ' --info' if $opts->{info
};
5648 # tar option "xf" does not autodetect compression when read from STDIN,
5649 # so we pipe to zcat
5650 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5651 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5653 my $tmpdir = "/var/tmp/vzdumptmp$$";
5656 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5657 local $ENV{VZDUMP_VMID
} = $vmid;
5658 local $ENV{VZDUMP_USER
} = $user;
5660 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5661 my $tmpfn = "$conffile.$$.tmp";
5663 # disable interrupts (always do cleanups)
5664 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5665 print STDERR
"got interrupt - ignored\n";
5670 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5671 die "interrupted by signal\n";
5674 if ($archive eq '-') {
5675 print "extracting archive from STDIN\n";
5676 run_command
($cmd, input
=> "<&STDIN");
5678 print "extracting archive '$archive'\n";
5682 return if $opts->{info
};
5686 my $statfile = "$tmpdir/qmrestore.stat";
5687 if (my $fd = IO
::File-
>new($statfile, "r")) {
5688 while (defined (my $line = <$fd>)) {
5689 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5690 $map->{$1} = $2 if $1;
5692 print STDERR
"unable to parse line in statfile - $line\n";
5698 my $confsrc = "$tmpdir/qemu-server.conf";
5700 my $srcfd = new IO
::File
($confsrc, "r") ||
5701 die "unable to open file '$confsrc'\n";
5703 my $outfd = new IO
::File
($tmpfn, "w") ||
5704 die "unable to write config for VM $vmid\n";
5706 my $cookie = { netcount
=> 0 };
5707 while (defined (my $line = <$srcfd>)) {
5708 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5720 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5727 rename $tmpfn, $conffile ||
5728 die "unable to commit configuration file '$conffile'\n";
5730 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5732 eval { rescan
($vmid, 1); };
5736 sub foreach_writable_storage
{
5737 my ($conf, $func) = @_;
5741 foreach my $ds (keys %$conf) {
5742 next if !is_valid_drivename
($ds);
5744 my $drive = parse_drive
($ds, $conf->{$ds});
5746 next if drive_is_cdrom
($drive);
5748 my $volid = $drive->{file
};
5750 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5751 $sidhash->{$sid} = $sid if $sid;
5754 foreach my $sid (sort keys %$sidhash) {
5759 sub do_snapshots_with_qemu
{
5760 my ($storecfg, $volid) = @_;
5762 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5764 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5765 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5769 if ($volid =~ m/\.(qcow2|qed)$/){
5776 sub qga_check_running
{
5779 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5781 warn "Qemu Guest Agent are not running - $@";
5787 sub template_create
{
5788 my ($vmid, $conf, $disk) = @_;
5790 my $storecfg = PVE
::Storage
::config
();
5792 foreach_drive
($conf, sub {
5793 my ($ds, $drive) = @_;
5795 return if drive_is_cdrom
($drive);
5796 return if $disk && $ds ne $disk;
5798 my $volid = $drive->{file
};
5799 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5801 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5802 $drive->{file
} = $voliddst;
5803 $conf->{$ds} = print_drive
($vmid, $drive);
5804 PVE
::QemuConfig-
>write_config($vmid, $conf);
5808 sub qemu_img_convert
{
5809 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5811 my $storecfg = PVE
::Storage
::config
();
5812 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5813 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5815 if ($src_storeid && $dst_storeid) {
5817 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5819 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5820 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5822 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5823 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5825 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5826 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5829 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5830 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5831 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5832 if ($is_zero_initialized) {
5833 push @$cmd, "zeroinit:$dst_path";
5835 push @$cmd, $dst_path;
5840 if($line =~ m/\((\S+)\/100\
%\)/){
5842 my $transferred = int($size * $percent / 100);
5843 my $remaining = $size - $transferred;
5845 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5850 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5852 die "copy failed: $err" if $err;
5856 sub qemu_img_format
{
5857 my ($scfg, $volname) = @_;
5859 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5866 sub qemu_drive_mirror
{
5867 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5869 my $storecfg = PVE
::Storage
::config
();
5870 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5872 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5874 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5876 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5878 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5880 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5881 $opts->{format
} = $format if $format;
5883 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5886 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5888 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5889 my $stat = @$stats[0];
5890 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5891 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5893 my $busy = $stat->{busy
};
5894 my $ready = $stat->{ready
};
5896 if (my $total = $stat->{len
}) {
5897 my $transferred = $stat->{offset
} || 0;
5898 my $remaining = $total - $transferred;
5899 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5901 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5905 if ($stat->{ready
} eq 'true') {
5907 last if $vmiddst != $vmid;
5909 # try to switch the disk if source and destination are on the same guest
5910 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5912 die $@ if $@ !~ m/cannot be completed/;
5921 my $cancel_job = sub {
5922 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5924 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5925 my $stat = @$stats[0];
5932 eval { &$cancel_job(); };
5933 die "mirroring error: $err";
5936 if ($vmiddst != $vmid) {
5937 # if we clone a disk for a new target vm, we don't switch the disk
5938 &$cancel_job(); # so we call block-job-cancel
5943 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5944 $newvmid, $storage, $format, $full, $newvollist) = @_;
5949 print "create linked clone of drive $drivename ($drive->{file})\n";
5950 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5951 push @$newvollist, $newvolid;
5953 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5954 $storeid = $storage if $storage;
5956 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5958 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5959 $format = qemu_img_format
($scfg, $volname);
5962 # test if requested format is supported - else use default
5963 my $supported = grep { $_ eq $format } @$validFormats;
5964 $format = $defFormat if !$supported;
5966 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5968 print "create full clone of drive $drivename ($drive->{file})\n";
5969 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5970 push @$newvollist, $newvolid;
5972 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5974 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5975 if (!$running || $snapname) {
5976 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5978 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5982 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5985 $disk->{format
} = undef;
5986 $disk->{file
} = $newvolid;
5987 $disk->{size
} = $size;
5992 # this only works if VM is running
5993 sub get_current_qemu_machine
{
5996 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5997 my $res = vm_qmp_command
($vmid, $cmd);
5999 my ($current, $default);
6000 foreach my $e (@$res) {
6001 $default = $e->{name
} if $e->{'is-default'};
6002 $current = $e->{name
} if $e->{'is-current'};
6005 # fallback to the default machine if current is not supported by qemu
6006 return $current || $default || 'pc';
6009 sub qemu_machine_feature_enabled
{
6010 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6015 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6017 $current_major = $3;
6018 $current_minor = $4;
6020 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6022 $current_major = $1;
6023 $current_minor = $2;
6026 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6031 sub qemu_machine_pxe
{
6032 my ($vmid, $conf, $machine) = @_;
6034 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6036 foreach my $opt (keys %$conf) {
6037 next if $opt !~ m/^net(\d+)$/;
6038 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6040 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6041 return $machine.".pxe" if $romfile =~ m/pxe/;
6048 sub qemu_use_old_bios_files
{
6049 my ($machine_type) = @_;
6051 return if !$machine_type;
6053 my $use_old_bios_files = undef;
6055 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6057 $use_old_bios_files = 1;
6059 my $kvmver = kvm_user_version
();
6060 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6061 # load new efi bios files on migration. So this hack is required to allow
6062 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6063 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6064 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6067 return ($use_old_bios_files, $machine_type);
6074 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6075 my (undef, $id, $function) = @_;
6076 my $res = { id
=> $id, function
=> $function};
6077 push @{$devices->{$id}}, $res;
6083 sub vm_iothreads_list
{
6086 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6089 foreach my $iothread (@$res) {
6090 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6097 my ($conf, $drive) = @_;
6101 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6103 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6109 my $controller = int($drive->{index} / $maxdev);
6110 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6112 return ($maxdev, $controller, $controller_prefix);
6115 # bash completion helper
6117 sub complete_backup_archives
{
6118 my ($cmdname, $pname, $cvalue) = @_;
6120 my $cfg = PVE
::Storage
::config
();
6124 if ($cvalue =~ m/^([^:]+):/) {
6128 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6131 foreach my $id (keys %$data) {
6132 foreach my $item (@{$data->{$id}}) {
6133 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6134 push @$res, $item->{volid
} if defined($item->{volid
});
6141 my $complete_vmid_full = sub {
6144 my $idlist = vmstatus
();
6148 foreach my $id (keys %$idlist) {
6149 my $d = $idlist->{$id};
6150 if (defined($running)) {
6151 next if $d->{template
};
6152 next if $running && $d->{status
} ne 'running';
6153 next if !$running && $d->{status
} eq 'running';
6162 return &$complete_vmid_full();
6165 sub complete_vmid_stopped
{
6166 return &$complete_vmid_full(0);
6169 sub complete_vmid_running
{
6170 return &$complete_vmid_full(1);
6173 sub complete_storage
{
6175 my $cfg = PVE
::Storage
::config
();
6176 my $ids = $cfg->{ids
};
6179 foreach my $sid (keys %$ids) {
6180 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6181 next if !$ids->{$sid}->{content
}->{images
};