1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
32 use PVE
::RPCEnvironment
;
33 use Time
::HiRes
qw(gettimeofday);
34 use File
::Copy
qw(copy);
37 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
39 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
41 # Note about locking: we use flock on the config file protect
42 # against concurent actions.
43 # Aditionaly, we have a 'lock' setting in the config file. This
44 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
45 # allowed when such lock is set. But you can ignore this kind of
46 # lock with the --skiplock flag.
48 cfs_register_file
('/qemu-server/',
52 PVE
::JSONSchema
::register_standard_option
('skiplock', {
53 description
=> "Ignore locks - only root is allowed to use this option.",
58 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
59 description
=> "Some command save/restore state from this location.",
65 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
66 description
=> "The name of the snapshot.",
67 type
=> 'string', format
=> 'pve-configid',
71 #no warnings 'redefine';
74 my ($controller, $vmid, $option, $value) = @_;
76 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
77 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
81 my $nodename = PVE
::INotify
::nodename
();
83 mkdir "/etc/pve/nodes/$nodename";
84 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
87 my $var_run_tmpdir = "/var/run/qemu-server";
88 mkdir $var_run_tmpdir;
90 my $lock_dir = "/var/lock/qemu-server";
93 my $pcisysfs = "/sys/bus/pci";
97 description
=> "Emulated CPU type.",
99 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Haswell-noTSX Broadwell Broadwell-noTSX Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
100 format_description
=> 'cputype',
105 description
=> "Do not identify as a KVM virtual machine.",
116 description
=> "Specifies whether a VM will be started during system bootup.",
122 description
=> "Automatic restart after crash (currently ignored).",
127 type
=> 'string', format
=> 'pve-hotplug-features',
128 description
=> "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
129 default => 'network,disk,usb',
134 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
140 description
=> "Lock/unlock the VM.",
141 enum
=> [qw(migrate backup snapshot rollback)],
146 description
=> "Limit of CPU usage.\n\nNOTE: If the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
154 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
162 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
169 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
175 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
183 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
184 enum
=> PVE
::Tools
::kvmkeymaplist
(),
189 type
=> 'string', format
=> 'dns-name',
190 description
=> "Set a name for the VM. Only used on the configuration web interface.",
195 description
=> "scsi controller model",
196 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
202 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
207 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
208 description
=> <<EODESC,
209 Used to enable special optimization/features for specific
212 other => unspecified OS
213 wxp => Microsoft Windows XP
214 w2k => Microsoft Windows 2000
215 w2k3 => Microsoft Windows 2003
216 w2k8 => Microsoft Windows 2008
217 wvista => Microsoft Windows Vista
218 win7 => Microsoft Windows 7
219 win8 => Microsoft Windows 8/2012
220 l24 => Linux 2.4 Kernel
221 l26 => Linux 2.6/3.X Kernel
222 solaris => solaris/opensolaris/openindiania kernel
224 other|l24|l26|solaris ... no special behaviour
225 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
231 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
232 pattern
=> '[acdn]{1,4}',
237 type
=> 'string', format
=> 'pve-qm-bootdisk',
238 description
=> "Enable booting from specified disk.",
239 pattern
=> '(ide|sata|scsi|virtio)\d+',
244 description
=> "The number of CPUs. Please use option -sockets instead.",
251 description
=> "The number of CPU sockets.",
258 description
=> "The number of cores per socket.",
265 description
=> "Enable/disable NUMA.",
271 description
=> "Number of hotplugged vcpus.",
278 description
=> "Enable/disable ACPI.",
284 description
=> "Enable/disable Qemu GuestAgent.",
290 description
=> "Enable/disable KVM hardware virtualization.",
296 description
=> "Enable/disable time drift fix.",
302 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
307 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
312 description
=> "Select the VGA type. If you want to use high resolution" .
313 " modes (>= 1280x1024x16) then you should use the options " .
314 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
315 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
316 "display sever. For win* OS you can select how many independent " .
317 "displays you want, Linux guests can add displays them self. " .
318 "You can also run without any graphic card, using a serial device" .
320 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
324 type
=> 'string', format
=> 'pve-qm-watchdog',
325 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
326 description
=> "Create a virtual hardware watchdog device. Once enabled" .
327 " (by a guest action), the watchdog must be periodically polled " .
328 "by an agent inside the guest or else the watchdog will reset " .
329 "the guest (or execute the respective action specified)",
334 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
335 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
336 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
339 startup
=> get_standard_option
('pve-startup-order'),
343 description
=> "Enable/disable Template.",
349 description
=> <<EODESCR,
350 NOTE: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
352 args: -no-reboot -no-hpet
359 description
=> "Enable/disable the USB tablet device. This device is " .
360 "usually needed to allow absolute mouse positioning with VNC. " .
361 "Else the mouse runs out of sync with normal VNC clients. " .
362 "If you're running lots of console-only guests on one host, " .
363 "you may consider disabling this to save some context switches. " .
364 "This is turned off by default if you use spice (-vga=qxl).",
369 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
373 migrate_downtime
=> {
376 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
382 type
=> 'string', format
=> 'pve-qm-drive',
383 typetext
=> 'volume',
384 description
=> "This is an alias for option -ide2",
388 description
=> "Emulated CPU type.",
392 parent
=> get_standard_option
('pve-snapshot-name', {
394 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
398 description
=> "Timestamp for snapshots.",
404 type
=> 'string', format
=> 'pve-volume-id',
405 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
408 description
=> "Specific the Qemu machine type.",
410 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
415 description
=> "Specify SMBIOS type 1 fields.",
416 type
=> 'string', format
=> 'pve-qm-smbios1',
423 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
429 enum
=> [ qw(seabios ovmf) ],
430 description
=> "Select BIOS implementation.",
431 default => 'seabios',
435 # what about other qemu settings ?
437 #machine => 'string',
450 ##soundhw => 'string',
452 while (my ($k, $v) = each %$confdesc) {
453 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
456 my $MAX_IDE_DISKS = 4;
457 my $MAX_SCSI_DISKS = 14;
458 my $MAX_VIRTIO_DISKS = 16;
459 my $MAX_SATA_DISKS = 6;
460 my $MAX_USB_DEVICES = 5;
462 my $MAX_UNUSED_DISKS = 8;
463 my $MAX_HOSTPCI_DEVICES = 4;
464 my $MAX_SERIAL_PORTS = 4;
465 my $MAX_PARALLEL_PORTS = 3;
467 my $MAX_MEM = 4194304;
468 my $STATICMEM = 1024;
472 type
=> 'string', format
=> 'pve-qm-numanode',
473 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
474 description
=> "numa topology",
476 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
478 for (my $i = 0; $i < $MAX_NUMA; $i++) {
479 $confdesc->{"numa$i"} = $numadesc;
482 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
483 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
484 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
485 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
489 type
=> 'string', format
=> 'pve-qm-net',
490 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,trunks=<vlanid[;vlanid]>][,firewall=0|1],link_down=0|1]",
491 description
=> <<EODESCR,
492 Specify network devices.
494 MODEL is one of: $nic_model_list_txt
496 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
497 automatically generated if not specified.
499 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
501 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
503 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
509 The DHCP server assign addresses to the guest starting from 10.0.2.15.
513 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
515 for (my $i = 0; $i < $MAX_NETS; $i++) {
516 $confdesc->{"net$i"} = $netdesc;
519 PVE
::JSONSchema
::register_format
('pve-volume-id-or-none', \
&verify_volume_id_or_none
);
520 sub verify_volume_id_or_none
{
521 my ($volid, $noerr) = @_;
523 return $volid if $volid eq 'none';
524 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
526 return undef if $noerr;
534 my %drivedesc_base = (
535 volume
=> { alias
=> 'file' },
538 format
=> 'pve-volume-id-or-none',
540 format_description
=> 'volume',
541 description
=> "The drive's backing volume.",
545 format_description
=> 'cdrom|disk',
546 enum
=> [qw(cdrom disk)],
547 description
=> "The drive's media type.",
553 format_description
=> 'count',
554 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
559 format_description
=> 'count',
560 description
=> "Force the drive's physical geometry to have a specific head count.",
565 format_description
=> 'count',
566 description
=> "Force the drive's physical geometry to have a specific sector count.",
571 format_description
=> 'none|lba|auto',
572 enum
=> [qw(none lba auto)],
573 description
=> "Force disk geometry bios translation mode.",
578 format_description
=> 'on|off',
579 description
=> "Whether the drive should be included when making snapshots.",
584 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
585 enum
=> [qw(none writethrough writeback unsafe directsync)],
586 description
=> "The drive's cache mode",
591 format_description
=> 'drive format',
592 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
593 description
=> "The drive's backing file's data format.",
598 format
=> 'disk-size',
599 description
=> "Disk size. This is purely informational and has no effect.",
604 format_description
=> 'on|off',
605 description
=> "Whether the drive should be included when making backups.",
610 format_description
=> 'enospc|ignore|report|stop',
611 enum
=> [qw(enospc ignore report stop)],
612 description
=> 'Write error action.',
617 format_description
=> 'native|threads',
618 enum
=> [qw(native threads)],
619 description
=> 'AIO type to use.',
624 format_description
=> 'ignore|on',
625 enum
=> [qw(ignore on)],
626 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
631 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
636 format
=> 'urlencoded',
637 format_description
=> 'serial',
638 maxLength
=> 20*3, # *3 since it's %xx url enoded
639 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
647 format_description
=> 'ignore|report|stop',
648 enum
=> [qw(ignore report stop)],
649 description
=> 'Read error action.',
654 my %iothread_fmt = ( iothread
=> {
656 format_description
=> 'off|on',
657 description
=> "Whether to use iothreads for this drive",
664 format
=> 'urlencoded',
665 format_description
=> 'model',
666 maxLength
=> 40*3, # *3 since it's %xx url enoded
667 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
675 format_description
=> 'nbqueues',
676 description
=> "Number of queues.",
682 my $add_throttle_desc = sub {
683 my ($key, $type, $what, $size, $longsize) = @_;
684 $drivedesc_base{$key} = {
686 format_description
=> $size,
687 description
=> "Maximum $what speed in $longsize per second.",
691 # throughput: (leaky bucket)
692 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
693 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
694 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
695 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
696 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
697 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
698 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
699 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
700 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
702 # pools: (pool of IO before throttling starts taking effect)
703 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
704 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
705 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
706 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
707 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
708 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
718 type
=> 'string', format
=> $ide_fmt,
719 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
721 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
730 type
=> 'string', format
=> $scsi_fmt,
731 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
733 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
741 type
=> 'string', format
=> $sata_fmt,
742 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
744 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
753 type
=> 'string', format
=> $virtio_fmt,
754 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
756 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
769 type
=> 'string', format
=> 'pve-qm-usb-device',
770 format_description
=> 'HOSTUSBDEVICE|spice',
771 description
=> 'The Host USB device or port or the value spice',
776 format_description
=> 'yes|no',
777 description
=> 'Specifies whether if given host option is a USB3 device or port',
783 type
=> 'string', format
=> $usb_fmt,
784 description
=> <<EODESCR,
785 Configure an USB device (n is 0 to 4). This can be used to
786 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
788 'bus-port(.port)*' (decimal numbers) or
789 'vendor_id:product_id' (hexadeciaml numbers) or
792 You can use the 'lsusb -t' command to list existing usb devices.
794 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
796 The value 'spice' can be used to add a usb redirection devices for spice.
798 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).
802 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
806 type
=> 'string', format
=> 'pve-qm-hostpci',
807 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
808 description
=> <<EODESCR,
809 Map host pci devices. HOSTPCIDEVICE syntax is:
811 'bus:dev.func' (hexadecimal numbers)
813 You can us the 'lspci' command to list existing pci devices.
815 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
817 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
819 Experimental: user reported problems with this option.
822 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
827 pattern
=> '(/dev/.+|socket)',
828 description
=> <<EODESCR,
829 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).
831 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
833 Experimental: user reported problems with this option.
840 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
841 description
=> <<EODESCR,
842 Map host parallel devices (n is 0 to 2).
844 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
846 Experimental: user reported problems with this option.
850 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
851 $confdesc->{"parallel$i"} = $paralleldesc;
854 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
855 $confdesc->{"serial$i"} = $serialdesc;
858 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
859 $confdesc->{"hostpci$i"} = $hostpcidesc;
862 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
863 $drivename_hash->{"ide$i"} = 1;
864 $confdesc->{"ide$i"} = $idedesc;
867 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
868 $drivename_hash->{"sata$i"} = 1;
869 $confdesc->{"sata$i"} = $satadesc;
872 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
873 $drivename_hash->{"scsi$i"} = 1;
874 $confdesc->{"scsi$i"} = $scsidesc ;
877 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
878 $drivename_hash->{"virtio$i"} = 1;
879 $confdesc->{"virtio$i"} = $virtiodesc;
882 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
883 $confdesc->{"usb$i"} = $usbdesc;
888 type
=> 'string', format
=> 'pve-volume-id',
889 description
=> "Reference to unused volumes.",
892 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
893 $confdesc->{"unused$i"} = $unuseddesc;
896 my $kvm_api_version = 0;
900 return $kvm_api_version if $kvm_api_version;
902 my $fh = IO
::File-
>new("</dev/kvm") ||
905 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
906 $kvm_api_version = $v;
911 return $kvm_api_version;
914 my $kvm_user_version;
916 sub kvm_user_version
{
918 return $kvm_user_version if $kvm_user_version;
920 $kvm_user_version = 'unknown';
924 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
925 $kvm_user_version = $2;
929 eval { run_command
("kvm -version", outfunc
=> $code); };
932 return $kvm_user_version;
936 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
938 sub valid_drive_names
{
939 # order is important - used to autoselect boot disk
940 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
941 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
942 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
943 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
946 sub is_valid_drivename
{
949 return defined($drivename_hash->{$dev});
954 return defined($confdesc->{$key});
958 return $nic_model_list;
961 sub os_list_description
{
966 w2k
=> 'Windows 2000',
967 w2k3
=>, 'Windows 2003',
968 w2k8
=> 'Windows 2008',
969 wvista
=> 'Windows Vista',
971 win8
=> 'Windows 8/2012',
981 return $cdrom_path if $cdrom_path;
983 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
984 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
985 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
989 my ($storecfg, $vmid, $cdrom) = @_;
991 if ($cdrom eq 'cdrom') {
992 return get_cdrom_path
();
993 } elsif ($cdrom eq 'none') {
995 } elsif ($cdrom =~ m
|^/|) {
998 return PVE
::Storage
::path
($storecfg, $cdrom);
1002 # try to convert old style file names to volume IDs
1003 sub filename_to_volume_id
{
1004 my ($vmid, $file, $media) = @_;
1006 if (!($file eq 'none' || $file eq 'cdrom' ||
1007 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1009 return undef if $file =~ m
|/|;
1011 if ($media && $media eq 'cdrom') {
1012 $file = "local:iso/$file";
1014 $file = "local:$vmid/$file";
1021 sub verify_media_type
{
1022 my ($opt, $vtype, $media) = @_;
1027 if ($media eq 'disk') {
1029 } elsif ($media eq 'cdrom') {
1032 die "internal error";
1035 return if ($vtype eq $etype);
1037 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1040 sub cleanup_drive_path
{
1041 my ($opt, $storecfg, $drive) = @_;
1043 # try to convert filesystem paths to volume IDs
1045 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1046 ($drive->{file
} !~ m
|^/dev/.+|) &&
1047 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1048 ($drive->{file
} !~ m/^\d+$/)) {
1049 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1050 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1051 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1052 verify_media_type
($opt, $vtype, $drive->{media
});
1053 $drive->{file
} = $volid;
1056 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1059 sub parse_hotplug_features
{
1064 return $res if $data eq '0';
1066 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1068 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1069 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1072 warn "ignoring unknown hotplug feature '$feature'\n";
1078 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1079 sub pve_verify_hotplug_features
{
1080 my ($value, $noerr) = @_;
1082 return $value if parse_hotplug_features
($value);
1084 return undef if $noerr;
1086 die "unable to parse hotplug option\n";
1089 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1090 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1091 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1092 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1093 # [,iothread=on][,serial=serial][,model=model]
1096 my ($key, $data) = @_;
1098 my ($interface, $index);
1100 if ($key =~ m/^([^\d]+)(\d+)$/) {
1107 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1108 : $confdesc->{$key}->{format
};
1110 warn "invalid drive key: $key\n";
1113 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1114 return undef if !$res;
1115 $res->{interface
} = $interface;
1116 $res->{index} = $index;
1119 foreach my $opt (qw(bps bps_rd bps_wr)) {
1120 if (my $bps = defined(delete $res->{$opt})) {
1121 if (defined($res->{"m$opt"})) {
1122 warn "both $opt and m$opt specified\n";
1126 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1129 return undef if $error;
1131 return undef if $res->{mbps_rd
} && $res->{mbps
};
1132 return undef if $res->{mbps_wr
} && $res->{mbps
};
1133 return undef if $res->{iops_rd
} && $res->{iops
};
1134 return undef if $res->{iops_wr
} && $res->{iops
};
1136 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1137 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1138 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1139 return undef if $res->{interface
} eq 'virtio';
1142 if (my $size = $res->{size
}) {
1143 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1150 my ($vmid, $drive) = @_;
1151 my $data = { %$drive };
1152 delete $data->{$_} for qw(index interface);
1153 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1157 my($fh, $noerr) = @_;
1160 my $SG_GET_VERSION_NUM = 0x2282;
1162 my $versionbuf = "\x00" x
8;
1163 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1165 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1168 my $version = unpack("I", $versionbuf);
1169 if ($version < 30000) {
1170 die "scsi generic interface too old\n" if !$noerr;
1174 my $buf = "\x00" x
36;
1175 my $sensebuf = "\x00" x
8;
1176 my $cmd = pack("C x3 C x1", 0x12, 36);
1178 # see /usr/include/scsi/sg.h
1179 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";
1181 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1182 length($sensebuf), 0, length($buf), $buf,
1183 $cmd, $sensebuf, 6000);
1185 $ret = ioctl($fh, $SG_IO, $packet);
1187 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1191 my @res = unpack($sg_io_hdr_t, $packet);
1192 if ($res[17] || $res[18]) {
1193 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1198 (my $byte0, my $byte1, $res->{vendor
},
1199 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1201 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1202 $res->{type
} = $byte0 & 31;
1210 my $fh = IO
::File-
>new("+<$path") || return undef;
1211 my $res = scsi_inquiry
($fh, 1);
1217 sub machine_type_is_q35
{
1220 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1223 sub print_tabletdevice_full
{
1226 my $q35 = machine_type_is_q35
($conf);
1228 # we use uhci for old VMs because tablet driver was buggy in older qemu
1229 my $usbbus = $q35 ?
"ehci" : "uhci";
1231 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1234 sub print_drivedevice_full
{
1235 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1240 if ($drive->{interface
} eq 'virtio') {
1241 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1242 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1243 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1244 } elsif ($drive->{interface
} eq 'scsi') {
1246 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1247 my $unit = $drive->{index} % $maxdev;
1248 my $devicetype = 'hd';
1250 if (drive_is_cdrom
($drive)) {
1253 if ($drive->{file
} =~ m
|^/|) {
1254 $path = $drive->{file
};
1255 if (my $info = path_is_scsi
($path)) {
1256 if ($info->{type
} == 0) {
1257 $devicetype = 'block';
1258 } elsif ($info->{type
} == 1) { # tape
1259 $devicetype = 'generic';
1263 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1266 if($path =~ m/^iscsi\:\/\
//){
1267 $devicetype = 'generic';
1271 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1272 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1274 $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}";
1277 } elsif ($drive->{interface
} eq 'ide'){
1279 my $controller = int($drive->{index} / $maxdev);
1280 my $unit = $drive->{index} % $maxdev;
1281 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1283 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1284 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1285 $model = URI
::Escape
::uri_unescape
($model);
1286 $device .= ",model=$model";
1288 } elsif ($drive->{interface
} eq 'sata'){
1289 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1290 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1291 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1292 } elsif ($drive->{interface
} eq 'usb') {
1294 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1296 die "unsupported interface type";
1299 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1304 sub get_initiator_name
{
1307 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1308 while (defined(my $line = <$fh>)) {
1309 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1318 sub print_drive_full
{
1319 my ($storecfg, $vmid, $drive) = @_;
1322 my $volid = $drive->{file
};
1325 if (drive_is_cdrom
($drive)) {
1326 $path = get_iso_path
($storecfg, $vmid, $volid);
1328 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1330 $path = PVE
::Storage
::path
($storecfg, $volid);
1331 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1332 $format = qemu_img_format
($scfg, $volname);
1340 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);
1341 foreach my $o (@qemu_drive_options) {
1342 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1344 if (my $serial = $drive->{serial
}) {
1345 $serial = URI
::Escape
::uri_unescape
($serial);
1346 $opts .= ",serial=$serial";
1349 $opts .= ",format=$format" if $format && !$drive->{format
};
1351 foreach my $o (qw(bps bps_rd bps_wr)) {
1352 my $v = $drive->{"m$o"};
1353 $opts .= ",$o=" . int($v*1024*1024) if $v;
1356 my $cache_direct = 0;
1358 if (my $cache = $drive->{cache
}) {
1359 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1360 } elsif (!drive_is_cdrom
($drive)) {
1361 $opts .= ",cache=none";
1365 # aio native works only with O_DIRECT
1366 if (!$drive->{aio
}) {
1368 $opts .= ",aio=native";
1370 $opts .= ",aio=threads";
1374 if (!drive_is_cdrom
($drive)) {
1376 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1377 $detectzeroes = 'off';
1378 } elsif ($drive->{discard
}) {
1379 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1381 # This used to be our default with discard not being specified:
1382 $detectzeroes = 'on';
1384 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1387 my $pathinfo = $path ?
"file=$path," : '';
1389 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1392 sub print_netdevice_full
{
1393 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1395 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1397 my $device = $net->{model
};
1398 if ($net->{model
} eq 'virtio') {
1399 $device = 'virtio-net-pci';
1402 my $pciaddr = print_pci_addr
("$netid", $bridges);
1403 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1404 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1405 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1406 my $vectors = $net->{queues
} * 2 + 2;
1407 $tmpstr .= ",vectors=$vectors,mq=on";
1409 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1411 if ($use_old_bios_files) {
1413 if ($device eq 'virtio-net-pci') {
1414 $romfile = 'pxe-virtio.rom';
1415 } elsif ($device eq 'e1000') {
1416 $romfile = 'pxe-e1000.rom';
1417 } elsif ($device eq 'ne2k') {
1418 $romfile = 'pxe-ne2k_pci.rom';
1419 } elsif ($device eq 'pcnet') {
1420 $romfile = 'pxe-pcnet.rom';
1421 } elsif ($device eq 'rtl8139') {
1422 $romfile = 'pxe-rtl8139.rom';
1424 $tmpstr .= ",romfile=$romfile" if $romfile;
1430 sub print_netdev_full
{
1431 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1434 if ($netid =~ m/^net(\d+)$/) {
1438 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1440 my $ifname = "tap${vmid}i$i";
1442 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1443 die "interface name '$ifname' is too long (max 15 character)\n"
1444 if length($ifname) >= 16;
1446 my $vhostparam = '';
1447 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1449 my $vmname = $conf->{name
} || "vm$vmid";
1452 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1454 if ($net->{bridge
}) {
1455 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1457 $netdev = "type=user,id=$netid,hostname=$vmname";
1460 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1465 sub drive_is_cdrom
{
1468 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1477 foreach my $kvp (split(/,/, $data)) {
1479 if ($kvp =~ m/^memory=(\S+)$/) {
1480 $res->{memory
} = $1;
1481 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1482 $res->{policy
} = $1;
1483 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1484 $res->{cpus
}->{start
} = $1;
1485 $res->{cpus
}->{end
} = $3;
1486 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1487 $res->{hostnodes
}->{start
} = $1;
1488 $res->{hostnodes
}->{end
} = $3;
1500 return undef if !$value;
1503 my @list = split(/,/, $value);
1507 foreach my $kv (@list) {
1509 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1512 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1515 my $pcidevices = lspci
($2);
1516 $res->{pciid
} = $pcidevices->{$2};
1518 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1519 $res->{rombar
} = $1;
1520 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1521 $res->{'x-vga'} = $1;
1522 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1523 $res->{pcie
} = 1 if $1 == 1;
1525 warn "unknown hostpci setting '$kv'\n";
1529 return undef if !$found;
1534 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1540 foreach my $kvp (split(/,/, $data)) {
1542 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) {
1544 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1545 $res->{model
} = $model;
1546 $res->{macaddr
} = $mac;
1547 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1548 $res->{bridge
} = $1;
1549 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1550 $res->{queues
} = $1;
1551 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1553 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1555 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1556 $res->{trunks
} = $1;
1557 } elsif ($kvp =~ m/^firewall=([01])$/) {
1558 $res->{firewall
} = $1;
1559 } elsif ($kvp =~ m/^link_down=([01])$/) {
1560 $res->{link_down
} = $1;
1567 return undef if !$res->{model
};
1575 my $res = "$net->{model}";
1576 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1577 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1578 $res .= ",rate=$net->{rate}" if $net->{rate
};
1579 $res .= ",tag=$net->{tag}" if $net->{tag
};
1580 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1581 $res .= ",firewall=1" if $net->{firewall
};
1582 $res .= ",link_down=1" if $net->{link_down
};
1583 $res .= ",queues=$net->{queues}" if $net->{queues
};
1588 sub add_random_macs
{
1589 my ($settings) = @_;
1591 foreach my $opt (keys %$settings) {
1592 next if $opt !~ m/^net(\d+)$/;
1593 my $net = parse_net
($settings->{$opt});
1595 $settings->{$opt} = print_net
($net);
1599 sub vm_is_volid_owner
{
1600 my ($storecfg, $vmid, $volid) = @_;
1602 if ($volid !~ m
|^/|) {
1604 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1605 if ($owner && ($owner == $vmid)) {
1613 sub split_flagged_list
{
1614 my $text = shift || '';
1615 $text =~ s/[,;]/ /g;
1617 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1620 sub join_flagged_list
{
1621 my ($how, $lst) = @_;
1622 join $how, map { $lst->{$_} . $_ } keys %$lst;
1625 sub vmconfig_delete_pending_option
{
1626 my ($conf, $key, $force) = @_;
1628 delete $conf->{pending
}->{$key};
1629 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1630 $pending_delete_hash->{$key} = $force ?
'!' : '';
1631 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1634 sub vmconfig_undelete_pending_option
{
1635 my ($conf, $key) = @_;
1637 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1638 delete $pending_delete_hash->{$key};
1640 if (%$pending_delete_hash) {
1641 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1643 delete $conf->{pending
}->{delete};
1647 sub vmconfig_register_unused_drive
{
1648 my ($storecfg, $vmid, $conf, $drive) = @_;
1650 if (!drive_is_cdrom
($drive)) {
1651 my $volid = $drive->{file
};
1652 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1653 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1658 sub vmconfig_cleanup_pending
{
1661 # remove pending changes when nothing changed
1663 foreach my $opt (keys %{$conf->{pending
}}) {
1664 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1666 delete $conf->{pending
}->{$opt};
1670 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1671 my $pending_delete_hash = {};
1672 while (my ($opt, $force) = each %$current_delete_hash) {
1673 if (defined($conf->{$opt})) {
1674 $pending_delete_hash->{$opt} = $force;
1680 if (%$pending_delete_hash) {
1681 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1683 delete $conf->{pending
}->{delete};
1689 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1693 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1694 format_description
=> 'UUID',
1700 format_description
=> 'str',
1706 format_description
=> 'str',
1712 format_description
=> 'name',
1718 format_description
=> 'name',
1724 format_description
=> 'str',
1730 format_description
=> 'str',
1738 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1745 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1748 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1750 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1751 sub verify_bootdisk
{
1752 my ($value, $noerr) = @_;
1754 return $value if is_valid_drivename
($value);
1756 return undef if $noerr;
1758 die "invalid boot disk '$value'\n";
1761 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1763 my ($value, $noerr) = @_;
1765 return $value if parse_numa
($value);
1767 return undef if $noerr;
1769 die "unable to parse numa options\n";
1772 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1774 my ($value, $noerr) = @_;
1776 return $value if parse_net
($value);
1778 return undef if $noerr;
1780 die "unable to parse network options\n";
1783 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1784 sub verify_hostpci
{
1785 my ($value, $noerr) = @_;
1787 return $value if parse_hostpci
($value);
1789 return undef if $noerr;
1791 die "unable to parse pci id\n";
1794 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1795 sub verify_watchdog
{
1796 my ($value, $noerr) = @_;
1798 return $value if parse_watchdog
($value);
1800 return undef if $noerr;
1802 die "unable to parse watchdog options\n";
1805 sub parse_watchdog
{
1808 return undef if !$value;
1812 foreach my $p (split(/,/, $value)) {
1813 next if $p =~ m/^\s*$/;
1815 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1817 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1818 $res->{action
} = $2;
1827 sub parse_usb_device
{
1830 return undef if !$value;
1833 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1834 $res->{vendorid
} = $2;
1835 $res->{productid
} = $4;
1836 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1837 $res->{hostbus
} = $1;
1838 $res->{hostport
} = $2;
1839 } elsif ($value =~ m/^spice$/i) {
1848 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1849 sub verify_usb_device
{
1850 my ($value, $noerr) = @_;
1852 return $value if parse_usb_device
($value);
1854 return undef if $noerr;
1856 die "unable to parse usb device\n";
1859 # add JSON properties for create and set function
1860 sub json_config_properties
{
1863 foreach my $opt (keys %$confdesc) {
1864 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1865 $prop->{$opt} = $confdesc->{$opt};
1872 my ($key, $value) = @_;
1874 die "unknown setting '$key'\n" if !$confdesc->{$key};
1876 my $type = $confdesc->{$key}->{type
};
1878 if (!defined($value)) {
1879 die "got undefined value\n";
1882 if ($value =~ m/[\n\r]/) {
1883 die "property contains a line feed\n";
1886 if ($type eq 'boolean') {
1887 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1888 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1889 die "type check ('boolean') failed - got '$value'\n";
1890 } elsif ($type eq 'integer') {
1891 return int($1) if $value =~ m/^(\d+)$/;
1892 die "type check ('integer') failed - got '$value'\n";
1893 } elsif ($type eq 'number') {
1894 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1895 die "type check ('number') failed - got '$value'\n";
1896 } elsif ($type eq 'string') {
1897 if (my $fmt = $confdesc->{$key}->{format
}) {
1898 if ($fmt eq 'pve-qm-drive') {
1899 # special case - we need to pass $key to parse_drive()
1900 my $drive = parse_drive
($key, $value);
1901 return $value if $drive;
1902 die "unable to parse drive options\n";
1904 PVE
::JSONSchema
::check_format
($fmt, $value);
1907 $value =~ s/^\"(.*)\"$/$1/;
1910 die "internal error"
1914 sub check_iommu_support
{
1915 #fixme : need to check IOMMU support
1916 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1926 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1927 utime undef, undef, $conf;
1931 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1933 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1935 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1937 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1939 # only remove disks owned by this VM
1940 foreach_drive
($conf, sub {
1941 my ($ds, $drive) = @_;
1943 return if drive_is_cdrom
($drive);
1945 my $volid = $drive->{file
};
1947 return if !$volid || $volid =~ m
|^/|;
1949 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1950 return if !$path || !$owner || ($owner != $vmid);
1952 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1955 if ($keep_empty_config) {
1956 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1961 # also remove unused disk
1963 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1966 PVE
::Storage
::foreach_volid
($dl, sub {
1967 my ($volid, $sid, $volname, $d) = @_;
1968 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1977 sub parse_vm_config
{
1978 my ($filename, $raw) = @_;
1980 return undef if !defined($raw);
1983 digest
=> Digest
::SHA
::sha1_hex
($raw),
1988 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1989 || die "got strange filename '$filename'";
1997 my @lines = split(/\n/, $raw);
1998 foreach my $line (@lines) {
1999 next if $line =~ m/^\s*$/;
2001 if ($line =~ m/^\[PENDING\]\s*$/i) {
2002 $section = 'pending';
2003 if (defined($descr)) {
2005 $conf->{description
} = $descr;
2008 $conf = $res->{$section} = {};
2011 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2013 if (defined($descr)) {
2015 $conf->{description
} = $descr;
2018 $conf = $res->{snapshots
}->{$section} = {};
2022 if ($line =~ m/^\#(.*)\s*$/) {
2023 $descr = '' if !defined($descr);
2024 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2028 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2029 $descr = '' if !defined($descr);
2030 $descr .= PVE
::Tools
::decode_text
($2);
2031 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2032 $conf->{snapstate
} = $1;
2033 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2036 $conf->{$key} = $value;
2037 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2039 if ($section eq 'pending') {
2040 $conf->{delete} = $value; # we parse this later
2042 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2044 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2047 eval { $value = check_type
($key, $value); };
2049 warn "vm $vmid - unable to parse value of '$key' - $@";
2051 my $fmt = $confdesc->{$key}->{format
};
2052 if ($fmt && $fmt eq 'pve-qm-drive') {
2053 my $v = parse_drive
($key, $value);
2054 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2055 $v->{file
} = $volid;
2056 $value = print_drive
($vmid, $v);
2058 warn "vm $vmid - unable to parse value of '$key'\n";
2063 if ($key eq 'cdrom') {
2064 $conf->{ide2
} = $value;
2066 $conf->{$key} = $value;
2072 if (defined($descr)) {
2074 $conf->{description
} = $descr;
2076 delete $res->{snapstate
}; # just to be sure
2081 sub write_vm_config
{
2082 my ($filename, $conf) = @_;
2084 delete $conf->{snapstate
}; # just to be sure
2086 if ($conf->{cdrom
}) {
2087 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2088 $conf->{ide2
} = $conf->{cdrom
};
2089 delete $conf->{cdrom
};
2092 # we do not use 'smp' any longer
2093 if ($conf->{sockets
}) {
2094 delete $conf->{smp
};
2095 } elsif ($conf->{smp
}) {
2096 $conf->{sockets
} = $conf->{smp
};
2097 delete $conf->{cores
};
2098 delete $conf->{smp
};
2101 my $used_volids = {};
2103 my $cleanup_config = sub {
2104 my ($cref, $pending, $snapname) = @_;
2106 foreach my $key (keys %$cref) {
2107 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2108 $key eq 'snapstate' || $key eq 'pending';
2109 my $value = $cref->{$key};
2110 if ($key eq 'delete') {
2111 die "propertry 'delete' is only allowed in [PENDING]\n"
2113 # fixme: check syntax?
2116 eval { $value = check_type
($key, $value); };
2117 die "unable to parse value of '$key' - $@" if $@;
2119 $cref->{$key} = $value;
2121 if (!$snapname && is_valid_drivename
($key)) {
2122 my $drive = parse_drive
($key, $value);
2123 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2128 &$cleanup_config($conf);
2130 &$cleanup_config($conf->{pending
}, 1);
2132 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2133 die "internal error" if $snapname eq 'pending';
2134 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2137 # remove 'unusedX' settings if we re-add a volume
2138 foreach my $key (keys %$conf) {
2139 my $value = $conf->{$key};
2140 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2141 delete $conf->{$key};
2145 my $generate_raw_config = sub {
2146 my ($conf, $pending) = @_;
2150 # add description as comment to top of file
2151 if (defined(my $descr = $conf->{description
})) {
2153 foreach my $cl (split(/\n/, $descr)) {
2154 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2157 $raw .= "#\n" if $pending;
2161 foreach my $key (sort keys %$conf) {
2162 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2163 $raw .= "$key: $conf->{$key}\n";
2168 my $raw = &$generate_raw_config($conf);
2170 if (scalar(keys %{$conf->{pending
}})){
2171 $raw .= "\n[PENDING]\n";
2172 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2175 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2176 $raw .= "\n[$snapname]\n";
2177 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2187 # we use static defaults from our JSON schema configuration
2188 foreach my $key (keys %$confdesc) {
2189 if (defined(my $default = $confdesc->{$key}->{default})) {
2190 $res->{$key} = $default;
2194 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2195 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2201 my $vmlist = PVE
::Cluster
::get_vmlist
();
2203 return $res if !$vmlist || !$vmlist->{ids
};
2204 my $ids = $vmlist->{ids
};
2206 foreach my $vmid (keys %$ids) {
2207 my $d = $ids->{$vmid};
2208 next if !$d->{node
} || $d->{node
} ne $nodename;
2209 next if !$d->{type
} || $d->{type
} ne 'qemu';
2210 $res->{$vmid}->{exists} = 1;
2215 # test if VM uses local resources (to prevent migration)
2216 sub check_local_resources
{
2217 my ($conf, $noerr) = @_;
2221 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2222 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2224 foreach my $k (keys %$conf) {
2225 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2226 # sockets are safe: they will recreated be on the target side post-migrate
2227 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2228 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2231 die "VM uses local resources\n" if $loc_res && !$noerr;
2236 # check if used storages are available on all nodes (use by migrate)
2237 sub check_storage_availability
{
2238 my ($storecfg, $conf, $node) = @_;
2240 foreach_drive
($conf, sub {
2241 my ($ds, $drive) = @_;
2243 my $volid = $drive->{file
};
2246 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2249 # check if storage is available on both nodes
2250 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2251 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2255 # list nodes where all VM images are available (used by has_feature API)
2257 my ($conf, $storecfg) = @_;
2259 my $nodelist = PVE
::Cluster
::get_nodelist
();
2260 my $nodehash = { map { $_ => 1 } @$nodelist };
2261 my $nodename = PVE
::INotify
::nodename
();
2263 foreach_drive
($conf, sub {
2264 my ($ds, $drive) = @_;
2266 my $volid = $drive->{file
};
2269 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2271 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2272 if ($scfg->{disable
}) {
2274 } elsif (my $avail = $scfg->{nodes
}) {
2275 foreach my $node (keys %$nodehash) {
2276 delete $nodehash->{$node} if !$avail->{$node};
2278 } elsif (!$scfg->{shared
}) {
2279 foreach my $node (keys %$nodehash) {
2280 delete $nodehash->{$node} if $node ne $nodename
2290 my ($pidfile, $pid) = @_;
2292 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2296 return undef if !$line;
2297 my @param = split(/\0/, $line);
2299 my $cmd = $param[0];
2300 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2302 for (my $i = 0; $i < scalar (@param); $i++) {
2305 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2306 my $p = $param[$i+1];
2307 return 1 if $p && ($p eq $pidfile);
2316 my ($vmid, $nocheck, $node) = @_;
2318 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2320 die "unable to find configuration file for VM $vmid - no such machine\n"
2321 if !$nocheck && ! -f
$filename;
2323 my $pidfile = pidfile_name
($vmid);
2325 if (my $fd = IO
::File-
>new("<$pidfile")) {
2330 my $mtime = $st->mtime;
2331 if ($mtime > time()) {
2332 warn "file '$filename' modified in future\n";
2335 if ($line =~ m/^(\d+)$/) {
2337 if (check_cmdline
($pidfile, $pid)) {
2338 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2350 my $vzlist = config_list
();
2352 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2354 while (defined(my $de = $fd->read)) {
2355 next if $de !~ m/^(\d+)\.pid$/;
2357 next if !defined($vzlist->{$vmid});
2358 if (my $pid = check_running
($vmid)) {
2359 $vzlist->{$vmid}->{pid
} = $pid;
2367 my ($storecfg, $conf) = @_;
2369 my $bootdisk = $conf->{bootdisk
};
2370 return undef if !$bootdisk;
2371 return undef if !is_valid_drivename
($bootdisk);
2373 return undef if !$conf->{$bootdisk};
2375 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2376 return undef if !defined($drive);
2378 return undef if drive_is_cdrom
($drive);
2380 my $volid = $drive->{file
};
2381 return undef if !$volid;
2383 return $drive->{size
};
2386 my $last_proc_pid_stat;
2388 # get VM status information
2389 # This must be fast and should not block ($full == false)
2390 # We only query KVM using QMP if $full == true (this can be slow)
2392 my ($opt_vmid, $full) = @_;
2396 my $storecfg = PVE
::Storage
::config
();
2398 my $list = vzlist
();
2399 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2401 my $cpucount = $cpuinfo->{cpus
} || 1;
2403 foreach my $vmid (keys %$list) {
2404 next if $opt_vmid && ($vmid ne $opt_vmid);
2406 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2407 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2410 $d->{pid
} = $list->{$vmid}->{pid
};
2412 # fixme: better status?
2413 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2415 my $size = disksize
($storecfg, $conf);
2416 if (defined($size)) {
2417 $d->{disk
} = 0; # no info available
2418 $d->{maxdisk
} = $size;
2424 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2425 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2426 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2428 $d->{name
} = $conf->{name
} || "VM $vmid";
2429 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2431 if ($conf->{balloon
}) {
2432 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2433 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2444 $d->{diskwrite
} = 0;
2446 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2451 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2452 foreach my $dev (keys %$netdev) {
2453 next if $dev !~ m/^tap([1-9]\d*)i/;
2455 my $d = $res->{$vmid};
2458 $d->{netout
} += $netdev->{$dev}->{receive
};
2459 $d->{netin
} += $netdev->{$dev}->{transmit
};
2462 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2463 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2468 my $ctime = gettimeofday
;
2470 foreach my $vmid (keys %$list) {
2472 my $d = $res->{$vmid};
2473 my $pid = $d->{pid
};
2476 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2477 next if !$pstat; # not running
2479 my $used = $pstat->{utime} + $pstat->{stime
};
2481 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2483 if ($pstat->{vsize
}) {
2484 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2487 my $old = $last_proc_pid_stat->{$pid};
2489 $last_proc_pid_stat->{$pid} = {
2497 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2499 if ($dtime > 1000) {
2500 my $dutime = $used - $old->{used
};
2502 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2503 $last_proc_pid_stat->{$pid} = {
2509 $d->{cpu
} = $old->{cpu
};
2513 return $res if !$full;
2515 my $qmpclient = PVE
::QMPClient-
>new();
2517 my $ballooncb = sub {
2518 my ($vmid, $resp) = @_;
2520 my $info = $resp->{'return'};
2521 return if !$info->{max_mem
};
2523 my $d = $res->{$vmid};
2525 # use memory assigned to VM
2526 $d->{maxmem
} = $info->{max_mem
};
2527 $d->{balloon
} = $info->{actual
};
2529 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2530 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2531 $d->{freemem
} = $info->{free_mem
};
2534 $d->{ballooninfo
} = $info;
2537 my $blockstatscb = sub {
2538 my ($vmid, $resp) = @_;
2539 my $data = $resp->{'return'} || [];
2540 my $totalrdbytes = 0;
2541 my $totalwrbytes = 0;
2543 for my $blockstat (@$data) {
2544 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2545 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2547 $blockstat->{device
} =~ s/drive-//;
2548 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2550 $res->{$vmid}->{diskread
} = $totalrdbytes;
2551 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2554 my $statuscb = sub {
2555 my ($vmid, $resp) = @_;
2557 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2558 # this fails if ballon driver is not loaded, so this must be
2559 # the last commnand (following command are aborted if this fails).
2560 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2562 my $status = 'unknown';
2563 if (!defined($status = $resp->{'return'}->{status
})) {
2564 warn "unable to get VM status\n";
2568 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2571 foreach my $vmid (keys %$list) {
2572 next if $opt_vmid && ($vmid ne $opt_vmid);
2573 next if !$res->{$vmid}->{pid
}; # not running
2574 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2577 $qmpclient->queue_execute(undef, 1);
2579 foreach my $vmid (keys %$list) {
2580 next if $opt_vmid && ($vmid ne $opt_vmid);
2581 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2588 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2591 my $current_size = 1024;
2592 my $dimm_size = 512;
2593 return if $current_size == $memory;
2595 for (my $j = 0; $j < 8; $j++) {
2596 for (my $i = 0; $i < 32; $i++) {
2597 my $name = "dimm${dimm_id}";
2599 my $numanode = $i % $sockets;
2600 $current_size += $dimm_size;
2601 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2602 return $current_size if $current_size >= $memory;
2608 sub foreach_reverse_dimm
{
2609 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2612 my $current_size = 4177920;
2613 my $dimm_size = 65536;
2614 return if $current_size == $memory;
2616 for (my $j = 0; $j < 8; $j++) {
2617 for (my $i = 0; $i < 32; $i++) {
2618 my $name = "dimm${dimm_id}";
2620 my $numanode = $i % $sockets;
2621 $current_size -= $dimm_size;
2622 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2623 return $current_size if $current_size <= $memory;
2630 my ($conf, $func) = @_;
2632 foreach my $ds (valid_drive_names
()) {
2633 next if !defined($conf->{$ds});
2635 my $drive = parse_drive
($ds, $conf->{$ds});
2638 &$func($ds, $drive);
2643 my ($conf, $func) = @_;
2647 my $test_volid = sub {
2648 my ($volid, $is_cdrom) = @_;
2652 $volhash->{$volid} = $is_cdrom || 0;
2655 foreach_drive
($conf, sub {
2656 my ($ds, $drive) = @_;
2657 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2660 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2661 my $snap = $conf->{snapshots
}->{$snapname};
2662 &$test_volid($snap->{vmstate
}, 0);
2663 foreach_drive
($snap, sub {
2664 my ($ds, $drive) = @_;
2665 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2669 foreach my $volid (keys %$volhash) {
2670 &$func($volid, $volhash->{$volid});
2674 sub vga_conf_has_spice
{
2677 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2682 sub config_to_command
{
2683 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2686 my $globalFlags = [];
2687 my $machineFlags = [];
2693 my $kvmver = kvm_user_version
();
2694 my $vernum = 0; # unknown
2695 my $ostype = $conf->{ostype
};
2696 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2697 $vernum = $1*1000000+$2*1000;
2698 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2699 $vernum = $1*1000000+$2*1000+$3;
2702 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2704 my $have_ovz = -f
'/proc/vz/vestat';
2706 my $q35 = machine_type_is_q35
($conf);
2707 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2708 my $machine_type = $forcemachine || $conf->{machine
};
2709 my $use_old_bios_files = undef;
2710 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2712 my $cpuunits = defined($conf->{cpuunits
}) ?
2713 $conf->{cpuunits
} : $defaults->{cpuunits
};
2715 push @$cmd, '/usr/bin/systemd-run';
2716 push @$cmd, '--scope';
2717 push @$cmd, '--slice', "qemu";
2718 push @$cmd, '--unit', $vmid;
2719 # set KillMode=none, so that systemd don't kill those scopes
2720 # at shutdown (pve-manager service should stop the VMs instead)
2721 push @$cmd, '-p', "KillMode=none";
2722 push @$cmd, '-p', "CPUShares=$cpuunits";
2723 if ($conf->{cpulimit
}) {
2724 my $cpulimit = int($conf->{cpulimit
} * 100);
2725 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2728 push @$cmd, '/usr/bin/kvm';
2730 push @$cmd, '-id', $vmid;
2734 my $qmpsocket = qmp_socket
($vmid);
2735 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2736 push @$cmd, '-mon', "chardev=qmp,mode=control";
2739 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2741 push @$cmd, '-daemonize';
2743 if ($conf->{smbios1
}) {
2744 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2747 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2748 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2749 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2750 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2751 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2752 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2753 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2757 # the q35 chipset support native usb2, so we enable usb controller
2758 # by default for this machine type
2759 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2761 $pciaddr = print_pci_addr
("piix3", $bridges);
2762 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2765 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2766 next if !$conf->{"usb$i"};
2767 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2768 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2771 # include usb device config
2772 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2775 # add usb3 controller if needed
2778 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2779 next if !$conf->{"usb$i"};
2780 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2781 next if !$d || !$d->{usb3
};
2785 $pciaddr = print_pci_addr
("xhci", $bridges);
2786 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2788 my $vga = $conf->{vga
};
2790 my $qxlnum = vga_conf_has_spice
($vga);
2791 $vga = 'qxl' if $qxlnum;
2794 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2795 $conf->{ostype
} eq 'win7' ||
2796 $conf->{ostype
} eq 'w2k8')) {
2803 # enable absolute mouse coordinates (needed by vnc)
2805 if (defined($conf->{tablet
})) {
2806 $tablet = $conf->{tablet
};
2808 $tablet = $defaults->{tablet
};
2809 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2810 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2813 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2817 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2818 my $d = parse_hostpci
($conf->{"hostpci$i"});
2821 my $pcie = $d->{pcie
};
2823 die "q35 machine model is not enabled" if !$q35;
2824 $pciaddr = print_pcie_addr
("hostpci$i");
2826 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2829 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2830 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2831 if ($xvga && $xvga ne '') {
2834 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2835 push @$cpuFlags , 'hv_vendor_id=proxmox';
2837 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2841 my $pcidevices = $d->{pciid
};
2842 my $multifunction = 1 if @$pcidevices > 1;
2845 foreach my $pcidevice (@$pcidevices) {
2847 my $id = "hostpci$i";
2848 $id .= ".$j" if $multifunction;
2849 my $addr = $pciaddr;
2850 $addr .= ".$j" if $multifunction;
2851 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2854 $devicestr .= "$rombar$xvga";
2855 $devicestr .= ",multifunction=on" if $multifunction;
2858 push @$devices, '-device', $devicestr;
2864 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2865 next if !$conf->{"usb$i"};
2866 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2869 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2871 if (defined($d->{usb3
}) && $d->{usb3
}) {
2872 $usbbus = ',bus=xhci.0';
2875 if (defined($d->{host
})) {
2876 $d = parse_usb_device
($d->{host
});
2877 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2878 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2879 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2880 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2881 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2882 # usb redir support for spice, currently no usb3
2883 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2884 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2890 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2891 if (my $path = $conf->{"serial$i"}) {
2892 if ($path eq 'socket') {
2893 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2894 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2895 push @$devices, '-device', "isa-serial,chardev=serial$i";
2897 die "no such serial device\n" if ! -c
$path;
2898 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2899 push @$devices, '-device', "isa-serial,chardev=serial$i";
2905 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2906 if (my $path = $conf->{"parallel$i"}) {
2907 die "no such parallel device\n" if ! -c
$path;
2908 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2909 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2910 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2914 my $vmname = $conf->{name
} || "vm$vmid";
2916 push @$cmd, '-name', $vmname;
2919 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2920 $sockets = $conf->{sockets
} if $conf->{sockets
};
2922 my $cores = $conf->{cores
} || 1;
2924 my $maxcpus = $sockets * $cores;
2926 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2928 my $allowed_vcpus = $cpuinfo->{cpus
};
2930 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2931 if ($allowed_vcpus < $maxcpus);
2933 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2935 push @$cmd, '-nodefaults';
2937 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2939 my $bootindex_hash = {};
2941 foreach my $o (split(//, $bootorder)) {
2942 $bootindex_hash->{$o} = $i*100;
2946 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2948 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2950 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2952 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2954 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2955 my $socket = vnc_socket
($vmid);
2956 push @$cmd, '-vnc', "unix:$socket,x509,password";
2958 push @$cmd, '-nographic';
2962 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2964 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2965 my $useLocaltime = $conf->{localtime};
2968 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2970 if ($ostype =~ m/^w/) { # windows
2971 $useLocaltime = 1 if !defined($conf->{localtime});
2973 # use time drift fix when acpi is enabled
2974 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2975 $tdf = 1 if !defined($conf->{tdf
});
2979 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2980 $ostype eq 'wvista') {
2981 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2982 push @$cmd, '-no-hpet';
2983 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2984 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2985 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2986 push @$cpuFlags , 'hv_time' if !$nokvm;
2989 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2993 if ($ostype eq 'win7' || $ostype eq 'win8') {
2994 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2998 push @$rtcFlags, 'driftfix=slew' if $tdf;
3001 push @$machineFlags, 'accel=tcg';
3003 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3006 if ($machine_type) {
3007 push @$machineFlags, "type=${machine_type}";
3010 if ($conf->{startdate
}) {
3011 push @$rtcFlags, "base=$conf->{startdate}";
3012 } elsif ($useLocaltime) {
3013 push @$rtcFlags, 'base=localtime';
3016 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3017 if (my $cputype = $conf->{cpu
}) {
3018 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3019 or die "Cannot parse cpu description: $cputype\n";
3020 $cpu = $cpuconf->{cputype
};
3021 $kvm_off = 1 if $cpuconf->{hidden
};
3024 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3026 push @$cpuFlags , '-x2apic'
3027 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3029 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3031 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3033 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3035 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3036 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3039 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3041 push @$cpuFlags, 'kvm=off' if $kvm_off;
3043 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3045 push @$cmd, '-cpu', $cpu;
3047 my $memory = $conf->{memory
} || $defaults->{memory
};
3048 my $static_memory = 0;
3049 my $dimm_memory = 0;
3051 if ($hotplug_features->{memory
}) {
3052 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3053 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3054 $static_memory = $STATICMEM;
3055 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3056 $dimm_memory = $memory - $static_memory;
3057 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3061 $static_memory = $memory;
3062 push @$cmd, '-m', $static_memory;
3065 if ($conf->{numa
}) {
3067 my $numa_totalmemory = undef;
3068 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3069 next if !$conf->{"numa$i"};
3070 my $numa = parse_numa
($conf->{"numa$i"});
3073 die "missing numa node$i memory value\n" if !$numa->{memory
};
3074 my $numa_memory = $numa->{memory
};
3075 $numa_totalmemory += $numa_memory;
3076 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3079 my $cpus_start = $numa->{cpus
}->{start
};
3080 die "missing numa node$i cpus\n" if !defined($cpus_start);
3081 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3082 my $cpus = $cpus_start;
3083 if (defined($cpus_end)) {
3084 $cpus .= "-$cpus_end";
3085 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3089 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3090 if (defined($hostnodes_start)) {
3091 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3092 my $hostnodes = $hostnodes_start;
3093 if (defined($hostnodes_end)) {
3094 $hostnodes .= "-$hostnodes_end";
3095 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3098 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3099 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3100 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3104 my $policy = $numa->{policy
};
3105 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3106 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3109 push @$cmd, '-object', $numa_object;
3110 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3113 die "total memory for NUMA nodes must be equal to vm static memory\n"
3114 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3116 #if no custom tology, we split memory and cores across numa nodes
3117 if(!$numa_totalmemory) {
3119 my $numa_memory = ($static_memory / $sockets) . "M";
3121 for (my $i = 0; $i < $sockets; $i++) {
3123 my $cpustart = ($cores * $i);
3124 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3125 my $cpus = $cpustart;
3126 $cpus .= "-$cpuend" if $cpuend;
3128 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3129 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3134 if ($hotplug_features->{memory
}) {
3135 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3136 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3137 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3138 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3140 #if dimm_memory is not aligned to dimm map
3141 if($current_size > $memory) {
3142 $conf->{memory
} = $current_size;
3143 PVE
::QemuConfig-
>write_config($vmid, $conf);
3148 push @$cmd, '-S' if $conf->{freeze
};
3150 # set keyboard layout
3151 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3152 push @$cmd, '-k', $kb if $kb;
3155 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3156 #push @$cmd, '-soundhw', 'es1370';
3157 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3159 if($conf->{agent
}) {
3160 my $qgasocket = qmp_socket
($vmid, 1);
3161 my $pciaddr = print_pci_addr
("qga0", $bridges);
3162 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3163 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3164 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3171 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3172 for(my $i = 1; $i < $qxlnum; $i++){
3173 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3174 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3177 # assume other OS works like Linux
3178 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3179 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3183 my $pciaddr = print_pci_addr
("spice", $bridges);
3185 my $nodename = PVE
::INotify
::nodename
();
3186 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3187 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3189 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3191 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3192 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3193 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3196 # enable balloon by default, unless explicitly disabled
3197 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3198 $pciaddr = print_pci_addr
("balloon0", $bridges);
3199 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3202 if ($conf->{watchdog
}) {
3203 my $wdopts = parse_watchdog
($conf->{watchdog
});
3204 $pciaddr = print_pci_addr
("watchdog", $bridges);
3205 my $watchdog = $wdopts->{model
} || 'i6300esb';
3206 push @$devices, '-device', "$watchdog$pciaddr";
3207 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3211 my $scsicontroller = {};
3212 my $ahcicontroller = {};
3213 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3215 # Add iscsi initiator name if available
3216 if (my $initiator = get_initiator_name
()) {
3217 push @$devices, '-iscsi', "initiator-name=$initiator";
3220 foreach_drive
($conf, sub {
3221 my ($ds, $drive) = @_;
3223 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3224 push @$vollist, $drive->{file
};
3227 $use_virtio = 1 if $ds =~ m/^virtio/;
3229 if (drive_is_cdrom
($drive)) {
3230 if ($bootindex_hash->{d
}) {
3231 $drive->{bootindex
} = $bootindex_hash->{d
};
3232 $bootindex_hash->{d
} += 1;
3235 if ($bootindex_hash->{c
}) {
3236 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3237 $bootindex_hash->{c
} += 1;
3241 if($drive->{interface
} eq 'virtio'){
3242 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3245 if ($drive->{interface
} eq 'scsi') {
3247 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3249 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3250 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3253 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3254 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3255 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3259 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3260 $queues = ",num_queues=$drive->{queues}";
3263 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3264 $scsicontroller->{$controller}=1;
3267 if ($drive->{interface
} eq 'sata') {
3268 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3269 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3270 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3271 $ahcicontroller->{$controller}=1;
3274 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3275 push @$devices, '-drive',$drive_cmd;
3276 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3279 for (my $i = 0; $i < $MAX_NETS; $i++) {
3280 next if !$conf->{"net$i"};
3281 my $d = parse_net
($conf->{"net$i"});
3284 $use_virtio = 1 if $d->{model
} eq 'virtio';
3286 if ($bootindex_hash->{n
}) {
3287 $d->{bootindex
} = $bootindex_hash->{n
};
3288 $bootindex_hash->{n
} += 1;
3291 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3292 push @$devices, '-netdev', $netdevfull;
3294 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3295 push @$devices, '-device', $netdevicefull;
3300 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3305 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3307 while (my ($k, $v) = each %$bridges) {
3308 $pciaddr = print_pci_addr
("pci.$k");
3309 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3314 if ($conf->{args
}) {
3315 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3319 push @$cmd, @$devices;
3320 push @$cmd, '-rtc', join(',', @$rtcFlags)
3321 if scalar(@$rtcFlags);
3322 push @$cmd, '-machine', join(',', @$machineFlags)
3323 if scalar(@$machineFlags);
3324 push @$cmd, '-global', join(',', @$globalFlags)
3325 if scalar(@$globalFlags);
3327 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3332 return "${var_run_tmpdir}/$vmid.vnc";
3338 my $res = vm_mon_cmd
($vmid, 'query-spice');
3340 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3344 my ($vmid, $qga) = @_;
3345 my $sockettype = $qga ?
'qga' : 'qmp';
3346 return "${var_run_tmpdir}/$vmid.$sockettype";
3351 return "${var_run_tmpdir}/$vmid.pid";
3354 sub vm_devices_list
{
3357 my $res = vm_mon_cmd
($vmid, 'query-pci');
3359 foreach my $pcibus (@$res) {
3360 foreach my $device (@{$pcibus->{devices
}}) {
3361 next if !$device->{'qdev_id'};
3362 if ($device->{'pci_bridge'}) {
3363 $devices->{$device->{'qdev_id'}} = 1;
3364 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3365 next if !$bridge_device->{'qdev_id'};
3366 $devices->{$bridge_device->{'qdev_id'}} = 1;
3367 $devices->{$device->{'qdev_id'}}++;
3370 $devices->{$device->{'qdev_id'}} = 1;
3375 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3376 foreach my $block (@$resblock) {
3377 if($block->{device
} =~ m/^drive-(\S+)/){
3382 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3383 foreach my $mice (@$resmice) {
3384 if ($mice->{name
} eq 'QEMU HID Tablet') {
3385 $devices->{tablet
} = 1;
3394 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3396 my $q35 = machine_type_is_q35
($conf);
3398 my $devices_list = vm_devices_list
($vmid);
3399 return 1 if defined($devices_list->{$deviceid});
3401 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3403 if ($deviceid eq 'tablet') {
3405 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3407 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3409 qemu_iothread_add
($vmid, $deviceid, $device);
3411 qemu_driveadd
($storecfg, $vmid, $device);
3412 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3414 qemu_deviceadd
($vmid, $devicefull);
3415 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3417 eval { qemu_drivedel
($vmid, $deviceid); };
3422 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3425 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3426 my $pciaddr = print_pci_addr
($deviceid);
3427 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3429 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3431 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3432 qemu_iothread_add
($vmid, $deviceid, $device);
3433 $devicefull .= ",iothread=iothread-$deviceid";
3436 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3437 $devicefull .= ",num_queues=$device->{queues}";
3440 qemu_deviceadd
($vmid, $devicefull);
3441 qemu_deviceaddverify
($vmid, $deviceid);
3443 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3445 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3446 qemu_driveadd
($storecfg, $vmid, $device);
3448 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3449 eval { qemu_deviceadd
($vmid, $devicefull); };
3451 eval { qemu_drivedel
($vmid, $deviceid); };
3456 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3458 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3460 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3461 my $use_old_bios_files = undef;
3462 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3464 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3465 qemu_deviceadd
($vmid, $netdevicefull);
3466 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3468 eval { qemu_netdevdel
($vmid, $deviceid); };
3473 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3476 my $pciaddr = print_pci_addr
($deviceid);
3477 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3479 qemu_deviceadd
($vmid, $devicefull);
3480 qemu_deviceaddverify
($vmid, $deviceid);
3483 die "can't hotplug device '$deviceid'\n";
3489 # fixme: this should raise exceptions on error!
3490 sub vm_deviceunplug
{
3491 my ($vmid, $conf, $deviceid) = @_;
3493 my $devices_list = vm_devices_list
($vmid);
3494 return 1 if !defined($devices_list->{$deviceid});
3496 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3498 if ($deviceid eq 'tablet') {
3500 qemu_devicedel
($vmid, $deviceid);
3502 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3504 qemu_devicedel
($vmid, $deviceid);
3505 qemu_devicedelverify
($vmid, $deviceid);
3506 qemu_drivedel
($vmid, $deviceid);
3507 qemu_iothread_del
($conf, $vmid, $deviceid);
3509 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3511 qemu_devicedel
($vmid, $deviceid);
3512 qemu_devicedelverify
($vmid, $deviceid);
3513 qemu_iothread_del
($conf, $vmid, $deviceid);
3515 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3517 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3518 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3519 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3521 qemu_devicedel
($vmid, $deviceid);
3522 qemu_drivedel
($vmid, $deviceid);
3523 qemu_deletescsihw
($conf, $vmid, $deviceid);
3525 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3527 qemu_devicedel
($vmid, $deviceid);
3528 qemu_devicedelverify
($vmid, $deviceid);
3529 qemu_netdevdel
($vmid, $deviceid);
3532 die "can't unplug device '$deviceid'\n";
3538 sub qemu_deviceadd
{
3539 my ($vmid, $devicefull) = @_;
3541 $devicefull = "driver=".$devicefull;
3542 my %options = split(/[=,]/, $devicefull);
3544 vm_mon_cmd
($vmid, "device_add" , %options);
3547 sub qemu_devicedel
{
3548 my ($vmid, $deviceid) = @_;
3550 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3553 sub qemu_iothread_add
{
3554 my($vmid, $deviceid, $device) = @_;
3556 if ($device->{iothread
}) {
3557 my $iothreads = vm_iothreads_list
($vmid);
3558 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3562 sub qemu_iothread_del
{
3563 my($conf, $vmid, $deviceid) = @_;
3565 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3566 if ($device->{iothread
}) {
3567 my $iothreads = vm_iothreads_list
($vmid);
3568 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3572 sub qemu_objectadd
{
3573 my($vmid, $objectid, $qomtype) = @_;
3575 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3580 sub qemu_objectdel
{
3581 my($vmid, $objectid) = @_;
3583 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3589 my ($storecfg, $vmid, $device) = @_;
3591 my $drive = print_drive_full
($storecfg, $vmid, $device);
3592 $drive =~ s/\\/\\\\/g;
3593 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3595 # If the command succeeds qemu prints: "OK
"
3596 return 1 if $ret =~ m/OK/s;
3598 die "adding drive failed
: $ret\n";
3602 my($vmid, $deviceid) = @_;
3604 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3607 return 1 if $ret eq "";
3609 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3610 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3612 die "deleting drive
$deviceid failed
: $ret\n";
3615 sub qemu_deviceaddverify {
3616 my ($vmid, $deviceid) = @_;
3618 for (my $i = 0; $i <= 5; $i++) {
3619 my $devices_list = vm_devices_list($vmid);
3620 return 1 if defined($devices_list->{$deviceid});
3624 die "error on hotplug device
'$deviceid'\n";
3628 sub qemu_devicedelverify {
3629 my ($vmid, $deviceid) = @_;
3631 # need to verify that the device is correctly removed as device_del
3632 # is async and empty return is not reliable
3634 for (my $i = 0; $i <= 5; $i++) {
3635 my $devices_list = vm_devices_list($vmid);
3636 return 1 if !defined($devices_list->{$deviceid});
3640 die "error on hot-unplugging device
'$deviceid'\n";
3643 sub qemu_findorcreatescsihw {
3644 my ($storecfg, $conf, $vmid, $device) = @_;
3646 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3648 my $scsihwid="$controller_prefix$controller";
3649 my $devices_list = vm_devices_list($vmid);
3651 if(!defined($devices_list->{$scsihwid})) {
3652 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3658 sub qemu_deletescsihw {
3659 my ($conf, $vmid, $opt) = @_;
3661 my $device = parse_drive($opt, $conf->{$opt});
3663 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3664 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3668 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3670 my $devices_list = vm_devices_list($vmid);
3671 foreach my $opt (keys %{$devices_list}) {
3672 if (PVE::QemuServer::is_valid_drivename($opt)) {
3673 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3674 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3680 my $scsihwid="scsihw
$controller";
3682 vm_deviceunplug($vmid, $conf, $scsihwid);
3687 sub qemu_add_pci_bridge {
3688 my ($storecfg, $conf, $vmid, $device) = @_;
3694 print_pci_addr($device, $bridges);
3696 while (my ($k, $v) = each %$bridges) {
3699 return 1 if !defined($bridgeid) || $bridgeid < 1;
3701 my $bridge = "pci
.$bridgeid";
3702 my $devices_list = vm_devices_list($vmid);
3704 if (!defined($devices_list->{$bridge})) {
3705 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3711 sub qemu_set_link_status {
3712 my ($vmid, $device, $up) = @_;
3714 vm_mon_cmd($vmid, "set_link
", name => $device,
3715 up => $up ? JSON::true : JSON::false);
3718 sub qemu_netdevadd {
3719 my ($vmid, $conf, $device, $deviceid) = @_;
3721 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3722 my %options = split(/[=,]/, $netdev);
3724 vm_mon_cmd($vmid, "netdev_add
", %options);
3728 sub qemu_netdevdel {
3729 my ($vmid, $deviceid) = @_;
3731 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3734 sub qemu_cpu_hotplug {
3735 my ($vmid, $conf, $vcpus) = @_;
3738 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3739 $sockets = $conf->{sockets} if $conf->{sockets};
3740 my $cores = $conf->{cores} || 1;
3741 my $maxcpus = $sockets * $cores;
3743 $vcpus = $maxcpus if !$vcpus;
3745 die "you can
't add more vcpus than maxcpus\n"
3746 if $vcpus > $maxcpus;
3748 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3749 die "online cpu unplug is not yet possible\n"
3750 if $vcpus < $currentvcpus;
3752 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3753 die "vcpus in running vm is different than configuration\n"
3754 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3756 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3757 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3761 sub qemu_memory_hotplug {
3762 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3764 return $value if !check_running($vmid);
3766 my $memory = $conf->{memory} || $defaults->{memory};
3767 $value = $defaults->{memory} if !$value;
3768 return $value if $value == $memory;
3770 my $static_memory = $STATICMEM;
3771 my $dimm_memory = $memory - $static_memory;
3773 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3774 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3778 $sockets = $conf->{sockets} if $conf->{sockets};
3780 if($value > $memory) {
3782 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3783 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3785 return if $current_size <= $conf->{memory};
3787 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3789 eval { qemu_objectdel($vmid, "mem-
$name"); };
3793 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3795 eval { qemu_objectdel($vmid, "mem-
$name"); };
3798 #update conf after each succesful module hotplug
3799 $conf->{memory} = $current_size;
3800 PVE::QemuConfig->write_config($vmid, $conf);
3805 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3806 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3808 return if $current_size >= $conf->{memory};
3809 print "try to unplug memory dimm
$name\n";
3813 eval { qemu_devicedel($vmid, $name) };
3815 my $dimm_list = qemu_dimm_list($vmid);
3816 last if !$dimm_list->{$name};
3817 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3821 #update conf after each succesful module unplug
3822 $conf->{memory} = $current_size;
3824 eval { qemu_objectdel($vmid, "mem-
$name"); };
3825 PVE::QemuConfig->write_config($vmid, $conf);
3830 sub qemu_dimm_list {
3833 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3836 foreach my $dimm (@$dimmarray) {
3838 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3839 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3840 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3841 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3842 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3847 sub qemu_block_set_io_throttle {
3848 my ($vmid, $deviceid,
3849 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3850 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3852 return if !check_running($vmid) ;
3854 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3856 bps_rd => int($bps_rd),
3857 bps_wr => int($bps_wr),
3859 iops_rd => int($iops_rd),
3860 iops_wr => int($iops_wr),
3861 bps_max => int($bps_max),
3862 bps_rd_max => int($bps_rd_max),
3863 bps_wr_max => int($bps_wr_max),
3864 iops_max => int($iops_max),
3865 iops_rd_max => int($iops_rd_max),
3866 iops_wr_max => int($iops_wr_max)
3871 # old code, only used to shutdown old VM after update
3873 my ($fh, $timeout) = @_;
3875 my $sel = new IO::Select;
3882 while (scalar (@ready = $sel->can_read($timeout))) {
3884 if ($count = $fh->sysread($buf, 8192)) {
3885 if ($buf =~ /^(.*)\(qemu\) $/s) {
3892 if (!defined($count)) {
3899 die "monitor
read timeout
\n" if !scalar(@ready);
3904 # old code, only used to shutdown old VM after update
3905 sub vm_monitor_command {
3906 my ($vmid, $cmdstr, $nocheck) = @_;
3911 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3913 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3915 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3916 die "unable to
connect to VM
$vmid socket - $!\n";
3920 # hack: migrate sometime blocks the monitor (when migrate_downtime
3922 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3923 $timeout = 60*60; # 1 hour
3927 my $data = __read_avail($sock, $timeout);
3929 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3930 die "got unexpected qemu monitor banner
\n";
3933 my $sel = new IO::Select;
3936 if (!scalar(my @ready = $sel->can_write($timeout))) {
3937 die "monitor
write error
- timeout
";
3940 my $fullcmd = "$cmdstr\r";
3942 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3945 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3946 die "monitor
write error
- $!";
3949 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3953 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3954 $timeout = 60*60; # 1 hour
3955 } elsif ($cmdstr =~ m/^(eject|change)/) {
3956 $timeout = 60; # note: cdrom mount command is slow
3958 if ($res = __read_avail($sock, $timeout)) {
3960 my @lines = split("\r?
\n", $res);
3962 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3964 $res = join("\n", @lines);
3972 syslog("err
", "VM
$vmid monitor command failed
- $err");
3979 sub qemu_block_resize {
3980 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3982 my $running = check_running($vmid);
3984 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3986 return if !$running;
3988 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3992 sub qemu_volume_snapshot {
3993 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3995 my $running = check_running($vmid);
3997 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3998 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4000 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4004 sub qemu_volume_snapshot_delete {
4005 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4007 my $running = check_running($vmid);
4009 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4011 return if !$running;
4013 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4016 sub set_migration_caps {
4022 "auto-converge
" => 1,
4024 "x-rdma-pin-all
" => 0,
4029 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4031 for my $supported_capability (@$supported_capabilities) {
4033 capability => $supported_capability->{capability},
4034 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4038 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4041 my $fast_plug_option = {
4050 # hotplug changes in [PENDING]
4051 # $selection hash can be used to only apply specified options, for
4052 # example: { cores => 1 } (only apply changed 'cores')
4053 # $errors ref is used to return error messages
4054 sub vmconfig_hotplug_pending {
4055 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4057 my $defaults = load_defaults();
4059 # commit values which do not have any impact on running VM first
4060 # Note: those option cannot raise errors, we we do not care about
4061 # $selection and always apply them.
4063 my $add_error = sub {
4064 my ($opt, $msg) = @_;
4065 $errors->{$opt} = "hotplug problem
- $msg";
4069 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4070 if ($fast_plug_option->{$opt}) {
4071 $conf->{$opt} = $conf->{pending}->{$opt};
4072 delete $conf->{pending}->{$opt};
4078 PVE::QemuConfig->write_config($vmid, $conf);
4079 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4082 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4084 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4085 while (my ($opt, $force) = each %$pending_delete_hash) {
4086 next if $selection && !$selection->{$opt};
4088 if ($opt eq 'hotplug') {
4089 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4090 } elsif ($opt eq 'tablet') {
4091 die "skip
\n" if !$hotplug_features->{usb};
4092 if ($defaults->{tablet}) {
4093 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4095 vm_deviceunplug($vmid, $conf, $opt);
4097 } elsif ($opt eq 'vcpus') {
4098 die "skip
\n" if !$hotplug_features->{cpu};
4099 qemu_cpu_hotplug($vmid, $conf, undef);
4100 } elsif ($opt eq 'balloon') {
4101 # enable balloon device is not hotpluggable
4102 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4103 } elsif ($fast_plug_option->{$opt}) {
4105 } elsif ($opt =~ m/^net(\d+)$/) {
4106 die "skip
\n" if !$hotplug_features->{network};
4107 vm_deviceunplug($vmid, $conf, $opt);
4108 } elsif (is_valid_drivename($opt)) {
4109 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4110 vm_deviceunplug($vmid, $conf, $opt);
4111 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4112 } elsif ($opt =~ m/^memory$/) {
4113 die "skip
\n" if !$hotplug_features->{memory};
4114 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4115 } elsif ($opt eq 'cpuunits') {
4116 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4117 } elsif ($opt eq 'cpulimit') {
4118 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4124 &$add_error($opt, $err) if $err ne "skip
\n";
4126 # save new config if hotplug was successful
4127 delete $conf->{$opt};
4128 vmconfig_undelete_pending_option($conf, $opt);
4129 PVE::QemuConfig->write_config($vmid, $conf);
4130 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4134 foreach my $opt (keys %{$conf->{pending}}) {
4135 next if $selection && !$selection->{$opt};
4136 my $value = $conf->{pending}->{$opt};
4138 if ($opt eq 'hotplug') {
4139 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4140 } elsif ($opt eq 'tablet') {
4141 die "skip
\n" if !$hotplug_features->{usb};
4143 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4144 } elsif ($value == 0) {
4145 vm_deviceunplug($vmid, $conf, $opt);
4147 } elsif ($opt eq 'vcpus') {
4148 die "skip
\n" if !$hotplug_features->{cpu};
4149 qemu_cpu_hotplug($vmid, $conf, $value);
4150 } elsif ($opt eq 'balloon') {
4151 # enable/disable balloning device is not hotpluggable
4152 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4153 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4154 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4156 # allow manual ballooning if shares is set to zero
4157 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4158 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4159 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4161 } elsif ($opt =~ m/^net(\d+)$/) {
4162 # some changes can be done without hotplug
4163 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4164 $vmid, $opt, $value);
4165 } elsif (is_valid_drivename($opt)) {
4166 # some changes can be done without hotplug
4167 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4168 $vmid, $opt, $value, 1);
4169 } elsif ($opt =~ m/^memory$/) { #dimms
4170 die "skip
\n" if !$hotplug_features->{memory};
4171 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4172 } elsif ($opt eq 'cpuunits') {
4173 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4174 } elsif ($opt eq 'cpulimit') {
4175 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4176 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4178 die "skip
\n"; # skip non-hot-pluggable options
4182 &$add_error($opt, $err) if $err ne "skip
\n";
4184 # save new config if hotplug was successful
4185 $conf->{$opt} = $value;
4186 delete $conf->{pending}->{$opt};
4187 PVE::QemuConfig->write_config($vmid, $conf);
4188 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4193 sub try_deallocate_drive {
4194 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4196 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4197 my $volid = $drive->{file};
4198 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4199 my $sid = PVE::Storage::parse_volume_id($volid);
4200 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4202 # check if the disk is really unused
4203 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4204 if is_volume_in_use($storecfg, $conf, $key, $volid);
4205 PVE::Storage::vdisk_free($storecfg, $volid);
4208 # If vm is not owner of this disk remove from config
4216 sub vmconfig_delete_or_detach_drive {
4217 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4219 my $drive = parse_drive($opt, $conf->{$opt});
4221 my $rpcenv = PVE::RPCEnvironment::get();
4222 my $authuser = $rpcenv->get_user();
4225 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4226 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4228 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4232 sub vmconfig_apply_pending {
4233 my ($vmid, $conf, $storecfg) = @_;
4237 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4238 while (my ($opt, $force) = each %$pending_delete_hash) {
4239 die "internal error
" if $opt =~ m/^unused/;
4240 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4241 if (!defined($conf->{$opt})) {
4242 vmconfig_undelete_pending_option($conf, $opt);
4243 PVE::QemuConfig->write_config($vmid, $conf);
4244 } elsif (is_valid_drivename($opt)) {
4245 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4246 vmconfig_undelete_pending_option($conf, $opt);
4247 delete $conf->{$opt};
4248 PVE::QemuConfig->write_config($vmid, $conf);
4250 vmconfig_undelete_pending_option($conf, $opt);
4251 delete $conf->{$opt};
4252 PVE::QemuConfig->write_config($vmid, $conf);
4256 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4258 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4259 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4261 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4262 # skip if nothing changed
4263 } elsif (is_valid_drivename($opt)) {
4264 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4265 if defined($conf->{$opt});
4266 $conf->{$opt} = $conf->{pending}->{$opt};
4268 $conf->{$opt} = $conf->{pending}->{$opt};
4271 delete $conf->{pending}->{$opt};
4272 PVE::QemuConfig->write_config($vmid, $conf);
4276 my $safe_num_ne = sub {
4279 return 0 if !defined($a) && !defined($b);
4280 return 1 if !defined($a);
4281 return 1 if !defined($b);
4286 my $safe_string_ne = sub {
4289 return 0 if !defined($a) && !defined($b);
4290 return 1 if !defined($a);
4291 return 1 if !defined($b);
4296 sub vmconfig_update_net {
4297 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4299 my $newnet = parse_net($value);
4301 if ($conf->{$opt}) {
4302 my $oldnet = parse_net($conf->{$opt});
4304 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4305 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4306 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4307 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4309 # for non online change, we try to hot-unplug
4310 die "skip
\n" if !$hotplug;
4311 vm_deviceunplug($vmid, $conf, $opt);
4314 die "internal error
" if $opt !~ m/net(\d+)/;
4315 my $iface = "tap
${vmid
}i
$1";
4317 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4318 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4319 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4320 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4321 PVE::Network::tap_unplug($iface);
4322 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4323 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4324 # Rate can be applied on its own but any change above needs to
4325 # include the rate in tap_plug since OVS resets everything.
4326 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4329 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4330 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4338 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4344 sub vmconfig_update_disk {
4345 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4347 # fixme: do we need force?
4349 my $drive = parse_drive($opt, $value);
4351 if ($conf->{$opt}) {
4353 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4355 my $media = $drive->{media} || 'disk';
4356 my $oldmedia = $old_drive->{media} || 'disk';
4357 die "unable to change media type
\n" if $media ne $oldmedia;
4359 if (!drive_is_cdrom($old_drive)) {
4361 if ($drive->{file} ne $old_drive->{file}) {
4363 die "skip
\n" if !$hotplug;
4365 # unplug and register as unused
4366 vm_deviceunplug($vmid, $conf, $opt);
4367 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4370 # update existing disk
4372 # skip non hotpluggable value
4373 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4374 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4375 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4376 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4381 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4382 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4383 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4384 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4385 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4386 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4387 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4388 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4389 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4390 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4391 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4392 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4394 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4395 ($drive->{mbps} || 0)*1024*1024,
4396 ($drive->{mbps_rd} || 0)*1024*1024,
4397 ($drive->{mbps_wr} || 0)*1024*1024,
4398 $drive->{iops} || 0,
4399 $drive->{iops_rd} || 0,
4400 $drive->{iops_wr} || 0,
4401 ($drive->{mbps_max} || 0)*1024*1024,
4402 ($drive->{mbps_rd_max} || 0)*1024*1024,
4403 ($drive->{mbps_wr_max} || 0)*1024*1024,
4404 $drive->{iops_max} || 0,
4405 $drive->{iops_rd_max} || 0,
4406 $drive->{iops_wr_max} || 0);
4415 if ($drive->{file} eq 'none') {
4416 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4418 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4419 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4420 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4428 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4430 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4431 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4435 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4436 $forcemachine, $spice_ticket) = @_;
4438 PVE::QemuConfig->lock_config($vmid, sub {
4439 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4441 die "you can
't start a vm if it's a template
\n" if PVE::QemuConfig->is_template($conf);
4443 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4445 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4447 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4448 vmconfig_apply_pending($vmid, $conf, $storecfg);
4449 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4452 my $defaults = load_defaults();
4454 # set environment variable useful inside network script
4455 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4457 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4459 my $migrate_port = 0;
4462 if ($statefile eq 'tcp') {
4463 my $localip = "localhost
";
4464 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4465 my $nodename = PVE::INotify::nodename();
4466 if ($datacenterconf->{migration_unsecure}) {
4467 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4468 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4470 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4471 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4472 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4473 push @$cmd, '-incoming', $migrate_uri;
4476 push @$cmd, '-loadstate', $statefile;
4483 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4484 my $d = parse_hostpci($conf->{"hostpci
$i"});
4486 my $pcidevices = $d->{pciid};
4487 foreach my $pcidevice (@$pcidevices) {
4488 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4490 my $info = pci_device_info("0000:$pciid");
4491 die "IOMMU
not present
\n" if !check_iommu_support();
4492 die "no pci device info
for device
'$pciid'\n" if !$info;
4493 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4494 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4498 PVE::Storage::activate_volumes($storecfg, $vollist);
4500 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4504 # deactivate volumes if start fails
4505 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4506 die "start failed
: $err";
4509 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4511 if ($statefile && $statefile ne 'tcp') {
4512 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4516 if ($migratedfrom) {
4519 set_migration_caps($vmid);
4524 print "spice listens on port
$spice_port\n";
4525 if ($spice_ticket) {
4526 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4527 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4533 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4534 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4535 if $conf->{balloon};
4538 foreach my $opt (keys %$conf) {
4539 next if $opt !~ m/^net\d+$/;
4540 my $nicconf = parse_net($conf->{$opt});
4541 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4545 vm_mon_cmd_nocheck($vmid, 'qom-set',
4546 path => "machine
/peripheral/balloon0
",
4547 property => "guest-stats-polling-interval
",
4548 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4554 my ($vmid, $execute, %params) = @_;
4556 my $cmd = { execute => $execute, arguments => \%params };
4557 vm_qmp_command($vmid, $cmd);
4560 sub vm_mon_cmd_nocheck {
4561 my ($vmid, $execute, %params) = @_;
4563 my $cmd = { execute => $execute, arguments => \%params };
4564 vm_qmp_command($vmid, $cmd, 1);
4567 sub vm_qmp_command {
4568 my ($vmid, $cmd, $nocheck) = @_;
4573 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4574 $timeout = $cmd->{arguments}->{timeout};
4575 delete $cmd->{arguments}->{timeout};
4579 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4580 my $sname = qmp_socket($vmid);
4581 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4582 my $qmpclient = PVE::QMPClient->new();
4584 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4585 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4586 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4587 if scalar(%{$cmd->{arguments}});
4588 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4590 die "unable to open monitor socket\n";
4594 syslog("err", "VM $vmid qmp command failed - $err");
4601 sub vm_human_monitor_command {
4602 my ($vmid, $cmdline) = @_;
4607 execute => 'human-monitor-command
',
4608 arguments => { 'command-line
' => $cmdline},
4611 return vm_qmp_command($vmid, $cmd);
4614 sub vm_commandline {
4615 my ($storecfg, $vmid) = @_;
4617 my $conf = PVE::QemuConfig->load_config($vmid);
4619 my $defaults = load_defaults();
4621 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4623 return join(' ', @$cmd);
4627 my ($vmid, $skiplock) = @_;
4629 PVE::QemuConfig->lock_config($vmid, sub {
4631 my $conf = PVE::QemuConfig->load_config($vmid);
4633 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4635 vm_mon_cmd($vmid, "system_reset");
4639 sub get_vm_volumes {
4643 foreach_volid($conf, sub {
4644 my ($volid, $is_cdrom) = @_;
4646 return if $volid =~ m|^/|;
4648 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4651 push @$vollist, $volid;
4657 sub vm_stop_cleanup {
4658 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4663 my $vollist = get_vm_volumes($conf);
4664 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4667 foreach my $ext (qw(mon qmp pid vnc qga)) {
4668 unlink "/var/run/qemu-server/${vmid}.$ext";
4671 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4673 warn $@ if $@; # avoid errors - just warn
4676 # Note: use $nockeck to skip tests if VM configuration file exists.
4677 # We need that when migration VMs to other nodes (files already moved)
4678 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4680 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4682 $force = 1 if !defined($force) && !$shutdown;
4685 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4686 kill 15, $pid if $pid;
4687 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4688 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4692 PVE
::QemuConfig-
>lock_config($vmid, sub {
4694 my $pid = check_running
($vmid, $nocheck);
4699 $conf = PVE
::QemuConfig-
>load_config($vmid);
4700 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4701 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4702 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4703 $timeout = $opts->{down
} if $opts->{down
};
4707 $timeout = 60 if !defined($timeout);
4711 if (defined($conf) && $conf->{agent
}) {
4712 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4714 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4717 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4724 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4729 if ($count >= $timeout) {
4731 warn "VM still running - terminating now with SIGTERM\n";
4734 die "VM quit/powerdown failed - got timeout\n";
4737 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4742 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4745 die "VM quit/powerdown failed\n";
4753 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4758 if ($count >= $timeout) {
4759 warn "VM still running - terminating now with SIGKILL\n";
4764 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4769 my ($vmid, $skiplock) = @_;
4771 PVE
::QemuConfig-
>lock_config($vmid, sub {
4773 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4775 PVE
::QemuConfig-
>check_lock($conf)
4776 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4778 vm_mon_cmd
($vmid, "stop");
4783 my ($vmid, $skiplock, $nocheck) = @_;
4785 PVE
::QemuConfig-
>lock_config($vmid, sub {
4789 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4791 PVE
::QemuConfig-
>check_lock($conf)
4792 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4794 vm_mon_cmd
($vmid, "cont");
4797 vm_mon_cmd_nocheck
($vmid, "cont");
4803 my ($vmid, $skiplock, $key) = @_;
4805 PVE
::QemuConfig-
>lock_config($vmid, sub {
4807 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4809 # there is no qmp command, so we use the human monitor command
4810 vm_human_monitor_command
($vmid, "sendkey $key");
4815 my ($storecfg, $vmid, $skiplock) = @_;
4817 PVE
::QemuConfig-
>lock_config($vmid, sub {
4819 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4821 if (!check_running
($vmid)) {
4822 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4824 die "VM $vmid is running - destroy failed\n";
4832 my ($filename, $buf) = @_;
4834 my $fh = IO
::File-
>new($filename, "w");
4835 return undef if !$fh;
4837 my $res = print $fh $buf;
4844 sub pci_device_info
{
4849 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4850 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4852 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4853 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4855 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4856 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4858 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4859 return undef if !defined($product) || $product !~ s/^0x//;
4864 product
=> $product,
4870 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4879 my $name = $dev->{name
};
4881 my $fn = "$pcisysfs/devices/$name/reset";
4883 return file_write
($fn, "1");
4886 sub pci_dev_bind_to_vfio
{
4889 my $name = $dev->{name
};
4891 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4893 if (!-d
$vfio_basedir) {
4894 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4896 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4898 my $testdir = "$vfio_basedir/$name";
4899 return 1 if -d
$testdir;
4901 my $data = "$dev->{vendor} $dev->{product}";
4902 return undef if !file_write
("$vfio_basedir/new_id", $data);
4904 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4905 if (!file_write
($fn, $name)) {
4906 return undef if -f
$fn;
4909 $fn = "$vfio_basedir/bind";
4910 if (! -d
$testdir) {
4911 return undef if !file_write
($fn, $name);
4917 sub pci_dev_group_bind_to_vfio
{
4920 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4922 if (!-d
$vfio_basedir) {
4923 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4925 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4927 # get IOMMU group devices
4928 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4929 my @devs = grep /^0000:/, readdir($D);
4932 foreach my $pciid (@devs) {
4933 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4935 # pci bridges, switches or root ports are not supported
4936 # they have a pci_bus subdirectory so skip them
4937 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4939 my $info = pci_device_info
($1);
4940 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4946 sub print_pci_addr
{
4947 my ($id, $bridges) = @_;
4951 piix3
=> { bus
=> 0, addr
=> 1 },
4952 #addr2 : first videocard
4953 balloon0
=> { bus
=> 0, addr
=> 3 },
4954 watchdog
=> { bus
=> 0, addr
=> 4 },
4955 scsihw0
=> { bus
=> 0, addr
=> 5 },
4956 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4957 scsihw1
=> { bus
=> 0, addr
=> 6 },
4958 ahci0
=> { bus
=> 0, addr
=> 7 },
4959 qga0
=> { bus
=> 0, addr
=> 8 },
4960 spice
=> { bus
=> 0, addr
=> 9 },
4961 virtio0
=> { bus
=> 0, addr
=> 10 },
4962 virtio1
=> { bus
=> 0, addr
=> 11 },
4963 virtio2
=> { bus
=> 0, addr
=> 12 },
4964 virtio3
=> { bus
=> 0, addr
=> 13 },
4965 virtio4
=> { bus
=> 0, addr
=> 14 },
4966 virtio5
=> { bus
=> 0, addr
=> 15 },
4967 hostpci0
=> { bus
=> 0, addr
=> 16 },
4968 hostpci1
=> { bus
=> 0, addr
=> 17 },
4969 net0
=> { bus
=> 0, addr
=> 18 },
4970 net1
=> { bus
=> 0, addr
=> 19 },
4971 net2
=> { bus
=> 0, addr
=> 20 },
4972 net3
=> { bus
=> 0, addr
=> 21 },
4973 net4
=> { bus
=> 0, addr
=> 22 },
4974 net5
=> { bus
=> 0, addr
=> 23 },
4975 vga1
=> { bus
=> 0, addr
=> 24 },
4976 vga2
=> { bus
=> 0, addr
=> 25 },
4977 vga3
=> { bus
=> 0, addr
=> 26 },
4978 hostpci2
=> { bus
=> 0, addr
=> 27 },
4979 hostpci3
=> { bus
=> 0, addr
=> 28 },
4980 #addr29 : usb-host (pve-usb.cfg)
4981 'pci.1' => { bus
=> 0, addr
=> 30 },
4982 'pci.2' => { bus
=> 0, addr
=> 31 },
4983 'net6' => { bus
=> 1, addr
=> 1 },
4984 'net7' => { bus
=> 1, addr
=> 2 },
4985 'net8' => { bus
=> 1, addr
=> 3 },
4986 'net9' => { bus
=> 1, addr
=> 4 },
4987 'net10' => { bus
=> 1, addr
=> 5 },
4988 'net11' => { bus
=> 1, addr
=> 6 },
4989 'net12' => { bus
=> 1, addr
=> 7 },
4990 'net13' => { bus
=> 1, addr
=> 8 },
4991 'net14' => { bus
=> 1, addr
=> 9 },
4992 'net15' => { bus
=> 1, addr
=> 10 },
4993 'net16' => { bus
=> 1, addr
=> 11 },
4994 'net17' => { bus
=> 1, addr
=> 12 },
4995 'net18' => { bus
=> 1, addr
=> 13 },
4996 'net19' => { bus
=> 1, addr
=> 14 },
4997 'net20' => { bus
=> 1, addr
=> 15 },
4998 'net21' => { bus
=> 1, addr
=> 16 },
4999 'net22' => { bus
=> 1, addr
=> 17 },
5000 'net23' => { bus
=> 1, addr
=> 18 },
5001 'net24' => { bus
=> 1, addr
=> 19 },
5002 'net25' => { bus
=> 1, addr
=> 20 },
5003 'net26' => { bus
=> 1, addr
=> 21 },
5004 'net27' => { bus
=> 1, addr
=> 22 },
5005 'net28' => { bus
=> 1, addr
=> 23 },
5006 'net29' => { bus
=> 1, addr
=> 24 },
5007 'net30' => { bus
=> 1, addr
=> 25 },
5008 'net31' => { bus
=> 1, addr
=> 26 },
5009 'xhci' => { bus
=> 1, addr
=> 27 },
5010 'virtio6' => { bus
=> 2, addr
=> 1 },
5011 'virtio7' => { bus
=> 2, addr
=> 2 },
5012 'virtio8' => { bus
=> 2, addr
=> 3 },
5013 'virtio9' => { bus
=> 2, addr
=> 4 },
5014 'virtio10' => { bus
=> 2, addr
=> 5 },
5015 'virtio11' => { bus
=> 2, addr
=> 6 },
5016 'virtio12' => { bus
=> 2, addr
=> 7 },
5017 'virtio13' => { bus
=> 2, addr
=> 8 },
5018 'virtio14' => { bus
=> 2, addr
=> 9 },
5019 'virtio15' => { bus
=> 2, addr
=> 10 },
5020 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5021 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5022 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5023 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5024 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5025 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5026 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5027 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5028 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5029 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5030 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5031 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5032 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5033 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5034 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5035 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5036 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5037 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5038 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5039 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5040 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5041 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5042 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5043 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5044 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5045 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5046 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5047 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5048 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5049 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5050 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5054 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5055 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5056 my $bus = $devices->{$id}->{bus
};
5057 $res = ",bus=pci.$bus,addr=$addr";
5058 $bridges->{$bus} = 1 if $bridges;
5064 sub print_pcie_addr
{
5069 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5070 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5071 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5072 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5075 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5076 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5077 my $bus = $devices->{$id}->{bus
};
5078 $res = ",bus=$bus,addr=$addr";
5084 # vzdump restore implementaion
5086 sub tar_archive_read_firstfile
{
5087 my $archive = shift;
5089 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5091 # try to detect archive type first
5092 my $pid = open (TMP
, "tar tf '$archive'|") ||
5093 die "unable to open file '$archive'\n";
5094 my $firstfile = <TMP
>;
5098 die "ERROR: archive contaions no data\n" if !$firstfile;
5104 sub tar_restore_cleanup
{
5105 my ($storecfg, $statfile) = @_;
5107 print STDERR
"starting cleanup\n";
5109 if (my $fd = IO
::File-
>new($statfile, "r")) {
5110 while (defined(my $line = <$fd>)) {
5111 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5114 if ($volid =~ m
|^/|) {
5115 unlink $volid || die 'unlink failed\n';
5117 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5119 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5121 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5123 print STDERR
"unable to parse line in statfile - $line";
5130 sub restore_archive
{
5131 my ($archive, $vmid, $user, $opts) = @_;
5133 my $format = $opts->{format
};
5136 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5137 $format = 'tar' if !$format;
5139 } elsif ($archive =~ m/\.tar$/) {
5140 $format = 'tar' if !$format;
5141 } elsif ($archive =~ m/.tar.lzo$/) {
5142 $format = 'tar' if !$format;
5144 } elsif ($archive =~ m/\.vma$/) {
5145 $format = 'vma' if !$format;
5146 } elsif ($archive =~ m/\.vma\.gz$/) {
5147 $format = 'vma' if !$format;
5149 } elsif ($archive =~ m/\.vma\.lzo$/) {
5150 $format = 'vma' if !$format;
5153 $format = 'vma' if !$format; # default
5156 # try to detect archive format
5157 if ($format eq 'tar') {
5158 return restore_tar_archive
($archive, $vmid, $user, $opts);
5160 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5164 sub restore_update_config_line
{
5165 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5167 return if $line =~ m/^\#qmdump\#/;
5168 return if $line =~ m/^\#vzdump\#/;
5169 return if $line =~ m/^lock:/;
5170 return if $line =~ m/^unused\d+:/;
5171 return if $line =~ m/^parent:/;
5172 return if $line =~ m/^template:/; # restored VM is never a template
5174 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5175 # try to convert old 1.X settings
5176 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5177 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5178 my ($model, $macaddr) = split(/\=/, $devconfig);
5179 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5182 bridge
=> "vmbr$ind",
5183 macaddr
=> $macaddr,
5185 my $netstr = print_net
($net);
5187 print $outfd "net$cookie->{netcount}: $netstr\n";
5188 $cookie->{netcount
}++;
5190 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5191 my ($id, $netstr) = ($1, $2);
5192 my $net = parse_net
($netstr);
5193 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5194 $netstr = print_net
($net);
5195 print $outfd "$id: $netstr\n";
5196 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5199 my $di = parse_drive
($virtdev, $value);
5200 if (defined($di->{backup
}) && !$di->{backup
}) {
5201 print $outfd "#$line";
5202 } elsif ($map->{$virtdev}) {
5203 delete $di->{format
}; # format can change on restore
5204 $di->{file
} = $map->{$virtdev};
5205 $value = print_drive
($vmid, $di);
5206 print $outfd "$virtdev: $value\n";
5216 my ($cfg, $vmid) = @_;
5218 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5220 my $volid_hash = {};
5221 foreach my $storeid (keys %$info) {
5222 foreach my $item (@{$info->{$storeid}}) {
5223 next if !($item->{volid
} && $item->{size
});
5224 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5225 $volid_hash->{$item->{volid
}} = $item;
5232 sub is_volume_in_use
{
5233 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5235 my $path = PVE
::Storage
::path
($storecfg, $volid);
5237 my $scan_config = sub {
5238 my ($cref, $snapname) = @_;
5240 foreach my $key (keys %$cref) {
5241 my $value = $cref->{$key};
5242 if (is_valid_drivename
($key)) {
5243 next if $skip_drive && $key eq $skip_drive;
5244 my $drive = parse_drive
($key, $value);
5245 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5246 return 1 if $volid eq $drive->{file
};
5247 if ($drive->{file
} =~ m!^/!) {
5248 return 1 if $drive->{file
} eq $path;
5250 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5252 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5254 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5262 return 1 if &$scan_config($conf);
5266 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5267 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5273 sub update_disksize
{
5274 my ($vmid, $conf, $volid_hash) = @_;
5280 # Note: it is allowed to define multiple storages with same path (alias), so
5281 # we need to check both 'volid' and real 'path' (two different volid can point
5282 # to the same path).
5287 foreach my $opt (keys %$conf) {
5288 if (is_valid_drivename
($opt)) {
5289 my $drive = parse_drive
($opt, $conf->{$opt});
5290 my $volid = $drive->{file
};
5293 $used->{$volid} = 1;
5294 if ($volid_hash->{$volid} &&
5295 (my $path = $volid_hash->{$volid}->{path
})) {
5296 $usedpath->{$path} = 1;
5299 next if drive_is_cdrom
($drive);
5300 next if !$volid_hash->{$volid};
5302 $drive->{size
} = $volid_hash->{$volid}->{size
};
5303 my $new = print_drive
($vmid, $drive);
5304 if ($new ne $conf->{$opt}) {
5306 $conf->{$opt} = $new;
5311 # remove 'unusedX' entry if volume is used
5312 foreach my $opt (keys %$conf) {
5313 next if $opt !~ m/^unused\d+$/;
5314 my $volid = $conf->{$opt};
5315 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5316 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5318 delete $conf->{$opt};
5322 foreach my $volid (sort keys %$volid_hash) {
5323 next if $volid =~ m/vm-$vmid-state-/;
5324 next if $used->{$volid};
5325 my $path = $volid_hash->{$volid}->{path
};
5326 next if !$path; # just to be sure
5327 next if $usedpath->{$path};
5329 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5330 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5337 my ($vmid, $nolock) = @_;
5339 my $cfg = PVE
::Storage
::config
();
5341 my $volid_hash = scan_volids
($cfg, $vmid);
5343 my $updatefn = sub {
5346 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5348 PVE
::QemuConfig-
>check_lock($conf);
5351 foreach my $volid (keys %$volid_hash) {
5352 my $info = $volid_hash->{$volid};
5353 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5356 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5358 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5361 if (defined($vmid)) {
5365 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5368 my $vmlist = config_list
();
5369 foreach my $vmid (keys %$vmlist) {
5373 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5379 sub restore_vma_archive
{
5380 my ($archive, $vmid, $user, $opts, $comp) = @_;
5382 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5383 my $readfrom = $archive;
5388 my $qarchive = PVE
::Tools
::shellquote
($archive);
5389 if ($comp eq 'gzip') {
5390 $uncomp = "zcat $qarchive|";
5391 } elsif ($comp eq 'lzop') {
5392 $uncomp = "lzop -d -c $qarchive|";
5394 die "unknown compression method '$comp'\n";
5399 my $tmpdir = "/var/tmp/vzdumptmp$$";
5402 # disable interrupts (always do cleanups)
5403 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5404 warn "got interrupt - ignored\n";
5407 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5408 POSIX
::mkfifo
($mapfifo, 0600);
5411 my $openfifo = sub {
5412 open($fifofh, '>', $mapfifo) || die $!;
5415 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5422 my $rpcenv = PVE
::RPCEnvironment
::get
();
5424 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5425 my $tmpfn = "$conffile.$$.tmp";
5427 # Note: $oldconf is undef if VM does not exists
5428 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5429 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5431 my $print_devmap = sub {
5432 my $virtdev_hash = {};
5434 my $cfgfn = "$tmpdir/qemu-server.conf";
5436 # we can read the config - that is already extracted
5437 my $fh = IO
::File-
>new($cfgfn, "r") ||
5438 "unable to read qemu-server.conf - $!\n";
5440 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5442 my $pve_firewall_dir = '/etc/pve/firewall';
5443 mkdir $pve_firewall_dir; # make sure the dir exists
5444 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5447 while (defined(my $line = <$fh>)) {
5448 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5449 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5450 die "archive does not contain data for drive '$virtdev'\n"
5451 if !$devinfo->{$devname};
5452 if (defined($opts->{storage
})) {
5453 $storeid = $opts->{storage
} || 'local';
5454 } elsif (!$storeid) {
5457 $format = 'raw' if !$format;
5458 $devinfo->{$devname}->{devname
} = $devname;
5459 $devinfo->{$devname}->{virtdev
} = $virtdev;
5460 $devinfo->{$devname}->{format
} = $format;
5461 $devinfo->{$devname}->{storeid
} = $storeid;
5463 # check permission on storage
5464 my $pool = $opts->{pool
}; # todo: do we need that?
5465 if ($user ne 'root@pam') {
5466 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5469 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5473 foreach my $devname (keys %$devinfo) {
5474 die "found no device mapping information for device '$devname'\n"
5475 if !$devinfo->{$devname}->{virtdev
};
5478 my $cfg = PVE
::Storage
::config
();
5480 # create empty/temp config
5482 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5483 foreach_drive
($oldconf, sub {
5484 my ($ds, $drive) = @_;
5486 return if drive_is_cdrom
($drive);
5488 my $volid = $drive->{file
};
5490 return if !$volid || $volid =~ m
|^/|;
5492 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5493 return if !$path || !$owner || ($owner != $vmid);
5495 # Note: only delete disk we want to restore
5496 # other volumes will become unused
5497 if ($virtdev_hash->{$ds}) {
5498 PVE
::Storage
::vdisk_free
($cfg, $volid);
5502 # delete vmstate files
5503 # since after the restore we have no snapshots anymore
5504 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5505 my $snap = $oldconf->{snapshots
}->{$snapname};
5506 if ($snap->{vmstate
}) {
5507 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5516 foreach my $virtdev (sort keys %$virtdev_hash) {
5517 my $d = $virtdev_hash->{$virtdev};
5518 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5519 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5521 # test if requested format is supported
5522 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5523 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5524 $d->{format
} = $defFormat if !$supported;
5526 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5527 $d->{format
}, undef, $alloc_size);
5528 print STDERR
"new volume ID is '$volid'\n";
5529 $d->{volid
} = $volid;
5530 my $path = PVE
::Storage
::path
($cfg, $volid);
5532 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5534 my $write_zeros = 1;
5535 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5539 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5541 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5542 $map->{$virtdev} = $volid;
5545 $fh->seek(0, 0) || die "seek failed - $!\n";
5547 my $outfd = new IO
::File
($tmpfn, "w") ||
5548 die "unable to write config for VM $vmid\n";
5550 my $cookie = { netcount
=> 0 };
5551 while (defined(my $line = <$fh>)) {
5552 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5561 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5562 die "interrupted by signal\n";
5564 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5566 $oldtimeout = alarm($timeout);
5573 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5574 my ($dev_id, $size, $devname) = ($1, $2, $3);
5575 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5576 } elsif ($line =~ m/^CTIME: /) {
5577 # we correctly received the vma config, so we can disable
5578 # the timeout now for disk allocation (set to 10 minutes, so
5579 # that we always timeout if something goes wrong)
5582 print $fifofh "done\n";
5583 my $tmp = $oldtimeout || 0;
5584 $oldtimeout = undef;
5590 print "restore vma archive: $cmd\n";
5591 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5595 alarm($oldtimeout) if $oldtimeout;
5598 foreach my $devname (keys %$devinfo) {
5599 my $volid = $devinfo->{$devname}->{volid
};
5600 push @$vollist, $volid if $volid;
5603 my $cfg = PVE
::Storage
::config
();
5604 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5612 foreach my $devname (keys %$devinfo) {
5613 my $volid = $devinfo->{$devname}->{volid
};
5616 if ($volid =~ m
|^/|) {
5617 unlink $volid || die 'unlink failed\n';
5619 PVE
::Storage
::vdisk_free
($cfg, $volid);
5621 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5623 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5630 rename($tmpfn, $conffile) ||
5631 die "unable to commit configuration file '$conffile'\n";
5633 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5635 eval { rescan
($vmid, 1); };
5639 sub restore_tar_archive
{
5640 my ($archive, $vmid, $user, $opts) = @_;
5642 if ($archive ne '-') {
5643 my $firstfile = tar_archive_read_firstfile
($archive);
5644 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5645 if $firstfile ne 'qemu-server.conf';
5648 my $storecfg = PVE
::Storage
::config
();
5650 # destroy existing data - keep empty config
5651 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5652 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5654 my $tocmd = "/usr/lib/qemu-server/qmextract";
5656 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5657 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5658 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5659 $tocmd .= ' --info' if $opts->{info
};
5661 # tar option "xf" does not autodetect compression when read from STDIN,
5662 # so we pipe to zcat
5663 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5664 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5666 my $tmpdir = "/var/tmp/vzdumptmp$$";
5669 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5670 local $ENV{VZDUMP_VMID
} = $vmid;
5671 local $ENV{VZDUMP_USER
} = $user;
5673 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5674 my $tmpfn = "$conffile.$$.tmp";
5676 # disable interrupts (always do cleanups)
5677 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5678 print STDERR
"got interrupt - ignored\n";
5683 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5684 die "interrupted by signal\n";
5687 if ($archive eq '-') {
5688 print "extracting archive from STDIN\n";
5689 run_command
($cmd, input
=> "<&STDIN");
5691 print "extracting archive '$archive'\n";
5695 return if $opts->{info
};
5699 my $statfile = "$tmpdir/qmrestore.stat";
5700 if (my $fd = IO
::File-
>new($statfile, "r")) {
5701 while (defined (my $line = <$fd>)) {
5702 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5703 $map->{$1} = $2 if $1;
5705 print STDERR
"unable to parse line in statfile - $line\n";
5711 my $confsrc = "$tmpdir/qemu-server.conf";
5713 my $srcfd = new IO
::File
($confsrc, "r") ||
5714 die "unable to open file '$confsrc'\n";
5716 my $outfd = new IO
::File
($tmpfn, "w") ||
5717 die "unable to write config for VM $vmid\n";
5719 my $cookie = { netcount
=> 0 };
5720 while (defined (my $line = <$srcfd>)) {
5721 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5733 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5740 rename $tmpfn, $conffile ||
5741 die "unable to commit configuration file '$conffile'\n";
5743 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5745 eval { rescan
($vmid, 1); };
5749 sub foreach_writable_storage
{
5750 my ($conf, $func) = @_;
5754 foreach my $ds (keys %$conf) {
5755 next if !is_valid_drivename
($ds);
5757 my $drive = parse_drive
($ds, $conf->{$ds});
5759 next if drive_is_cdrom
($drive);
5761 my $volid = $drive->{file
};
5763 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5764 $sidhash->{$sid} = $sid if $sid;
5767 foreach my $sid (sort keys %$sidhash) {
5772 sub do_snapshots_with_qemu
{
5773 my ($storecfg, $volid) = @_;
5775 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5777 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5778 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5782 if ($volid =~ m/\.(qcow2|qed)$/){
5789 sub qga_check_running
{
5792 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5794 warn "Qemu Guest Agent are not running - $@";
5800 sub template_create
{
5801 my ($vmid, $conf, $disk) = @_;
5803 my $storecfg = PVE
::Storage
::config
();
5805 foreach_drive
($conf, sub {
5806 my ($ds, $drive) = @_;
5808 return if drive_is_cdrom
($drive);
5809 return if $disk && $ds ne $disk;
5811 my $volid = $drive->{file
};
5812 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5814 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5815 $drive->{file
} = $voliddst;
5816 $conf->{$ds} = print_drive
($vmid, $drive);
5817 PVE
::QemuConfig-
>write_config($vmid, $conf);
5821 sub qemu_img_convert
{
5822 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5824 my $storecfg = PVE
::Storage
::config
();
5825 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5826 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5828 if ($src_storeid && $dst_storeid) {
5830 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5832 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5833 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5835 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5836 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5838 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5839 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5842 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5843 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5844 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5845 if ($is_zero_initialized) {
5846 push @$cmd, "zeroinit:$dst_path";
5848 push @$cmd, $dst_path;
5853 if($line =~ m/\((\S+)\/100\
%\)/){
5855 my $transferred = int($size * $percent / 100);
5856 my $remaining = $size - $transferred;
5858 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5863 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5865 die "copy failed: $err" if $err;
5869 sub qemu_img_format
{
5870 my ($scfg, $volname) = @_;
5872 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5879 sub qemu_drive_mirror
{
5880 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5882 my $storecfg = PVE
::Storage
::config
();
5883 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5885 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5887 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5889 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5891 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5893 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5894 $opts->{format
} = $format if $format;
5896 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5899 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5901 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5902 my $stat = @$stats[0];
5903 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5904 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5906 my $busy = $stat->{busy
};
5907 my $ready = $stat->{ready
};
5909 if (my $total = $stat->{len
}) {
5910 my $transferred = $stat->{offset
} || 0;
5911 my $remaining = $total - $transferred;
5912 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5914 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5918 if ($stat->{ready
} eq 'true') {
5920 last if $vmiddst != $vmid;
5922 # try to switch the disk if source and destination are on the same guest
5923 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5925 die $@ if $@ !~ m/cannot be completed/;
5934 my $cancel_job = sub {
5935 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5937 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5938 my $stat = @$stats[0];
5945 eval { &$cancel_job(); };
5946 die "mirroring error: $err";
5949 if ($vmiddst != $vmid) {
5950 # if we clone a disk for a new target vm, we don't switch the disk
5951 &$cancel_job(); # so we call block-job-cancel
5956 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5957 $newvmid, $storage, $format, $full, $newvollist) = @_;
5962 print "create linked clone of drive $drivename ($drive->{file})\n";
5963 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5964 push @$newvollist, $newvolid;
5966 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5967 $storeid = $storage if $storage;
5969 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5971 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5972 $format = qemu_img_format
($scfg, $volname);
5975 # test if requested format is supported - else use default
5976 my $supported = grep { $_ eq $format } @$validFormats;
5977 $format = $defFormat if !$supported;
5979 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5981 print "create full clone of drive $drivename ($drive->{file})\n";
5982 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5983 push @$newvollist, $newvolid;
5985 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5987 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5988 if (!$running || $snapname) {
5989 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5991 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5995 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5998 $disk->{format
} = undef;
5999 $disk->{file
} = $newvolid;
6000 $disk->{size
} = $size;
6005 # this only works if VM is running
6006 sub get_current_qemu_machine
{
6009 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6010 my $res = vm_qmp_command
($vmid, $cmd);
6012 my ($current, $default);
6013 foreach my $e (@$res) {
6014 $default = $e->{name
} if $e->{'is-default'};
6015 $current = $e->{name
} if $e->{'is-current'};
6018 # fallback to the default machine if current is not supported by qemu
6019 return $current || $default || 'pc';
6022 sub qemu_machine_feature_enabled
{
6023 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6028 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6030 $current_major = $3;
6031 $current_minor = $4;
6033 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6035 $current_major = $1;
6036 $current_minor = $2;
6039 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6044 sub qemu_machine_pxe
{
6045 my ($vmid, $conf, $machine) = @_;
6047 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6049 foreach my $opt (keys %$conf) {
6050 next if $opt !~ m/^net(\d+)$/;
6051 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6053 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6054 return $machine.".pxe" if $romfile =~ m/pxe/;
6061 sub qemu_use_old_bios_files
{
6062 my ($machine_type) = @_;
6064 return if !$machine_type;
6066 my $use_old_bios_files = undef;
6068 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6070 $use_old_bios_files = 1;
6072 my $kvmver = kvm_user_version
();
6073 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6074 # load new efi bios files on migration. So this hack is required to allow
6075 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6076 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6077 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6080 return ($use_old_bios_files, $machine_type);
6087 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6088 my (undef, $id, $function) = @_;
6089 my $res = { id
=> $id, function
=> $function};
6090 push @{$devices->{$id}}, $res;
6096 sub vm_iothreads_list
{
6099 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6102 foreach my $iothread (@$res) {
6103 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6110 my ($conf, $drive) = @_;
6114 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6116 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6122 my $controller = int($drive->{index} / $maxdev);
6123 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6125 return ($maxdev, $controller, $controller_prefix);
6128 # bash completion helper
6130 sub complete_backup_archives
{
6131 my ($cmdname, $pname, $cvalue) = @_;
6133 my $cfg = PVE
::Storage
::config
();
6137 if ($cvalue =~ m/^([^:]+):/) {
6141 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6144 foreach my $id (keys %$data) {
6145 foreach my $item (@{$data->{$id}}) {
6146 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6147 push @$res, $item->{volid
} if defined($item->{volid
});
6154 my $complete_vmid_full = sub {
6157 my $idlist = vmstatus
();
6161 foreach my $id (keys %$idlist) {
6162 my $d = $idlist->{$id};
6163 if (defined($running)) {
6164 next if $d->{template
};
6165 next if $running && $d->{status
} ne 'running';
6166 next if !$running && $d->{status
} eq 'running';
6175 return &$complete_vmid_full();
6178 sub complete_vmid_stopped
{
6179 return &$complete_vmid_full(0);
6182 sub complete_vmid_running
{
6183 return &$complete_vmid_full(1);
6186 sub complete_storage
{
6188 my $cfg = PVE
::Storage
::config
();
6189 my $ids = $cfg->{ids
};
6192 foreach my $sid (keys %$ids) {
6193 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6194 next if !$ids->{$sid}->{content
}->{images
};