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) ],
104 description
=> "Do not identify as a KVM virtual machine.",
115 description
=> "Specifies whether a VM will be started during system bootup.",
121 description
=> "Automatic restart after crash (currently ignored).",
126 type
=> 'string', format
=> 'pve-hotplug-features',
127 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'.",
128 default => 'network,disk,usb',
133 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
139 description
=> "Lock/unlock the VM.",
140 enum
=> [qw(migrate backup snapshot rollback)],
145 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.",
153 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.",
161 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
168 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
174 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",
182 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
183 enum
=> PVE
::Tools
::kvmkeymaplist
(),
188 type
=> 'string', format
=> 'dns-name',
189 description
=> "Set a name for the VM. Only used on the configuration web interface.",
194 description
=> "scsi controller model",
195 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
201 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
206 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
207 description
=> <<EODESC,
208 Used to enable special optimization/features for specific
211 other => unspecified OS
212 wxp => Microsoft Windows XP
213 w2k => Microsoft Windows 2000
214 w2k3 => Microsoft Windows 2003
215 w2k8 => Microsoft Windows 2008
216 wvista => Microsoft Windows Vista
217 win7 => Microsoft Windows 7
218 win8 => Microsoft Windows 8/2012
219 l24 => Linux 2.4 Kernel
220 l26 => Linux 2.6/3.X Kernel
221 solaris => solaris/opensolaris/openindiania kernel
223 other|l24|l26|solaris ... no special behaviour
224 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
230 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
231 pattern
=> '[acdn]{1,4}',
236 type
=> 'string', format
=> 'pve-qm-bootdisk',
237 description
=> "Enable booting from specified disk.",
238 pattern
=> '(ide|sata|scsi|virtio)\d+',
243 description
=> "The number of CPUs. Please use option -sockets instead.",
250 description
=> "The number of CPU sockets.",
257 description
=> "The number of cores per socket.",
264 description
=> "Enable/disable NUMA.",
270 description
=> "Number of hotplugged vcpus.",
277 description
=> "Enable/disable ACPI.",
283 description
=> "Enable/disable Qemu GuestAgent.",
289 description
=> "Enable/disable KVM hardware virtualization.",
295 description
=> "Enable/disable time drift fix.",
301 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
306 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
311 description
=> "Select the VGA type. If you want to use high resolution" .
312 " modes (>= 1280x1024x16) then you should use the options " .
313 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
314 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
315 "display sever. For win* OS you can select how many independent " .
316 "displays you want, Linux guests can add displays them self. " .
317 "You can also run without any graphic card, using a serial device" .
319 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
323 type
=> 'string', format
=> 'pve-qm-watchdog',
324 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
325 description
=> "Create a virtual hardware watchdog device. Once enabled" .
326 " (by a guest action), the watchdog must be periodically polled " .
327 "by an agent inside the guest or else the watchdog will reset " .
328 "the guest (or execute the respective action specified)",
333 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
334 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'.",
335 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
338 startup
=> get_standard_option
('pve-startup-order'),
342 description
=> "Enable/disable Template.",
348 description
=> <<EODESCR,
349 NOTE: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
351 args: -no-reboot -no-hpet
358 description
=> "Enable/disable the USB tablet device. This device is " .
359 "usually needed to allow absolute mouse positioning with VNC. " .
360 "Else the mouse runs out of sync with normal VNC clients. " .
361 "If you're running lots of console-only guests on one host, " .
362 "you may consider disabling this to save some context switches. " .
363 "This is turned off by default if you use spice (-vga=qxl).",
368 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
372 migrate_downtime
=> {
375 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
381 type
=> 'string', format
=> 'pve-qm-drive',
382 typetext
=> 'volume',
383 description
=> "This is an alias for option -ide2",
387 description
=> "Emulated CPU type.",
391 parent
=> get_standard_option
('pve-snapshot-name', {
393 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
397 description
=> "Timestamp for snapshots.",
403 type
=> 'string', format
=> 'pve-volume-id',
404 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
407 description
=> "Specific the Qemu machine type.",
409 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
414 description
=> "Specify SMBIOS type 1 fields.",
415 type
=> 'string', format
=> 'pve-qm-smbios1',
422 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
428 enum
=> [ qw(seabios ovmf) ],
429 description
=> "Select BIOS implementation.",
430 default => 'seabios',
434 # what about other qemu settings ?
436 #machine => 'string',
449 ##soundhw => 'string',
451 while (my ($k, $v) = each %$confdesc) {
452 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
455 my $MAX_IDE_DISKS = 4;
456 my $MAX_SCSI_DISKS = 14;
457 my $MAX_VIRTIO_DISKS = 16;
458 my $MAX_SATA_DISKS = 6;
459 my $MAX_USB_DEVICES = 5;
461 my $MAX_UNUSED_DISKS = 8;
462 my $MAX_HOSTPCI_DEVICES = 4;
463 my $MAX_SERIAL_PORTS = 4;
464 my $MAX_PARALLEL_PORTS = 3;
466 my $MAX_MEM = 4194304;
467 my $STATICMEM = 1024;
471 type
=> 'string', format
=> 'pve-qm-numanode',
472 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
473 description
=> "numa topology",
475 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
477 for (my $i = 0; $i < $MAX_NUMA; $i++) {
478 $confdesc->{"numa$i"} = $numadesc;
481 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
482 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
483 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
484 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
488 type
=> 'string', format
=> 'pve-qm-net',
489 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]",
490 description
=> <<EODESCR,
491 Specify network devices.
493 MODEL is one of: $nic_model_list_txt
495 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
496 automatically generated if not specified.
498 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
500 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'.
502 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
508 The DHCP server assign addresses to the guest starting from 10.0.2.15.
512 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
514 for (my $i = 0; $i < $MAX_NETS; $i++) {
515 $confdesc->{"net$i"} = $netdesc;
520 my %drivedesc_base = (
521 volume
=> { alias
=> 'file' },
523 type
=> 'pve-volume-id',
525 format_description
=> 'volume',
526 description
=> "The drive's backing volume.",
530 format_description
=> 'cdrom|disk',
531 enum
=> [qw(cdrom disk)],
532 description
=> "The drive's media type.",
538 format_description
=> 'count',
539 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
544 format_description
=> 'count',
545 description
=> "Force the drive's physical geometry to have a specific head count.",
550 format_description
=> 'count',
551 description
=> "Force the drive's physical geometry to have a specific sector count.",
556 format_description
=> 'none|lba|auto',
557 enum
=> [qw(none lba auto)],
558 description
=> "Force disk geometry bios translation mode.",
563 format_description
=> 'on|off',
564 description
=> "Whether the drive should be included when making snapshots.",
569 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
570 enum
=> [qw(none writethrough writeback unsafe directsync)],
571 description
=> "The drive's cache mode",
576 format_description
=> 'drive format',
577 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
578 description
=> "The drive's backing file's data format.",
583 format
=> 'disk-size',
584 description
=> "Disk size. This is purely informational and has no effect.",
589 format_description
=> 'on|off',
590 description
=> "Whether the drive should be included when making backups.",
595 format_description
=> 'enospc|ignore|report|stop',
596 enum
=> [qw(enospc ignore report stop)],
597 description
=> 'Write error action.',
602 format_description
=> 'native|threads',
603 enum
=> [qw(native threads)],
604 description
=> 'AIO type to use.',
609 format_description
=> 'ignore|on',
610 enum
=> [qw(ignore on)],
611 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
616 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
621 format
=> 'urlencoded',
622 format_description
=> 'serial',
623 maxLength
=> 20*3, # *3 since it's %xx url enoded
624 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
632 format_description
=> 'ignore|report|stop',
633 enum
=> [qw(ignore report stop)],
634 description
=> 'Read error action.',
639 my %iothread_fmt = ( iothread
=> {
641 format_description
=> 'off|on',
642 description
=> "Whether to use iothreads for this drive",
649 format
=> 'urlencoded',
650 format_description
=> 'model',
651 maxLength
=> 40*3, # *3 since it's %xx url enoded
652 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
660 format_description
=> 'nbqueues',
661 description
=> "Number of queues.",
667 my $add_throttle_desc = sub {
668 my ($key, $type, $what, $size, $longsize) = @_;
669 $drivedesc_base{$key} = {
671 format_description
=> $size,
672 description
=> "Maximum $what speed in $longsize per second.",
676 # throughput: (leaky bucket)
677 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
678 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
679 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
680 $add_throttle_desc->('mbps', 'float', 'r/w speed', 'mbps', 'megabytes');
681 $add_throttle_desc->('mbps_rd', 'float', 'read speed', 'mbps', 'megabytes');
682 $add_throttle_desc->('mbps_wr', 'float', 'write speed', 'mbps', 'megabytes');
683 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
684 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
685 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
687 # pools: (pool of IO before throttling starts taking effect)
688 $add_throttle_desc->('mbps_max', 'float', 'unthrottled r/w pool', 'mbps', 'megabytes');
689 $add_throttle_desc->('mbps_rd_max', 'float', 'unthrottled read pool', 'mbps', 'megabytes');
690 $add_throttle_desc->('mbps_wr_max', 'float', 'unthrottled write pool', 'mbps', 'megabytes');
691 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
692 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
693 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
703 type
=> 'string', format
=> $ide_fmt,
704 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
706 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
715 type
=> 'string', format
=> $scsi_fmt,
716 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
718 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
726 type
=> 'string', format
=> $sata_fmt,
727 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
729 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
738 type
=> 'string', format
=> $virtio_fmt,
739 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
741 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
754 type
=> 'string', format
=> 'pve-qm-usb-device',
755 format_description
=> 'HOSTUSBDEVICE|spice',
756 description
=> 'The Host USB device or port or the value spice',
761 format_description
=> 'yes|no',
762 description
=> 'Specifies whether if given host option is a USB3 device or port',
768 type
=> 'string', format
=> $usbformat,
769 description
=> <<EODESCR,
770 Configure an USB device (n is 0 to 4). This can be used to
771 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
773 'bus-port(.port)*' (decimal numbers) or
774 'vendor_id:product_id' (hexadeciaml numbers) or
777 You can use the 'lsusb -t' command to list existing usb devices.
779 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
781 The value 'spice' can be used to add a usb redirection devices for spice.
783 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).
787 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
791 type
=> 'string', format
=> 'pve-qm-hostpci',
792 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
793 description
=> <<EODESCR,
794 Map host pci devices. HOSTPCIDEVICE syntax is:
796 'bus:dev.func' (hexadecimal numbers)
798 You can us the 'lspci' command to list existing pci devices.
800 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
802 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
804 Experimental: user reported problems with this option.
807 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
812 pattern
=> '(/dev/.+|socket)',
813 description
=> <<EODESCR,
814 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).
816 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
818 Experimental: user reported problems with this option.
825 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
826 description
=> <<EODESCR,
827 Map host parallel devices (n is 0 to 2).
829 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
831 Experimental: user reported problems with this option.
835 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
836 $confdesc->{"parallel$i"} = $paralleldesc;
839 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
840 $confdesc->{"serial$i"} = $serialdesc;
843 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
844 $confdesc->{"hostpci$i"} = $hostpcidesc;
847 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
848 $drivename_hash->{"ide$i"} = 1;
849 $confdesc->{"ide$i"} = $idedesc;
852 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
853 $drivename_hash->{"sata$i"} = 1;
854 $confdesc->{"sata$i"} = $satadesc;
857 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
858 $drivename_hash->{"scsi$i"} = 1;
859 $confdesc->{"scsi$i"} = $scsidesc ;
862 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
863 $drivename_hash->{"virtio$i"} = 1;
864 $confdesc->{"virtio$i"} = $virtiodesc;
867 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
868 $confdesc->{"usb$i"} = $usbdesc;
873 type
=> 'string', format
=> 'pve-volume-id',
874 description
=> "Reference to unused volumes.",
877 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
878 $confdesc->{"unused$i"} = $unuseddesc;
881 my $kvm_api_version = 0;
885 return $kvm_api_version if $kvm_api_version;
887 my $fh = IO
::File-
>new("</dev/kvm") ||
890 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
891 $kvm_api_version = $v;
896 return $kvm_api_version;
899 my $kvm_user_version;
901 sub kvm_user_version
{
903 return $kvm_user_version if $kvm_user_version;
905 $kvm_user_version = 'unknown';
909 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
910 $kvm_user_version = $2;
914 eval { run_command
("kvm -version", outfunc
=> $code); };
917 return $kvm_user_version;
921 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
923 sub valid_drive_names
{
924 # order is important - used to autoselect boot disk
925 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
926 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
927 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
928 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
931 sub is_valid_drivename
{
934 return defined($drivename_hash->{$dev});
939 return defined($confdesc->{$key});
943 return $nic_model_list;
946 sub os_list_description
{
951 w2k
=> 'Windows 2000',
952 w2k3
=>, 'Windows 2003',
953 w2k8
=> 'Windows 2008',
954 wvista
=> 'Windows Vista',
956 win8
=> 'Windows 8/2012',
966 return $cdrom_path if $cdrom_path;
968 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
969 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
970 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
974 my ($storecfg, $vmid, $cdrom) = @_;
976 if ($cdrom eq 'cdrom') {
977 return get_cdrom_path
();
978 } elsif ($cdrom eq 'none') {
980 } elsif ($cdrom =~ m
|^/|) {
983 return PVE
::Storage
::path
($storecfg, $cdrom);
987 # try to convert old style file names to volume IDs
988 sub filename_to_volume_id
{
989 my ($vmid, $file, $media) = @_;
991 if (!($file eq 'none' || $file eq 'cdrom' ||
992 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
994 return undef if $file =~ m
|/|;
996 if ($media && $media eq 'cdrom') {
997 $file = "local:iso/$file";
999 $file = "local:$vmid/$file";
1006 sub verify_media_type
{
1007 my ($opt, $vtype, $media) = @_;
1012 if ($media eq 'disk') {
1014 } elsif ($media eq 'cdrom') {
1017 die "internal error";
1020 return if ($vtype eq $etype);
1022 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1025 sub cleanup_drive_path
{
1026 my ($opt, $storecfg, $drive) = @_;
1028 # try to convert filesystem paths to volume IDs
1030 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1031 ($drive->{file
} !~ m
|^/dev/.+|) &&
1032 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1033 ($drive->{file
} !~ m/^\d+$/)) {
1034 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1035 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1036 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1037 verify_media_type
($opt, $vtype, $drive->{media
});
1038 $drive->{file
} = $volid;
1041 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1044 sub parse_hotplug_features
{
1049 return $res if $data eq '0';
1051 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1053 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1054 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1057 warn "ignoring unknown hotplug feature '$feature'\n";
1063 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1064 sub pve_verify_hotplug_features
{
1065 my ($value, $noerr) = @_;
1067 return $value if parse_hotplug_features
($value);
1069 return undef if $noerr;
1071 die "unable to parse hotplug option\n";
1074 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1075 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1076 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1077 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1078 # [,iothread=on][,serial=serial][,model=model]
1081 my ($key, $data) = @_;
1083 my ($interface, $index);
1085 if ($key =~ m/^([^\d]+)(\d+)$/) {
1092 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1093 : $confdesc->{$key}->{format
};
1095 warn "invalid drive key: $key\n";
1098 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1099 return undef if !$res;
1100 $res->{interface
} = $interface;
1101 $res->{index} = $index;
1104 foreach my $opt (qw(bps bps_rd bps_wr)) {
1105 if (my $bps = defined(delete $res->{$opt})) {
1106 if (defined($res->{"m$opt"})) {
1107 warn "both $opt and m$opt specified\n";
1111 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1114 return undef if $error;
1116 return undef if $res->{mbps_rd
} && $res->{mbps
};
1117 return undef if $res->{mbps_wr
} && $res->{mbps
};
1118 return undef if $res->{iops_rd
} && $res->{iops
};
1119 return undef if $res->{iops_wr
} && $res->{iops
};
1121 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1122 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1123 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1124 return undef if $res->{interface
} eq 'virtio';
1127 if (my $size = $res->{size
}) {
1128 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1135 my ($vmid, $drive) = @_;
1136 my $data = { %$drive };
1137 delete $data->{$_} for qw(index interface);
1138 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1142 my($fh, $noerr) = @_;
1145 my $SG_GET_VERSION_NUM = 0x2282;
1147 my $versionbuf = "\x00" x
8;
1148 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1150 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1153 my $version = unpack("I", $versionbuf);
1154 if ($version < 30000) {
1155 die "scsi generic interface too old\n" if !$noerr;
1159 my $buf = "\x00" x
36;
1160 my $sensebuf = "\x00" x
8;
1161 my $cmd = pack("C x3 C x1", 0x12, 36);
1163 # see /usr/include/scsi/sg.h
1164 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";
1166 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1167 length($sensebuf), 0, length($buf), $buf,
1168 $cmd, $sensebuf, 6000);
1170 $ret = ioctl($fh, $SG_IO, $packet);
1172 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1176 my @res = unpack($sg_io_hdr_t, $packet);
1177 if ($res[17] || $res[18]) {
1178 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1183 (my $byte0, my $byte1, $res->{vendor
},
1184 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1186 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1187 $res->{type
} = $byte0 & 31;
1195 my $fh = IO
::File-
>new("+<$path") || return undef;
1196 my $res = scsi_inquiry
($fh, 1);
1202 sub machine_type_is_q35
{
1205 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1208 sub print_tabletdevice_full
{
1211 my $q35 = machine_type_is_q35
($conf);
1213 # we use uhci for old VMs because tablet driver was buggy in older qemu
1214 my $usbbus = $q35 ?
"ehci" : "uhci";
1216 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1219 sub print_drivedevice_full
{
1220 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1225 if ($drive->{interface
} eq 'virtio') {
1226 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1227 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1228 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1229 } elsif ($drive->{interface
} eq 'scsi') {
1231 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1232 my $unit = $drive->{index} % $maxdev;
1233 my $devicetype = 'hd';
1235 if (drive_is_cdrom
($drive)) {
1238 if ($drive->{file
} =~ m
|^/|) {
1239 $path = $drive->{file
};
1240 if (my $info = path_is_scsi
($path)) {
1241 if ($info->{type
} == 0) {
1242 $devicetype = 'block';
1243 } elsif ($info->{type
} == 1) { # tape
1244 $devicetype = 'generic';
1248 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1251 if($path =~ m/^iscsi\:\/\
//){
1252 $devicetype = 'generic';
1256 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1257 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1259 $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}";
1262 } elsif ($drive->{interface
} eq 'ide'){
1264 my $controller = int($drive->{index} / $maxdev);
1265 my $unit = $drive->{index} % $maxdev;
1266 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1268 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1269 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1270 $model = URI
::Escape
::uri_unescape
($model);
1271 $device .= ",model=$model";
1273 } elsif ($drive->{interface
} eq 'sata'){
1274 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1275 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1276 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1277 } elsif ($drive->{interface
} eq 'usb') {
1279 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1281 die "unsupported interface type";
1284 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1289 sub get_initiator_name
{
1292 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1293 while (defined(my $line = <$fh>)) {
1294 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1303 sub print_drive_full
{
1304 my ($storecfg, $vmid, $drive) = @_;
1307 my $volid = $drive->{file
};
1310 if (drive_is_cdrom
($drive)) {
1311 $path = get_iso_path
($storecfg, $vmid, $volid);
1313 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1315 $path = PVE
::Storage
::path
($storecfg, $volid);
1316 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1317 $format = qemu_img_format
($scfg, $volname);
1325 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);
1326 foreach my $o (@qemu_drive_options) {
1327 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1329 if (my $serial = $drive->{serial
}) {
1330 $serial = URI
::Escape
::uri_unescape
($serial);
1331 $opts .= ",serial=$serial";
1334 $opts .= ",format=$format" if $format && !$drive->{format
};
1336 foreach my $o (qw(bps bps_rd bps_wr)) {
1337 my $v = $drive->{"m$o"};
1338 $opts .= ",$o=" . int($v*1024*1024) if $v;
1341 my $cache_direct = 0;
1343 if (my $cache = $drive->{cache
}) {
1344 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1345 } elsif (!drive_is_cdrom
($drive)) {
1346 $opts .= ",cache=none";
1350 # aio native works only with O_DIRECT
1351 if (!$drive->{aio
}) {
1353 $opts .= ",aio=native";
1355 $opts .= ",aio=threads";
1359 if (!drive_is_cdrom
($drive)) {
1361 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1362 $detectzeroes = 'off';
1363 } elsif ($drive->{discard
}) {
1364 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1366 # This used to be our default with discard not being specified:
1367 $detectzeroes = 'on';
1369 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1372 my $pathinfo = $path ?
"file=$path," : '';
1374 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1377 sub print_netdevice_full
{
1378 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1380 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1382 my $device = $net->{model
};
1383 if ($net->{model
} eq 'virtio') {
1384 $device = 'virtio-net-pci';
1387 my $pciaddr = print_pci_addr
("$netid", $bridges);
1388 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1389 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1390 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1391 my $vectors = $net->{queues
} * 2 + 2;
1392 $tmpstr .= ",vectors=$vectors,mq=on";
1394 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1396 if ($use_old_bios_files) {
1398 if ($device eq 'virtio-net-pci') {
1399 $romfile = 'pxe-virtio.rom';
1400 } elsif ($device eq 'e1000') {
1401 $romfile = 'pxe-e1000.rom';
1402 } elsif ($device eq 'ne2k') {
1403 $romfile = 'pxe-ne2k_pci.rom';
1404 } elsif ($device eq 'pcnet') {
1405 $romfile = 'pxe-pcnet.rom';
1406 } elsif ($device eq 'rtl8139') {
1407 $romfile = 'pxe-rtl8139.rom';
1409 $tmpstr .= ",romfile=$romfile" if $romfile;
1415 sub print_netdev_full
{
1416 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1419 if ($netid =~ m/^net(\d+)$/) {
1423 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1425 my $ifname = "tap${vmid}i$i";
1427 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1428 die "interface name '$ifname' is too long (max 15 character)\n"
1429 if length($ifname) >= 16;
1431 my $vhostparam = '';
1432 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1434 my $vmname = $conf->{name
} || "vm$vmid";
1437 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1439 if ($net->{bridge
}) {
1440 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1442 $netdev = "type=user,id=$netid,hostname=$vmname";
1445 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1450 sub drive_is_cdrom
{
1453 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1462 foreach my $kvp (split(/,/, $data)) {
1464 if ($kvp =~ m/^memory=(\S+)$/) {
1465 $res->{memory
} = $1;
1466 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1467 $res->{policy
} = $1;
1468 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1469 $res->{cpus
}->{start
} = $1;
1470 $res->{cpus
}->{end
} = $3;
1471 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1472 $res->{hostnodes
}->{start
} = $1;
1473 $res->{hostnodes
}->{end
} = $3;
1485 return undef if !$value;
1488 my @list = split(/,/, $value);
1492 foreach my $kv (@list) {
1494 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1497 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1500 my $pcidevices = lspci
($2);
1501 $res->{pciid
} = $pcidevices->{$2};
1503 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1504 $res->{rombar
} = $1;
1505 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1506 $res->{'x-vga'} = $1;
1507 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1508 $res->{pcie
} = 1 if $1 == 1;
1510 warn "unknown hostpci setting '$kv'\n";
1514 return undef if !$found;
1519 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1525 foreach my $kvp (split(/,/, $data)) {
1527 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) {
1529 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1530 $res->{model
} = $model;
1531 $res->{macaddr
} = $mac;
1532 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1533 $res->{bridge
} = $1;
1534 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1535 $res->{queues
} = $1;
1536 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1538 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1540 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1541 $res->{trunks
} = $1;
1542 } elsif ($kvp =~ m/^firewall=([01])$/) {
1543 $res->{firewall
} = $1;
1544 } elsif ($kvp =~ m/^link_down=([01])$/) {
1545 $res->{link_down
} = $1;
1552 return undef if !$res->{model
};
1560 my $res = "$net->{model}";
1561 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1562 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1563 $res .= ",rate=$net->{rate}" if $net->{rate
};
1564 $res .= ",tag=$net->{tag}" if $net->{tag
};
1565 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1566 $res .= ",firewall=1" if $net->{firewall
};
1567 $res .= ",link_down=1" if $net->{link_down
};
1568 $res .= ",queues=$net->{queues}" if $net->{queues
};
1573 sub add_random_macs
{
1574 my ($settings) = @_;
1576 foreach my $opt (keys %$settings) {
1577 next if $opt !~ m/^net(\d+)$/;
1578 my $net = parse_net
($settings->{$opt});
1580 $settings->{$opt} = print_net
($net);
1584 sub vm_is_volid_owner
{
1585 my ($storecfg, $vmid, $volid) = @_;
1587 if ($volid !~ m
|^/|) {
1589 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1590 if ($owner && ($owner == $vmid)) {
1598 sub split_flagged_list
{
1599 my $text = shift || '';
1600 $text =~ s/[,;]/ /g;
1602 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1605 sub join_flagged_list
{
1606 my ($how, $lst) = @_;
1607 join $how, map { $lst->{$_} . $_ } keys %$lst;
1610 sub vmconfig_delete_pending_option
{
1611 my ($conf, $key, $force) = @_;
1613 delete $conf->{pending
}->{$key};
1614 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1615 $pending_delete_hash->{$key} = $force ?
'!' : '';
1616 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1619 sub vmconfig_undelete_pending_option
{
1620 my ($conf, $key) = @_;
1622 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1623 delete $pending_delete_hash->{$key};
1625 if (%$pending_delete_hash) {
1626 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1628 delete $conf->{pending
}->{delete};
1632 sub vmconfig_register_unused_drive
{
1633 my ($storecfg, $vmid, $conf, $drive) = @_;
1635 if (!drive_is_cdrom
($drive)) {
1636 my $volid = $drive->{file
};
1637 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1638 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1643 sub vmconfig_cleanup_pending
{
1646 # remove pending changes when nothing changed
1648 foreach my $opt (keys %{$conf->{pending
}}) {
1649 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1651 delete $conf->{pending
}->{$opt};
1655 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1656 my $pending_delete_hash = {};
1657 while (my ($opt, $force) = each %$current_delete_hash) {
1658 if (defined($conf->{$opt})) {
1659 $pending_delete_hash->{$opt} = $force;
1665 if (%$pending_delete_hash) {
1666 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1668 delete $conf->{pending
}->{delete};
1674 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1675 my $smbios1_desc = {
1678 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1679 format_description
=> 'UUID',
1685 format_description
=> 'str',
1691 format_description
=> 'str',
1697 format_description
=> 'name',
1703 format_description
=> 'name',
1709 format_description
=> 'str',
1715 format_description
=> 'str',
1723 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_desc, $data) };
1730 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_desc);
1733 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_desc);
1735 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1736 sub verify_bootdisk
{
1737 my ($value, $noerr) = @_;
1739 return $value if is_valid_drivename
($value);
1741 return undef if $noerr;
1743 die "invalid boot disk '$value'\n";
1746 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1748 my ($value, $noerr) = @_;
1750 return $value if parse_numa
($value);
1752 return undef if $noerr;
1754 die "unable to parse numa options\n";
1757 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1759 my ($value, $noerr) = @_;
1761 return $value if parse_net
($value);
1763 return undef if $noerr;
1765 die "unable to parse network options\n";
1768 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1769 sub verify_hostpci
{
1770 my ($value, $noerr) = @_;
1772 return $value if parse_hostpci
($value);
1774 return undef if $noerr;
1776 die "unable to parse pci id\n";
1779 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1780 sub verify_watchdog
{
1781 my ($value, $noerr) = @_;
1783 return $value if parse_watchdog
($value);
1785 return undef if $noerr;
1787 die "unable to parse watchdog options\n";
1790 sub parse_watchdog
{
1793 return undef if !$value;
1797 foreach my $p (split(/,/, $value)) {
1798 next if $p =~ m/^\s*$/;
1800 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1802 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1803 $res->{action
} = $2;
1812 sub parse_usb_device
{
1815 return undef if !$value;
1818 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1819 $res->{vendorid
} = $2;
1820 $res->{productid
} = $4;
1821 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1822 $res->{hostbus
} = $1;
1823 $res->{hostport
} = $2;
1824 } elsif ($value =~ m/^spice$/i) {
1833 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1834 sub verify_usb_device
{
1835 my ($value, $noerr) = @_;
1837 return $value if parse_usb_device
($value);
1839 return undef if $noerr;
1841 die "unable to parse usb device\n";
1844 # add JSON properties for create and set function
1845 sub json_config_properties
{
1848 foreach my $opt (keys %$confdesc) {
1849 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1850 $prop->{$opt} = $confdesc->{$opt};
1857 my ($key, $value) = @_;
1859 die "unknown setting '$key'\n" if !$confdesc->{$key};
1861 my $type = $confdesc->{$key}->{type
};
1863 if (!defined($value)) {
1864 die "got undefined value\n";
1867 if ($value =~ m/[\n\r]/) {
1868 die "property contains a line feed\n";
1871 if ($type eq 'boolean') {
1872 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1873 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1874 die "type check ('boolean') failed - got '$value'\n";
1875 } elsif ($type eq 'integer') {
1876 return int($1) if $value =~ m/^(\d+)$/;
1877 die "type check ('integer') failed - got '$value'\n";
1878 } elsif ($type eq 'number') {
1879 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1880 die "type check ('number') failed - got '$value'\n";
1881 } elsif ($type eq 'string') {
1882 if (my $fmt = $confdesc->{$key}->{format
}) {
1883 if ($fmt eq 'pve-qm-drive') {
1884 # special case - we need to pass $key to parse_drive()
1885 my $drive = parse_drive
($key, $value);
1886 return $value if $drive;
1887 die "unable to parse drive options\n";
1889 PVE
::JSONSchema
::check_format
($fmt, $value);
1892 $value =~ s/^\"(.*)\"$/$1/;
1895 die "internal error"
1899 sub check_iommu_support
{
1900 #fixme : need to check IOMMU support
1901 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1911 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1912 utime undef, undef, $conf;
1916 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1918 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1920 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1922 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1924 # only remove disks owned by this VM
1925 foreach_drive
($conf, sub {
1926 my ($ds, $drive) = @_;
1928 return if drive_is_cdrom
($drive);
1930 my $volid = $drive->{file
};
1932 return if !$volid || $volid =~ m
|^/|;
1934 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1935 return if !$path || !$owner || ($owner != $vmid);
1937 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1940 if ($keep_empty_config) {
1941 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1946 # also remove unused disk
1948 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1951 PVE
::Storage
::foreach_volid
($dl, sub {
1952 my ($volid, $sid, $volname, $d) = @_;
1953 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1962 sub parse_vm_config
{
1963 my ($filename, $raw) = @_;
1965 return undef if !defined($raw);
1968 digest
=> Digest
::SHA
::sha1_hex
($raw),
1973 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1974 || die "got strange filename '$filename'";
1982 my @lines = split(/\n/, $raw);
1983 foreach my $line (@lines) {
1984 next if $line =~ m/^\s*$/;
1986 if ($line =~ m/^\[PENDING\]\s*$/i) {
1987 $section = 'pending';
1988 if (defined($descr)) {
1990 $conf->{description
} = $descr;
1993 $conf = $res->{$section} = {};
1996 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1998 if (defined($descr)) {
2000 $conf->{description
} = $descr;
2003 $conf = $res->{snapshots
}->{$section} = {};
2007 if ($line =~ m/^\#(.*)\s*$/) {
2008 $descr = '' if !defined($descr);
2009 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2013 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2014 $descr = '' if !defined($descr);
2015 $descr .= PVE
::Tools
::decode_text
($2);
2016 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2017 $conf->{snapstate
} = $1;
2018 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2021 $conf->{$key} = $value;
2022 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2024 if ($section eq 'pending') {
2025 $conf->{delete} = $value; # we parse this later
2027 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2029 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2032 eval { $value = check_type
($key, $value); };
2034 warn "vm $vmid - unable to parse value of '$key' - $@";
2036 my $fmt = $confdesc->{$key}->{format
};
2037 if ($fmt && $fmt eq 'pve-qm-drive') {
2038 my $v = parse_drive
($key, $value);
2039 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2040 $v->{file
} = $volid;
2041 $value = print_drive
($vmid, $v);
2043 warn "vm $vmid - unable to parse value of '$key'\n";
2048 if ($key eq 'cdrom') {
2049 $conf->{ide2
} = $value;
2051 $conf->{$key} = $value;
2057 if (defined($descr)) {
2059 $conf->{description
} = $descr;
2061 delete $res->{snapstate
}; # just to be sure
2066 sub write_vm_config
{
2067 my ($filename, $conf) = @_;
2069 delete $conf->{snapstate
}; # just to be sure
2071 if ($conf->{cdrom
}) {
2072 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2073 $conf->{ide2
} = $conf->{cdrom
};
2074 delete $conf->{cdrom
};
2077 # we do not use 'smp' any longer
2078 if ($conf->{sockets
}) {
2079 delete $conf->{smp
};
2080 } elsif ($conf->{smp
}) {
2081 $conf->{sockets
} = $conf->{smp
};
2082 delete $conf->{cores
};
2083 delete $conf->{smp
};
2086 my $used_volids = {};
2088 my $cleanup_config = sub {
2089 my ($cref, $pending, $snapname) = @_;
2091 foreach my $key (keys %$cref) {
2092 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2093 $key eq 'snapstate' || $key eq 'pending';
2094 my $value = $cref->{$key};
2095 if ($key eq 'delete') {
2096 die "propertry 'delete' is only allowed in [PENDING]\n"
2098 # fixme: check syntax?
2101 eval { $value = check_type
($key, $value); };
2102 die "unable to parse value of '$key' - $@" if $@;
2104 $cref->{$key} = $value;
2106 if (!$snapname && is_valid_drivename
($key)) {
2107 my $drive = parse_drive
($key, $value);
2108 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2113 &$cleanup_config($conf);
2115 &$cleanup_config($conf->{pending
}, 1);
2117 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2118 die "internal error" if $snapname eq 'pending';
2119 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2122 # remove 'unusedX' settings if we re-add a volume
2123 foreach my $key (keys %$conf) {
2124 my $value = $conf->{$key};
2125 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2126 delete $conf->{$key};
2130 my $generate_raw_config = sub {
2131 my ($conf, $pending) = @_;
2135 # add description as comment to top of file
2136 if (defined(my $descr = $conf->{description
})) {
2138 foreach my $cl (split(/\n/, $descr)) {
2139 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2142 $raw .= "#\n" if $pending;
2146 foreach my $key (sort keys %$conf) {
2147 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2148 $raw .= "$key: $conf->{$key}\n";
2153 my $raw = &$generate_raw_config($conf);
2155 if (scalar(keys %{$conf->{pending
}})){
2156 $raw .= "\n[PENDING]\n";
2157 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2160 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2161 $raw .= "\n[$snapname]\n";
2162 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2172 # we use static defaults from our JSON schema configuration
2173 foreach my $key (keys %$confdesc) {
2174 if (defined(my $default = $confdesc->{$key}->{default})) {
2175 $res->{$key} = $default;
2179 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2180 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2186 my $vmlist = PVE
::Cluster
::get_vmlist
();
2188 return $res if !$vmlist || !$vmlist->{ids
};
2189 my $ids = $vmlist->{ids
};
2191 foreach my $vmid (keys %$ids) {
2192 my $d = $ids->{$vmid};
2193 next if !$d->{node
} || $d->{node
} ne $nodename;
2194 next if !$d->{type
} || $d->{type
} ne 'qemu';
2195 $res->{$vmid}->{exists} = 1;
2200 # test if VM uses local resources (to prevent migration)
2201 sub check_local_resources
{
2202 my ($conf, $noerr) = @_;
2206 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2207 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2209 foreach my $k (keys %$conf) {
2210 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2211 # sockets are safe: they will recreated be on the target side post-migrate
2212 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2213 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2216 die "VM uses local resources\n" if $loc_res && !$noerr;
2221 # check if used storages are available on all nodes (use by migrate)
2222 sub check_storage_availability
{
2223 my ($storecfg, $conf, $node) = @_;
2225 foreach_drive
($conf, sub {
2226 my ($ds, $drive) = @_;
2228 my $volid = $drive->{file
};
2231 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2234 # check if storage is available on both nodes
2235 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2236 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2240 # list nodes where all VM images are available (used by has_feature API)
2242 my ($conf, $storecfg) = @_;
2244 my $nodelist = PVE
::Cluster
::get_nodelist
();
2245 my $nodehash = { map { $_ => 1 } @$nodelist };
2246 my $nodename = PVE
::INotify
::nodename
();
2248 foreach_drive
($conf, sub {
2249 my ($ds, $drive) = @_;
2251 my $volid = $drive->{file
};
2254 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2256 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2257 if ($scfg->{disable
}) {
2259 } elsif (my $avail = $scfg->{nodes
}) {
2260 foreach my $node (keys %$nodehash) {
2261 delete $nodehash->{$node} if !$avail->{$node};
2263 } elsif (!$scfg->{shared
}) {
2264 foreach my $node (keys %$nodehash) {
2265 delete $nodehash->{$node} if $node ne $nodename
2275 my ($pidfile, $pid) = @_;
2277 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2281 return undef if !$line;
2282 my @param = split(/\0/, $line);
2284 my $cmd = $param[0];
2285 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2287 for (my $i = 0; $i < scalar (@param); $i++) {
2290 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2291 my $p = $param[$i+1];
2292 return 1 if $p && ($p eq $pidfile);
2301 my ($vmid, $nocheck, $node) = @_;
2303 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2305 die "unable to find configuration file for VM $vmid - no such machine\n"
2306 if !$nocheck && ! -f
$filename;
2308 my $pidfile = pidfile_name
($vmid);
2310 if (my $fd = IO
::File-
>new("<$pidfile")) {
2315 my $mtime = $st->mtime;
2316 if ($mtime > time()) {
2317 warn "file '$filename' modified in future\n";
2320 if ($line =~ m/^(\d+)$/) {
2322 if (check_cmdline
($pidfile, $pid)) {
2323 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2335 my $vzlist = config_list
();
2337 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2339 while (defined(my $de = $fd->read)) {
2340 next if $de !~ m/^(\d+)\.pid$/;
2342 next if !defined($vzlist->{$vmid});
2343 if (my $pid = check_running
($vmid)) {
2344 $vzlist->{$vmid}->{pid
} = $pid;
2352 my ($storecfg, $conf) = @_;
2354 my $bootdisk = $conf->{bootdisk
};
2355 return undef if !$bootdisk;
2356 return undef if !is_valid_drivename
($bootdisk);
2358 return undef if !$conf->{$bootdisk};
2360 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2361 return undef if !defined($drive);
2363 return undef if drive_is_cdrom
($drive);
2365 my $volid = $drive->{file
};
2366 return undef if !$volid;
2368 return $drive->{size
};
2371 my $last_proc_pid_stat;
2373 # get VM status information
2374 # This must be fast and should not block ($full == false)
2375 # We only query KVM using QMP if $full == true (this can be slow)
2377 my ($opt_vmid, $full) = @_;
2381 my $storecfg = PVE
::Storage
::config
();
2383 my $list = vzlist
();
2384 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2386 my $cpucount = $cpuinfo->{cpus
} || 1;
2388 foreach my $vmid (keys %$list) {
2389 next if $opt_vmid && ($vmid ne $opt_vmid);
2391 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2392 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2395 $d->{pid
} = $list->{$vmid}->{pid
};
2397 # fixme: better status?
2398 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2400 my $size = disksize
($storecfg, $conf);
2401 if (defined($size)) {
2402 $d->{disk
} = 0; # no info available
2403 $d->{maxdisk
} = $size;
2409 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2410 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2411 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2413 $d->{name
} = $conf->{name
} || "VM $vmid";
2414 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2416 if ($conf->{balloon
}) {
2417 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2418 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2429 $d->{diskwrite
} = 0;
2431 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2436 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2437 foreach my $dev (keys %$netdev) {
2438 next if $dev !~ m/^tap([1-9]\d*)i/;
2440 my $d = $res->{$vmid};
2443 $d->{netout
} += $netdev->{$dev}->{receive
};
2444 $d->{netin
} += $netdev->{$dev}->{transmit
};
2447 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2448 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2453 my $ctime = gettimeofday
;
2455 foreach my $vmid (keys %$list) {
2457 my $d = $res->{$vmid};
2458 my $pid = $d->{pid
};
2461 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2462 next if !$pstat; # not running
2464 my $used = $pstat->{utime} + $pstat->{stime
};
2466 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2468 if ($pstat->{vsize
}) {
2469 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2472 my $old = $last_proc_pid_stat->{$pid};
2474 $last_proc_pid_stat->{$pid} = {
2482 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2484 if ($dtime > 1000) {
2485 my $dutime = $used - $old->{used
};
2487 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2488 $last_proc_pid_stat->{$pid} = {
2494 $d->{cpu
} = $old->{cpu
};
2498 return $res if !$full;
2500 my $qmpclient = PVE
::QMPClient-
>new();
2502 my $ballooncb = sub {
2503 my ($vmid, $resp) = @_;
2505 my $info = $resp->{'return'};
2506 return if !$info->{max_mem
};
2508 my $d = $res->{$vmid};
2510 # use memory assigned to VM
2511 $d->{maxmem
} = $info->{max_mem
};
2512 $d->{balloon
} = $info->{actual
};
2514 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2515 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2516 $d->{freemem
} = $info->{free_mem
};
2519 $d->{ballooninfo
} = $info;
2522 my $blockstatscb = sub {
2523 my ($vmid, $resp) = @_;
2524 my $data = $resp->{'return'} || [];
2525 my $totalrdbytes = 0;
2526 my $totalwrbytes = 0;
2528 for my $blockstat (@$data) {
2529 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2530 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2532 $blockstat->{device
} =~ s/drive-//;
2533 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2535 $res->{$vmid}->{diskread
} = $totalrdbytes;
2536 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2539 my $statuscb = sub {
2540 my ($vmid, $resp) = @_;
2542 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2543 # this fails if ballon driver is not loaded, so this must be
2544 # the last commnand (following command are aborted if this fails).
2545 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2547 my $status = 'unknown';
2548 if (!defined($status = $resp->{'return'}->{status
})) {
2549 warn "unable to get VM status\n";
2553 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2556 foreach my $vmid (keys %$list) {
2557 next if $opt_vmid && ($vmid ne $opt_vmid);
2558 next if !$res->{$vmid}->{pid
}; # not running
2559 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2562 $qmpclient->queue_execute(undef, 1);
2564 foreach my $vmid (keys %$list) {
2565 next if $opt_vmid && ($vmid ne $opt_vmid);
2566 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2573 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2576 my $current_size = 1024;
2577 my $dimm_size = 512;
2578 return if $current_size == $memory;
2580 for (my $j = 0; $j < 8; $j++) {
2581 for (my $i = 0; $i < 32; $i++) {
2582 my $name = "dimm${dimm_id}";
2584 my $numanode = $i % $sockets;
2585 $current_size += $dimm_size;
2586 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2587 return $current_size if $current_size >= $memory;
2593 sub foreach_reverse_dimm
{
2594 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2597 my $current_size = 4177920;
2598 my $dimm_size = 65536;
2599 return if $current_size == $memory;
2601 for (my $j = 0; $j < 8; $j++) {
2602 for (my $i = 0; $i < 32; $i++) {
2603 my $name = "dimm${dimm_id}";
2605 my $numanode = $i % $sockets;
2606 $current_size -= $dimm_size;
2607 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2608 return $current_size if $current_size <= $memory;
2615 my ($conf, $func) = @_;
2617 foreach my $ds (valid_drive_names
()) {
2618 next if !defined($conf->{$ds});
2620 my $drive = parse_drive
($ds, $conf->{$ds});
2623 &$func($ds, $drive);
2628 my ($conf, $func) = @_;
2632 my $test_volid = sub {
2633 my ($volid, $is_cdrom) = @_;
2637 $volhash->{$volid} = $is_cdrom || 0;
2640 foreach_drive
($conf, sub {
2641 my ($ds, $drive) = @_;
2642 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2645 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2646 my $snap = $conf->{snapshots
}->{$snapname};
2647 &$test_volid($snap->{vmstate
}, 0);
2648 foreach_drive
($snap, sub {
2649 my ($ds, $drive) = @_;
2650 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2654 foreach my $volid (keys %$volhash) {
2655 &$func($volid, $volhash->{$volid});
2659 sub vga_conf_has_spice
{
2662 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2667 sub config_to_command
{
2668 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2671 my $globalFlags = [];
2672 my $machineFlags = [];
2678 my $kvmver = kvm_user_version
();
2679 my $vernum = 0; # unknown
2680 my $ostype = $conf->{ostype
};
2681 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2682 $vernum = $1*1000000+$2*1000;
2683 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2684 $vernum = $1*1000000+$2*1000+$3;
2687 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2689 my $have_ovz = -f
'/proc/vz/vestat';
2691 my $q35 = machine_type_is_q35
($conf);
2692 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2693 my $machine_type = $forcemachine || $conf->{machine
};
2694 my $use_old_bios_files = undef;
2695 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2697 my $cpuunits = defined($conf->{cpuunits
}) ?
2698 $conf->{cpuunits
} : $defaults->{cpuunits
};
2700 push @$cmd, '/usr/bin/systemd-run';
2701 push @$cmd, '--scope';
2702 push @$cmd, '--slice', "qemu";
2703 push @$cmd, '--unit', $vmid;
2704 # set KillMode=none, so that systemd don't kill those scopes
2705 # at shutdown (pve-manager service should stop the VMs instead)
2706 push @$cmd, '-p', "KillMode=none";
2707 push @$cmd, '-p', "CPUShares=$cpuunits";
2708 if ($conf->{cpulimit
}) {
2709 my $cpulimit = int($conf->{cpulimit
} * 100);
2710 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2713 push @$cmd, '/usr/bin/kvm';
2715 push @$cmd, '-id', $vmid;
2719 my $qmpsocket = qmp_socket
($vmid);
2720 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2721 push @$cmd, '-mon', "chardev=qmp,mode=control";
2724 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2726 push @$cmd, '-daemonize';
2728 if ($conf->{smbios1
}) {
2729 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2732 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2733 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2734 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2735 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2736 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2737 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2738 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2742 # the q35 chipset support native usb2, so we enable usb controller
2743 # by default for this machine type
2744 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2746 $pciaddr = print_pci_addr
("piix3", $bridges);
2747 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2750 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2751 next if !$conf->{"usb$i"};
2752 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2753 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2756 # include usb device config
2757 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2760 # add usb3 controller if needed
2763 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2764 next if !$conf->{"usb$i"};
2765 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2766 next if !$d || !$d->{usb3
};
2770 $pciaddr = print_pci_addr
("xhci", $bridges);
2771 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2773 my $vga = $conf->{vga
};
2775 my $qxlnum = vga_conf_has_spice
($vga);
2776 $vga = 'qxl' if $qxlnum;
2779 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2780 $conf->{ostype
} eq 'win7' ||
2781 $conf->{ostype
} eq 'w2k8')) {
2788 # enable absolute mouse coordinates (needed by vnc)
2790 if (defined($conf->{tablet
})) {
2791 $tablet = $conf->{tablet
};
2793 $tablet = $defaults->{tablet
};
2794 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2795 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2798 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2802 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2803 my $d = parse_hostpci
($conf->{"hostpci$i"});
2806 my $pcie = $d->{pcie
};
2808 die "q35 machine model is not enabled" if !$q35;
2809 $pciaddr = print_pcie_addr
("hostpci$i");
2811 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2814 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2815 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2816 if ($xvga && $xvga ne '') {
2819 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2820 push @$cpuFlags , 'hv_vendor_id=proxmox';
2822 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2826 my $pcidevices = $d->{pciid
};
2827 my $multifunction = 1 if @$pcidevices > 1;
2830 foreach my $pcidevice (@$pcidevices) {
2832 my $id = "hostpci$i";
2833 $id .= ".$j" if $multifunction;
2834 my $addr = $pciaddr;
2835 $addr .= ".$j" if $multifunction;
2836 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2839 $devicestr .= "$rombar$xvga";
2840 $devicestr .= ",multifunction=on" if $multifunction;
2843 push @$devices, '-device', $devicestr;
2849 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2850 next if !$conf->{"usb$i"};
2851 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2854 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2856 if (defined($d->{usb3
}) && $d->{usb3
}) {
2857 $usbbus = ',bus=xhci.0';
2860 if (defined($d->{host
})) {
2861 $d = parse_usb_device
($d->{host
});
2862 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2863 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2864 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2865 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2866 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2867 # usb redir support for spice, currently no usb3
2868 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2869 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2875 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2876 if (my $path = $conf->{"serial$i"}) {
2877 if ($path eq 'socket') {
2878 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2879 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2880 push @$devices, '-device', "isa-serial,chardev=serial$i";
2882 die "no such serial device\n" if ! -c
$path;
2883 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2884 push @$devices, '-device', "isa-serial,chardev=serial$i";
2890 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2891 if (my $path = $conf->{"parallel$i"}) {
2892 die "no such parallel device\n" if ! -c
$path;
2893 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2894 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2895 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2899 my $vmname = $conf->{name
} || "vm$vmid";
2901 push @$cmd, '-name', $vmname;
2904 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2905 $sockets = $conf->{sockets
} if $conf->{sockets
};
2907 my $cores = $conf->{cores
} || 1;
2909 my $maxcpus = $sockets * $cores;
2911 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2913 my $allowed_vcpus = $cpuinfo->{cpus
};
2915 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2916 if ($allowed_vcpus < $maxcpus);
2918 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2920 push @$cmd, '-nodefaults';
2922 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2924 my $bootindex_hash = {};
2926 foreach my $o (split(//, $bootorder)) {
2927 $bootindex_hash->{$o} = $i*100;
2931 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2933 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2935 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2937 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2939 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2940 my $socket = vnc_socket
($vmid);
2941 push @$cmd, '-vnc', "unix:$socket,x509,password";
2943 push @$cmd, '-nographic';
2947 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2949 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2950 my $useLocaltime = $conf->{localtime};
2953 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2955 if ($ostype =~ m/^w/) { # windows
2956 $useLocaltime = 1 if !defined($conf->{localtime});
2958 # use time drift fix when acpi is enabled
2959 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2960 $tdf = 1 if !defined($conf->{tdf
});
2964 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2965 $ostype eq 'wvista') {
2966 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2967 push @$cmd, '-no-hpet';
2968 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2969 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2970 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2971 push @$cpuFlags , 'hv_time' if !$nokvm;
2974 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2978 if ($ostype eq 'win7' || $ostype eq 'win8') {
2979 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2983 push @$rtcFlags, 'driftfix=slew' if $tdf;
2986 push @$machineFlags, 'accel=tcg';
2988 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2991 if ($machine_type) {
2992 push @$machineFlags, "type=${machine_type}";
2995 if ($conf->{startdate
}) {
2996 push @$rtcFlags, "base=$conf->{startdate}";
2997 } elsif ($useLocaltime) {
2998 push @$rtcFlags, 'base=localtime';
3001 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3002 if (my $cputype = $conf->{cpu
}) {
3003 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpudesc, $cputype)
3004 or die "Cannot parse cpu description: $cputype\n";
3005 $cpu = $cpuconf->{cputype
};
3006 $kvm_off = 1 if $cpuconf->{hidden
};
3009 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3011 push @$cpuFlags , '-x2apic'
3012 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3014 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3016 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3018 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3020 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3021 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3024 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3026 push @$cpuFlags, 'kvm=off' if $kvm_off;
3028 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3030 push @$cmd, '-cpu', $cpu;
3032 my $memory = $conf->{memory
} || $defaults->{memory
};
3033 my $static_memory = 0;
3034 my $dimm_memory = 0;
3036 if ($hotplug_features->{memory
}) {
3037 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3038 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3039 $static_memory = $STATICMEM;
3040 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3041 $dimm_memory = $memory - $static_memory;
3042 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3046 $static_memory = $memory;
3047 push @$cmd, '-m', $static_memory;
3050 if ($conf->{numa
}) {
3052 my $numa_totalmemory = undef;
3053 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3054 next if !$conf->{"numa$i"};
3055 my $numa = parse_numa
($conf->{"numa$i"});
3058 die "missing numa node$i memory value\n" if !$numa->{memory
};
3059 my $numa_memory = $numa->{memory
};
3060 $numa_totalmemory += $numa_memory;
3061 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3064 my $cpus_start = $numa->{cpus
}->{start
};
3065 die "missing numa node$i cpus\n" if !defined($cpus_start);
3066 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3067 my $cpus = $cpus_start;
3068 if (defined($cpus_end)) {
3069 $cpus .= "-$cpus_end";
3070 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3074 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3075 if (defined($hostnodes_start)) {
3076 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3077 my $hostnodes = $hostnodes_start;
3078 if (defined($hostnodes_end)) {
3079 $hostnodes .= "-$hostnodes_end";
3080 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3083 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3084 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3085 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3089 my $policy = $numa->{policy
};
3090 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3091 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3094 push @$cmd, '-object', $numa_object;
3095 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3098 die "total memory for NUMA nodes must be equal to vm static memory\n"
3099 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3101 #if no custom tology, we split memory and cores across numa nodes
3102 if(!$numa_totalmemory) {
3104 my $numa_memory = ($static_memory / $sockets) . "M";
3106 for (my $i = 0; $i < $sockets; $i++) {
3108 my $cpustart = ($cores * $i);
3109 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3110 my $cpus = $cpustart;
3111 $cpus .= "-$cpuend" if $cpuend;
3113 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3114 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3119 if ($hotplug_features->{memory
}) {
3120 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3121 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3122 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3123 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3125 #if dimm_memory is not aligned to dimm map
3126 if($current_size > $memory) {
3127 $conf->{memory
} = $current_size;
3128 PVE
::QemuConfig-
>write_config($vmid, $conf);
3133 push @$cmd, '-S' if $conf->{freeze
};
3135 # set keyboard layout
3136 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3137 push @$cmd, '-k', $kb if $kb;
3140 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3141 #push @$cmd, '-soundhw', 'es1370';
3142 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3144 if($conf->{agent
}) {
3145 my $qgasocket = qmp_socket
($vmid, 1);
3146 my $pciaddr = print_pci_addr
("qga0", $bridges);
3147 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3148 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3149 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3156 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3157 for(my $i = 1; $i < $qxlnum; $i++){
3158 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3159 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3162 # assume other OS works like Linux
3163 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3164 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3168 my $pciaddr = print_pci_addr
("spice", $bridges);
3170 my $nodename = PVE
::INotify
::nodename
();
3171 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3172 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3174 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3176 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3177 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3178 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3181 # enable balloon by default, unless explicitly disabled
3182 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3183 $pciaddr = print_pci_addr
("balloon0", $bridges);
3184 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3187 if ($conf->{watchdog
}) {
3188 my $wdopts = parse_watchdog
($conf->{watchdog
});
3189 $pciaddr = print_pci_addr
("watchdog", $bridges);
3190 my $watchdog = $wdopts->{model
} || 'i6300esb';
3191 push @$devices, '-device', "$watchdog$pciaddr";
3192 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3196 my $scsicontroller = {};
3197 my $ahcicontroller = {};
3198 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3200 # Add iscsi initiator name if available
3201 if (my $initiator = get_initiator_name
()) {
3202 push @$devices, '-iscsi', "initiator-name=$initiator";
3205 foreach_drive
($conf, sub {
3206 my ($ds, $drive) = @_;
3208 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3209 push @$vollist, $drive->{file
};
3212 $use_virtio = 1 if $ds =~ m/^virtio/;
3214 if (drive_is_cdrom
($drive)) {
3215 if ($bootindex_hash->{d
}) {
3216 $drive->{bootindex
} = $bootindex_hash->{d
};
3217 $bootindex_hash->{d
} += 1;
3220 if ($bootindex_hash->{c
}) {
3221 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3222 $bootindex_hash->{c
} += 1;
3226 if($drive->{interface
} eq 'virtio'){
3227 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3230 if ($drive->{interface
} eq 'scsi') {
3232 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3234 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3235 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3238 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3239 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3240 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3244 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3245 $queues = ",num_queues=$drive->{queues}";
3248 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3249 $scsicontroller->{$controller}=1;
3252 if ($drive->{interface
} eq 'sata') {
3253 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3254 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3255 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3256 $ahcicontroller->{$controller}=1;
3259 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3260 push @$devices, '-drive',$drive_cmd;
3261 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3264 for (my $i = 0; $i < $MAX_NETS; $i++) {
3265 next if !$conf->{"net$i"};
3266 my $d = parse_net
($conf->{"net$i"});
3269 $use_virtio = 1 if $d->{model
} eq 'virtio';
3271 if ($bootindex_hash->{n
}) {
3272 $d->{bootindex
} = $bootindex_hash->{n
};
3273 $bootindex_hash->{n
} += 1;
3276 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3277 push @$devices, '-netdev', $netdevfull;
3279 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3280 push @$devices, '-device', $netdevicefull;
3285 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3290 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3292 while (my ($k, $v) = each %$bridges) {
3293 $pciaddr = print_pci_addr
("pci.$k");
3294 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3299 if ($conf->{args
}) {
3300 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3304 push @$cmd, @$devices;
3305 push @$cmd, '-rtc', join(',', @$rtcFlags)
3306 if scalar(@$rtcFlags);
3307 push @$cmd, '-machine', join(',', @$machineFlags)
3308 if scalar(@$machineFlags);
3309 push @$cmd, '-global', join(',', @$globalFlags)
3310 if scalar(@$globalFlags);
3312 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3317 return "${var_run_tmpdir}/$vmid.vnc";
3323 my $res = vm_mon_cmd
($vmid, 'query-spice');
3325 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3329 my ($vmid, $qga) = @_;
3330 my $sockettype = $qga ?
'qga' : 'qmp';
3331 return "${var_run_tmpdir}/$vmid.$sockettype";
3336 return "${var_run_tmpdir}/$vmid.pid";
3339 sub vm_devices_list
{
3342 my $res = vm_mon_cmd
($vmid, 'query-pci');
3344 foreach my $pcibus (@$res) {
3345 foreach my $device (@{$pcibus->{devices
}}) {
3346 next if !$device->{'qdev_id'};
3347 if ($device->{'pci_bridge'}) {
3348 $devices->{$device->{'qdev_id'}} = 1;
3349 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3350 next if !$bridge_device->{'qdev_id'};
3351 $devices->{$bridge_device->{'qdev_id'}} = 1;
3352 $devices->{$device->{'qdev_id'}}++;
3355 $devices->{$device->{'qdev_id'}} = 1;
3360 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3361 foreach my $block (@$resblock) {
3362 if($block->{device
} =~ m/^drive-(\S+)/){
3367 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3368 foreach my $mice (@$resmice) {
3369 if ($mice->{name
} eq 'QEMU HID Tablet') {
3370 $devices->{tablet
} = 1;
3379 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3381 my $q35 = machine_type_is_q35
($conf);
3383 my $devices_list = vm_devices_list
($vmid);
3384 return 1 if defined($devices_list->{$deviceid});
3386 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3388 if ($deviceid eq 'tablet') {
3390 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3392 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3394 qemu_iothread_add
($vmid, $deviceid, $device);
3396 qemu_driveadd
($storecfg, $vmid, $device);
3397 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3399 qemu_deviceadd
($vmid, $devicefull);
3400 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3402 eval { qemu_drivedel
($vmid, $deviceid); };
3407 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3410 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3411 my $pciaddr = print_pci_addr
($deviceid);
3412 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3414 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3416 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3417 qemu_iothread_add
($vmid, $deviceid, $device);
3418 $devicefull .= ",iothread=iothread-$deviceid";
3421 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3422 $devicefull .= ",num_queues=$device->{queues}";
3425 qemu_deviceadd
($vmid, $devicefull);
3426 qemu_deviceaddverify
($vmid, $deviceid);
3428 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3430 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3431 qemu_driveadd
($storecfg, $vmid, $device);
3433 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3434 eval { qemu_deviceadd
($vmid, $devicefull); };
3436 eval { qemu_drivedel
($vmid, $deviceid); };
3441 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3443 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3445 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3446 my $use_old_bios_files = undef;
3447 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3449 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3450 qemu_deviceadd
($vmid, $netdevicefull);
3451 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3453 eval { qemu_netdevdel
($vmid, $deviceid); };
3458 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3461 my $pciaddr = print_pci_addr
($deviceid);
3462 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3464 qemu_deviceadd
($vmid, $devicefull);
3465 qemu_deviceaddverify
($vmid, $deviceid);
3468 die "can't hotplug device '$deviceid'\n";
3474 # fixme: this should raise exceptions on error!
3475 sub vm_deviceunplug
{
3476 my ($vmid, $conf, $deviceid) = @_;
3478 my $devices_list = vm_devices_list
($vmid);
3479 return 1 if !defined($devices_list->{$deviceid});
3481 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3483 if ($deviceid eq 'tablet') {
3485 qemu_devicedel
($vmid, $deviceid);
3487 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3489 qemu_devicedel
($vmid, $deviceid);
3490 qemu_devicedelverify
($vmid, $deviceid);
3491 qemu_drivedel
($vmid, $deviceid);
3492 qemu_iothread_del
($conf, $vmid, $deviceid);
3494 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3496 qemu_devicedel
($vmid, $deviceid);
3497 qemu_devicedelverify
($vmid, $deviceid);
3498 qemu_iothread_del
($conf, $vmid, $deviceid);
3500 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3502 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3503 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3504 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3506 qemu_devicedel
($vmid, $deviceid);
3507 qemu_drivedel
($vmid, $deviceid);
3508 qemu_deletescsihw
($conf, $vmid, $deviceid);
3510 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3512 qemu_devicedel
($vmid, $deviceid);
3513 qemu_devicedelverify
($vmid, $deviceid);
3514 qemu_netdevdel
($vmid, $deviceid);
3517 die "can't unplug device '$deviceid'\n";
3523 sub qemu_deviceadd
{
3524 my ($vmid, $devicefull) = @_;
3526 $devicefull = "driver=".$devicefull;
3527 my %options = split(/[=,]/, $devicefull);
3529 vm_mon_cmd
($vmid, "device_add" , %options);
3532 sub qemu_devicedel
{
3533 my ($vmid, $deviceid) = @_;
3535 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3538 sub qemu_iothread_add
{
3539 my($vmid, $deviceid, $device) = @_;
3541 if ($device->{iothread
}) {
3542 my $iothreads = vm_iothreads_list
($vmid);
3543 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3547 sub qemu_iothread_del
{
3548 my($conf, $vmid, $deviceid) = @_;
3550 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3551 if ($device->{iothread
}) {
3552 my $iothreads = vm_iothreads_list
($vmid);
3553 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3557 sub qemu_objectadd
{
3558 my($vmid, $objectid, $qomtype) = @_;
3560 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3565 sub qemu_objectdel
{
3566 my($vmid, $objectid) = @_;
3568 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3574 my ($storecfg, $vmid, $device) = @_;
3576 my $drive = print_drive_full
($storecfg, $vmid, $device);
3577 $drive =~ s/\\/\\\\/g;
3578 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3580 # If the command succeeds qemu prints: "OK
"
3581 return 1 if $ret =~ m/OK/s;
3583 die "adding drive failed
: $ret\n";
3587 my($vmid, $deviceid) = @_;
3589 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3592 return 1 if $ret eq "";
3594 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3595 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3597 die "deleting drive
$deviceid failed
: $ret\n";
3600 sub qemu_deviceaddverify {
3601 my ($vmid, $deviceid) = @_;
3603 for (my $i = 0; $i <= 5; $i++) {
3604 my $devices_list = vm_devices_list($vmid);
3605 return 1 if defined($devices_list->{$deviceid});
3609 die "error on hotplug device
'$deviceid'\n";
3613 sub qemu_devicedelverify {
3614 my ($vmid, $deviceid) = @_;
3616 # need to verify that the device is correctly removed as device_del
3617 # is async and empty return is not reliable
3619 for (my $i = 0; $i <= 5; $i++) {
3620 my $devices_list = vm_devices_list($vmid);
3621 return 1 if !defined($devices_list->{$deviceid});
3625 die "error on hot-unplugging device
'$deviceid'\n";
3628 sub qemu_findorcreatescsihw {
3629 my ($storecfg, $conf, $vmid, $device) = @_;
3631 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3633 my $scsihwid="$controller_prefix$controller";
3634 my $devices_list = vm_devices_list($vmid);
3636 if(!defined($devices_list->{$scsihwid})) {
3637 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3643 sub qemu_deletescsihw {
3644 my ($conf, $vmid, $opt) = @_;
3646 my $device = parse_drive($opt, $conf->{$opt});
3648 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3649 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3653 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3655 my $devices_list = vm_devices_list($vmid);
3656 foreach my $opt (keys %{$devices_list}) {
3657 if (PVE::QemuServer::is_valid_drivename($opt)) {
3658 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3659 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3665 my $scsihwid="scsihw
$controller";
3667 vm_deviceunplug($vmid, $conf, $scsihwid);
3672 sub qemu_add_pci_bridge {
3673 my ($storecfg, $conf, $vmid, $device) = @_;
3679 print_pci_addr($device, $bridges);
3681 while (my ($k, $v) = each %$bridges) {
3684 return 1 if !defined($bridgeid) || $bridgeid < 1;
3686 my $bridge = "pci
.$bridgeid";
3687 my $devices_list = vm_devices_list($vmid);
3689 if (!defined($devices_list->{$bridge})) {
3690 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3696 sub qemu_set_link_status {
3697 my ($vmid, $device, $up) = @_;
3699 vm_mon_cmd($vmid, "set_link
", name => $device,
3700 up => $up ? JSON::true : JSON::false);
3703 sub qemu_netdevadd {
3704 my ($vmid, $conf, $device, $deviceid) = @_;
3706 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3707 my %options = split(/[=,]/, $netdev);
3709 vm_mon_cmd($vmid, "netdev_add
", %options);
3713 sub qemu_netdevdel {
3714 my ($vmid, $deviceid) = @_;
3716 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3719 sub qemu_cpu_hotplug {
3720 my ($vmid, $conf, $vcpus) = @_;
3723 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3724 $sockets = $conf->{sockets} if $conf->{sockets};
3725 my $cores = $conf->{cores} || 1;
3726 my $maxcpus = $sockets * $cores;
3728 $vcpus = $maxcpus if !$vcpus;
3730 die "you can
't add more vcpus than maxcpus\n"
3731 if $vcpus > $maxcpus;
3733 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3734 die "online cpu unplug is not yet possible\n"
3735 if $vcpus < $currentvcpus;
3737 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3738 die "vcpus in running vm is different than configuration\n"
3739 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3741 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3742 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3746 sub qemu_memory_hotplug {
3747 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3749 return $value if !check_running($vmid);
3751 my $memory = $conf->{memory} || $defaults->{memory};
3752 $value = $defaults->{memory} if !$value;
3753 return $value if $value == $memory;
3755 my $static_memory = $STATICMEM;
3756 my $dimm_memory = $memory - $static_memory;
3758 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3759 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3763 $sockets = $conf->{sockets} if $conf->{sockets};
3765 if($value > $memory) {
3767 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3768 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3770 return if $current_size <= $conf->{memory};
3772 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3774 eval { qemu_objectdel($vmid, "mem-
$name"); };
3778 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3780 eval { qemu_objectdel($vmid, "mem-
$name"); };
3783 #update conf after each succesful module hotplug
3784 $conf->{memory} = $current_size;
3785 PVE::QemuConfig->write_config($vmid, $conf);
3790 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3791 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3793 return if $current_size >= $conf->{memory};
3794 print "try to unplug memory dimm
$name\n";
3798 eval { qemu_devicedel($vmid, $name) };
3800 my $dimm_list = qemu_dimm_list($vmid);
3801 last if !$dimm_list->{$name};
3802 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3806 #update conf after each succesful module unplug
3807 $conf->{memory} = $current_size;
3809 eval { qemu_objectdel($vmid, "mem-
$name"); };
3810 PVE::QemuConfig->write_config($vmid, $conf);
3815 sub qemu_dimm_list {
3818 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3821 foreach my $dimm (@$dimmarray) {
3823 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3824 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3825 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3826 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3827 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3832 sub qemu_block_set_io_throttle {
3833 my ($vmid, $deviceid,
3834 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3835 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3837 return if !check_running($vmid) ;
3839 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3841 bps_rd => int($bps_rd),
3842 bps_wr => int($bps_wr),
3844 iops_rd => int($iops_rd),
3845 iops_wr => int($iops_wr),
3846 bps_max => int($bps_max),
3847 bps_rd_max => int($bps_rd_max),
3848 bps_wr_max => int($bps_wr_max),
3849 iops_max => int($iops_max),
3850 iops_rd_max => int($iops_rd_max),
3851 iops_wr_max => int($iops_wr_max)
3856 # old code, only used to shutdown old VM after update
3858 my ($fh, $timeout) = @_;
3860 my $sel = new IO::Select;
3867 while (scalar (@ready = $sel->can_read($timeout))) {
3869 if ($count = $fh->sysread($buf, 8192)) {
3870 if ($buf =~ /^(.*)\(qemu\) $/s) {
3877 if (!defined($count)) {
3884 die "monitor
read timeout
\n" if !scalar(@ready);
3889 # old code, only used to shutdown old VM after update
3890 sub vm_monitor_command {
3891 my ($vmid, $cmdstr, $nocheck) = @_;
3896 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3898 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3900 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3901 die "unable to
connect to VM
$vmid socket - $!\n";
3905 # hack: migrate sometime blocks the monitor (when migrate_downtime
3907 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3908 $timeout = 60*60; # 1 hour
3912 my $data = __read_avail($sock, $timeout);
3914 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3915 die "got unexpected qemu monitor banner
\n";
3918 my $sel = new IO::Select;
3921 if (!scalar(my @ready = $sel->can_write($timeout))) {
3922 die "monitor
write error
- timeout
";
3925 my $fullcmd = "$cmdstr\r";
3927 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3930 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3931 die "monitor
write error
- $!";
3934 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3938 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3939 $timeout = 60*60; # 1 hour
3940 } elsif ($cmdstr =~ m/^(eject|change)/) {
3941 $timeout = 60; # note: cdrom mount command is slow
3943 if ($res = __read_avail($sock, $timeout)) {
3945 my @lines = split("\r?
\n", $res);
3947 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3949 $res = join("\n", @lines);
3957 syslog("err
", "VM
$vmid monitor command failed
- $err");
3964 sub qemu_block_resize {
3965 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3967 my $running = check_running($vmid);
3969 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3971 return if !$running;
3973 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3977 sub qemu_volume_snapshot {
3978 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3980 my $running = check_running($vmid);
3982 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3983 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3985 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3989 sub qemu_volume_snapshot_delete {
3990 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3992 my $running = check_running($vmid);
3994 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3996 return if !$running;
3998 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4001 sub set_migration_caps {
4007 "auto-converge
" => 1,
4009 "x-rdma-pin-all
" => 0,
4014 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4016 for my $supported_capability (@$supported_capabilities) {
4018 capability => $supported_capability->{capability},
4019 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4023 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4026 my $fast_plug_option = {
4035 # hotplug changes in [PENDING]
4036 # $selection hash can be used to only apply specified options, for
4037 # example: { cores => 1 } (only apply changed 'cores')
4038 # $errors ref is used to return error messages
4039 sub vmconfig_hotplug_pending {
4040 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4042 my $defaults = load_defaults();
4044 # commit values which do not have any impact on running VM first
4045 # Note: those option cannot raise errors, we we do not care about
4046 # $selection and always apply them.
4048 my $add_error = sub {
4049 my ($opt, $msg) = @_;
4050 $errors->{$opt} = "hotplug problem
- $msg";
4054 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4055 if ($fast_plug_option->{$opt}) {
4056 $conf->{$opt} = $conf->{pending}->{$opt};
4057 delete $conf->{pending}->{$opt};
4063 PVE::QemuConfig->write_config($vmid, $conf);
4064 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4067 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4069 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4070 while (my ($opt, $force) = each %$pending_delete_hash) {
4071 next if $selection && !$selection->{$opt};
4073 if ($opt eq 'hotplug') {
4074 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4075 } elsif ($opt eq 'tablet') {
4076 die "skip
\n" if !$hotplug_features->{usb};
4077 if ($defaults->{tablet}) {
4078 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4080 vm_deviceunplug($vmid, $conf, $opt);
4082 } elsif ($opt eq 'vcpus') {
4083 die "skip
\n" if !$hotplug_features->{cpu};
4084 qemu_cpu_hotplug($vmid, $conf, undef);
4085 } elsif ($opt eq 'balloon') {
4086 # enable balloon device is not hotpluggable
4087 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4088 } elsif ($fast_plug_option->{$opt}) {
4090 } elsif ($opt =~ m/^net(\d+)$/) {
4091 die "skip
\n" if !$hotplug_features->{network};
4092 vm_deviceunplug($vmid, $conf, $opt);
4093 } elsif (is_valid_drivename($opt)) {
4094 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4095 vm_deviceunplug($vmid, $conf, $opt);
4096 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4097 } elsif ($opt =~ m/^memory$/) {
4098 die "skip
\n" if !$hotplug_features->{memory};
4099 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4100 } elsif ($opt eq 'cpuunits') {
4101 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4102 } elsif ($opt eq 'cpulimit') {
4103 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4109 &$add_error($opt, $err) if $err ne "skip
\n";
4111 # save new config if hotplug was successful
4112 delete $conf->{$opt};
4113 vmconfig_undelete_pending_option($conf, $opt);
4114 PVE::QemuConfig->write_config($vmid, $conf);
4115 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4119 foreach my $opt (keys %{$conf->{pending}}) {
4120 next if $selection && !$selection->{$opt};
4121 my $value = $conf->{pending}->{$opt};
4123 if ($opt eq 'hotplug') {
4124 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4125 } elsif ($opt eq 'tablet') {
4126 die "skip
\n" if !$hotplug_features->{usb};
4128 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4129 } elsif ($value == 0) {
4130 vm_deviceunplug($vmid, $conf, $opt);
4132 } elsif ($opt eq 'vcpus') {
4133 die "skip
\n" if !$hotplug_features->{cpu};
4134 qemu_cpu_hotplug($vmid, $conf, $value);
4135 } elsif ($opt eq 'balloon') {
4136 # enable/disable balloning device is not hotpluggable
4137 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4138 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4139 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4141 # allow manual ballooning if shares is set to zero
4142 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4143 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4144 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4146 } elsif ($opt =~ m/^net(\d+)$/) {
4147 # some changes can be done without hotplug
4148 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4149 $vmid, $opt, $value);
4150 } elsif (is_valid_drivename($opt)) {
4151 # some changes can be done without hotplug
4152 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4153 $vmid, $opt, $value, 1);
4154 } elsif ($opt =~ m/^memory$/) { #dimms
4155 die "skip
\n" if !$hotplug_features->{memory};
4156 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4157 } elsif ($opt eq 'cpuunits') {
4158 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4159 } elsif ($opt eq 'cpulimit') {
4160 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4161 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4163 die "skip
\n"; # skip non-hot-pluggable options
4167 &$add_error($opt, $err) if $err ne "skip
\n";
4169 # save new config if hotplug was successful
4170 $conf->{$opt} = $value;
4171 delete $conf->{pending}->{$opt};
4172 PVE::QemuConfig->write_config($vmid, $conf);
4173 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4178 sub try_deallocate_drive {
4179 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4181 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4182 my $volid = $drive->{file};
4183 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4184 my $sid = PVE::Storage::parse_volume_id($volid);
4185 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4187 # check if the disk is really unused
4188 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4189 if is_volume_in_use($storecfg, $conf, $key, $volid);
4190 PVE::Storage::vdisk_free($storecfg, $volid);
4193 # If vm is not owner of this disk remove from config
4201 sub vmconfig_delete_or_detach_drive {
4202 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4204 my $drive = parse_drive($opt, $conf->{$opt});
4206 my $rpcenv = PVE::RPCEnvironment::get();
4207 my $authuser = $rpcenv->get_user();
4210 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4211 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4213 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4217 sub vmconfig_apply_pending {
4218 my ($vmid, $conf, $storecfg) = @_;
4222 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4223 while (my ($opt, $force) = each %$pending_delete_hash) {
4224 die "internal error
" if $opt =~ m/^unused/;
4225 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4226 if (!defined($conf->{$opt})) {
4227 vmconfig_undelete_pending_option($conf, $opt);
4228 PVE::QemuConfig->write_config($vmid, $conf);
4229 } elsif (is_valid_drivename($opt)) {
4230 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4231 vmconfig_undelete_pending_option($conf, $opt);
4232 delete $conf->{$opt};
4233 PVE::QemuConfig->write_config($vmid, $conf);
4235 vmconfig_undelete_pending_option($conf, $opt);
4236 delete $conf->{$opt};
4237 PVE::QemuConfig->write_config($vmid, $conf);
4241 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4243 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4244 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4246 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4247 # skip if nothing changed
4248 } elsif (is_valid_drivename($opt)) {
4249 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4250 if defined($conf->{$opt});
4251 $conf->{$opt} = $conf->{pending}->{$opt};
4253 $conf->{$opt} = $conf->{pending}->{$opt};
4256 delete $conf->{pending}->{$opt};
4257 PVE::QemuConfig->write_config($vmid, $conf);
4261 my $safe_num_ne = sub {
4264 return 0 if !defined($a) && !defined($b);
4265 return 1 if !defined($a);
4266 return 1 if !defined($b);
4271 my $safe_string_ne = sub {
4274 return 0 if !defined($a) && !defined($b);
4275 return 1 if !defined($a);
4276 return 1 if !defined($b);
4281 sub vmconfig_update_net {
4282 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4284 my $newnet = parse_net($value);
4286 if ($conf->{$opt}) {
4287 my $oldnet = parse_net($conf->{$opt});
4289 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4290 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4291 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4292 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4294 # for non online change, we try to hot-unplug
4295 die "skip
\n" if !$hotplug;
4296 vm_deviceunplug($vmid, $conf, $opt);
4299 die "internal error
" if $opt !~ m/net(\d+)/;
4300 my $iface = "tap
${vmid
}i
$1";
4302 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4303 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4304 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4305 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4306 PVE::Network::tap_unplug($iface);
4307 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4308 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4309 # Rate can be applied on its own but any change above needs to
4310 # include the rate in tap_plug since OVS resets everything.
4311 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4314 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4315 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4323 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4329 sub vmconfig_update_disk {
4330 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4332 # fixme: do we need force?
4334 my $drive = parse_drive($opt, $value);
4336 if ($conf->{$opt}) {
4338 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4340 my $media = $drive->{media} || 'disk';
4341 my $oldmedia = $old_drive->{media} || 'disk';
4342 die "unable to change media type
\n" if $media ne $oldmedia;
4344 if (!drive_is_cdrom($old_drive)) {
4346 if ($drive->{file} ne $old_drive->{file}) {
4348 die "skip
\n" if !$hotplug;
4350 # unplug and register as unused
4351 vm_deviceunplug($vmid, $conf, $opt);
4352 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4355 # update existing disk
4357 # skip non hotpluggable value
4358 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4359 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4360 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4361 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4366 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4367 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4368 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4369 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4370 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4371 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4372 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4373 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4374 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4375 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4376 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4377 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4379 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4380 ($drive->{mbps} || 0)*1024*1024,
4381 ($drive->{mbps_rd} || 0)*1024*1024,
4382 ($drive->{mbps_wr} || 0)*1024*1024,
4383 $drive->{iops} || 0,
4384 $drive->{iops_rd} || 0,
4385 $drive->{iops_wr} || 0,
4386 ($drive->{mbps_max} || 0)*1024*1024,
4387 ($drive->{mbps_rd_max} || 0)*1024*1024,
4388 ($drive->{mbps_wr_max} || 0)*1024*1024,
4389 $drive->{iops_max} || 0,
4390 $drive->{iops_rd_max} || 0,
4391 $drive->{iops_wr_max} || 0);
4400 if ($drive->{file} eq 'none') {
4401 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4403 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4404 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4405 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4413 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4415 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4416 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4420 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4421 $forcemachine, $spice_ticket) = @_;
4423 PVE::QemuConfig->lock_config($vmid, sub {
4424 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4426 die "you can
't start a vm if it's a template
\n" if PVE::QemuConfig->is_template($conf);
4428 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4430 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4432 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4433 vmconfig_apply_pending($vmid, $conf, $storecfg);
4434 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4437 my $defaults = load_defaults();
4439 # set environment variable useful inside network script
4440 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4442 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4444 my $migrate_port = 0;
4447 if ($statefile eq 'tcp') {
4448 my $localip = "localhost
";
4449 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4450 my $nodename = PVE::INotify::nodename();
4451 if ($datacenterconf->{migration_unsecure}) {
4452 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4453 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4455 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4456 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4457 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4458 push @$cmd, '-incoming', $migrate_uri;
4461 push @$cmd, '-loadstate', $statefile;
4468 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4469 my $d = parse_hostpci($conf->{"hostpci
$i"});
4471 my $pcidevices = $d->{pciid};
4472 foreach my $pcidevice (@$pcidevices) {
4473 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4475 my $info = pci_device_info("0000:$pciid");
4476 die "IOMMU
not present
\n" if !check_iommu_support();
4477 die "no pci device info
for device
'$pciid'\n" if !$info;
4478 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4479 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4483 PVE::Storage::activate_volumes($storecfg, $vollist);
4485 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4489 # deactivate volumes if start fails
4490 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4491 die "start failed
: $err";
4494 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4496 if ($statefile && $statefile ne 'tcp') {
4497 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4501 if ($migratedfrom) {
4504 set_migration_caps($vmid);
4509 print "spice listens on port
$spice_port\n";
4510 if ($spice_ticket) {
4511 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4512 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4518 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4519 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4520 if $conf->{balloon};
4523 foreach my $opt (keys %$conf) {
4524 next if $opt !~ m/^net\d+$/;
4525 my $nicconf = parse_net($conf->{$opt});
4526 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4530 vm_mon_cmd_nocheck($vmid, 'qom-set',
4531 path => "machine
/peripheral/balloon0
",
4532 property => "guest-stats-polling-interval
",
4533 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4539 my ($vmid, $execute, %params) = @_;
4541 my $cmd = { execute => $execute, arguments => \%params };
4542 vm_qmp_command($vmid, $cmd);
4545 sub vm_mon_cmd_nocheck {
4546 my ($vmid, $execute, %params) = @_;
4548 my $cmd = { execute => $execute, arguments => \%params };
4549 vm_qmp_command($vmid, $cmd, 1);
4552 sub vm_qmp_command {
4553 my ($vmid, $cmd, $nocheck) = @_;
4558 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4559 $timeout = $cmd->{arguments}->{timeout};
4560 delete $cmd->{arguments}->{timeout};
4564 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4565 my $sname = qmp_socket($vmid);
4566 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4567 my $qmpclient = PVE::QMPClient->new();
4569 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4570 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4571 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4572 if scalar(%{$cmd->{arguments}});
4573 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4575 die "unable to open monitor socket\n";
4579 syslog("err", "VM $vmid qmp command failed - $err");
4586 sub vm_human_monitor_command {
4587 my ($vmid, $cmdline) = @_;
4592 execute => 'human-monitor-command
',
4593 arguments => { 'command-line
' => $cmdline},
4596 return vm_qmp_command($vmid, $cmd);
4599 sub vm_commandline {
4600 my ($storecfg, $vmid) = @_;
4602 my $conf = PVE::QemuConfig->load_config($vmid);
4604 my $defaults = load_defaults();
4606 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4608 return join(' ', @$cmd);
4612 my ($vmid, $skiplock) = @_;
4614 PVE::QemuConfig->lock_config($vmid, sub {
4616 my $conf = PVE::QemuConfig->load_config($vmid);
4618 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4620 vm_mon_cmd($vmid, "system_reset");
4624 sub get_vm_volumes {
4628 foreach_volid($conf, sub {
4629 my ($volid, $is_cdrom) = @_;
4631 return if $volid =~ m|^/|;
4633 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4636 push @$vollist, $volid;
4642 sub vm_stop_cleanup {
4643 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4648 my $vollist = get_vm_volumes($conf);
4649 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4652 foreach my $ext (qw(mon qmp pid vnc qga)) {
4653 unlink "/var/run/qemu-server/${vmid}.$ext";
4656 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4658 warn $@ if $@; # avoid errors - just warn
4661 # Note: use $nockeck to skip tests if VM configuration file exists.
4662 # We need that when migration VMs to other nodes (files already moved)
4663 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4665 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4667 $force = 1 if !defined($force) && !$shutdown;
4670 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4671 kill 15, $pid if $pid;
4672 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4673 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4677 PVE
::QemuConfig-
>lock_config($vmid, sub {
4679 my $pid = check_running
($vmid, $nocheck);
4684 $conf = PVE
::QemuConfig-
>load_config($vmid);
4685 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4686 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4687 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4688 $timeout = $opts->{down
} if $opts->{down
};
4692 $timeout = 60 if !defined($timeout);
4696 if (defined($conf) && $conf->{agent
}) {
4697 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4699 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4702 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4709 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4714 if ($count >= $timeout) {
4716 warn "VM still running - terminating now with SIGTERM\n";
4719 die "VM quit/powerdown failed - got timeout\n";
4722 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4727 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4730 die "VM quit/powerdown failed\n";
4738 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4743 if ($count >= $timeout) {
4744 warn "VM still running - terminating now with SIGKILL\n";
4749 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4754 my ($vmid, $skiplock) = @_;
4756 PVE
::QemuConfig-
>lock_config($vmid, sub {
4758 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4760 PVE
::QemuConfig-
>check_lock($conf)
4761 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4763 vm_mon_cmd
($vmid, "stop");
4768 my ($vmid, $skiplock, $nocheck) = @_;
4770 PVE
::QemuConfig-
>lock_config($vmid, sub {
4774 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4776 PVE
::QemuConfig-
>check_lock($conf)
4777 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4779 vm_mon_cmd
($vmid, "cont");
4782 vm_mon_cmd_nocheck
($vmid, "cont");
4788 my ($vmid, $skiplock, $key) = @_;
4790 PVE
::QemuConfig-
>lock_config($vmid, sub {
4792 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4794 # there is no qmp command, so we use the human monitor command
4795 vm_human_monitor_command
($vmid, "sendkey $key");
4800 my ($storecfg, $vmid, $skiplock) = @_;
4802 PVE
::QemuConfig-
>lock_config($vmid, sub {
4804 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4806 if (!check_running
($vmid)) {
4807 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4809 die "VM $vmid is running - destroy failed\n";
4817 my ($filename, $buf) = @_;
4819 my $fh = IO
::File-
>new($filename, "w");
4820 return undef if !$fh;
4822 my $res = print $fh $buf;
4829 sub pci_device_info
{
4834 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4835 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4837 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4838 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4840 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4841 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4843 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4844 return undef if !defined($product) || $product !~ s/^0x//;
4849 product
=> $product,
4855 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4864 my $name = $dev->{name
};
4866 my $fn = "$pcisysfs/devices/$name/reset";
4868 return file_write
($fn, "1");
4871 sub pci_dev_bind_to_vfio
{
4874 my $name = $dev->{name
};
4876 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4878 if (!-d
$vfio_basedir) {
4879 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4881 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4883 my $testdir = "$vfio_basedir/$name";
4884 return 1 if -d
$testdir;
4886 my $data = "$dev->{vendor} $dev->{product}";
4887 return undef if !file_write
("$vfio_basedir/new_id", $data);
4889 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4890 if (!file_write
($fn, $name)) {
4891 return undef if -f
$fn;
4894 $fn = "$vfio_basedir/bind";
4895 if (! -d
$testdir) {
4896 return undef if !file_write
($fn, $name);
4902 sub pci_dev_group_bind_to_vfio
{
4905 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4907 if (!-d
$vfio_basedir) {
4908 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4910 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4912 # get IOMMU group devices
4913 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4914 my @devs = grep /^0000:/, readdir($D);
4917 foreach my $pciid (@devs) {
4918 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4920 # pci bridges, switches or root ports are not supported
4921 # they have a pci_bus subdirectory so skip them
4922 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4924 my $info = pci_device_info
($1);
4925 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4931 sub print_pci_addr
{
4932 my ($id, $bridges) = @_;
4936 piix3
=> { bus
=> 0, addr
=> 1 },
4937 #addr2 : first videocard
4938 balloon0
=> { bus
=> 0, addr
=> 3 },
4939 watchdog
=> { bus
=> 0, addr
=> 4 },
4940 scsihw0
=> { bus
=> 0, addr
=> 5 },
4941 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4942 scsihw1
=> { bus
=> 0, addr
=> 6 },
4943 ahci0
=> { bus
=> 0, addr
=> 7 },
4944 qga0
=> { bus
=> 0, addr
=> 8 },
4945 spice
=> { bus
=> 0, addr
=> 9 },
4946 virtio0
=> { bus
=> 0, addr
=> 10 },
4947 virtio1
=> { bus
=> 0, addr
=> 11 },
4948 virtio2
=> { bus
=> 0, addr
=> 12 },
4949 virtio3
=> { bus
=> 0, addr
=> 13 },
4950 virtio4
=> { bus
=> 0, addr
=> 14 },
4951 virtio5
=> { bus
=> 0, addr
=> 15 },
4952 hostpci0
=> { bus
=> 0, addr
=> 16 },
4953 hostpci1
=> { bus
=> 0, addr
=> 17 },
4954 net0
=> { bus
=> 0, addr
=> 18 },
4955 net1
=> { bus
=> 0, addr
=> 19 },
4956 net2
=> { bus
=> 0, addr
=> 20 },
4957 net3
=> { bus
=> 0, addr
=> 21 },
4958 net4
=> { bus
=> 0, addr
=> 22 },
4959 net5
=> { bus
=> 0, addr
=> 23 },
4960 vga1
=> { bus
=> 0, addr
=> 24 },
4961 vga2
=> { bus
=> 0, addr
=> 25 },
4962 vga3
=> { bus
=> 0, addr
=> 26 },
4963 hostpci2
=> { bus
=> 0, addr
=> 27 },
4964 hostpci3
=> { bus
=> 0, addr
=> 28 },
4965 #addr29 : usb-host (pve-usb.cfg)
4966 'pci.1' => { bus
=> 0, addr
=> 30 },
4967 'pci.2' => { bus
=> 0, addr
=> 31 },
4968 'net6' => { bus
=> 1, addr
=> 1 },
4969 'net7' => { bus
=> 1, addr
=> 2 },
4970 'net8' => { bus
=> 1, addr
=> 3 },
4971 'net9' => { bus
=> 1, addr
=> 4 },
4972 'net10' => { bus
=> 1, addr
=> 5 },
4973 'net11' => { bus
=> 1, addr
=> 6 },
4974 'net12' => { bus
=> 1, addr
=> 7 },
4975 'net13' => { bus
=> 1, addr
=> 8 },
4976 'net14' => { bus
=> 1, addr
=> 9 },
4977 'net15' => { bus
=> 1, addr
=> 10 },
4978 'net16' => { bus
=> 1, addr
=> 11 },
4979 'net17' => { bus
=> 1, addr
=> 12 },
4980 'net18' => { bus
=> 1, addr
=> 13 },
4981 'net19' => { bus
=> 1, addr
=> 14 },
4982 'net20' => { bus
=> 1, addr
=> 15 },
4983 'net21' => { bus
=> 1, addr
=> 16 },
4984 'net22' => { bus
=> 1, addr
=> 17 },
4985 'net23' => { bus
=> 1, addr
=> 18 },
4986 'net24' => { bus
=> 1, addr
=> 19 },
4987 'net25' => { bus
=> 1, addr
=> 20 },
4988 'net26' => { bus
=> 1, addr
=> 21 },
4989 'net27' => { bus
=> 1, addr
=> 22 },
4990 'net28' => { bus
=> 1, addr
=> 23 },
4991 'net29' => { bus
=> 1, addr
=> 24 },
4992 'net30' => { bus
=> 1, addr
=> 25 },
4993 'net31' => { bus
=> 1, addr
=> 26 },
4994 'xhci' => { bus
=> 1, addr
=> 27 },
4995 'virtio6' => { bus
=> 2, addr
=> 1 },
4996 'virtio7' => { bus
=> 2, addr
=> 2 },
4997 'virtio8' => { bus
=> 2, addr
=> 3 },
4998 'virtio9' => { bus
=> 2, addr
=> 4 },
4999 'virtio10' => { bus
=> 2, addr
=> 5 },
5000 'virtio11' => { bus
=> 2, addr
=> 6 },
5001 'virtio12' => { bus
=> 2, addr
=> 7 },
5002 'virtio13' => { bus
=> 2, addr
=> 8 },
5003 'virtio14' => { bus
=> 2, addr
=> 9 },
5004 'virtio15' => { bus
=> 2, addr
=> 10 },
5005 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5006 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5007 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5008 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5009 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5010 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5011 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5012 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5013 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5014 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5015 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5016 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5017 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5018 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5019 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5020 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5021 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5022 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5023 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5024 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5025 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5026 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5027 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5028 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5029 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5030 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5031 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5032 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5033 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5034 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5035 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5039 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5040 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5041 my $bus = $devices->{$id}->{bus
};
5042 $res = ",bus=pci.$bus,addr=$addr";
5043 $bridges->{$bus} = 1 if $bridges;
5049 sub print_pcie_addr
{
5054 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5055 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5056 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5057 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5060 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5061 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5062 my $bus = $devices->{$id}->{bus
};
5063 $res = ",bus=$bus,addr=$addr";
5069 # vzdump restore implementaion
5071 sub tar_archive_read_firstfile
{
5072 my $archive = shift;
5074 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5076 # try to detect archive type first
5077 my $pid = open (TMP
, "tar tf '$archive'|") ||
5078 die "unable to open file '$archive'\n";
5079 my $firstfile = <TMP
>;
5083 die "ERROR: archive contaions no data\n" if !$firstfile;
5089 sub tar_restore_cleanup
{
5090 my ($storecfg, $statfile) = @_;
5092 print STDERR
"starting cleanup\n";
5094 if (my $fd = IO
::File-
>new($statfile, "r")) {
5095 while (defined(my $line = <$fd>)) {
5096 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5099 if ($volid =~ m
|^/|) {
5100 unlink $volid || die 'unlink failed\n';
5102 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5104 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5106 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5108 print STDERR
"unable to parse line in statfile - $line";
5115 sub restore_archive
{
5116 my ($archive, $vmid, $user, $opts) = @_;
5118 my $format = $opts->{format
};
5121 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5122 $format = 'tar' if !$format;
5124 } elsif ($archive =~ m/\.tar$/) {
5125 $format = 'tar' if !$format;
5126 } elsif ($archive =~ m/.tar.lzo$/) {
5127 $format = 'tar' if !$format;
5129 } elsif ($archive =~ m/\.vma$/) {
5130 $format = 'vma' if !$format;
5131 } elsif ($archive =~ m/\.vma\.gz$/) {
5132 $format = 'vma' if !$format;
5134 } elsif ($archive =~ m/\.vma\.lzo$/) {
5135 $format = 'vma' if !$format;
5138 $format = 'vma' if !$format; # default
5141 # try to detect archive format
5142 if ($format eq 'tar') {
5143 return restore_tar_archive
($archive, $vmid, $user, $opts);
5145 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5149 sub restore_update_config_line
{
5150 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5152 return if $line =~ m/^\#qmdump\#/;
5153 return if $line =~ m/^\#vzdump\#/;
5154 return if $line =~ m/^lock:/;
5155 return if $line =~ m/^unused\d+:/;
5156 return if $line =~ m/^parent:/;
5157 return if $line =~ m/^template:/; # restored VM is never a template
5159 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5160 # try to convert old 1.X settings
5161 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5162 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5163 my ($model, $macaddr) = split(/\=/, $devconfig);
5164 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5167 bridge
=> "vmbr$ind",
5168 macaddr
=> $macaddr,
5170 my $netstr = print_net
($net);
5172 print $outfd "net$cookie->{netcount}: $netstr\n";
5173 $cookie->{netcount
}++;
5175 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5176 my ($id, $netstr) = ($1, $2);
5177 my $net = parse_net
($netstr);
5178 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5179 $netstr = print_net
($net);
5180 print $outfd "$id: $netstr\n";
5181 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5184 my $di = parse_drive
($virtdev, $value);
5185 if (defined($di->{backup
}) && !$di->{backup
}) {
5186 print $outfd "#$line";
5187 } elsif ($map->{$virtdev}) {
5188 delete $di->{format
}; # format can change on restore
5189 $di->{file
} = $map->{$virtdev};
5190 $value = print_drive
($vmid, $di);
5191 print $outfd "$virtdev: $value\n";
5201 my ($cfg, $vmid) = @_;
5203 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5205 my $volid_hash = {};
5206 foreach my $storeid (keys %$info) {
5207 foreach my $item (@{$info->{$storeid}}) {
5208 next if !($item->{volid
} && $item->{size
});
5209 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5210 $volid_hash->{$item->{volid
}} = $item;
5217 sub is_volume_in_use
{
5218 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5220 my $path = PVE
::Storage
::path
($storecfg, $volid);
5222 my $scan_config = sub {
5223 my ($cref, $snapname) = @_;
5225 foreach my $key (keys %$cref) {
5226 my $value = $cref->{$key};
5227 if (is_valid_drivename
($key)) {
5228 next if $skip_drive && $key eq $skip_drive;
5229 my $drive = parse_drive
($key, $value);
5230 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5231 return 1 if $volid eq $drive->{file
};
5232 if ($drive->{file
} =~ m!^/!) {
5233 return 1 if $drive->{file
} eq $path;
5235 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5237 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5239 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5247 return 1 if &$scan_config($conf);
5251 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5252 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5258 sub update_disksize
{
5259 my ($vmid, $conf, $volid_hash) = @_;
5265 # Note: it is allowed to define multiple storages with same path (alias), so
5266 # we need to check both 'volid' and real 'path' (two different volid can point
5267 # to the same path).
5272 foreach my $opt (keys %$conf) {
5273 if (is_valid_drivename
($opt)) {
5274 my $drive = parse_drive
($opt, $conf->{$opt});
5275 my $volid = $drive->{file
};
5278 $used->{$volid} = 1;
5279 if ($volid_hash->{$volid} &&
5280 (my $path = $volid_hash->{$volid}->{path
})) {
5281 $usedpath->{$path} = 1;
5284 next if drive_is_cdrom
($drive);
5285 next if !$volid_hash->{$volid};
5287 $drive->{size
} = $volid_hash->{$volid}->{size
};
5288 my $new = print_drive
($vmid, $drive);
5289 if ($new ne $conf->{$opt}) {
5291 $conf->{$opt} = $new;
5296 # remove 'unusedX' entry if volume is used
5297 foreach my $opt (keys %$conf) {
5298 next if $opt !~ m/^unused\d+$/;
5299 my $volid = $conf->{$opt};
5300 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5301 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5303 delete $conf->{$opt};
5307 foreach my $volid (sort keys %$volid_hash) {
5308 next if $volid =~ m/vm-$vmid-state-/;
5309 next if $used->{$volid};
5310 my $path = $volid_hash->{$volid}->{path
};
5311 next if !$path; # just to be sure
5312 next if $usedpath->{$path};
5314 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5315 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5322 my ($vmid, $nolock) = @_;
5324 my $cfg = PVE
::Storage
::config
();
5326 my $volid_hash = scan_volids
($cfg, $vmid);
5328 my $updatefn = sub {
5331 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5333 PVE
::QemuConfig-
>check_lock($conf);
5336 foreach my $volid (keys %$volid_hash) {
5337 my $info = $volid_hash->{$volid};
5338 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5341 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5343 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5346 if (defined($vmid)) {
5350 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5353 my $vmlist = config_list
();
5354 foreach my $vmid (keys %$vmlist) {
5358 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5364 sub restore_vma_archive
{
5365 my ($archive, $vmid, $user, $opts, $comp) = @_;
5367 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5368 my $readfrom = $archive;
5373 my $qarchive = PVE
::Tools
::shellquote
($archive);
5374 if ($comp eq 'gzip') {
5375 $uncomp = "zcat $qarchive|";
5376 } elsif ($comp eq 'lzop') {
5377 $uncomp = "lzop -d -c $qarchive|";
5379 die "unknown compression method '$comp'\n";
5384 my $tmpdir = "/var/tmp/vzdumptmp$$";
5387 # disable interrupts (always do cleanups)
5388 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5389 warn "got interrupt - ignored\n";
5392 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5393 POSIX
::mkfifo
($mapfifo, 0600);
5396 my $openfifo = sub {
5397 open($fifofh, '>', $mapfifo) || die $!;
5400 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5407 my $rpcenv = PVE
::RPCEnvironment
::get
();
5409 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5410 my $tmpfn = "$conffile.$$.tmp";
5412 # Note: $oldconf is undef if VM does not exists
5413 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5414 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5416 my $print_devmap = sub {
5417 my $virtdev_hash = {};
5419 my $cfgfn = "$tmpdir/qemu-server.conf";
5421 # we can read the config - that is already extracted
5422 my $fh = IO
::File-
>new($cfgfn, "r") ||
5423 "unable to read qemu-server.conf - $!\n";
5425 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5427 my $pve_firewall_dir = '/etc/pve/firewall';
5428 mkdir $pve_firewall_dir; # make sure the dir exists
5429 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5432 while (defined(my $line = <$fh>)) {
5433 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5434 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5435 die "archive does not contain data for drive '$virtdev'\n"
5436 if !$devinfo->{$devname};
5437 if (defined($opts->{storage
})) {
5438 $storeid = $opts->{storage
} || 'local';
5439 } elsif (!$storeid) {
5442 $format = 'raw' if !$format;
5443 $devinfo->{$devname}->{devname
} = $devname;
5444 $devinfo->{$devname}->{virtdev
} = $virtdev;
5445 $devinfo->{$devname}->{format
} = $format;
5446 $devinfo->{$devname}->{storeid
} = $storeid;
5448 # check permission on storage
5449 my $pool = $opts->{pool
}; # todo: do we need that?
5450 if ($user ne 'root@pam') {
5451 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5454 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5458 foreach my $devname (keys %$devinfo) {
5459 die "found no device mapping information for device '$devname'\n"
5460 if !$devinfo->{$devname}->{virtdev
};
5463 my $cfg = PVE
::Storage
::config
();
5465 # create empty/temp config
5467 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5468 foreach_drive
($oldconf, sub {
5469 my ($ds, $drive) = @_;
5471 return if drive_is_cdrom
($drive);
5473 my $volid = $drive->{file
};
5475 return if !$volid || $volid =~ m
|^/|;
5477 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5478 return if !$path || !$owner || ($owner != $vmid);
5480 # Note: only delete disk we want to restore
5481 # other volumes will become unused
5482 if ($virtdev_hash->{$ds}) {
5483 PVE
::Storage
::vdisk_free
($cfg, $volid);
5487 # delete vmstate files
5488 # since after the restore we have no snapshots anymore
5489 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5490 my $snap = $oldconf->{snapshots
}->{$snapname};
5491 if ($snap->{vmstate
}) {
5492 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5501 foreach my $virtdev (sort keys %$virtdev_hash) {
5502 my $d = $virtdev_hash->{$virtdev};
5503 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5504 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5506 # test if requested format is supported
5507 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5508 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5509 $d->{format
} = $defFormat if !$supported;
5511 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5512 $d->{format
}, undef, $alloc_size);
5513 print STDERR
"new volume ID is '$volid'\n";
5514 $d->{volid
} = $volid;
5515 my $path = PVE
::Storage
::path
($cfg, $volid);
5517 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5519 my $write_zeros = 1;
5520 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5524 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5526 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5527 $map->{$virtdev} = $volid;
5530 $fh->seek(0, 0) || die "seek failed - $!\n";
5532 my $outfd = new IO
::File
($tmpfn, "w") ||
5533 die "unable to write config for VM $vmid\n";
5535 my $cookie = { netcount
=> 0 };
5536 while (defined(my $line = <$fh>)) {
5537 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5546 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5547 die "interrupted by signal\n";
5549 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5551 $oldtimeout = alarm($timeout);
5558 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5559 my ($dev_id, $size, $devname) = ($1, $2, $3);
5560 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5561 } elsif ($line =~ m/^CTIME: /) {
5562 # we correctly received the vma config, so we can disable
5563 # the timeout now for disk allocation (set to 10 minutes, so
5564 # that we always timeout if something goes wrong)
5567 print $fifofh "done\n";
5568 my $tmp = $oldtimeout || 0;
5569 $oldtimeout = undef;
5575 print "restore vma archive: $cmd\n";
5576 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5580 alarm($oldtimeout) if $oldtimeout;
5583 foreach my $devname (keys %$devinfo) {
5584 my $volid = $devinfo->{$devname}->{volid
};
5585 push @$vollist, $volid if $volid;
5588 my $cfg = PVE
::Storage
::config
();
5589 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5597 foreach my $devname (keys %$devinfo) {
5598 my $volid = $devinfo->{$devname}->{volid
};
5601 if ($volid =~ m
|^/|) {
5602 unlink $volid || die 'unlink failed\n';
5604 PVE
::Storage
::vdisk_free
($cfg, $volid);
5606 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5608 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5615 rename($tmpfn, $conffile) ||
5616 die "unable to commit configuration file '$conffile'\n";
5618 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5620 eval { rescan
($vmid, 1); };
5624 sub restore_tar_archive
{
5625 my ($archive, $vmid, $user, $opts) = @_;
5627 if ($archive ne '-') {
5628 my $firstfile = tar_archive_read_firstfile
($archive);
5629 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5630 if $firstfile ne 'qemu-server.conf';
5633 my $storecfg = PVE
::Storage
::config
();
5635 # destroy existing data - keep empty config
5636 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5637 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5639 my $tocmd = "/usr/lib/qemu-server/qmextract";
5641 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5642 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5643 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5644 $tocmd .= ' --info' if $opts->{info
};
5646 # tar option "xf" does not autodetect compression when read from STDIN,
5647 # so we pipe to zcat
5648 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5649 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5651 my $tmpdir = "/var/tmp/vzdumptmp$$";
5654 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5655 local $ENV{VZDUMP_VMID
} = $vmid;
5656 local $ENV{VZDUMP_USER
} = $user;
5658 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5659 my $tmpfn = "$conffile.$$.tmp";
5661 # disable interrupts (always do cleanups)
5662 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5663 print STDERR
"got interrupt - ignored\n";
5668 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5669 die "interrupted by signal\n";
5672 if ($archive eq '-') {
5673 print "extracting archive from STDIN\n";
5674 run_command
($cmd, input
=> "<&STDIN");
5676 print "extracting archive '$archive'\n";
5680 return if $opts->{info
};
5684 my $statfile = "$tmpdir/qmrestore.stat";
5685 if (my $fd = IO
::File-
>new($statfile, "r")) {
5686 while (defined (my $line = <$fd>)) {
5687 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5688 $map->{$1} = $2 if $1;
5690 print STDERR
"unable to parse line in statfile - $line\n";
5696 my $confsrc = "$tmpdir/qemu-server.conf";
5698 my $srcfd = new IO
::File
($confsrc, "r") ||
5699 die "unable to open file '$confsrc'\n";
5701 my $outfd = new IO
::File
($tmpfn, "w") ||
5702 die "unable to write config for VM $vmid\n";
5704 my $cookie = { netcount
=> 0 };
5705 while (defined (my $line = <$srcfd>)) {
5706 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5718 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5725 rename $tmpfn, $conffile ||
5726 die "unable to commit configuration file '$conffile'\n";
5728 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5730 eval { rescan
($vmid, 1); };
5734 sub foreach_writable_storage
{
5735 my ($conf, $func) = @_;
5739 foreach my $ds (keys %$conf) {
5740 next if !is_valid_drivename
($ds);
5742 my $drive = parse_drive
($ds, $conf->{$ds});
5744 next if drive_is_cdrom
($drive);
5746 my $volid = $drive->{file
};
5748 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5749 $sidhash->{$sid} = $sid if $sid;
5752 foreach my $sid (sort keys %$sidhash) {
5757 sub do_snapshots_with_qemu
{
5758 my ($storecfg, $volid) = @_;
5760 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5762 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5763 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5767 if ($volid =~ m/\.(qcow2|qed)$/){
5774 sub qga_check_running
{
5777 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5779 warn "Qemu Guest Agent are not running - $@";
5785 sub template_create
{
5786 my ($vmid, $conf, $disk) = @_;
5788 my $storecfg = PVE
::Storage
::config
();
5790 foreach_drive
($conf, sub {
5791 my ($ds, $drive) = @_;
5793 return if drive_is_cdrom
($drive);
5794 return if $disk && $ds ne $disk;
5796 my $volid = $drive->{file
};
5797 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5799 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5800 $drive->{file
} = $voliddst;
5801 $conf->{$ds} = print_drive
($vmid, $drive);
5802 PVE
::QemuConfig-
>write_config($vmid, $conf);
5806 sub qemu_img_convert
{
5807 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5809 my $storecfg = PVE
::Storage
::config
();
5810 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5811 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5813 if ($src_storeid && $dst_storeid) {
5815 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5817 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5818 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5820 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5821 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5823 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5824 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5827 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5828 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5829 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5830 if ($is_zero_initialized) {
5831 push @$cmd, "zeroinit:$dst_path";
5833 push @$cmd, $dst_path;
5838 if($line =~ m/\((\S+)\/100\
%\)/){
5840 my $transferred = int($size * $percent / 100);
5841 my $remaining = $size - $transferred;
5843 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5848 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5850 die "copy failed: $err" if $err;
5854 sub qemu_img_format
{
5855 my ($scfg, $volname) = @_;
5857 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5864 sub qemu_drive_mirror
{
5865 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5867 my $storecfg = PVE
::Storage
::config
();
5868 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5870 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5872 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5874 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5876 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5878 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5879 $opts->{format
} = $format if $format;
5881 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5884 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5886 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5887 my $stat = @$stats[0];
5888 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5889 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5891 my $busy = $stat->{busy
};
5892 my $ready = $stat->{ready
};
5894 if (my $total = $stat->{len
}) {
5895 my $transferred = $stat->{offset
} || 0;
5896 my $remaining = $total - $transferred;
5897 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5899 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5903 if ($stat->{ready
} eq 'true') {
5905 last if $vmiddst != $vmid;
5907 # try to switch the disk if source and destination are on the same guest
5908 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5910 die $@ if $@ !~ m/cannot be completed/;
5919 my $cancel_job = sub {
5920 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5922 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5923 my $stat = @$stats[0];
5930 eval { &$cancel_job(); };
5931 die "mirroring error: $err";
5934 if ($vmiddst != $vmid) {
5935 # if we clone a disk for a new target vm, we don't switch the disk
5936 &$cancel_job(); # so we call block-job-cancel
5941 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5942 $newvmid, $storage, $format, $full, $newvollist) = @_;
5947 print "create linked clone of drive $drivename ($drive->{file})\n";
5948 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5949 push @$newvollist, $newvolid;
5951 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5952 $storeid = $storage if $storage;
5954 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5956 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5957 $format = qemu_img_format
($scfg, $volname);
5960 # test if requested format is supported - else use default
5961 my $supported = grep { $_ eq $format } @$validFormats;
5962 $format = $defFormat if !$supported;
5964 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5966 print "create full clone of drive $drivename ($drive->{file})\n";
5967 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5968 push @$newvollist, $newvolid;
5970 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5972 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5973 if (!$running || $snapname) {
5974 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5976 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5980 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5983 $disk->{format
} = undef;
5984 $disk->{file
} = $newvolid;
5985 $disk->{size
} = $size;
5990 # this only works if VM is running
5991 sub get_current_qemu_machine
{
5994 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5995 my $res = vm_qmp_command
($vmid, $cmd);
5997 my ($current, $default);
5998 foreach my $e (@$res) {
5999 $default = $e->{name
} if $e->{'is-default'};
6000 $current = $e->{name
} if $e->{'is-current'};
6003 # fallback to the default machine if current is not supported by qemu
6004 return $current || $default || 'pc';
6007 sub qemu_machine_feature_enabled
{
6008 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6013 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6015 $current_major = $3;
6016 $current_minor = $4;
6018 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6020 $current_major = $1;
6021 $current_minor = $2;
6024 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6029 sub qemu_machine_pxe
{
6030 my ($vmid, $conf, $machine) = @_;
6032 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6034 foreach my $opt (keys %$conf) {
6035 next if $opt !~ m/^net(\d+)$/;
6036 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6038 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6039 return $machine.".pxe" if $romfile =~ m/pxe/;
6046 sub qemu_use_old_bios_files
{
6047 my ($machine_type) = @_;
6049 return if !$machine_type;
6051 my $use_old_bios_files = undef;
6053 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6055 $use_old_bios_files = 1;
6057 my $kvmver = kvm_user_version
();
6058 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6059 # load new efi bios files on migration. So this hack is required to allow
6060 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6061 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6062 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6065 return ($use_old_bios_files, $machine_type);
6072 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6073 my (undef, $id, $function) = @_;
6074 my $res = { id
=> $id, function
=> $function};
6075 push @{$devices->{$id}}, $res;
6081 sub vm_iothreads_list
{
6084 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6087 foreach my $iothread (@$res) {
6088 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6095 my ($conf, $drive) = @_;
6099 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6101 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6107 my $controller = int($drive->{index} / $maxdev);
6108 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6110 return ($maxdev, $controller, $controller_prefix);
6113 # bash completion helper
6115 sub complete_backup_archives
{
6116 my ($cmdname, $pname, $cvalue) = @_;
6118 my $cfg = PVE
::Storage
::config
();
6122 if ($cvalue =~ m/^([^:]+):/) {
6126 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6129 foreach my $id (keys %$data) {
6130 foreach my $item (@{$data->{$id}}) {
6131 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6132 push @$res, $item->{volid
} if defined($item->{volid
});
6139 my $complete_vmid_full = sub {
6142 my $idlist = vmstatus
();
6146 foreach my $id (keys %$idlist) {
6147 my $d = $idlist->{$id};
6148 if (defined($running)) {
6149 next if $d->{template
};
6150 next if $running && $d->{status
} ne 'running';
6151 next if !$running && $d->{status
} eq 'running';
6160 return &$complete_vmid_full();
6163 sub complete_vmid_stopped
{
6164 return &$complete_vmid_full(0);
6167 sub complete_vmid_running
{
6168 return &$complete_vmid_full(1);
6171 sub complete_storage
{
6173 my $cfg = PVE
::Storage
::config
();
6174 my $ids = $cfg->{ids
};
6177 foreach my $sid (keys %$ids) {
6178 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6179 next if !$ids->{$sid}->{content
}->{images
};