1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
32 use PVE
::RPCEnvironment
;
33 use Time
::HiRes
qw(gettimeofday);
34 use File
::Copy
qw(copy);
37 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
39 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
41 # Note about locking: we use flock on the config file protect
42 # against concurent actions.
43 # Aditionaly, we have a 'lock' setting in the config file. This
44 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
45 # allowed when such lock is set. But you can ignore this kind of
46 # lock with the --skiplock flag.
48 cfs_register_file
('/qemu-server/',
52 PVE
::JSONSchema
::register_standard_option
('skiplock', {
53 description
=> "Ignore locks - only root is allowed to use this option.",
58 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
59 description
=> "Some command save/restore state from this location.",
65 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
66 description
=> "The name of the snapshot.",
67 type
=> 'string', format
=> 'pve-configid',
71 #no warnings 'redefine';
74 my ($controller, $vmid, $option, $value) = @_;
76 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
77 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
81 my $nodename = PVE
::INotify
::nodename
();
83 mkdir "/etc/pve/nodes/$nodename";
84 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
87 my $var_run_tmpdir = "/var/run/qemu-server";
88 mkdir $var_run_tmpdir;
90 my $lock_dir = "/var/lock/qemu-server";
93 my $pcisysfs = "/sys/bus/pci";
97 description
=> "Emulated CPU type.",
99 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Haswell-noTSX Broadwell Broadwell-noTSX Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
100 format_description
=> 'cputype',
105 description
=> "Do not identify as a KVM virtual machine.",
116 description
=> "Specifies whether a VM will be started during system bootup.",
122 description
=> "Automatic restart after crash (currently ignored).",
127 type
=> 'string', format
=> 'pve-hotplug-features',
128 description
=> "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
129 default => 'network,disk,usb',
134 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
140 description
=> "Lock/unlock the VM.",
141 enum
=> [qw(migrate backup snapshot rollback)],
146 description
=> "Limit of CPU usage.\n\nNOTE: If the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
154 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
162 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
169 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
175 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
183 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
184 enum
=> PVE
::Tools
::kvmkeymaplist
(),
189 type
=> 'string', format
=> 'dns-name',
190 description
=> "Set a name for the VM. Only used on the configuration web interface.",
195 description
=> "scsi controller model",
196 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
202 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
207 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
208 description
=> <<EODESC,
209 Used to enable special optimization/features for specific
212 other => unspecified OS
213 wxp => Microsoft Windows XP
214 w2k => Microsoft Windows 2000
215 w2k3 => Microsoft Windows 2003
216 w2k8 => Microsoft Windows 2008
217 wvista => Microsoft Windows Vista
218 win7 => Microsoft Windows 7
219 win8 => Microsoft Windows 8/2012
220 l24 => Linux 2.4 Kernel
221 l26 => Linux 2.6/3.X Kernel
222 solaris => solaris/opensolaris/openindiania kernel
224 other|l24|l26|solaris ... no special behaviour
225 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
231 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
232 pattern
=> '[acdn]{1,4}',
237 type
=> 'string', format
=> 'pve-qm-bootdisk',
238 description
=> "Enable booting from specified disk.",
239 pattern
=> '(ide|sata|scsi|virtio)\d+',
244 description
=> "The number of CPUs. Please use option -sockets instead.",
251 description
=> "The number of CPU sockets.",
258 description
=> "The number of cores per socket.",
265 description
=> "Enable/disable NUMA.",
271 description
=> "Number of hotplugged vcpus.",
278 description
=> "Enable/disable ACPI.",
284 description
=> "Enable/disable Qemu GuestAgent.",
290 description
=> "Enable/disable KVM hardware virtualization.",
296 description
=> "Enable/disable time drift fix.",
302 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
307 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
312 description
=> "Select the VGA type. If you want to use high resolution" .
313 " modes (>= 1280x1024x16) then you should use the options " .
314 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
315 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
316 "display sever. For win* OS you can select how many independent " .
317 "displays you want, Linux guests can add displays them self. " .
318 "You can also run without any graphic card, using a serial device" .
320 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
324 type
=> 'string', format
=> 'pve-qm-watchdog',
325 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
326 description
=> "Create a virtual hardware watchdog device. Once enabled" .
327 " (by a guest action), the watchdog must be periodically polled " .
328 "by an agent inside the guest or else the watchdog will reset " .
329 "the guest (or execute the respective action specified)",
334 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
335 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
336 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
339 startup
=> get_standard_option
('pve-startup-order'),
343 description
=> "Enable/disable Template.",
349 description
=> <<EODESCR,
350 NOTE: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
352 args: -no-reboot -no-hpet
359 description
=> "Enable/disable the USB tablet device. This device is " .
360 "usually needed to allow absolute mouse positioning with VNC. " .
361 "Else the mouse runs out of sync with normal VNC clients. " .
362 "If you're running lots of console-only guests on one host, " .
363 "you may consider disabling this to save some context switches. " .
364 "This is turned off by default if you use spice (-vga=qxl).",
369 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
373 migrate_downtime
=> {
376 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
382 type
=> 'string', format
=> 'pve-qm-drive',
383 typetext
=> 'volume',
384 description
=> "This is an alias for option -ide2",
388 description
=> "Emulated CPU type.",
392 parent
=> get_standard_option
('pve-snapshot-name', {
394 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
398 description
=> "Timestamp for snapshots.",
404 type
=> 'string', format
=> 'pve-volume-id',
405 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
408 description
=> "Specific the Qemu machine type.",
410 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
415 description
=> "Specify SMBIOS type 1 fields.",
416 type
=> 'string', format
=> 'pve-qm-smbios1',
423 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
429 enum
=> [ qw(seabios ovmf) ],
430 description
=> "Select BIOS implementation.",
431 default => 'seabios',
435 # what about other qemu settings ?
437 #machine => 'string',
450 ##soundhw => 'string',
452 while (my ($k, $v) = each %$confdesc) {
453 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
456 my $MAX_IDE_DISKS = 4;
457 my $MAX_SCSI_DISKS = 14;
458 my $MAX_VIRTIO_DISKS = 16;
459 my $MAX_SATA_DISKS = 6;
460 my $MAX_USB_DEVICES = 5;
462 my $MAX_UNUSED_DISKS = 8;
463 my $MAX_HOSTPCI_DEVICES = 4;
464 my $MAX_SERIAL_PORTS = 4;
465 my $MAX_PARALLEL_PORTS = 3;
467 my $MAX_MEM = 4194304;
468 my $STATICMEM = 1024;
473 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
474 description
=> "CPUs accessing this numa node.",
475 format_description
=> "id[-id];...",
479 description
=> "Amount of memory this numa node provides.",
480 format_description
=> "mb",
485 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
486 description
=> "host numa nodes to use",
487 format_description
=> "id[-id];...",
492 enum
=> [qw(preferred bind interleave)],
493 format_description
=> 'preferred|bind|interleave',
494 description
=> "numa allocation policy.",
498 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
501 type
=> 'string', format
=> $numa_fmt,
502 description
=> "numa topology",
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
506 for (my $i = 0; $i < $MAX_NUMA; $i++) {
507 $confdesc->{"numa$i"} = $numadesc;
510 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
511 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
512 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
513 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
517 type
=> 'string', format
=> 'pve-qm-net',
518 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]",
519 description
=> <<EODESCR,
520 Specify network devices.
522 MODEL is one of: $nic_model_list_txt
524 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
525 automatically generated if not specified.
527 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
529 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'.
531 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
537 The DHCP server assign addresses to the guest starting from 10.0.2.15.
541 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
543 for (my $i = 0; $i < $MAX_NETS; $i++) {
544 $confdesc->{"net$i"} = $netdesc;
547 PVE
::JSONSchema
::register_format
('pve-volume-id-or-none', \
&verify_volume_id_or_none
);
548 sub verify_volume_id_or_none
{
549 my ($volid, $noerr) = @_;
551 return $volid if $volid eq 'none';
552 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
554 return undef if $noerr;
562 my %drivedesc_base = (
563 volume
=> { alias
=> 'file' },
566 format
=> 'pve-volume-id-or-none',
568 format_description
=> 'volume',
569 description
=> "The drive's backing volume.",
573 format_description
=> 'cdrom|disk',
574 enum
=> [qw(cdrom disk)],
575 description
=> "The drive's media type.",
581 format_description
=> 'count',
582 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
587 format_description
=> 'count',
588 description
=> "Force the drive's physical geometry to have a specific head count.",
593 format_description
=> 'count',
594 description
=> "Force the drive's physical geometry to have a specific sector count.",
599 format_description
=> 'none|lba|auto',
600 enum
=> [qw(none lba auto)],
601 description
=> "Force disk geometry bios translation mode.",
606 format_description
=> 'on|off',
607 description
=> "Whether the drive should be included when making snapshots.",
612 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
613 enum
=> [qw(none writethrough writeback unsafe directsync)],
614 description
=> "The drive's cache mode",
619 format_description
=> 'drive format',
620 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
621 description
=> "The drive's backing file's data format.",
626 format
=> 'disk-size',
627 description
=> "Disk size. This is purely informational and has no effect.",
632 format_description
=> 'on|off',
633 description
=> "Whether the drive should be included when making backups.",
638 format_description
=> 'enospc|ignore|report|stop',
639 enum
=> [qw(enospc ignore report stop)],
640 description
=> 'Write error action.',
645 format_description
=> 'native|threads',
646 enum
=> [qw(native threads)],
647 description
=> 'AIO type to use.',
652 format_description
=> 'ignore|on',
653 enum
=> [qw(ignore on)],
654 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
659 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
664 format
=> 'urlencoded',
665 format_description
=> 'serial',
666 maxLength
=> 20*3, # *3 since it's %xx url enoded
667 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
675 format_description
=> 'ignore|report|stop',
676 enum
=> [qw(ignore report stop)],
677 description
=> 'Read error action.',
682 my %iothread_fmt = ( iothread
=> {
684 format_description
=> 'off|on',
685 description
=> "Whether to use iothreads for this drive",
692 format
=> 'urlencoded',
693 format_description
=> 'model',
694 maxLength
=> 40*3, # *3 since it's %xx url enoded
695 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
703 format_description
=> 'nbqueues',
704 description
=> "Number of queues.",
710 my $add_throttle_desc = sub {
711 my ($key, $type, $what, $size, $longsize) = @_;
712 $drivedesc_base{$key} = {
714 format_description
=> $size,
715 description
=> "Maximum $what speed in $longsize per second.",
719 # throughput: (leaky bucket)
720 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
721 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
722 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
723 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
724 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
725 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
726 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
727 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
728 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
730 # pools: (pool of IO before throttling starts taking effect)
731 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
732 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
733 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
734 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
735 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
736 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
746 type
=> 'string', format
=> $ide_fmt,
747 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
749 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
758 type
=> 'string', format
=> $scsi_fmt,
759 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
761 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
769 type
=> 'string', format
=> $sata_fmt,
770 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
772 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
781 type
=> 'string', format
=> $virtio_fmt,
782 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
784 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
797 type
=> 'string', format
=> 'pve-qm-usb-device',
798 format_description
=> 'HOSTUSBDEVICE|spice',
799 description
=> 'The Host USB device or port or the value spice',
804 format_description
=> 'yes|no',
805 description
=> 'Specifies whether if given host option is a USB3 device or port',
811 type
=> 'string', format
=> $usb_fmt,
812 description
=> <<EODESCR,
813 Configure an USB device (n is 0 to 4). This can be used to
814 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
816 'bus-port(.port)*' (decimal numbers) or
817 'vendor_id:product_id' (hexadeciaml numbers) or
820 You can use the 'lsusb -t' command to list existing usb devices.
822 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
824 The value 'spice' can be used to add a usb redirection devices for spice.
826 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).
830 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
834 type
=> 'string', format
=> 'pve-qm-hostpci',
835 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
836 description
=> <<EODESCR,
837 Map host pci devices. HOSTPCIDEVICE syntax is:
839 'bus:dev.func' (hexadecimal numbers)
841 You can us the 'lspci' command to list existing pci devices.
843 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
845 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
847 Experimental: user reported problems with this option.
850 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
855 pattern
=> '(/dev/.+|socket)',
856 description
=> <<EODESCR,
857 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).
859 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
861 Experimental: user reported problems with this option.
868 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
869 description
=> <<EODESCR,
870 Map host parallel devices (n is 0 to 2).
872 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
874 Experimental: user reported problems with this option.
878 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
879 $confdesc->{"parallel$i"} = $paralleldesc;
882 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
883 $confdesc->{"serial$i"} = $serialdesc;
886 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
887 $confdesc->{"hostpci$i"} = $hostpcidesc;
890 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
891 $drivename_hash->{"ide$i"} = 1;
892 $confdesc->{"ide$i"} = $idedesc;
895 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
896 $drivename_hash->{"sata$i"} = 1;
897 $confdesc->{"sata$i"} = $satadesc;
900 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
901 $drivename_hash->{"scsi$i"} = 1;
902 $confdesc->{"scsi$i"} = $scsidesc ;
905 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
906 $drivename_hash->{"virtio$i"} = 1;
907 $confdesc->{"virtio$i"} = $virtiodesc;
910 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
911 $confdesc->{"usb$i"} = $usbdesc;
916 type
=> 'string', format
=> 'pve-volume-id',
917 description
=> "Reference to unused volumes.",
920 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
921 $confdesc->{"unused$i"} = $unuseddesc;
924 my $kvm_api_version = 0;
928 return $kvm_api_version if $kvm_api_version;
930 my $fh = IO
::File-
>new("</dev/kvm") ||
933 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
934 $kvm_api_version = $v;
939 return $kvm_api_version;
942 my $kvm_user_version;
944 sub kvm_user_version
{
946 return $kvm_user_version if $kvm_user_version;
948 $kvm_user_version = 'unknown';
952 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
953 $kvm_user_version = $2;
957 eval { run_command
("kvm -version", outfunc
=> $code); };
960 return $kvm_user_version;
964 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
966 sub valid_drive_names
{
967 # order is important - used to autoselect boot disk
968 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
969 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
970 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
971 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
974 sub is_valid_drivename
{
977 return defined($drivename_hash->{$dev});
982 return defined($confdesc->{$key});
986 return $nic_model_list;
989 sub os_list_description
{
994 w2k
=> 'Windows 2000',
995 w2k3
=>, 'Windows 2003',
996 w2k8
=> 'Windows 2008',
997 wvista
=> 'Windows Vista',
999 win8
=> 'Windows 8/2012',
1007 sub get_cdrom_path
{
1009 return $cdrom_path if $cdrom_path;
1011 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1012 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1013 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1017 my ($storecfg, $vmid, $cdrom) = @_;
1019 if ($cdrom eq 'cdrom') {
1020 return get_cdrom_path
();
1021 } elsif ($cdrom eq 'none') {
1023 } elsif ($cdrom =~ m
|^/|) {
1026 return PVE
::Storage
::path
($storecfg, $cdrom);
1030 # try to convert old style file names to volume IDs
1031 sub filename_to_volume_id
{
1032 my ($vmid, $file, $media) = @_;
1034 if (!($file eq 'none' || $file eq 'cdrom' ||
1035 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1037 return undef if $file =~ m
|/|;
1039 if ($media && $media eq 'cdrom') {
1040 $file = "local:iso/$file";
1042 $file = "local:$vmid/$file";
1049 sub verify_media_type
{
1050 my ($opt, $vtype, $media) = @_;
1055 if ($media eq 'disk') {
1057 } elsif ($media eq 'cdrom') {
1060 die "internal error";
1063 return if ($vtype eq $etype);
1065 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1068 sub cleanup_drive_path
{
1069 my ($opt, $storecfg, $drive) = @_;
1071 # try to convert filesystem paths to volume IDs
1073 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1074 ($drive->{file
} !~ m
|^/dev/.+|) &&
1075 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1076 ($drive->{file
} !~ m/^\d+$/)) {
1077 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1078 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1079 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1080 verify_media_type
($opt, $vtype, $drive->{media
});
1081 $drive->{file
} = $volid;
1084 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1087 sub parse_hotplug_features
{
1092 return $res if $data eq '0';
1094 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1096 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1097 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1100 warn "ignoring unknown hotplug feature '$feature'\n";
1106 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1107 sub pve_verify_hotplug_features
{
1108 my ($value, $noerr) = @_;
1110 return $value if parse_hotplug_features
($value);
1112 return undef if $noerr;
1114 die "unable to parse hotplug option\n";
1117 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1118 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1119 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1120 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1121 # [,iothread=on][,serial=serial][,model=model]
1124 my ($key, $data) = @_;
1126 my ($interface, $index);
1128 if ($key =~ m/^([^\d]+)(\d+)$/) {
1135 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1136 : $confdesc->{$key}->{format
};
1138 warn "invalid drive key: $key\n";
1141 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1142 return undef if !$res;
1143 $res->{interface
} = $interface;
1144 $res->{index} = $index;
1147 foreach my $opt (qw(bps bps_rd bps_wr)) {
1148 if (my $bps = defined(delete $res->{$opt})) {
1149 if (defined($res->{"m$opt"})) {
1150 warn "both $opt and m$opt specified\n";
1154 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1157 return undef if $error;
1159 return undef if $res->{mbps_rd
} && $res->{mbps
};
1160 return undef if $res->{mbps_wr
} && $res->{mbps
};
1161 return undef if $res->{iops_rd
} && $res->{iops
};
1162 return undef if $res->{iops_wr
} && $res->{iops
};
1164 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1165 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1166 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1167 return undef if $res->{interface
} eq 'virtio';
1170 if (my $size = $res->{size
}) {
1171 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1178 my ($vmid, $drive) = @_;
1179 my $data = { %$drive };
1180 delete $data->{$_} for qw(index interface);
1181 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1185 my($fh, $noerr) = @_;
1188 my $SG_GET_VERSION_NUM = 0x2282;
1190 my $versionbuf = "\x00" x
8;
1191 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1193 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1196 my $version = unpack("I", $versionbuf);
1197 if ($version < 30000) {
1198 die "scsi generic interface too old\n" if !$noerr;
1202 my $buf = "\x00" x
36;
1203 my $sensebuf = "\x00" x
8;
1204 my $cmd = pack("C x3 C x1", 0x12, 36);
1206 # see /usr/include/scsi/sg.h
1207 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";
1209 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1210 length($sensebuf), 0, length($buf), $buf,
1211 $cmd, $sensebuf, 6000);
1213 $ret = ioctl($fh, $SG_IO, $packet);
1215 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1219 my @res = unpack($sg_io_hdr_t, $packet);
1220 if ($res[17] || $res[18]) {
1221 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1226 (my $byte0, my $byte1, $res->{vendor
},
1227 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1229 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1230 $res->{type
} = $byte0 & 31;
1238 my $fh = IO
::File-
>new("+<$path") || return undef;
1239 my $res = scsi_inquiry
($fh, 1);
1245 sub machine_type_is_q35
{
1248 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1251 sub print_tabletdevice_full
{
1254 my $q35 = machine_type_is_q35
($conf);
1256 # we use uhci for old VMs because tablet driver was buggy in older qemu
1257 my $usbbus = $q35 ?
"ehci" : "uhci";
1259 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1262 sub print_drivedevice_full
{
1263 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1268 if ($drive->{interface
} eq 'virtio') {
1269 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1270 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1271 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1272 } elsif ($drive->{interface
} eq 'scsi') {
1274 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1275 my $unit = $drive->{index} % $maxdev;
1276 my $devicetype = 'hd';
1278 if (drive_is_cdrom
($drive)) {
1281 if ($drive->{file
} =~ m
|^/|) {
1282 $path = $drive->{file
};
1283 if (my $info = path_is_scsi
($path)) {
1284 if ($info->{type
} == 0) {
1285 $devicetype = 'block';
1286 } elsif ($info->{type
} == 1) { # tape
1287 $devicetype = 'generic';
1291 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1294 if($path =~ m/^iscsi\:\/\
//){
1295 $devicetype = 'generic';
1299 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1300 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1302 $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}";
1305 } elsif ($drive->{interface
} eq 'ide'){
1307 my $controller = int($drive->{index} / $maxdev);
1308 my $unit = $drive->{index} % $maxdev;
1309 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1311 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1312 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1313 $model = URI
::Escape
::uri_unescape
($model);
1314 $device .= ",model=$model";
1316 } elsif ($drive->{interface
} eq 'sata'){
1317 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1318 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1319 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1320 } elsif ($drive->{interface
} eq 'usb') {
1322 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1324 die "unsupported interface type";
1327 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1332 sub get_initiator_name
{
1335 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1336 while (defined(my $line = <$fh>)) {
1337 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1346 sub print_drive_full
{
1347 my ($storecfg, $vmid, $drive) = @_;
1350 my $volid = $drive->{file
};
1353 if (drive_is_cdrom
($drive)) {
1354 $path = get_iso_path
($storecfg, $vmid, $volid);
1356 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1358 $path = PVE
::Storage
::path
($storecfg, $volid);
1359 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1360 $format = qemu_img_format
($scfg, $volname);
1368 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);
1369 foreach my $o (@qemu_drive_options) {
1370 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1372 if (my $serial = $drive->{serial
}) {
1373 $serial = URI
::Escape
::uri_unescape
($serial);
1374 $opts .= ",serial=$serial";
1377 $opts .= ",format=$format" if $format && !$drive->{format
};
1379 foreach my $o (qw(bps bps_rd bps_wr)) {
1380 my $v = $drive->{"m$o"};
1381 $opts .= ",$o=" . int($v*1024*1024) if $v;
1384 my $cache_direct = 0;
1386 if (my $cache = $drive->{cache
}) {
1387 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1388 } elsif (!drive_is_cdrom
($drive)) {
1389 $opts .= ",cache=none";
1393 # aio native works only with O_DIRECT
1394 if (!$drive->{aio
}) {
1396 $opts .= ",aio=native";
1398 $opts .= ",aio=threads";
1402 if (!drive_is_cdrom
($drive)) {
1404 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1405 $detectzeroes = 'off';
1406 } elsif ($drive->{discard
}) {
1407 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1409 # This used to be our default with discard not being specified:
1410 $detectzeroes = 'on';
1412 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1415 my $pathinfo = $path ?
"file=$path," : '';
1417 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1420 sub print_netdevice_full
{
1421 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1423 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1425 my $device = $net->{model
};
1426 if ($net->{model
} eq 'virtio') {
1427 $device = 'virtio-net-pci';
1430 my $pciaddr = print_pci_addr
("$netid", $bridges);
1431 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1432 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1433 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1434 my $vectors = $net->{queues
} * 2 + 2;
1435 $tmpstr .= ",vectors=$vectors,mq=on";
1437 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1439 if ($use_old_bios_files) {
1441 if ($device eq 'virtio-net-pci') {
1442 $romfile = 'pxe-virtio.rom';
1443 } elsif ($device eq 'e1000') {
1444 $romfile = 'pxe-e1000.rom';
1445 } elsif ($device eq 'ne2k') {
1446 $romfile = 'pxe-ne2k_pci.rom';
1447 } elsif ($device eq 'pcnet') {
1448 $romfile = 'pxe-pcnet.rom';
1449 } elsif ($device eq 'rtl8139') {
1450 $romfile = 'pxe-rtl8139.rom';
1452 $tmpstr .= ",romfile=$romfile" if $romfile;
1458 sub print_netdev_full
{
1459 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1462 if ($netid =~ m/^net(\d+)$/) {
1466 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1468 my $ifname = "tap${vmid}i$i";
1470 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1471 die "interface name '$ifname' is too long (max 15 character)\n"
1472 if length($ifname) >= 16;
1474 my $vhostparam = '';
1475 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1477 my $vmname = $conf->{name
} || "vm$vmid";
1480 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1482 if ($net->{bridge
}) {
1483 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1485 $netdev = "type=user,id=$netid,hostname=$vmname";
1488 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1493 sub drive_is_cdrom
{
1496 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1500 sub parse_number_sets
{
1503 foreach my $part (split(/;/, $set)) {
1504 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1505 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1506 push @$res, [ $1, $2 ];
1508 die "invalid range: $part\n";
1517 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1518 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1519 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1526 return undef if !$value;
1529 my @list = split(/,/, $value);
1533 foreach my $kv (@list) {
1535 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1538 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1541 my $pcidevices = lspci
($2);
1542 $res->{pciid
} = $pcidevices->{$2};
1544 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1545 $res->{rombar
} = $1;
1546 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1547 $res->{'x-vga'} = $1;
1548 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1549 $res->{pcie
} = 1 if $1 == 1;
1551 warn "unknown hostpci setting '$kv'\n";
1555 return undef if !$found;
1560 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1566 foreach my $kvp (split(/,/, $data)) {
1568 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) {
1570 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1571 $res->{model
} = $model;
1572 $res->{macaddr
} = $mac;
1573 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1574 $res->{bridge
} = $1;
1575 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1576 $res->{queues
} = $1;
1577 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1579 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1581 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1582 $res->{trunks
} = $1;
1583 } elsif ($kvp =~ m/^firewall=([01])$/) {
1584 $res->{firewall
} = $1;
1585 } elsif ($kvp =~ m/^link_down=([01])$/) {
1586 $res->{link_down
} = $1;
1593 return undef if !$res->{model
};
1601 my $res = "$net->{model}";
1602 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1603 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1604 $res .= ",rate=$net->{rate}" if $net->{rate
};
1605 $res .= ",tag=$net->{tag}" if $net->{tag
};
1606 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1607 $res .= ",firewall=1" if $net->{firewall
};
1608 $res .= ",link_down=1" if $net->{link_down
};
1609 $res .= ",queues=$net->{queues}" if $net->{queues
};
1614 sub add_random_macs
{
1615 my ($settings) = @_;
1617 foreach my $opt (keys %$settings) {
1618 next if $opt !~ m/^net(\d+)$/;
1619 my $net = parse_net
($settings->{$opt});
1621 $settings->{$opt} = print_net
($net);
1625 sub vm_is_volid_owner
{
1626 my ($storecfg, $vmid, $volid) = @_;
1628 if ($volid !~ m
|^/|) {
1630 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1631 if ($owner && ($owner == $vmid)) {
1639 sub split_flagged_list
{
1640 my $text = shift || '';
1641 $text =~ s/[,;]/ /g;
1643 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1646 sub join_flagged_list
{
1647 my ($how, $lst) = @_;
1648 join $how, map { $lst->{$_} . $_ } keys %$lst;
1651 sub vmconfig_delete_pending_option
{
1652 my ($conf, $key, $force) = @_;
1654 delete $conf->{pending
}->{$key};
1655 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1656 $pending_delete_hash->{$key} = $force ?
'!' : '';
1657 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1660 sub vmconfig_undelete_pending_option
{
1661 my ($conf, $key) = @_;
1663 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1664 delete $pending_delete_hash->{$key};
1666 if (%$pending_delete_hash) {
1667 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1669 delete $conf->{pending
}->{delete};
1673 sub vmconfig_register_unused_drive
{
1674 my ($storecfg, $vmid, $conf, $drive) = @_;
1676 if (!drive_is_cdrom
($drive)) {
1677 my $volid = $drive->{file
};
1678 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1679 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1684 sub vmconfig_cleanup_pending
{
1687 # remove pending changes when nothing changed
1689 foreach my $opt (keys %{$conf->{pending
}}) {
1690 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1692 delete $conf->{pending
}->{$opt};
1696 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1697 my $pending_delete_hash = {};
1698 while (my ($opt, $force) = each %$current_delete_hash) {
1699 if (defined($conf->{$opt})) {
1700 $pending_delete_hash->{$opt} = $force;
1706 if (%$pending_delete_hash) {
1707 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1709 delete $conf->{pending
}->{delete};
1715 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1719 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1720 format_description
=> 'UUID',
1726 format_description
=> 'str',
1732 format_description
=> 'str',
1738 format_description
=> 'name',
1744 format_description
=> 'name',
1750 format_description
=> 'str',
1756 format_description
=> 'str',
1764 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1771 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1774 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1776 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1777 sub verify_bootdisk
{
1778 my ($value, $noerr) = @_;
1780 return $value if is_valid_drivename
($value);
1782 return undef if $noerr;
1784 die "invalid boot disk '$value'\n";
1787 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1789 my ($value, $noerr) = @_;
1791 return $value if parse_net
($value);
1793 return undef if $noerr;
1795 die "unable to parse network options\n";
1798 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1799 sub verify_hostpci
{
1800 my ($value, $noerr) = @_;
1802 return $value if parse_hostpci
($value);
1804 return undef if $noerr;
1806 die "unable to parse pci id\n";
1809 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1810 sub verify_watchdog
{
1811 my ($value, $noerr) = @_;
1813 return $value if parse_watchdog
($value);
1815 return undef if $noerr;
1817 die "unable to parse watchdog options\n";
1820 sub parse_watchdog
{
1823 return undef if !$value;
1827 foreach my $p (split(/,/, $value)) {
1828 next if $p =~ m/^\s*$/;
1830 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1832 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1833 $res->{action
} = $2;
1842 sub parse_usb_device
{
1845 return undef if !$value;
1848 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1849 $res->{vendorid
} = $2;
1850 $res->{productid
} = $4;
1851 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1852 $res->{hostbus
} = $1;
1853 $res->{hostport
} = $2;
1854 } elsif ($value =~ m/^spice$/i) {
1863 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1864 sub verify_usb_device
{
1865 my ($value, $noerr) = @_;
1867 return $value if parse_usb_device
($value);
1869 return undef if $noerr;
1871 die "unable to parse usb device\n";
1874 # add JSON properties for create and set function
1875 sub json_config_properties
{
1878 foreach my $opt (keys %$confdesc) {
1879 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1880 $prop->{$opt} = $confdesc->{$opt};
1887 my ($key, $value) = @_;
1889 die "unknown setting '$key'\n" if !$confdesc->{$key};
1891 my $type = $confdesc->{$key}->{type
};
1893 if (!defined($value)) {
1894 die "got undefined value\n";
1897 if ($value =~ m/[\n\r]/) {
1898 die "property contains a line feed\n";
1901 if ($type eq 'boolean') {
1902 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1903 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1904 die "type check ('boolean') failed - got '$value'\n";
1905 } elsif ($type eq 'integer') {
1906 return int($1) if $value =~ m/^(\d+)$/;
1907 die "type check ('integer') failed - got '$value'\n";
1908 } elsif ($type eq 'number') {
1909 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1910 die "type check ('number') failed - got '$value'\n";
1911 } elsif ($type eq 'string') {
1912 if (my $fmt = $confdesc->{$key}->{format
}) {
1913 if ($fmt eq 'pve-qm-drive') {
1914 # special case - we need to pass $key to parse_drive()
1915 my $drive = parse_drive
($key, $value);
1916 return $value if $drive;
1917 die "unable to parse drive options\n";
1919 PVE
::JSONSchema
::check_format
($fmt, $value);
1922 $value =~ s/^\"(.*)\"$/$1/;
1925 die "internal error"
1929 sub check_iommu_support
{
1930 #fixme : need to check IOMMU support
1931 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1941 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1942 utime undef, undef, $conf;
1946 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1948 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1950 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1952 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1954 # only remove disks owned by this VM
1955 foreach_drive
($conf, sub {
1956 my ($ds, $drive) = @_;
1958 return if drive_is_cdrom
($drive);
1960 my $volid = $drive->{file
};
1962 return if !$volid || $volid =~ m
|^/|;
1964 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1965 return if !$path || !$owner || ($owner != $vmid);
1967 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1970 if ($keep_empty_config) {
1971 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1976 # also remove unused disk
1978 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1981 PVE
::Storage
::foreach_volid
($dl, sub {
1982 my ($volid, $sid, $volname, $d) = @_;
1983 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1992 sub parse_vm_config
{
1993 my ($filename, $raw) = @_;
1995 return undef if !defined($raw);
1998 digest
=> Digest
::SHA
::sha1_hex
($raw),
2003 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2004 || die "got strange filename '$filename'";
2012 my @lines = split(/\n/, $raw);
2013 foreach my $line (@lines) {
2014 next if $line =~ m/^\s*$/;
2016 if ($line =~ m/^\[PENDING\]\s*$/i) {
2017 $section = 'pending';
2018 if (defined($descr)) {
2020 $conf->{description
} = $descr;
2023 $conf = $res->{$section} = {};
2026 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2028 if (defined($descr)) {
2030 $conf->{description
} = $descr;
2033 $conf = $res->{snapshots
}->{$section} = {};
2037 if ($line =~ m/^\#(.*)\s*$/) {
2038 $descr = '' if !defined($descr);
2039 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2043 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2044 $descr = '' if !defined($descr);
2045 $descr .= PVE
::Tools
::decode_text
($2);
2046 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2047 $conf->{snapstate
} = $1;
2048 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2051 $conf->{$key} = $value;
2052 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2054 if ($section eq 'pending') {
2055 $conf->{delete} = $value; # we parse this later
2057 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2059 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2062 eval { $value = check_type
($key, $value); };
2064 warn "vm $vmid - unable to parse value of '$key' - $@";
2066 my $fmt = $confdesc->{$key}->{format
};
2067 if ($fmt && $fmt eq 'pve-qm-drive') {
2068 my $v = parse_drive
($key, $value);
2069 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2070 $v->{file
} = $volid;
2071 $value = print_drive
($vmid, $v);
2073 warn "vm $vmid - unable to parse value of '$key'\n";
2078 if ($key eq 'cdrom') {
2079 $conf->{ide2
} = $value;
2081 $conf->{$key} = $value;
2087 if (defined($descr)) {
2089 $conf->{description
} = $descr;
2091 delete $res->{snapstate
}; # just to be sure
2096 sub write_vm_config
{
2097 my ($filename, $conf) = @_;
2099 delete $conf->{snapstate
}; # just to be sure
2101 if ($conf->{cdrom
}) {
2102 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2103 $conf->{ide2
} = $conf->{cdrom
};
2104 delete $conf->{cdrom
};
2107 # we do not use 'smp' any longer
2108 if ($conf->{sockets
}) {
2109 delete $conf->{smp
};
2110 } elsif ($conf->{smp
}) {
2111 $conf->{sockets
} = $conf->{smp
};
2112 delete $conf->{cores
};
2113 delete $conf->{smp
};
2116 my $used_volids = {};
2118 my $cleanup_config = sub {
2119 my ($cref, $pending, $snapname) = @_;
2121 foreach my $key (keys %$cref) {
2122 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2123 $key eq 'snapstate' || $key eq 'pending';
2124 my $value = $cref->{$key};
2125 if ($key eq 'delete') {
2126 die "propertry 'delete' is only allowed in [PENDING]\n"
2128 # fixme: check syntax?
2131 eval { $value = check_type
($key, $value); };
2132 die "unable to parse value of '$key' - $@" if $@;
2134 $cref->{$key} = $value;
2136 if (!$snapname && is_valid_drivename
($key)) {
2137 my $drive = parse_drive
($key, $value);
2138 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2143 &$cleanup_config($conf);
2145 &$cleanup_config($conf->{pending
}, 1);
2147 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2148 die "internal error" if $snapname eq 'pending';
2149 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2152 # remove 'unusedX' settings if we re-add a volume
2153 foreach my $key (keys %$conf) {
2154 my $value = $conf->{$key};
2155 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2156 delete $conf->{$key};
2160 my $generate_raw_config = sub {
2161 my ($conf, $pending) = @_;
2165 # add description as comment to top of file
2166 if (defined(my $descr = $conf->{description
})) {
2168 foreach my $cl (split(/\n/, $descr)) {
2169 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2172 $raw .= "#\n" if $pending;
2176 foreach my $key (sort keys %$conf) {
2177 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2178 $raw .= "$key: $conf->{$key}\n";
2183 my $raw = &$generate_raw_config($conf);
2185 if (scalar(keys %{$conf->{pending
}})){
2186 $raw .= "\n[PENDING]\n";
2187 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2190 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2191 $raw .= "\n[$snapname]\n";
2192 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2202 # we use static defaults from our JSON schema configuration
2203 foreach my $key (keys %$confdesc) {
2204 if (defined(my $default = $confdesc->{$key}->{default})) {
2205 $res->{$key} = $default;
2209 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2210 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2216 my $vmlist = PVE
::Cluster
::get_vmlist
();
2218 return $res if !$vmlist || !$vmlist->{ids
};
2219 my $ids = $vmlist->{ids
};
2221 foreach my $vmid (keys %$ids) {
2222 my $d = $ids->{$vmid};
2223 next if !$d->{node
} || $d->{node
} ne $nodename;
2224 next if !$d->{type
} || $d->{type
} ne 'qemu';
2225 $res->{$vmid}->{exists} = 1;
2230 # test if VM uses local resources (to prevent migration)
2231 sub check_local_resources
{
2232 my ($conf, $noerr) = @_;
2236 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2237 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2239 foreach my $k (keys %$conf) {
2240 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2241 # sockets are safe: they will recreated be on the target side post-migrate
2242 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2243 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2246 die "VM uses local resources\n" if $loc_res && !$noerr;
2251 # check if used storages are available on all nodes (use by migrate)
2252 sub check_storage_availability
{
2253 my ($storecfg, $conf, $node) = @_;
2255 foreach_drive
($conf, sub {
2256 my ($ds, $drive) = @_;
2258 my $volid = $drive->{file
};
2261 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2264 # check if storage is available on both nodes
2265 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2266 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2270 # list nodes where all VM images are available (used by has_feature API)
2272 my ($conf, $storecfg) = @_;
2274 my $nodelist = PVE
::Cluster
::get_nodelist
();
2275 my $nodehash = { map { $_ => 1 } @$nodelist };
2276 my $nodename = PVE
::INotify
::nodename
();
2278 foreach_drive
($conf, sub {
2279 my ($ds, $drive) = @_;
2281 my $volid = $drive->{file
};
2284 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2286 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2287 if ($scfg->{disable
}) {
2289 } elsif (my $avail = $scfg->{nodes
}) {
2290 foreach my $node (keys %$nodehash) {
2291 delete $nodehash->{$node} if !$avail->{$node};
2293 } elsif (!$scfg->{shared
}) {
2294 foreach my $node (keys %$nodehash) {
2295 delete $nodehash->{$node} if $node ne $nodename
2305 my ($pidfile, $pid) = @_;
2307 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2311 return undef if !$line;
2312 my @param = split(/\0/, $line);
2314 my $cmd = $param[0];
2315 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2317 for (my $i = 0; $i < scalar (@param); $i++) {
2320 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2321 my $p = $param[$i+1];
2322 return 1 if $p && ($p eq $pidfile);
2331 my ($vmid, $nocheck, $node) = @_;
2333 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2335 die "unable to find configuration file for VM $vmid - no such machine\n"
2336 if !$nocheck && ! -f
$filename;
2338 my $pidfile = pidfile_name
($vmid);
2340 if (my $fd = IO
::File-
>new("<$pidfile")) {
2345 my $mtime = $st->mtime;
2346 if ($mtime > time()) {
2347 warn "file '$filename' modified in future\n";
2350 if ($line =~ m/^(\d+)$/) {
2352 if (check_cmdline
($pidfile, $pid)) {
2353 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2365 my $vzlist = config_list
();
2367 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2369 while (defined(my $de = $fd->read)) {
2370 next if $de !~ m/^(\d+)\.pid$/;
2372 next if !defined($vzlist->{$vmid});
2373 if (my $pid = check_running
($vmid)) {
2374 $vzlist->{$vmid}->{pid
} = $pid;
2382 my ($storecfg, $conf) = @_;
2384 my $bootdisk = $conf->{bootdisk
};
2385 return undef if !$bootdisk;
2386 return undef if !is_valid_drivename
($bootdisk);
2388 return undef if !$conf->{$bootdisk};
2390 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2391 return undef if !defined($drive);
2393 return undef if drive_is_cdrom
($drive);
2395 my $volid = $drive->{file
};
2396 return undef if !$volid;
2398 return $drive->{size
};
2401 my $last_proc_pid_stat;
2403 # get VM status information
2404 # This must be fast and should not block ($full == false)
2405 # We only query KVM using QMP if $full == true (this can be slow)
2407 my ($opt_vmid, $full) = @_;
2411 my $storecfg = PVE
::Storage
::config
();
2413 my $list = vzlist
();
2414 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2416 my $cpucount = $cpuinfo->{cpus
} || 1;
2418 foreach my $vmid (keys %$list) {
2419 next if $opt_vmid && ($vmid ne $opt_vmid);
2421 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2422 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2425 $d->{pid
} = $list->{$vmid}->{pid
};
2427 # fixme: better status?
2428 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2430 my $size = disksize
($storecfg, $conf);
2431 if (defined($size)) {
2432 $d->{disk
} = 0; # no info available
2433 $d->{maxdisk
} = $size;
2439 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2440 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2441 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2443 $d->{name
} = $conf->{name
} || "VM $vmid";
2444 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2446 if ($conf->{balloon
}) {
2447 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2448 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2459 $d->{diskwrite
} = 0;
2461 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2466 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2467 foreach my $dev (keys %$netdev) {
2468 next if $dev !~ m/^tap([1-9]\d*)i/;
2470 my $d = $res->{$vmid};
2473 $d->{netout
} += $netdev->{$dev}->{receive
};
2474 $d->{netin
} += $netdev->{$dev}->{transmit
};
2477 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2478 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2483 my $ctime = gettimeofday
;
2485 foreach my $vmid (keys %$list) {
2487 my $d = $res->{$vmid};
2488 my $pid = $d->{pid
};
2491 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2492 next if !$pstat; # not running
2494 my $used = $pstat->{utime} + $pstat->{stime
};
2496 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2498 if ($pstat->{vsize
}) {
2499 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2502 my $old = $last_proc_pid_stat->{$pid};
2504 $last_proc_pid_stat->{$pid} = {
2512 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2514 if ($dtime > 1000) {
2515 my $dutime = $used - $old->{used
};
2517 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2518 $last_proc_pid_stat->{$pid} = {
2524 $d->{cpu
} = $old->{cpu
};
2528 return $res if !$full;
2530 my $qmpclient = PVE
::QMPClient-
>new();
2532 my $ballooncb = sub {
2533 my ($vmid, $resp) = @_;
2535 my $info = $resp->{'return'};
2536 return if !$info->{max_mem
};
2538 my $d = $res->{$vmid};
2540 # use memory assigned to VM
2541 $d->{maxmem
} = $info->{max_mem
};
2542 $d->{balloon
} = $info->{actual
};
2544 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2545 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2546 $d->{freemem
} = $info->{free_mem
};
2549 $d->{ballooninfo
} = $info;
2552 my $blockstatscb = sub {
2553 my ($vmid, $resp) = @_;
2554 my $data = $resp->{'return'} || [];
2555 my $totalrdbytes = 0;
2556 my $totalwrbytes = 0;
2558 for my $blockstat (@$data) {
2559 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2560 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2562 $blockstat->{device
} =~ s/drive-//;
2563 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2565 $res->{$vmid}->{diskread
} = $totalrdbytes;
2566 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2569 my $statuscb = sub {
2570 my ($vmid, $resp) = @_;
2572 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2573 # this fails if ballon driver is not loaded, so this must be
2574 # the last commnand (following command are aborted if this fails).
2575 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2577 my $status = 'unknown';
2578 if (!defined($status = $resp->{'return'}->{status
})) {
2579 warn "unable to get VM status\n";
2583 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2586 foreach my $vmid (keys %$list) {
2587 next if $opt_vmid && ($vmid ne $opt_vmid);
2588 next if !$res->{$vmid}->{pid
}; # not running
2589 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2592 $qmpclient->queue_execute(undef, 1);
2594 foreach my $vmid (keys %$list) {
2595 next if $opt_vmid && ($vmid ne $opt_vmid);
2596 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2603 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2606 my $current_size = 1024;
2607 my $dimm_size = 512;
2608 return if $current_size == $memory;
2610 for (my $j = 0; $j < 8; $j++) {
2611 for (my $i = 0; $i < 32; $i++) {
2612 my $name = "dimm${dimm_id}";
2614 my $numanode = $i % $sockets;
2615 $current_size += $dimm_size;
2616 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2617 return $current_size if $current_size >= $memory;
2623 sub foreach_reverse_dimm
{
2624 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2627 my $current_size = 4177920;
2628 my $dimm_size = 65536;
2629 return if $current_size == $memory;
2631 for (my $j = 0; $j < 8; $j++) {
2632 for (my $i = 0; $i < 32; $i++) {
2633 my $name = "dimm${dimm_id}";
2635 my $numanode = $i % $sockets;
2636 $current_size -= $dimm_size;
2637 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2638 return $current_size if $current_size <= $memory;
2645 my ($conf, $func) = @_;
2647 foreach my $ds (valid_drive_names
()) {
2648 next if !defined($conf->{$ds});
2650 my $drive = parse_drive
($ds, $conf->{$ds});
2653 &$func($ds, $drive);
2658 my ($conf, $func) = @_;
2662 my $test_volid = sub {
2663 my ($volid, $is_cdrom) = @_;
2667 $volhash->{$volid} = $is_cdrom || 0;
2670 foreach_drive
($conf, sub {
2671 my ($ds, $drive) = @_;
2672 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2675 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2676 my $snap = $conf->{snapshots
}->{$snapname};
2677 &$test_volid($snap->{vmstate
}, 0);
2678 foreach_drive
($snap, sub {
2679 my ($ds, $drive) = @_;
2680 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2684 foreach my $volid (keys %$volhash) {
2685 &$func($volid, $volhash->{$volid});
2689 sub vga_conf_has_spice
{
2692 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2697 sub config_to_command
{
2698 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2701 my $globalFlags = [];
2702 my $machineFlags = [];
2708 my $kvmver = kvm_user_version
();
2709 my $vernum = 0; # unknown
2710 my $ostype = $conf->{ostype
};
2711 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2712 $vernum = $1*1000000+$2*1000;
2713 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2714 $vernum = $1*1000000+$2*1000+$3;
2717 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2719 my $have_ovz = -f
'/proc/vz/vestat';
2721 my $q35 = machine_type_is_q35
($conf);
2722 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2723 my $machine_type = $forcemachine || $conf->{machine
};
2724 my $use_old_bios_files = undef;
2725 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2727 my $cpuunits = defined($conf->{cpuunits
}) ?
2728 $conf->{cpuunits
} : $defaults->{cpuunits
};
2730 push @$cmd, '/usr/bin/systemd-run';
2731 push @$cmd, '--scope';
2732 push @$cmd, '--slice', "qemu";
2733 push @$cmd, '--unit', $vmid;
2734 # set KillMode=none, so that systemd don't kill those scopes
2735 # at shutdown (pve-manager service should stop the VMs instead)
2736 push @$cmd, '-p', "KillMode=none";
2737 push @$cmd, '-p', "CPUShares=$cpuunits";
2738 if ($conf->{cpulimit
}) {
2739 my $cpulimit = int($conf->{cpulimit
} * 100);
2740 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2743 push @$cmd, '/usr/bin/kvm';
2745 push @$cmd, '-id', $vmid;
2749 my $qmpsocket = qmp_socket
($vmid);
2750 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2751 push @$cmd, '-mon', "chardev=qmp,mode=control";
2754 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2756 push @$cmd, '-daemonize';
2758 if ($conf->{smbios1
}) {
2759 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2762 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2763 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2764 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2765 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2766 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2767 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2768 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2772 # the q35 chipset support native usb2, so we enable usb controller
2773 # by default for this machine type
2774 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2776 $pciaddr = print_pci_addr
("piix3", $bridges);
2777 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2780 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2781 next if !$conf->{"usb$i"};
2782 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2783 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2786 # include usb device config
2787 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2790 # add usb3 controller if needed
2793 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2794 next if !$conf->{"usb$i"};
2795 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2796 next if !$d || !$d->{usb3
};
2800 $pciaddr = print_pci_addr
("xhci", $bridges);
2801 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2803 my $vga = $conf->{vga
};
2805 my $qxlnum = vga_conf_has_spice
($vga);
2806 $vga = 'qxl' if $qxlnum;
2809 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2810 $conf->{ostype
} eq 'win7' ||
2811 $conf->{ostype
} eq 'w2k8')) {
2818 # enable absolute mouse coordinates (needed by vnc)
2820 if (defined($conf->{tablet
})) {
2821 $tablet = $conf->{tablet
};
2823 $tablet = $defaults->{tablet
};
2824 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2825 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2828 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2832 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2833 my $d = parse_hostpci
($conf->{"hostpci$i"});
2836 my $pcie = $d->{pcie
};
2838 die "q35 machine model is not enabled" if !$q35;
2839 $pciaddr = print_pcie_addr
("hostpci$i");
2841 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2844 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2845 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2846 if ($xvga && $xvga ne '') {
2849 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2850 push @$cpuFlags , 'hv_vendor_id=proxmox';
2852 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2856 my $pcidevices = $d->{pciid
};
2857 my $multifunction = 1 if @$pcidevices > 1;
2860 foreach my $pcidevice (@$pcidevices) {
2862 my $id = "hostpci$i";
2863 $id .= ".$j" if $multifunction;
2864 my $addr = $pciaddr;
2865 $addr .= ".$j" if $multifunction;
2866 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2869 $devicestr .= "$rombar$xvga";
2870 $devicestr .= ",multifunction=on" if $multifunction;
2873 push @$devices, '-device', $devicestr;
2879 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2880 next if !$conf->{"usb$i"};
2881 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2884 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2886 if (defined($d->{usb3
}) && $d->{usb3
}) {
2887 $usbbus = ',bus=xhci.0';
2890 if (defined($d->{host
})) {
2891 $d = parse_usb_device
($d->{host
});
2892 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2893 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2894 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2895 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2896 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2897 # usb redir support for spice, currently no usb3
2898 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2899 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2905 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2906 if (my $path = $conf->{"serial$i"}) {
2907 if ($path eq 'socket') {
2908 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2909 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2910 push @$devices, '-device', "isa-serial,chardev=serial$i";
2912 die "no such serial device\n" if ! -c
$path;
2913 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2914 push @$devices, '-device', "isa-serial,chardev=serial$i";
2920 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2921 if (my $path = $conf->{"parallel$i"}) {
2922 die "no such parallel device\n" if ! -c
$path;
2923 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2924 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2925 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2929 my $vmname = $conf->{name
} || "vm$vmid";
2931 push @$cmd, '-name', $vmname;
2934 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2935 $sockets = $conf->{sockets
} if $conf->{sockets
};
2937 my $cores = $conf->{cores
} || 1;
2939 my $maxcpus = $sockets * $cores;
2941 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2943 my $allowed_vcpus = $cpuinfo->{cpus
};
2945 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2946 if ($allowed_vcpus < $maxcpus);
2948 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2950 push @$cmd, '-nodefaults';
2952 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2954 my $bootindex_hash = {};
2956 foreach my $o (split(//, $bootorder)) {
2957 $bootindex_hash->{$o} = $i*100;
2961 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2963 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2965 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2967 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2969 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2970 my $socket = vnc_socket
($vmid);
2971 push @$cmd, '-vnc', "unix:$socket,x509,password";
2973 push @$cmd, '-nographic';
2977 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2979 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2980 my $useLocaltime = $conf->{localtime};
2983 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2985 if ($ostype =~ m/^w/) { # windows
2986 $useLocaltime = 1 if !defined($conf->{localtime});
2988 # use time drift fix when acpi is enabled
2989 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2990 $tdf = 1 if !defined($conf->{tdf
});
2994 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2995 $ostype eq 'wvista') {
2996 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2997 push @$cmd, '-no-hpet';
2998 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2999 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3000 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3001 push @$cpuFlags , 'hv_time' if !$nokvm;
3004 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3008 if ($ostype eq 'win7' || $ostype eq 'win8') {
3009 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3013 push @$rtcFlags, 'driftfix=slew' if $tdf;
3016 push @$machineFlags, 'accel=tcg';
3018 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3021 if ($machine_type) {
3022 push @$machineFlags, "type=${machine_type}";
3025 if ($conf->{startdate
}) {
3026 push @$rtcFlags, "base=$conf->{startdate}";
3027 } elsif ($useLocaltime) {
3028 push @$rtcFlags, 'base=localtime';
3031 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3032 if (my $cputype = $conf->{cpu
}) {
3033 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3034 or die "Cannot parse cpu description: $cputype\n";
3035 $cpu = $cpuconf->{cputype
};
3036 $kvm_off = 1 if $cpuconf->{hidden
};
3039 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3041 push @$cpuFlags , '-x2apic'
3042 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3044 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3046 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3048 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3050 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3051 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3054 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3056 push @$cpuFlags, 'kvm=off' if $kvm_off;
3058 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3060 push @$cmd, '-cpu', $cpu;
3062 my $memory = $conf->{memory
} || $defaults->{memory
};
3063 my $static_memory = 0;
3064 my $dimm_memory = 0;
3066 if ($hotplug_features->{memory
}) {
3067 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3068 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3069 $static_memory = $STATICMEM;
3070 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3071 $dimm_memory = $memory - $static_memory;
3072 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3076 $static_memory = $memory;
3077 push @$cmd, '-m', $static_memory;
3080 if ($conf->{numa
}) {
3082 my $numa_totalmemory = undef;
3083 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3084 next if !$conf->{"numa$i"};
3085 my $numa = parse_numa
($conf->{"numa$i"});
3088 die "missing numa node$i memory value\n" if !$numa->{memory
};
3089 my $numa_memory = $numa->{memory
};
3090 $numa_totalmemory += $numa_memory;
3091 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3094 my $cpulists = $numa->{cpus
};
3095 die "missing numa node$i cpus\n" if !defined($cpulists);
3096 my $cpus = join(',', map {
3097 my ($start, $end) = @$_;
3098 defined($end) ?
"$start-$end" : $start
3102 my $hostnodelists = $numa->{hostnodes
};
3103 if (defined($hostnodelists)) {
3105 foreach my $hostnoderange (@$hostnodelists) {
3106 my ($start, $end) = @$hostnoderange;
3107 $hostnodes .= ',' if $hostnodes;
3108 $hostnodes .= $start;
3109 $hostnodes .= "-$end" if defined($end);
3111 for (my $i = $start; $i <= $end; ++$i ) {
3112 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3117 my $policy = $numa->{policy
};
3118 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3119 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3122 push @$cmd, '-object', $numa_object;
3123 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3126 die "total memory for NUMA nodes must be equal to vm static memory\n"
3127 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3129 #if no custom tology, we split memory and cores across numa nodes
3130 if(!$numa_totalmemory) {
3132 my $numa_memory = ($static_memory / $sockets) . "M";
3134 for (my $i = 0; $i < $sockets; $i++) {
3136 my $cpustart = ($cores * $i);
3137 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3138 my $cpus = $cpustart;
3139 $cpus .= "-$cpuend" if $cpuend;
3141 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3142 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3147 if ($hotplug_features->{memory
}) {
3148 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3149 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3150 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3151 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3153 #if dimm_memory is not aligned to dimm map
3154 if($current_size > $memory) {
3155 $conf->{memory
} = $current_size;
3156 PVE
::QemuConfig-
>write_config($vmid, $conf);
3161 push @$cmd, '-S' if $conf->{freeze
};
3163 # set keyboard layout
3164 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3165 push @$cmd, '-k', $kb if $kb;
3168 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3169 #push @$cmd, '-soundhw', 'es1370';
3170 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3172 if($conf->{agent
}) {
3173 my $qgasocket = qmp_socket
($vmid, 1);
3174 my $pciaddr = print_pci_addr
("qga0", $bridges);
3175 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3176 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3177 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3184 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3185 for(my $i = 1; $i < $qxlnum; $i++){
3186 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3187 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3190 # assume other OS works like Linux
3191 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3192 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3196 my $pciaddr = print_pci_addr
("spice", $bridges);
3198 my $nodename = PVE
::INotify
::nodename
();
3199 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3200 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3202 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3204 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3205 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3206 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3209 # enable balloon by default, unless explicitly disabled
3210 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3211 $pciaddr = print_pci_addr
("balloon0", $bridges);
3212 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3215 if ($conf->{watchdog
}) {
3216 my $wdopts = parse_watchdog
($conf->{watchdog
});
3217 $pciaddr = print_pci_addr
("watchdog", $bridges);
3218 my $watchdog = $wdopts->{model
} || 'i6300esb';
3219 push @$devices, '-device', "$watchdog$pciaddr";
3220 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3224 my $scsicontroller = {};
3225 my $ahcicontroller = {};
3226 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3228 # Add iscsi initiator name if available
3229 if (my $initiator = get_initiator_name
()) {
3230 push @$devices, '-iscsi', "initiator-name=$initiator";
3233 foreach_drive
($conf, sub {
3234 my ($ds, $drive) = @_;
3236 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3237 push @$vollist, $drive->{file
};
3240 $use_virtio = 1 if $ds =~ m/^virtio/;
3242 if (drive_is_cdrom
($drive)) {
3243 if ($bootindex_hash->{d
}) {
3244 $drive->{bootindex
} = $bootindex_hash->{d
};
3245 $bootindex_hash->{d
} += 1;
3248 if ($bootindex_hash->{c
}) {
3249 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3250 $bootindex_hash->{c
} += 1;
3254 if($drive->{interface
} eq 'virtio'){
3255 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3258 if ($drive->{interface
} eq 'scsi') {
3260 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3262 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3263 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3266 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3267 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3268 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3272 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3273 $queues = ",num_queues=$drive->{queues}";
3276 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3277 $scsicontroller->{$controller}=1;
3280 if ($drive->{interface
} eq 'sata') {
3281 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3282 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3283 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3284 $ahcicontroller->{$controller}=1;
3287 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3288 push @$devices, '-drive',$drive_cmd;
3289 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3292 for (my $i = 0; $i < $MAX_NETS; $i++) {
3293 next if !$conf->{"net$i"};
3294 my $d = parse_net
($conf->{"net$i"});
3297 $use_virtio = 1 if $d->{model
} eq 'virtio';
3299 if ($bootindex_hash->{n
}) {
3300 $d->{bootindex
} = $bootindex_hash->{n
};
3301 $bootindex_hash->{n
} += 1;
3304 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3305 push @$devices, '-netdev', $netdevfull;
3307 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3308 push @$devices, '-device', $netdevicefull;
3313 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3318 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3320 while (my ($k, $v) = each %$bridges) {
3321 $pciaddr = print_pci_addr
("pci.$k");
3322 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3327 if ($conf->{args
}) {
3328 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3332 push @$cmd, @$devices;
3333 push @$cmd, '-rtc', join(',', @$rtcFlags)
3334 if scalar(@$rtcFlags);
3335 push @$cmd, '-machine', join(',', @$machineFlags)
3336 if scalar(@$machineFlags);
3337 push @$cmd, '-global', join(',', @$globalFlags)
3338 if scalar(@$globalFlags);
3340 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3345 return "${var_run_tmpdir}/$vmid.vnc";
3351 my $res = vm_mon_cmd
($vmid, 'query-spice');
3353 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3357 my ($vmid, $qga) = @_;
3358 my $sockettype = $qga ?
'qga' : 'qmp';
3359 return "${var_run_tmpdir}/$vmid.$sockettype";
3364 return "${var_run_tmpdir}/$vmid.pid";
3367 sub vm_devices_list
{
3370 my $res = vm_mon_cmd
($vmid, 'query-pci');
3372 foreach my $pcibus (@$res) {
3373 foreach my $device (@{$pcibus->{devices
}}) {
3374 next if !$device->{'qdev_id'};
3375 if ($device->{'pci_bridge'}) {
3376 $devices->{$device->{'qdev_id'}} = 1;
3377 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3378 next if !$bridge_device->{'qdev_id'};
3379 $devices->{$bridge_device->{'qdev_id'}} = 1;
3380 $devices->{$device->{'qdev_id'}}++;
3383 $devices->{$device->{'qdev_id'}} = 1;
3388 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3389 foreach my $block (@$resblock) {
3390 if($block->{device
} =~ m/^drive-(\S+)/){
3395 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3396 foreach my $mice (@$resmice) {
3397 if ($mice->{name
} eq 'QEMU HID Tablet') {
3398 $devices->{tablet
} = 1;
3407 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3409 my $q35 = machine_type_is_q35
($conf);
3411 my $devices_list = vm_devices_list
($vmid);
3412 return 1 if defined($devices_list->{$deviceid});
3414 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3416 if ($deviceid eq 'tablet') {
3418 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3420 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3422 qemu_iothread_add
($vmid, $deviceid, $device);
3424 qemu_driveadd
($storecfg, $vmid, $device);
3425 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3427 qemu_deviceadd
($vmid, $devicefull);
3428 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3430 eval { qemu_drivedel
($vmid, $deviceid); };
3435 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3438 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3439 my $pciaddr = print_pci_addr
($deviceid);
3440 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3442 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3444 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3445 qemu_iothread_add
($vmid, $deviceid, $device);
3446 $devicefull .= ",iothread=iothread-$deviceid";
3449 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3450 $devicefull .= ",num_queues=$device->{queues}";
3453 qemu_deviceadd
($vmid, $devicefull);
3454 qemu_deviceaddverify
($vmid, $deviceid);
3456 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3458 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3459 qemu_driveadd
($storecfg, $vmid, $device);
3461 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3462 eval { qemu_deviceadd
($vmid, $devicefull); };
3464 eval { qemu_drivedel
($vmid, $deviceid); };
3469 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3471 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3473 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3474 my $use_old_bios_files = undef;
3475 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3477 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3478 qemu_deviceadd
($vmid, $netdevicefull);
3479 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3481 eval { qemu_netdevdel
($vmid, $deviceid); };
3486 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3489 my $pciaddr = print_pci_addr
($deviceid);
3490 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3492 qemu_deviceadd
($vmid, $devicefull);
3493 qemu_deviceaddverify
($vmid, $deviceid);
3496 die "can't hotplug device '$deviceid'\n";
3502 # fixme: this should raise exceptions on error!
3503 sub vm_deviceunplug
{
3504 my ($vmid, $conf, $deviceid) = @_;
3506 my $devices_list = vm_devices_list
($vmid);
3507 return 1 if !defined($devices_list->{$deviceid});
3509 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3511 if ($deviceid eq 'tablet') {
3513 qemu_devicedel
($vmid, $deviceid);
3515 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3517 qemu_devicedel
($vmid, $deviceid);
3518 qemu_devicedelverify
($vmid, $deviceid);
3519 qemu_drivedel
($vmid, $deviceid);
3520 qemu_iothread_del
($conf, $vmid, $deviceid);
3522 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3524 qemu_devicedel
($vmid, $deviceid);
3525 qemu_devicedelverify
($vmid, $deviceid);
3526 qemu_iothread_del
($conf, $vmid, $deviceid);
3528 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3530 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3531 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3532 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3534 qemu_devicedel
($vmid, $deviceid);
3535 qemu_drivedel
($vmid, $deviceid);
3536 qemu_deletescsihw
($conf, $vmid, $deviceid);
3538 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3540 qemu_devicedel
($vmid, $deviceid);
3541 qemu_devicedelverify
($vmid, $deviceid);
3542 qemu_netdevdel
($vmid, $deviceid);
3545 die "can't unplug device '$deviceid'\n";
3551 sub qemu_deviceadd
{
3552 my ($vmid, $devicefull) = @_;
3554 $devicefull = "driver=".$devicefull;
3555 my %options = split(/[=,]/, $devicefull);
3557 vm_mon_cmd
($vmid, "device_add" , %options);
3560 sub qemu_devicedel
{
3561 my ($vmid, $deviceid) = @_;
3563 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3566 sub qemu_iothread_add
{
3567 my($vmid, $deviceid, $device) = @_;
3569 if ($device->{iothread
}) {
3570 my $iothreads = vm_iothreads_list
($vmid);
3571 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3575 sub qemu_iothread_del
{
3576 my($conf, $vmid, $deviceid) = @_;
3578 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3579 if ($device->{iothread
}) {
3580 my $iothreads = vm_iothreads_list
($vmid);
3581 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3585 sub qemu_objectadd
{
3586 my($vmid, $objectid, $qomtype) = @_;
3588 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3593 sub qemu_objectdel
{
3594 my($vmid, $objectid) = @_;
3596 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3602 my ($storecfg, $vmid, $device) = @_;
3604 my $drive = print_drive_full
($storecfg, $vmid, $device);
3605 $drive =~ s/\\/\\\\/g;
3606 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3608 # If the command succeeds qemu prints: "OK
"
3609 return 1 if $ret =~ m/OK/s;
3611 die "adding drive failed
: $ret\n";
3615 my($vmid, $deviceid) = @_;
3617 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3620 return 1 if $ret eq "";
3622 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3623 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3625 die "deleting drive
$deviceid failed
: $ret\n";
3628 sub qemu_deviceaddverify {
3629 my ($vmid, $deviceid) = @_;
3631 for (my $i = 0; $i <= 5; $i++) {
3632 my $devices_list = vm_devices_list($vmid);
3633 return 1 if defined($devices_list->{$deviceid});
3637 die "error on hotplug device
'$deviceid'\n";
3641 sub qemu_devicedelverify {
3642 my ($vmid, $deviceid) = @_;
3644 # need to verify that the device is correctly removed as device_del
3645 # is async and empty return is not reliable
3647 for (my $i = 0; $i <= 5; $i++) {
3648 my $devices_list = vm_devices_list($vmid);
3649 return 1 if !defined($devices_list->{$deviceid});
3653 die "error on hot-unplugging device
'$deviceid'\n";
3656 sub qemu_findorcreatescsihw {
3657 my ($storecfg, $conf, $vmid, $device) = @_;
3659 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3661 my $scsihwid="$controller_prefix$controller";
3662 my $devices_list = vm_devices_list($vmid);
3664 if(!defined($devices_list->{$scsihwid})) {
3665 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3671 sub qemu_deletescsihw {
3672 my ($conf, $vmid, $opt) = @_;
3674 my $device = parse_drive($opt, $conf->{$opt});
3676 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3677 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3681 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3683 my $devices_list = vm_devices_list($vmid);
3684 foreach my $opt (keys %{$devices_list}) {
3685 if (PVE::QemuServer::is_valid_drivename($opt)) {
3686 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3687 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3693 my $scsihwid="scsihw
$controller";
3695 vm_deviceunplug($vmid, $conf, $scsihwid);
3700 sub qemu_add_pci_bridge {
3701 my ($storecfg, $conf, $vmid, $device) = @_;
3707 print_pci_addr($device, $bridges);
3709 while (my ($k, $v) = each %$bridges) {
3712 return 1 if !defined($bridgeid) || $bridgeid < 1;
3714 my $bridge = "pci
.$bridgeid";
3715 my $devices_list = vm_devices_list($vmid);
3717 if (!defined($devices_list->{$bridge})) {
3718 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3724 sub qemu_set_link_status {
3725 my ($vmid, $device, $up) = @_;
3727 vm_mon_cmd($vmid, "set_link
", name => $device,
3728 up => $up ? JSON::true : JSON::false);
3731 sub qemu_netdevadd {
3732 my ($vmid, $conf, $device, $deviceid) = @_;
3734 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3735 my %options = split(/[=,]/, $netdev);
3737 vm_mon_cmd($vmid, "netdev_add
", %options);
3741 sub qemu_netdevdel {
3742 my ($vmid, $deviceid) = @_;
3744 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3747 sub qemu_cpu_hotplug {
3748 my ($vmid, $conf, $vcpus) = @_;
3751 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3752 $sockets = $conf->{sockets} if $conf->{sockets};
3753 my $cores = $conf->{cores} || 1;
3754 my $maxcpus = $sockets * $cores;
3756 $vcpus = $maxcpus if !$vcpus;
3758 die "you can
't add more vcpus than maxcpus\n"
3759 if $vcpus > $maxcpus;
3761 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3762 die "online cpu unplug is not yet possible\n"
3763 if $vcpus < $currentvcpus;
3765 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3766 die "vcpus in running vm is different than configuration\n"
3767 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3769 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3770 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3774 sub qemu_memory_hotplug {
3775 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3777 return $value if !check_running($vmid);
3779 my $memory = $conf->{memory} || $defaults->{memory};
3780 $value = $defaults->{memory} if !$value;
3781 return $value if $value == $memory;
3783 my $static_memory = $STATICMEM;
3784 my $dimm_memory = $memory - $static_memory;
3786 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3787 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3791 $sockets = $conf->{sockets} if $conf->{sockets};
3793 if($value > $memory) {
3795 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3796 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3798 return if $current_size <= $conf->{memory};
3800 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3802 eval { qemu_objectdel($vmid, "mem-
$name"); };
3806 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3808 eval { qemu_objectdel($vmid, "mem-
$name"); };
3811 #update conf after each succesful module hotplug
3812 $conf->{memory} = $current_size;
3813 PVE::QemuConfig->write_config($vmid, $conf);
3818 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3819 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3821 return if $current_size >= $conf->{memory};
3822 print "try to unplug memory dimm
$name\n";
3826 eval { qemu_devicedel($vmid, $name) };
3828 my $dimm_list = qemu_dimm_list($vmid);
3829 last if !$dimm_list->{$name};
3830 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3834 #update conf after each succesful module unplug
3835 $conf->{memory} = $current_size;
3837 eval { qemu_objectdel($vmid, "mem-
$name"); };
3838 PVE::QemuConfig->write_config($vmid, $conf);
3843 sub qemu_dimm_list {
3846 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3849 foreach my $dimm (@$dimmarray) {
3851 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3852 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3853 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3854 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3855 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3860 sub qemu_block_set_io_throttle {
3861 my ($vmid, $deviceid,
3862 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3863 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3865 return if !check_running($vmid) ;
3867 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3869 bps_rd => int($bps_rd),
3870 bps_wr => int($bps_wr),
3872 iops_rd => int($iops_rd),
3873 iops_wr => int($iops_wr),
3874 bps_max => int($bps_max),
3875 bps_rd_max => int($bps_rd_max),
3876 bps_wr_max => int($bps_wr_max),
3877 iops_max => int($iops_max),
3878 iops_rd_max => int($iops_rd_max),
3879 iops_wr_max => int($iops_wr_max)
3884 # old code, only used to shutdown old VM after update
3886 my ($fh, $timeout) = @_;
3888 my $sel = new IO::Select;
3895 while (scalar (@ready = $sel->can_read($timeout))) {
3897 if ($count = $fh->sysread($buf, 8192)) {
3898 if ($buf =~ /^(.*)\(qemu\) $/s) {
3905 if (!defined($count)) {
3912 die "monitor
read timeout
\n" if !scalar(@ready);
3917 # old code, only used to shutdown old VM after update
3918 sub vm_monitor_command {
3919 my ($vmid, $cmdstr, $nocheck) = @_;
3924 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3926 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3928 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3929 die "unable to
connect to VM
$vmid socket - $!\n";
3933 # hack: migrate sometime blocks the monitor (when migrate_downtime
3935 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3936 $timeout = 60*60; # 1 hour
3940 my $data = __read_avail($sock, $timeout);
3942 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3943 die "got unexpected qemu monitor banner
\n";
3946 my $sel = new IO::Select;
3949 if (!scalar(my @ready = $sel->can_write($timeout))) {
3950 die "monitor
write error
- timeout
";
3953 my $fullcmd = "$cmdstr\r";
3955 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3958 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3959 die "monitor
write error
- $!";
3962 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3966 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3967 $timeout = 60*60; # 1 hour
3968 } elsif ($cmdstr =~ m/^(eject|change)/) {
3969 $timeout = 60; # note: cdrom mount command is slow
3971 if ($res = __read_avail($sock, $timeout)) {
3973 my @lines = split("\r?
\n", $res);
3975 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3977 $res = join("\n", @lines);
3985 syslog("err
", "VM
$vmid monitor command failed
- $err");
3992 sub qemu_block_resize {
3993 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3995 my $running = check_running($vmid);
3997 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3999 return if !$running;
4001 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4005 sub qemu_volume_snapshot {
4006 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4008 my $running = check_running($vmid);
4010 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4011 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4013 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4017 sub qemu_volume_snapshot_delete {
4018 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4020 my $running = check_running($vmid);
4022 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4024 return if !$running;
4026 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4029 sub set_migration_caps {
4035 "auto-converge
" => 1,
4037 "x-rdma-pin-all
" => 0,
4042 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4044 for my $supported_capability (@$supported_capabilities) {
4046 capability => $supported_capability->{capability},
4047 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4051 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4054 my $fast_plug_option = {
4063 # hotplug changes in [PENDING]
4064 # $selection hash can be used to only apply specified options, for
4065 # example: { cores => 1 } (only apply changed 'cores')
4066 # $errors ref is used to return error messages
4067 sub vmconfig_hotplug_pending {
4068 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4070 my $defaults = load_defaults();
4072 # commit values which do not have any impact on running VM first
4073 # Note: those option cannot raise errors, we we do not care about
4074 # $selection and always apply them.
4076 my $add_error = sub {
4077 my ($opt, $msg) = @_;
4078 $errors->{$opt} = "hotplug problem
- $msg";
4082 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4083 if ($fast_plug_option->{$opt}) {
4084 $conf->{$opt} = $conf->{pending}->{$opt};
4085 delete $conf->{pending}->{$opt};
4091 PVE::QemuConfig->write_config($vmid, $conf);
4092 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4095 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4097 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4098 while (my ($opt, $force) = each %$pending_delete_hash) {
4099 next if $selection && !$selection->{$opt};
4101 if ($opt eq 'hotplug') {
4102 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4103 } elsif ($opt eq 'tablet') {
4104 die "skip
\n" if !$hotplug_features->{usb};
4105 if ($defaults->{tablet}) {
4106 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4108 vm_deviceunplug($vmid, $conf, $opt);
4110 } elsif ($opt eq 'vcpus') {
4111 die "skip
\n" if !$hotplug_features->{cpu};
4112 qemu_cpu_hotplug($vmid, $conf, undef);
4113 } elsif ($opt eq 'balloon') {
4114 # enable balloon device is not hotpluggable
4115 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4116 } elsif ($fast_plug_option->{$opt}) {
4118 } elsif ($opt =~ m/^net(\d+)$/) {
4119 die "skip
\n" if !$hotplug_features->{network};
4120 vm_deviceunplug($vmid, $conf, $opt);
4121 } elsif (is_valid_drivename($opt)) {
4122 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4123 vm_deviceunplug($vmid, $conf, $opt);
4124 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4125 } elsif ($opt =~ m/^memory$/) {
4126 die "skip
\n" if !$hotplug_features->{memory};
4127 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4128 } elsif ($opt eq 'cpuunits') {
4129 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4130 } elsif ($opt eq 'cpulimit') {
4131 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4137 &$add_error($opt, $err) if $err ne "skip
\n";
4139 # save new config if hotplug was successful
4140 delete $conf->{$opt};
4141 vmconfig_undelete_pending_option($conf, $opt);
4142 PVE::QemuConfig->write_config($vmid, $conf);
4143 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4147 foreach my $opt (keys %{$conf->{pending}}) {
4148 next if $selection && !$selection->{$opt};
4149 my $value = $conf->{pending}->{$opt};
4151 if ($opt eq 'hotplug') {
4152 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4153 } elsif ($opt eq 'tablet') {
4154 die "skip
\n" if !$hotplug_features->{usb};
4156 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4157 } elsif ($value == 0) {
4158 vm_deviceunplug($vmid, $conf, $opt);
4160 } elsif ($opt eq 'vcpus') {
4161 die "skip
\n" if !$hotplug_features->{cpu};
4162 qemu_cpu_hotplug($vmid, $conf, $value);
4163 } elsif ($opt eq 'balloon') {
4164 # enable/disable balloning device is not hotpluggable
4165 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4166 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4167 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4169 # allow manual ballooning if shares is set to zero
4170 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4171 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4172 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4174 } elsif ($opt =~ m/^net(\d+)$/) {
4175 # some changes can be done without hotplug
4176 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4177 $vmid, $opt, $value);
4178 } elsif (is_valid_drivename($opt)) {
4179 # some changes can be done without hotplug
4180 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4181 $vmid, $opt, $value, 1);
4182 } elsif ($opt =~ m/^memory$/) { #dimms
4183 die "skip
\n" if !$hotplug_features->{memory};
4184 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4185 } elsif ($opt eq 'cpuunits') {
4186 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4187 } elsif ($opt eq 'cpulimit') {
4188 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4189 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4191 die "skip
\n"; # skip non-hot-pluggable options
4195 &$add_error($opt, $err) if $err ne "skip
\n";
4197 # save new config if hotplug was successful
4198 $conf->{$opt} = $value;
4199 delete $conf->{pending}->{$opt};
4200 PVE::QemuConfig->write_config($vmid, $conf);
4201 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4206 sub try_deallocate_drive {
4207 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4209 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4210 my $volid = $drive->{file};
4211 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4212 my $sid = PVE::Storage::parse_volume_id($volid);
4213 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4215 # check if the disk is really unused
4216 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4217 if is_volume_in_use($storecfg, $conf, $key, $volid);
4218 PVE::Storage::vdisk_free($storecfg, $volid);
4221 # If vm is not owner of this disk remove from config
4229 sub vmconfig_delete_or_detach_drive {
4230 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4232 my $drive = parse_drive($opt, $conf->{$opt});
4234 my $rpcenv = PVE::RPCEnvironment::get();
4235 my $authuser = $rpcenv->get_user();
4238 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4239 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4241 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4245 sub vmconfig_apply_pending {
4246 my ($vmid, $conf, $storecfg) = @_;
4250 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4251 while (my ($opt, $force) = each %$pending_delete_hash) {
4252 die "internal error
" if $opt =~ m/^unused/;
4253 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4254 if (!defined($conf->{$opt})) {
4255 vmconfig_undelete_pending_option($conf, $opt);
4256 PVE::QemuConfig->write_config($vmid, $conf);
4257 } elsif (is_valid_drivename($opt)) {
4258 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4259 vmconfig_undelete_pending_option($conf, $opt);
4260 delete $conf->{$opt};
4261 PVE::QemuConfig->write_config($vmid, $conf);
4263 vmconfig_undelete_pending_option($conf, $opt);
4264 delete $conf->{$opt};
4265 PVE::QemuConfig->write_config($vmid, $conf);
4269 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4271 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4272 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4274 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4275 # skip if nothing changed
4276 } elsif (is_valid_drivename($opt)) {
4277 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4278 if defined($conf->{$opt});
4279 $conf->{$opt} = $conf->{pending}->{$opt};
4281 $conf->{$opt} = $conf->{pending}->{$opt};
4284 delete $conf->{pending}->{$opt};
4285 PVE::QemuConfig->write_config($vmid, $conf);
4289 my $safe_num_ne = sub {
4292 return 0 if !defined($a) && !defined($b);
4293 return 1 if !defined($a);
4294 return 1 if !defined($b);
4299 my $safe_string_ne = sub {
4302 return 0 if !defined($a) && !defined($b);
4303 return 1 if !defined($a);
4304 return 1 if !defined($b);
4309 sub vmconfig_update_net {
4310 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4312 my $newnet = parse_net($value);
4314 if ($conf->{$opt}) {
4315 my $oldnet = parse_net($conf->{$opt});
4317 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4318 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4319 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4320 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4322 # for non online change, we try to hot-unplug
4323 die "skip
\n" if !$hotplug;
4324 vm_deviceunplug($vmid, $conf, $opt);
4327 die "internal error
" if $opt !~ m/net(\d+)/;
4328 my $iface = "tap
${vmid
}i
$1";
4330 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4331 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4332 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4333 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4334 PVE::Network::tap_unplug($iface);
4335 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4336 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4337 # Rate can be applied on its own but any change above needs to
4338 # include the rate in tap_plug since OVS resets everything.
4339 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4342 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4343 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4351 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4357 sub vmconfig_update_disk {
4358 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4360 # fixme: do we need force?
4362 my $drive = parse_drive($opt, $value);
4364 if ($conf->{$opt}) {
4366 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4368 my $media = $drive->{media} || 'disk';
4369 my $oldmedia = $old_drive->{media} || 'disk';
4370 die "unable to change media type
\n" if $media ne $oldmedia;
4372 if (!drive_is_cdrom($old_drive)) {
4374 if ($drive->{file} ne $old_drive->{file}) {
4376 die "skip
\n" if !$hotplug;
4378 # unplug and register as unused
4379 vm_deviceunplug($vmid, $conf, $opt);
4380 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4383 # update existing disk
4385 # skip non hotpluggable value
4386 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4387 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4388 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4389 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4394 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4395 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4396 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4397 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4398 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4399 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4400 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4401 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4402 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4403 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4404 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4405 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4407 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4408 ($drive->{mbps} || 0)*1024*1024,
4409 ($drive->{mbps_rd} || 0)*1024*1024,
4410 ($drive->{mbps_wr} || 0)*1024*1024,
4411 $drive->{iops} || 0,
4412 $drive->{iops_rd} || 0,
4413 $drive->{iops_wr} || 0,
4414 ($drive->{mbps_max} || 0)*1024*1024,
4415 ($drive->{mbps_rd_max} || 0)*1024*1024,
4416 ($drive->{mbps_wr_max} || 0)*1024*1024,
4417 $drive->{iops_max} || 0,
4418 $drive->{iops_rd_max} || 0,
4419 $drive->{iops_wr_max} || 0);
4428 if ($drive->{file} eq 'none') {
4429 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4431 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4432 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4433 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4441 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4443 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4444 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4448 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4449 $forcemachine, $spice_ticket) = @_;
4451 PVE::QemuConfig->lock_config($vmid, sub {
4452 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4454 die "you can
't start a vm if it's a template
\n" if PVE::QemuConfig->is_template($conf);
4456 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4458 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4460 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4461 vmconfig_apply_pending($vmid, $conf, $storecfg);
4462 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4465 my $defaults = load_defaults();
4467 # set environment variable useful inside network script
4468 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4470 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4472 my $migrate_port = 0;
4475 if ($statefile eq 'tcp') {
4476 my $localip = "localhost
";
4477 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4478 my $nodename = PVE::INotify::nodename();
4479 if ($datacenterconf->{migration_unsecure}) {
4480 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4481 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4483 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4484 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4485 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4486 push @$cmd, '-incoming', $migrate_uri;
4489 push @$cmd, '-loadstate', $statefile;
4496 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4497 my $d = parse_hostpci($conf->{"hostpci
$i"});
4499 my $pcidevices = $d->{pciid};
4500 foreach my $pcidevice (@$pcidevices) {
4501 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4503 my $info = pci_device_info("0000:$pciid");
4504 die "IOMMU
not present
\n" if !check_iommu_support();
4505 die "no pci device info
for device
'$pciid'\n" if !$info;
4506 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4507 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4511 PVE::Storage::activate_volumes($storecfg, $vollist);
4513 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4517 # deactivate volumes if start fails
4518 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4519 die "start failed
: $err";
4522 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4524 if ($statefile && $statefile ne 'tcp') {
4525 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4529 if ($migratedfrom) {
4532 set_migration_caps($vmid);
4537 print "spice listens on port
$spice_port\n";
4538 if ($spice_ticket) {
4539 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4540 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4546 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4547 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4548 if $conf->{balloon};
4551 foreach my $opt (keys %$conf) {
4552 next if $opt !~ m/^net\d+$/;
4553 my $nicconf = parse_net($conf->{$opt});
4554 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4558 vm_mon_cmd_nocheck($vmid, 'qom-set',
4559 path => "machine
/peripheral/balloon0
",
4560 property => "guest-stats-polling-interval
",
4561 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4567 my ($vmid, $execute, %params) = @_;
4569 my $cmd = { execute => $execute, arguments => \%params };
4570 vm_qmp_command($vmid, $cmd);
4573 sub vm_mon_cmd_nocheck {
4574 my ($vmid, $execute, %params) = @_;
4576 my $cmd = { execute => $execute, arguments => \%params };
4577 vm_qmp_command($vmid, $cmd, 1);
4580 sub vm_qmp_command {
4581 my ($vmid, $cmd, $nocheck) = @_;
4586 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4587 $timeout = $cmd->{arguments}->{timeout};
4588 delete $cmd->{arguments}->{timeout};
4592 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4593 my $sname = qmp_socket($vmid);
4594 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4595 my $qmpclient = PVE::QMPClient->new();
4597 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4598 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4599 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4600 if scalar(%{$cmd->{arguments}});
4601 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4603 die "unable to open monitor socket\n";
4607 syslog("err", "VM $vmid qmp command failed - $err");
4614 sub vm_human_monitor_command {
4615 my ($vmid, $cmdline) = @_;
4620 execute => 'human-monitor-command
',
4621 arguments => { 'command-line
' => $cmdline},
4624 return vm_qmp_command($vmid, $cmd);
4627 sub vm_commandline {
4628 my ($storecfg, $vmid) = @_;
4630 my $conf = PVE::QemuConfig->load_config($vmid);
4632 my $defaults = load_defaults();
4634 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4636 return join(' ', @$cmd);
4640 my ($vmid, $skiplock) = @_;
4642 PVE::QemuConfig->lock_config($vmid, sub {
4644 my $conf = PVE::QemuConfig->load_config($vmid);
4646 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4648 vm_mon_cmd($vmid, "system_reset");
4652 sub get_vm_volumes {
4656 foreach_volid($conf, sub {
4657 my ($volid, $is_cdrom) = @_;
4659 return if $volid =~ m|^/|;
4661 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4664 push @$vollist, $volid;
4670 sub vm_stop_cleanup {
4671 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4676 my $vollist = get_vm_volumes($conf);
4677 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4680 foreach my $ext (qw(mon qmp pid vnc qga)) {
4681 unlink "/var/run/qemu-server/${vmid}.$ext";
4684 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4686 warn $@ if $@; # avoid errors - just warn
4689 # Note: use $nockeck to skip tests if VM configuration file exists.
4690 # We need that when migration VMs to other nodes (files already moved)
4691 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4693 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4695 $force = 1 if !defined($force) && !$shutdown;
4698 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4699 kill 15, $pid if $pid;
4700 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4701 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4705 PVE
::QemuConfig-
>lock_config($vmid, sub {
4707 my $pid = check_running
($vmid, $nocheck);
4712 $conf = PVE
::QemuConfig-
>load_config($vmid);
4713 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4714 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4715 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4716 $timeout = $opts->{down
} if $opts->{down
};
4720 $timeout = 60 if !defined($timeout);
4724 if (defined($conf) && $conf->{agent
}) {
4725 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4727 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4730 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4737 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4742 if ($count >= $timeout) {
4744 warn "VM still running - terminating now with SIGTERM\n";
4747 die "VM quit/powerdown failed - got timeout\n";
4750 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4755 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4758 die "VM quit/powerdown failed\n";
4766 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4771 if ($count >= $timeout) {
4772 warn "VM still running - terminating now with SIGKILL\n";
4777 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4782 my ($vmid, $skiplock) = @_;
4784 PVE
::QemuConfig-
>lock_config($vmid, sub {
4786 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4788 PVE
::QemuConfig-
>check_lock($conf)
4789 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4791 vm_mon_cmd
($vmid, "stop");
4796 my ($vmid, $skiplock, $nocheck) = @_;
4798 PVE
::QemuConfig-
>lock_config($vmid, sub {
4802 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4804 PVE
::QemuConfig-
>check_lock($conf)
4805 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4807 vm_mon_cmd
($vmid, "cont");
4810 vm_mon_cmd_nocheck
($vmid, "cont");
4816 my ($vmid, $skiplock, $key) = @_;
4818 PVE
::QemuConfig-
>lock_config($vmid, sub {
4820 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4822 # there is no qmp command, so we use the human monitor command
4823 vm_human_monitor_command
($vmid, "sendkey $key");
4828 my ($storecfg, $vmid, $skiplock) = @_;
4830 PVE
::QemuConfig-
>lock_config($vmid, sub {
4832 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4834 if (!check_running
($vmid)) {
4835 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4837 die "VM $vmid is running - destroy failed\n";
4845 my ($filename, $buf) = @_;
4847 my $fh = IO
::File-
>new($filename, "w");
4848 return undef if !$fh;
4850 my $res = print $fh $buf;
4857 sub pci_device_info
{
4862 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4863 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4865 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4866 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4868 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4869 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4871 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4872 return undef if !defined($product) || $product !~ s/^0x//;
4877 product
=> $product,
4883 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4892 my $name = $dev->{name
};
4894 my $fn = "$pcisysfs/devices/$name/reset";
4896 return file_write
($fn, "1");
4899 sub pci_dev_bind_to_vfio
{
4902 my $name = $dev->{name
};
4904 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4906 if (!-d
$vfio_basedir) {
4907 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4909 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4911 my $testdir = "$vfio_basedir/$name";
4912 return 1 if -d
$testdir;
4914 my $data = "$dev->{vendor} $dev->{product}";
4915 return undef if !file_write
("$vfio_basedir/new_id", $data);
4917 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4918 if (!file_write
($fn, $name)) {
4919 return undef if -f
$fn;
4922 $fn = "$vfio_basedir/bind";
4923 if (! -d
$testdir) {
4924 return undef if !file_write
($fn, $name);
4930 sub pci_dev_group_bind_to_vfio
{
4933 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4935 if (!-d
$vfio_basedir) {
4936 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4938 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4940 # get IOMMU group devices
4941 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4942 my @devs = grep /^0000:/, readdir($D);
4945 foreach my $pciid (@devs) {
4946 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4948 # pci bridges, switches or root ports are not supported
4949 # they have a pci_bus subdirectory so skip them
4950 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4952 my $info = pci_device_info
($1);
4953 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4959 sub print_pci_addr
{
4960 my ($id, $bridges) = @_;
4964 piix3
=> { bus
=> 0, addr
=> 1 },
4965 #addr2 : first videocard
4966 balloon0
=> { bus
=> 0, addr
=> 3 },
4967 watchdog
=> { bus
=> 0, addr
=> 4 },
4968 scsihw0
=> { bus
=> 0, addr
=> 5 },
4969 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4970 scsihw1
=> { bus
=> 0, addr
=> 6 },
4971 ahci0
=> { bus
=> 0, addr
=> 7 },
4972 qga0
=> { bus
=> 0, addr
=> 8 },
4973 spice
=> { bus
=> 0, addr
=> 9 },
4974 virtio0
=> { bus
=> 0, addr
=> 10 },
4975 virtio1
=> { bus
=> 0, addr
=> 11 },
4976 virtio2
=> { bus
=> 0, addr
=> 12 },
4977 virtio3
=> { bus
=> 0, addr
=> 13 },
4978 virtio4
=> { bus
=> 0, addr
=> 14 },
4979 virtio5
=> { bus
=> 0, addr
=> 15 },
4980 hostpci0
=> { bus
=> 0, addr
=> 16 },
4981 hostpci1
=> { bus
=> 0, addr
=> 17 },
4982 net0
=> { bus
=> 0, addr
=> 18 },
4983 net1
=> { bus
=> 0, addr
=> 19 },
4984 net2
=> { bus
=> 0, addr
=> 20 },
4985 net3
=> { bus
=> 0, addr
=> 21 },
4986 net4
=> { bus
=> 0, addr
=> 22 },
4987 net5
=> { bus
=> 0, addr
=> 23 },
4988 vga1
=> { bus
=> 0, addr
=> 24 },
4989 vga2
=> { bus
=> 0, addr
=> 25 },
4990 vga3
=> { bus
=> 0, addr
=> 26 },
4991 hostpci2
=> { bus
=> 0, addr
=> 27 },
4992 hostpci3
=> { bus
=> 0, addr
=> 28 },
4993 #addr29 : usb-host (pve-usb.cfg)
4994 'pci.1' => { bus
=> 0, addr
=> 30 },
4995 'pci.2' => { bus
=> 0, addr
=> 31 },
4996 'net6' => { bus
=> 1, addr
=> 1 },
4997 'net7' => { bus
=> 1, addr
=> 2 },
4998 'net8' => { bus
=> 1, addr
=> 3 },
4999 'net9' => { bus
=> 1, addr
=> 4 },
5000 'net10' => { bus
=> 1, addr
=> 5 },
5001 'net11' => { bus
=> 1, addr
=> 6 },
5002 'net12' => { bus
=> 1, addr
=> 7 },
5003 'net13' => { bus
=> 1, addr
=> 8 },
5004 'net14' => { bus
=> 1, addr
=> 9 },
5005 'net15' => { bus
=> 1, addr
=> 10 },
5006 'net16' => { bus
=> 1, addr
=> 11 },
5007 'net17' => { bus
=> 1, addr
=> 12 },
5008 'net18' => { bus
=> 1, addr
=> 13 },
5009 'net19' => { bus
=> 1, addr
=> 14 },
5010 'net20' => { bus
=> 1, addr
=> 15 },
5011 'net21' => { bus
=> 1, addr
=> 16 },
5012 'net22' => { bus
=> 1, addr
=> 17 },
5013 'net23' => { bus
=> 1, addr
=> 18 },
5014 'net24' => { bus
=> 1, addr
=> 19 },
5015 'net25' => { bus
=> 1, addr
=> 20 },
5016 'net26' => { bus
=> 1, addr
=> 21 },
5017 'net27' => { bus
=> 1, addr
=> 22 },
5018 'net28' => { bus
=> 1, addr
=> 23 },
5019 'net29' => { bus
=> 1, addr
=> 24 },
5020 'net30' => { bus
=> 1, addr
=> 25 },
5021 'net31' => { bus
=> 1, addr
=> 26 },
5022 'xhci' => { bus
=> 1, addr
=> 27 },
5023 'virtio6' => { bus
=> 2, addr
=> 1 },
5024 'virtio7' => { bus
=> 2, addr
=> 2 },
5025 'virtio8' => { bus
=> 2, addr
=> 3 },
5026 'virtio9' => { bus
=> 2, addr
=> 4 },
5027 'virtio10' => { bus
=> 2, addr
=> 5 },
5028 'virtio11' => { bus
=> 2, addr
=> 6 },
5029 'virtio12' => { bus
=> 2, addr
=> 7 },
5030 'virtio13' => { bus
=> 2, addr
=> 8 },
5031 'virtio14' => { bus
=> 2, addr
=> 9 },
5032 'virtio15' => { bus
=> 2, addr
=> 10 },
5033 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5034 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5035 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5036 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5037 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5038 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5039 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5040 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5041 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5042 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5043 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5044 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5045 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5046 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5047 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5048 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5049 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5050 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5051 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5052 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5053 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5054 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5055 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5056 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5057 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5058 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5059 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5060 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5061 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5062 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5063 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5067 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5068 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5069 my $bus = $devices->{$id}->{bus
};
5070 $res = ",bus=pci.$bus,addr=$addr";
5071 $bridges->{$bus} = 1 if $bridges;
5077 sub print_pcie_addr
{
5082 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5083 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5084 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5085 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5088 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5089 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5090 my $bus = $devices->{$id}->{bus
};
5091 $res = ",bus=$bus,addr=$addr";
5097 # vzdump restore implementaion
5099 sub tar_archive_read_firstfile
{
5100 my $archive = shift;
5102 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5104 # try to detect archive type first
5105 my $pid = open (TMP
, "tar tf '$archive'|") ||
5106 die "unable to open file '$archive'\n";
5107 my $firstfile = <TMP
>;
5111 die "ERROR: archive contaions no data\n" if !$firstfile;
5117 sub tar_restore_cleanup
{
5118 my ($storecfg, $statfile) = @_;
5120 print STDERR
"starting cleanup\n";
5122 if (my $fd = IO
::File-
>new($statfile, "r")) {
5123 while (defined(my $line = <$fd>)) {
5124 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5127 if ($volid =~ m
|^/|) {
5128 unlink $volid || die 'unlink failed\n';
5130 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5132 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5134 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5136 print STDERR
"unable to parse line in statfile - $line";
5143 sub restore_archive
{
5144 my ($archive, $vmid, $user, $opts) = @_;
5146 my $format = $opts->{format
};
5149 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5150 $format = 'tar' if !$format;
5152 } elsif ($archive =~ m/\.tar$/) {
5153 $format = 'tar' if !$format;
5154 } elsif ($archive =~ m/.tar.lzo$/) {
5155 $format = 'tar' if !$format;
5157 } elsif ($archive =~ m/\.vma$/) {
5158 $format = 'vma' if !$format;
5159 } elsif ($archive =~ m/\.vma\.gz$/) {
5160 $format = 'vma' if !$format;
5162 } elsif ($archive =~ m/\.vma\.lzo$/) {
5163 $format = 'vma' if !$format;
5166 $format = 'vma' if !$format; # default
5169 # try to detect archive format
5170 if ($format eq 'tar') {
5171 return restore_tar_archive
($archive, $vmid, $user, $opts);
5173 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5177 sub restore_update_config_line
{
5178 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5180 return if $line =~ m/^\#qmdump\#/;
5181 return if $line =~ m/^\#vzdump\#/;
5182 return if $line =~ m/^lock:/;
5183 return if $line =~ m/^unused\d+:/;
5184 return if $line =~ m/^parent:/;
5185 return if $line =~ m/^template:/; # restored VM is never a template
5187 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5188 # try to convert old 1.X settings
5189 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5190 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5191 my ($model, $macaddr) = split(/\=/, $devconfig);
5192 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5195 bridge
=> "vmbr$ind",
5196 macaddr
=> $macaddr,
5198 my $netstr = print_net
($net);
5200 print $outfd "net$cookie->{netcount}: $netstr\n";
5201 $cookie->{netcount
}++;
5203 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5204 my ($id, $netstr) = ($1, $2);
5205 my $net = parse_net
($netstr);
5206 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5207 $netstr = print_net
($net);
5208 print $outfd "$id: $netstr\n";
5209 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5212 my $di = parse_drive
($virtdev, $value);
5213 if (defined($di->{backup
}) && !$di->{backup
}) {
5214 print $outfd "#$line";
5215 } elsif ($map->{$virtdev}) {
5216 delete $di->{format
}; # format can change on restore
5217 $di->{file
} = $map->{$virtdev};
5218 $value = print_drive
($vmid, $di);
5219 print $outfd "$virtdev: $value\n";
5229 my ($cfg, $vmid) = @_;
5231 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5233 my $volid_hash = {};
5234 foreach my $storeid (keys %$info) {
5235 foreach my $item (@{$info->{$storeid}}) {
5236 next if !($item->{volid
} && $item->{size
});
5237 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5238 $volid_hash->{$item->{volid
}} = $item;
5245 sub is_volume_in_use
{
5246 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5248 my $path = PVE
::Storage
::path
($storecfg, $volid);
5250 my $scan_config = sub {
5251 my ($cref, $snapname) = @_;
5253 foreach my $key (keys %$cref) {
5254 my $value = $cref->{$key};
5255 if (is_valid_drivename
($key)) {
5256 next if $skip_drive && $key eq $skip_drive;
5257 my $drive = parse_drive
($key, $value);
5258 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5259 return 1 if $volid eq $drive->{file
};
5260 if ($drive->{file
} =~ m!^/!) {
5261 return 1 if $drive->{file
} eq $path;
5263 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5265 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5267 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5275 return 1 if &$scan_config($conf);
5279 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5280 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5286 sub update_disksize
{
5287 my ($vmid, $conf, $volid_hash) = @_;
5293 # Note: it is allowed to define multiple storages with same path (alias), so
5294 # we need to check both 'volid' and real 'path' (two different volid can point
5295 # to the same path).
5300 foreach my $opt (keys %$conf) {
5301 if (is_valid_drivename
($opt)) {
5302 my $drive = parse_drive
($opt, $conf->{$opt});
5303 my $volid = $drive->{file
};
5306 $used->{$volid} = 1;
5307 if ($volid_hash->{$volid} &&
5308 (my $path = $volid_hash->{$volid}->{path
})) {
5309 $usedpath->{$path} = 1;
5312 next if drive_is_cdrom
($drive);
5313 next if !$volid_hash->{$volid};
5315 $drive->{size
} = $volid_hash->{$volid}->{size
};
5316 my $new = print_drive
($vmid, $drive);
5317 if ($new ne $conf->{$opt}) {
5319 $conf->{$opt} = $new;
5324 # remove 'unusedX' entry if volume is used
5325 foreach my $opt (keys %$conf) {
5326 next if $opt !~ m/^unused\d+$/;
5327 my $volid = $conf->{$opt};
5328 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5329 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5331 delete $conf->{$opt};
5335 foreach my $volid (sort keys %$volid_hash) {
5336 next if $volid =~ m/vm-$vmid-state-/;
5337 next if $used->{$volid};
5338 my $path = $volid_hash->{$volid}->{path
};
5339 next if !$path; # just to be sure
5340 next if $usedpath->{$path};
5342 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5343 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5350 my ($vmid, $nolock) = @_;
5352 my $cfg = PVE
::Storage
::config
();
5354 my $volid_hash = scan_volids
($cfg, $vmid);
5356 my $updatefn = sub {
5359 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5361 PVE
::QemuConfig-
>check_lock($conf);
5364 foreach my $volid (keys %$volid_hash) {
5365 my $info = $volid_hash->{$volid};
5366 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5369 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5371 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5374 if (defined($vmid)) {
5378 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5381 my $vmlist = config_list
();
5382 foreach my $vmid (keys %$vmlist) {
5386 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5392 sub restore_vma_archive
{
5393 my ($archive, $vmid, $user, $opts, $comp) = @_;
5395 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5396 my $readfrom = $archive;
5401 my $qarchive = PVE
::Tools
::shellquote
($archive);
5402 if ($comp eq 'gzip') {
5403 $uncomp = "zcat $qarchive|";
5404 } elsif ($comp eq 'lzop') {
5405 $uncomp = "lzop -d -c $qarchive|";
5407 die "unknown compression method '$comp'\n";
5412 my $tmpdir = "/var/tmp/vzdumptmp$$";
5415 # disable interrupts (always do cleanups)
5416 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5417 warn "got interrupt - ignored\n";
5420 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5421 POSIX
::mkfifo
($mapfifo, 0600);
5424 my $openfifo = sub {
5425 open($fifofh, '>', $mapfifo) || die $!;
5428 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5435 my $rpcenv = PVE
::RPCEnvironment
::get
();
5437 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5438 my $tmpfn = "$conffile.$$.tmp";
5440 # Note: $oldconf is undef if VM does not exists
5441 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5442 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5444 my $print_devmap = sub {
5445 my $virtdev_hash = {};
5447 my $cfgfn = "$tmpdir/qemu-server.conf";
5449 # we can read the config - that is already extracted
5450 my $fh = IO
::File-
>new($cfgfn, "r") ||
5451 "unable to read qemu-server.conf - $!\n";
5453 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5455 my $pve_firewall_dir = '/etc/pve/firewall';
5456 mkdir $pve_firewall_dir; # make sure the dir exists
5457 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5460 while (defined(my $line = <$fh>)) {
5461 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5462 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5463 die "archive does not contain data for drive '$virtdev'\n"
5464 if !$devinfo->{$devname};
5465 if (defined($opts->{storage
})) {
5466 $storeid = $opts->{storage
} || 'local';
5467 } elsif (!$storeid) {
5470 $format = 'raw' if !$format;
5471 $devinfo->{$devname}->{devname
} = $devname;
5472 $devinfo->{$devname}->{virtdev
} = $virtdev;
5473 $devinfo->{$devname}->{format
} = $format;
5474 $devinfo->{$devname}->{storeid
} = $storeid;
5476 # check permission on storage
5477 my $pool = $opts->{pool
}; # todo: do we need that?
5478 if ($user ne 'root@pam') {
5479 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5482 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5486 foreach my $devname (keys %$devinfo) {
5487 die "found no device mapping information for device '$devname'\n"
5488 if !$devinfo->{$devname}->{virtdev
};
5491 my $cfg = PVE
::Storage
::config
();
5493 # create empty/temp config
5495 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5496 foreach_drive
($oldconf, sub {
5497 my ($ds, $drive) = @_;
5499 return if drive_is_cdrom
($drive);
5501 my $volid = $drive->{file
};
5503 return if !$volid || $volid =~ m
|^/|;
5505 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5506 return if !$path || !$owner || ($owner != $vmid);
5508 # Note: only delete disk we want to restore
5509 # other volumes will become unused
5510 if ($virtdev_hash->{$ds}) {
5511 PVE
::Storage
::vdisk_free
($cfg, $volid);
5515 # delete vmstate files
5516 # since after the restore we have no snapshots anymore
5517 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5518 my $snap = $oldconf->{snapshots
}->{$snapname};
5519 if ($snap->{vmstate
}) {
5520 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5529 foreach my $virtdev (sort keys %$virtdev_hash) {
5530 my $d = $virtdev_hash->{$virtdev};
5531 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5532 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5534 # test if requested format is supported
5535 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5536 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5537 $d->{format
} = $defFormat if !$supported;
5539 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5540 $d->{format
}, undef, $alloc_size);
5541 print STDERR
"new volume ID is '$volid'\n";
5542 $d->{volid
} = $volid;
5543 my $path = PVE
::Storage
::path
($cfg, $volid);
5545 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5547 my $write_zeros = 1;
5548 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5552 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5554 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5555 $map->{$virtdev} = $volid;
5558 $fh->seek(0, 0) || die "seek failed - $!\n";
5560 my $outfd = new IO
::File
($tmpfn, "w") ||
5561 die "unable to write config for VM $vmid\n";
5563 my $cookie = { netcount
=> 0 };
5564 while (defined(my $line = <$fh>)) {
5565 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5574 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5575 die "interrupted by signal\n";
5577 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5579 $oldtimeout = alarm($timeout);
5586 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5587 my ($dev_id, $size, $devname) = ($1, $2, $3);
5588 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5589 } elsif ($line =~ m/^CTIME: /) {
5590 # we correctly received the vma config, so we can disable
5591 # the timeout now for disk allocation (set to 10 minutes, so
5592 # that we always timeout if something goes wrong)
5595 print $fifofh "done\n";
5596 my $tmp = $oldtimeout || 0;
5597 $oldtimeout = undef;
5603 print "restore vma archive: $cmd\n";
5604 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5608 alarm($oldtimeout) if $oldtimeout;
5611 foreach my $devname (keys %$devinfo) {
5612 my $volid = $devinfo->{$devname}->{volid
};
5613 push @$vollist, $volid if $volid;
5616 my $cfg = PVE
::Storage
::config
();
5617 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5625 foreach my $devname (keys %$devinfo) {
5626 my $volid = $devinfo->{$devname}->{volid
};
5629 if ($volid =~ m
|^/|) {
5630 unlink $volid || die 'unlink failed\n';
5632 PVE
::Storage
::vdisk_free
($cfg, $volid);
5634 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5636 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5643 rename($tmpfn, $conffile) ||
5644 die "unable to commit configuration file '$conffile'\n";
5646 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5648 eval { rescan
($vmid, 1); };
5652 sub restore_tar_archive
{
5653 my ($archive, $vmid, $user, $opts) = @_;
5655 if ($archive ne '-') {
5656 my $firstfile = tar_archive_read_firstfile
($archive);
5657 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5658 if $firstfile ne 'qemu-server.conf';
5661 my $storecfg = PVE
::Storage
::config
();
5663 # destroy existing data - keep empty config
5664 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5665 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5667 my $tocmd = "/usr/lib/qemu-server/qmextract";
5669 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5670 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5671 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5672 $tocmd .= ' --info' if $opts->{info
};
5674 # tar option "xf" does not autodetect compression when read from STDIN,
5675 # so we pipe to zcat
5676 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5677 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5679 my $tmpdir = "/var/tmp/vzdumptmp$$";
5682 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5683 local $ENV{VZDUMP_VMID
} = $vmid;
5684 local $ENV{VZDUMP_USER
} = $user;
5686 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5687 my $tmpfn = "$conffile.$$.tmp";
5689 # disable interrupts (always do cleanups)
5690 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5691 print STDERR
"got interrupt - ignored\n";
5696 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5697 die "interrupted by signal\n";
5700 if ($archive eq '-') {
5701 print "extracting archive from STDIN\n";
5702 run_command
($cmd, input
=> "<&STDIN");
5704 print "extracting archive '$archive'\n";
5708 return if $opts->{info
};
5712 my $statfile = "$tmpdir/qmrestore.stat";
5713 if (my $fd = IO
::File-
>new($statfile, "r")) {
5714 while (defined (my $line = <$fd>)) {
5715 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5716 $map->{$1} = $2 if $1;
5718 print STDERR
"unable to parse line in statfile - $line\n";
5724 my $confsrc = "$tmpdir/qemu-server.conf";
5726 my $srcfd = new IO
::File
($confsrc, "r") ||
5727 die "unable to open file '$confsrc'\n";
5729 my $outfd = new IO
::File
($tmpfn, "w") ||
5730 die "unable to write config for VM $vmid\n";
5732 my $cookie = { netcount
=> 0 };
5733 while (defined (my $line = <$srcfd>)) {
5734 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5746 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5753 rename $tmpfn, $conffile ||
5754 die "unable to commit configuration file '$conffile'\n";
5756 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5758 eval { rescan
($vmid, 1); };
5762 sub foreach_writable_storage
{
5763 my ($conf, $func) = @_;
5767 foreach my $ds (keys %$conf) {
5768 next if !is_valid_drivename
($ds);
5770 my $drive = parse_drive
($ds, $conf->{$ds});
5772 next if drive_is_cdrom
($drive);
5774 my $volid = $drive->{file
};
5776 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5777 $sidhash->{$sid} = $sid if $sid;
5780 foreach my $sid (sort keys %$sidhash) {
5785 sub do_snapshots_with_qemu
{
5786 my ($storecfg, $volid) = @_;
5788 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5790 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5791 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5795 if ($volid =~ m/\.(qcow2|qed)$/){
5802 sub qga_check_running
{
5805 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5807 warn "Qemu Guest Agent are not running - $@";
5813 sub template_create
{
5814 my ($vmid, $conf, $disk) = @_;
5816 my $storecfg = PVE
::Storage
::config
();
5818 foreach_drive
($conf, sub {
5819 my ($ds, $drive) = @_;
5821 return if drive_is_cdrom
($drive);
5822 return if $disk && $ds ne $disk;
5824 my $volid = $drive->{file
};
5825 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5827 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5828 $drive->{file
} = $voliddst;
5829 $conf->{$ds} = print_drive
($vmid, $drive);
5830 PVE
::QemuConfig-
>write_config($vmid, $conf);
5834 sub qemu_img_convert
{
5835 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5837 my $storecfg = PVE
::Storage
::config
();
5838 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5839 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5841 if ($src_storeid && $dst_storeid) {
5843 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5845 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5846 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5848 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5849 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5851 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5852 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5855 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5856 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5857 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5858 if ($is_zero_initialized) {
5859 push @$cmd, "zeroinit:$dst_path";
5861 push @$cmd, $dst_path;
5866 if($line =~ m/\((\S+)\/100\
%\)/){
5868 my $transferred = int($size * $percent / 100);
5869 my $remaining = $size - $transferred;
5871 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5876 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5878 die "copy failed: $err" if $err;
5882 sub qemu_img_format
{
5883 my ($scfg, $volname) = @_;
5885 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5892 sub qemu_drive_mirror
{
5893 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5895 my $storecfg = PVE
::Storage
::config
();
5896 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5898 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5900 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5902 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5904 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5906 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5907 $opts->{format
} = $format if $format;
5909 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5912 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5914 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5915 my $stat = @$stats[0];
5916 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5917 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5919 my $busy = $stat->{busy
};
5920 my $ready = $stat->{ready
};
5922 if (my $total = $stat->{len
}) {
5923 my $transferred = $stat->{offset
} || 0;
5924 my $remaining = $total - $transferred;
5925 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5927 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5931 if ($stat->{ready
} eq 'true') {
5933 last if $vmiddst != $vmid;
5935 # try to switch the disk if source and destination are on the same guest
5936 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5938 die $@ if $@ !~ m/cannot be completed/;
5947 my $cancel_job = sub {
5948 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5950 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5951 my $stat = @$stats[0];
5958 eval { &$cancel_job(); };
5959 die "mirroring error: $err";
5962 if ($vmiddst != $vmid) {
5963 # if we clone a disk for a new target vm, we don't switch the disk
5964 &$cancel_job(); # so we call block-job-cancel
5969 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5970 $newvmid, $storage, $format, $full, $newvollist) = @_;
5975 print "create linked clone of drive $drivename ($drive->{file})\n";
5976 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5977 push @$newvollist, $newvolid;
5979 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5980 $storeid = $storage if $storage;
5982 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5984 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5985 $format = qemu_img_format
($scfg, $volname);
5988 # test if requested format is supported - else use default
5989 my $supported = grep { $_ eq $format } @$validFormats;
5990 $format = $defFormat if !$supported;
5992 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5994 print "create full clone of drive $drivename ($drive->{file})\n";
5995 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5996 push @$newvollist, $newvolid;
5998 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6000 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6001 if (!$running || $snapname) {
6002 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6004 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
6008 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6011 $disk->{format
} = undef;
6012 $disk->{file
} = $newvolid;
6013 $disk->{size
} = $size;
6018 # this only works if VM is running
6019 sub get_current_qemu_machine
{
6022 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6023 my $res = vm_qmp_command
($vmid, $cmd);
6025 my ($current, $default);
6026 foreach my $e (@$res) {
6027 $default = $e->{name
} if $e->{'is-default'};
6028 $current = $e->{name
} if $e->{'is-current'};
6031 # fallback to the default machine if current is not supported by qemu
6032 return $current || $default || 'pc';
6035 sub qemu_machine_feature_enabled
{
6036 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6041 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6043 $current_major = $3;
6044 $current_minor = $4;
6046 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6048 $current_major = $1;
6049 $current_minor = $2;
6052 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6057 sub qemu_machine_pxe
{
6058 my ($vmid, $conf, $machine) = @_;
6060 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6062 foreach my $opt (keys %$conf) {
6063 next if $opt !~ m/^net(\d+)$/;
6064 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6066 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6067 return $machine.".pxe" if $romfile =~ m/pxe/;
6074 sub qemu_use_old_bios_files
{
6075 my ($machine_type) = @_;
6077 return if !$machine_type;
6079 my $use_old_bios_files = undef;
6081 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6083 $use_old_bios_files = 1;
6085 my $kvmver = kvm_user_version
();
6086 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6087 # load new efi bios files on migration. So this hack is required to allow
6088 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6089 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6090 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6093 return ($use_old_bios_files, $machine_type);
6100 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6101 my (undef, $id, $function) = @_;
6102 my $res = { id
=> $id, function
=> $function};
6103 push @{$devices->{$id}}, $res;
6109 sub vm_iothreads_list
{
6112 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6115 foreach my $iothread (@$res) {
6116 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6123 my ($conf, $drive) = @_;
6127 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6129 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6135 my $controller = int($drive->{index} / $maxdev);
6136 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6138 return ($maxdev, $controller, $controller_prefix);
6141 # bash completion helper
6143 sub complete_backup_archives
{
6144 my ($cmdname, $pname, $cvalue) = @_;
6146 my $cfg = PVE
::Storage
::config
();
6150 if ($cvalue =~ m/^([^:]+):/) {
6154 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6157 foreach my $id (keys %$data) {
6158 foreach my $item (@{$data->{$id}}) {
6159 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6160 push @$res, $item->{volid
} if defined($item->{volid
});
6167 my $complete_vmid_full = sub {
6170 my $idlist = vmstatus
();
6174 foreach my $id (keys %$idlist) {
6175 my $d = $idlist->{$id};
6176 if (defined($running)) {
6177 next if $d->{template
};
6178 next if $running && $d->{status
} ne 'running';
6179 next if !$running && $d->{status
} eq 'running';
6188 return &$complete_vmid_full();
6191 sub complete_vmid_stopped
{
6192 return &$complete_vmid_full(0);
6195 sub complete_vmid_running
{
6196 return &$complete_vmid_full(1);
6199 sub complete_storage
{
6201 my $cfg = PVE
::Storage
::config
();
6202 my $ids = $cfg->{ids
};
6205 foreach my $sid (keys %$ids) {
6206 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6207 next if !$ids->{$sid}->{content
}->{images
};