1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
32 use PVE
::RPCEnvironment
;
33 use Time
::HiRes
qw(gettimeofday);
34 use File
::Copy
qw(copy);
37 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
39 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
41 # Note about locking: we use flock on the config file protect
42 # against concurent actions.
43 # Aditionaly, we have a 'lock' setting in the config file. This
44 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
45 # allowed when such lock is set. But you can ignore this kind of
46 # lock with the --skiplock flag.
48 cfs_register_file
('/qemu-server/',
52 PVE
::JSONSchema
::register_standard_option
('skiplock', {
53 description
=> "Ignore locks - only root is allowed to use this option.",
58 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
59 description
=> "Some command save/restore state from this location.",
65 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
66 description
=> "The name of the snapshot.",
67 type
=> 'string', format
=> 'pve-configid',
71 #no warnings 'redefine';
74 my ($controller, $vmid, $option, $value) = @_;
76 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
77 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
81 my $nodename = PVE
::INotify
::nodename
();
83 mkdir "/etc/pve/nodes/$nodename";
84 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
87 my $var_run_tmpdir = "/var/run/qemu-server";
88 mkdir $var_run_tmpdir;
90 my $lock_dir = "/var/lock/qemu-server";
93 my $pcisysfs = "/sys/bus/pci";
97 description
=> "Emulated CPU type.",
99 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Haswell-noTSX Broadwell Broadwell-noTSX Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
100 format_description
=> 'cputype',
105 description
=> "Do not identify as a KVM virtual machine.",
116 description
=> "Specifies whether a VM will be started during system bootup.",
122 description
=> "Automatic restart after crash (currently ignored).",
127 type
=> 'string', format
=> 'pve-hotplug-features',
128 description
=> "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
129 default => 'network,disk,usb',
134 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
140 description
=> "Lock/unlock the VM.",
141 enum
=> [qw(migrate backup snapshot rollback)],
146 description
=> "Limit of CPU usage.\n\nNOTE: If the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
154 description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
162 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
169 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
175 description
=> "Amount of memory shares for auto-ballooning. The larger the number is, the more memory this VM gets. Number is relative to weights of all other running VMs. Using zero disables auto-ballooning",
183 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
184 enum
=> PVE
::Tools
::kvmkeymaplist
(),
189 type
=> 'string', format
=> 'dns-name',
190 description
=> "Set a name for the VM. Only used on the configuration web interface.",
195 description
=> "scsi controller model",
196 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
202 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
207 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
208 description
=> <<EODESC,
209 Used to enable special optimization/features for specific
212 other => unspecified OS
213 wxp => Microsoft Windows XP
214 w2k => Microsoft Windows 2000
215 w2k3 => Microsoft Windows 2003
216 w2k8 => Microsoft Windows 2008
217 wvista => Microsoft Windows Vista
218 win7 => Microsoft Windows 7
219 win8 => Microsoft Windows 8/2012
220 l24 => Linux 2.4 Kernel
221 l26 => Linux 2.6/3.X Kernel
222 solaris => solaris/opensolaris/openindiania kernel
224 other|l24|l26|solaris ... no special behaviour
225 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
231 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
232 pattern
=> '[acdn]{1,4}',
237 type
=> 'string', format
=> 'pve-qm-bootdisk',
238 description
=> "Enable booting from specified disk.",
239 pattern
=> '(ide|sata|scsi|virtio)\d+',
244 description
=> "The number of CPUs. Please use option -sockets instead.",
251 description
=> "The number of CPU sockets.",
258 description
=> "The number of cores per socket.",
265 description
=> "Enable/disable NUMA.",
271 description
=> "Number of hotplugged vcpus.",
278 description
=> "Enable/disable ACPI.",
284 description
=> "Enable/disable Qemu GuestAgent.",
290 description
=> "Enable/disable KVM hardware virtualization.",
296 description
=> "Enable/disable time drift fix.",
302 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
307 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
312 description
=> "Select the VGA type. If you want to use high resolution" .
313 " modes (>= 1280x1024x16) then you should use the options " .
314 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
315 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
316 "display sever. For win* OS you can select how many independent " .
317 "displays you want, Linux guests can add displays them self. " .
318 "You can also run without any graphic card, using a serial device" .
320 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
324 type
=> 'string', format
=> 'pve-qm-watchdog',
325 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
326 description
=> "Create a virtual hardware watchdog device. Once enabled" .
327 " (by a guest action), the watchdog must be periodically polled " .
328 "by an agent inside the guest or else the watchdog will reset " .
329 "the guest (or execute the respective action specified)",
334 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
335 description
=> "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
336 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
339 startup
=> get_standard_option
('pve-startup-order'),
343 description
=> "Enable/disable Template.",
349 description
=> <<EODESCR,
350 NOTE: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
352 args: -no-reboot -no-hpet
359 description
=> "Enable/disable the USB tablet device. This device is " .
360 "usually needed to allow absolute mouse positioning with VNC. " .
361 "Else the mouse runs out of sync with normal VNC clients. " .
362 "If you're running lots of console-only guests on one host, " .
363 "you may consider disabling this to save some context switches. " .
364 "This is turned off by default if you use spice (-vga=qxl).",
369 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
373 migrate_downtime
=> {
376 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
382 type
=> 'string', format
=> 'pve-qm-drive',
383 typetext
=> 'volume',
384 description
=> "This is an alias for option -ide2",
388 description
=> "Emulated CPU type.",
392 parent
=> get_standard_option
('pve-snapshot-name', {
394 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
398 description
=> "Timestamp for snapshots.",
404 type
=> 'string', format
=> 'pve-volume-id',
405 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
408 description
=> "Specific the Qemu machine type.",
410 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
415 description
=> "Specify SMBIOS type 1 fields.",
416 type
=> 'string', format
=> 'pve-qm-smbios1',
423 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
429 enum
=> [ qw(seabios ovmf) ],
430 description
=> "Select BIOS implementation.",
431 default => 'seabios',
435 # what about other qemu settings ?
437 #machine => 'string',
450 ##soundhw => 'string',
452 while (my ($k, $v) = each %$confdesc) {
453 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
456 my $MAX_IDE_DISKS = 4;
457 my $MAX_SCSI_DISKS = 14;
458 my $MAX_VIRTIO_DISKS = 16;
459 my $MAX_SATA_DISKS = 6;
460 my $MAX_USB_DEVICES = 5;
462 my $MAX_UNUSED_DISKS = 8;
463 my $MAX_HOSTPCI_DEVICES = 4;
464 my $MAX_SERIAL_PORTS = 4;
465 my $MAX_PARALLEL_PORTS = 3;
467 my $MAX_MEM = 4194304;
468 my $STATICMEM = 1024;
473 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
474 description
=> "CPUs accessing this numa node.",
475 format_description
=> "id[-id];...",
479 description
=> "Amount of memory this numa node provides.",
480 format_description
=> "mb",
485 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
486 description
=> "host numa nodes to use",
487 format_description
=> "id[-id];...",
492 enum
=> [qw(preferred bind interleave)],
493 format_description
=> 'preferred|bind|interleave',
494 description
=> "numa allocation policy.",
498 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
501 type
=> 'string', format
=> $numa_fmt,
502 description
=> "numa topology",
504 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
506 for (my $i = 0; $i < $MAX_NUMA; $i++) {
507 $confdesc->{"numa$i"} = $numadesc;
510 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
511 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
512 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
513 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
518 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
519 description
=> "MAC address",
520 format_description
=> "XX:XX:XX:XX:XX:XX",
523 model
=> { alias
=> 'macaddr', default_key
=> 1 },
524 (map { $_ => { group
=> 'model' } } @$nic_model_list),
527 description
=> 'Bridge to attach the network device to.',
528 format_description
=> 'bridge',
533 minimum
=> 0, maximum
=> 16,
534 description
=> 'Number of packet queues to be used on the device.',
535 format_description
=> 'number',
541 description
=> 'Rate limit in mbps as floating point number.',
542 format_description
=> 'mbps',
547 minimum
=> 2, maximum
=> 4094,
548 description
=> 'VLAN tag to apply to packets on this interface.',
549 format_description
=> 'vlanid',
554 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
555 description
=> 'VLAN trunks to pass through this interface.',
556 format_description
=> 'id;id...',
561 description
=> 'Whether this interface should be protected by the firewall.',
562 format_description
=> '0|1',
567 description
=> 'Whether this interface should be DISconnected (like pulling the plug).',
568 format_description
=> '0|1',
574 type
=> 'string', format
=> 'pve-qm-net',
575 description
=> <<EODESCR,
576 Specify network devices.
578 MODEL is one of: $nic_model_list_txt
580 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
581 automatically generated if not specified.
583 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
585 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'.
587 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
593 The DHCP server assign addresses to the guest starting from 10.0.2.15.
597 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
599 for (my $i = 0; $i < $MAX_NETS; $i++) {
600 $confdesc->{"net$i"} = $netdesc;
603 PVE
::JSONSchema
::register_format
('pve-volume-id-or-none', \
&verify_volume_id_or_none
);
604 sub verify_volume_id_or_none
{
605 my ($volid, $noerr) = @_;
607 return $volid if $volid eq 'none';
608 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
610 return undef if $noerr;
618 my %drivedesc_base = (
619 volume
=> { alias
=> 'file' },
622 format
=> 'pve-volume-id-or-none',
624 format_description
=> 'volume',
625 description
=> "The drive's backing volume.",
629 format_description
=> 'cdrom|disk',
630 enum
=> [qw(cdrom disk)],
631 description
=> "The drive's media type.",
637 format_description
=> 'count',
638 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
643 format_description
=> 'count',
644 description
=> "Force the drive's physical geometry to have a specific head count.",
649 format_description
=> 'count',
650 description
=> "Force the drive's physical geometry to have a specific sector count.",
655 format_description
=> 'none|lba|auto',
656 enum
=> [qw(none lba auto)],
657 description
=> "Force disk geometry bios translation mode.",
662 format_description
=> 'on|off',
663 description
=> "Whether the drive should be included when making snapshots.",
668 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
669 enum
=> [qw(none writethrough writeback unsafe directsync)],
670 description
=> "The drive's cache mode",
675 format_description
=> 'drive format',
676 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
677 description
=> "The drive's backing file's data format.",
682 format
=> 'disk-size',
683 description
=> "Disk size. This is purely informational and has no effect.",
688 format_description
=> 'on|off',
689 description
=> "Whether the drive should be included when making backups.",
694 format_description
=> 'enospc|ignore|report|stop',
695 enum
=> [qw(enospc ignore report stop)],
696 description
=> 'Write error action.',
701 format_description
=> 'native|threads',
702 enum
=> [qw(native threads)],
703 description
=> 'AIO type to use.',
708 format_description
=> 'ignore|on',
709 enum
=> [qw(ignore on)],
710 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
715 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
720 format
=> 'urlencoded',
721 format_description
=> 'serial',
722 maxLength
=> 20*3, # *3 since it's %xx url enoded
723 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
731 format_description
=> 'ignore|report|stop',
732 enum
=> [qw(ignore report stop)],
733 description
=> 'Read error action.',
738 my %iothread_fmt = ( iothread
=> {
740 format_description
=> 'off|on',
741 description
=> "Whether to use iothreads for this drive",
748 format
=> 'urlencoded',
749 format_description
=> 'model',
750 maxLength
=> 40*3, # *3 since it's %xx url enoded
751 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
759 format_description
=> 'nbqueues',
760 description
=> "Number of queues.",
766 my $add_throttle_desc = sub {
767 my ($key, $type, $what, $size, $longsize) = @_;
768 $drivedesc_base{$key} = {
770 format_description
=> $size,
771 description
=> "Maximum $what speed in $longsize per second.",
775 # throughput: (leaky bucket)
776 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
777 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
778 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
779 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
780 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
781 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
782 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
783 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
784 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
786 # pools: (pool of IO before throttling starts taking effect)
787 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
788 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
789 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
790 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
791 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
792 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
802 type
=> 'string', format
=> $ide_fmt,
803 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
805 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
814 type
=> 'string', format
=> $scsi_fmt,
815 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
817 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
825 type
=> 'string', format
=> $sata_fmt,
826 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
828 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
837 type
=> 'string', format
=> $virtio_fmt,
838 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
840 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
853 type
=> 'string', format
=> 'pve-qm-usb-device',
854 format_description
=> 'HOSTUSBDEVICE|spice',
855 description
=> 'The Host USB device or port or the value spice',
860 format_description
=> 'yes|no',
861 description
=> 'Specifies whether if given host option is a USB3 device or port',
867 type
=> 'string', format
=> $usb_fmt,
868 description
=> <<EODESCR,
869 Configure an USB device (n is 0 to 4). This can be used to
870 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
872 'bus-port(.port)*' (decimal numbers) or
873 'vendor_id:product_id' (hexadeciaml numbers) or
876 You can use the 'lsusb -t' command to list existing usb devices.
878 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
880 The value 'spice' can be used to add a usb redirection devices for spice.
882 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).
886 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
890 type
=> 'string', format
=> 'pve-qm-hostpci',
891 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
892 description
=> <<EODESCR,
893 Map host pci devices. HOSTPCIDEVICE syntax is:
895 'bus:dev.func' (hexadecimal numbers)
897 You can us the 'lspci' command to list existing pci devices.
899 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
901 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
903 Experimental: user reported problems with this option.
906 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
911 pattern
=> '(/dev/.+|socket)',
912 description
=> <<EODESCR,
913 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).
915 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
917 Experimental: user reported problems with this option.
924 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
925 description
=> <<EODESCR,
926 Map host parallel devices (n is 0 to 2).
928 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
930 Experimental: user reported problems with this option.
934 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
935 $confdesc->{"parallel$i"} = $paralleldesc;
938 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
939 $confdesc->{"serial$i"} = $serialdesc;
942 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
943 $confdesc->{"hostpci$i"} = $hostpcidesc;
946 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
947 $drivename_hash->{"ide$i"} = 1;
948 $confdesc->{"ide$i"} = $idedesc;
951 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
952 $drivename_hash->{"sata$i"} = 1;
953 $confdesc->{"sata$i"} = $satadesc;
956 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
957 $drivename_hash->{"scsi$i"} = 1;
958 $confdesc->{"scsi$i"} = $scsidesc ;
961 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
962 $drivename_hash->{"virtio$i"} = 1;
963 $confdesc->{"virtio$i"} = $virtiodesc;
966 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
967 $confdesc->{"usb$i"} = $usbdesc;
972 type
=> 'string', format
=> 'pve-volume-id',
973 description
=> "Reference to unused volumes.",
976 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
977 $confdesc->{"unused$i"} = $unuseddesc;
980 my $kvm_api_version = 0;
984 return $kvm_api_version if $kvm_api_version;
986 my $fh = IO
::File-
>new("</dev/kvm") ||
989 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
990 $kvm_api_version = $v;
995 return $kvm_api_version;
998 my $kvm_user_version;
1000 sub kvm_user_version
{
1002 return $kvm_user_version if $kvm_user_version;
1004 $kvm_user_version = 'unknown';
1008 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1009 $kvm_user_version = $2;
1013 eval { run_command
("kvm -version", outfunc
=> $code); };
1016 return $kvm_user_version;
1020 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1022 sub valid_drive_names
{
1023 # order is important - used to autoselect boot disk
1024 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1025 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1026 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1027 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1030 sub is_valid_drivename
{
1033 return defined($drivename_hash->{$dev});
1038 return defined($confdesc->{$key});
1042 return $nic_model_list;
1045 sub os_list_description
{
1049 wxp
=> 'Windows XP',
1050 w2k
=> 'Windows 2000',
1051 w2k3
=>, 'Windows 2003',
1052 w2k8
=> 'Windows 2008',
1053 wvista
=> 'Windows Vista',
1054 win7
=> 'Windows 7',
1055 win8
=> 'Windows 8/2012',
1063 sub get_cdrom_path
{
1065 return $cdrom_path if $cdrom_path;
1067 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1068 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1069 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1073 my ($storecfg, $vmid, $cdrom) = @_;
1075 if ($cdrom eq 'cdrom') {
1076 return get_cdrom_path
();
1077 } elsif ($cdrom eq 'none') {
1079 } elsif ($cdrom =~ m
|^/|) {
1082 return PVE
::Storage
::path
($storecfg, $cdrom);
1086 # try to convert old style file names to volume IDs
1087 sub filename_to_volume_id
{
1088 my ($vmid, $file, $media) = @_;
1090 if (!($file eq 'none' || $file eq 'cdrom' ||
1091 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1093 return undef if $file =~ m
|/|;
1095 if ($media && $media eq 'cdrom') {
1096 $file = "local:iso/$file";
1098 $file = "local:$vmid/$file";
1105 sub verify_media_type
{
1106 my ($opt, $vtype, $media) = @_;
1111 if ($media eq 'disk') {
1113 } elsif ($media eq 'cdrom') {
1116 die "internal error";
1119 return if ($vtype eq $etype);
1121 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1124 sub cleanup_drive_path
{
1125 my ($opt, $storecfg, $drive) = @_;
1127 # try to convert filesystem paths to volume IDs
1129 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1130 ($drive->{file
} !~ m
|^/dev/.+|) &&
1131 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1132 ($drive->{file
} !~ m/^\d+$/)) {
1133 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1134 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1135 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1136 verify_media_type
($opt, $vtype, $drive->{media
});
1137 $drive->{file
} = $volid;
1140 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1143 sub parse_hotplug_features
{
1148 return $res if $data eq '0';
1150 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1152 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1153 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1156 warn "ignoring unknown hotplug feature '$feature'\n";
1162 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1163 sub pve_verify_hotplug_features
{
1164 my ($value, $noerr) = @_;
1166 return $value if parse_hotplug_features
($value);
1168 return undef if $noerr;
1170 die "unable to parse hotplug option\n";
1173 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1174 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1175 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1176 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1177 # [,iothread=on][,serial=serial][,model=model]
1180 my ($key, $data) = @_;
1182 my ($interface, $index);
1184 if ($key =~ m/^([^\d]+)(\d+)$/) {
1191 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1192 : $confdesc->{$key}->{format
};
1194 warn "invalid drive key: $key\n";
1197 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1198 return undef if !$res;
1199 $res->{interface
} = $interface;
1200 $res->{index} = $index;
1203 foreach my $opt (qw(bps bps_rd bps_wr)) {
1204 if (my $bps = defined(delete $res->{$opt})) {
1205 if (defined($res->{"m$opt"})) {
1206 warn "both $opt and m$opt specified\n";
1210 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1213 return undef if $error;
1215 return undef if $res->{mbps_rd
} && $res->{mbps
};
1216 return undef if $res->{mbps_wr
} && $res->{mbps
};
1217 return undef if $res->{iops_rd
} && $res->{iops
};
1218 return undef if $res->{iops_wr
} && $res->{iops
};
1220 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1221 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1222 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1223 return undef if $res->{interface
} eq 'virtio';
1226 if (my $size = $res->{size
}) {
1227 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1234 my ($vmid, $drive) = @_;
1235 my $data = { %$drive };
1236 delete $data->{$_} for qw(index interface);
1237 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1241 my($fh, $noerr) = @_;
1244 my $SG_GET_VERSION_NUM = 0x2282;
1246 my $versionbuf = "\x00" x
8;
1247 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1249 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1252 my $version = unpack("I", $versionbuf);
1253 if ($version < 30000) {
1254 die "scsi generic interface too old\n" if !$noerr;
1258 my $buf = "\x00" x
36;
1259 my $sensebuf = "\x00" x
8;
1260 my $cmd = pack("C x3 C x1", 0x12, 36);
1262 # see /usr/include/scsi/sg.h
1263 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";
1265 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1266 length($sensebuf), 0, length($buf), $buf,
1267 $cmd, $sensebuf, 6000);
1269 $ret = ioctl($fh, $SG_IO, $packet);
1271 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1275 my @res = unpack($sg_io_hdr_t, $packet);
1276 if ($res[17] || $res[18]) {
1277 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1282 (my $byte0, my $byte1, $res->{vendor
},
1283 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1285 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1286 $res->{type
} = $byte0 & 31;
1294 my $fh = IO
::File-
>new("+<$path") || return undef;
1295 my $res = scsi_inquiry
($fh, 1);
1301 sub machine_type_is_q35
{
1304 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1307 sub print_tabletdevice_full
{
1310 my $q35 = machine_type_is_q35
($conf);
1312 # we use uhci for old VMs because tablet driver was buggy in older qemu
1313 my $usbbus = $q35 ?
"ehci" : "uhci";
1315 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1318 sub print_drivedevice_full
{
1319 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1324 if ($drive->{interface
} eq 'virtio') {
1325 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1326 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1327 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1328 } elsif ($drive->{interface
} eq 'scsi') {
1330 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1331 my $unit = $drive->{index} % $maxdev;
1332 my $devicetype = 'hd';
1334 if (drive_is_cdrom
($drive)) {
1337 if ($drive->{file
} =~ m
|^/|) {
1338 $path = $drive->{file
};
1339 if (my $info = path_is_scsi
($path)) {
1340 if ($info->{type
} == 0) {
1341 $devicetype = 'block';
1342 } elsif ($info->{type
} == 1) { # tape
1343 $devicetype = 'generic';
1347 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1350 if($path =~ m/^iscsi\:\/\
//){
1351 $devicetype = 'generic';
1355 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1356 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1358 $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}";
1361 } elsif ($drive->{interface
} eq 'ide'){
1363 my $controller = int($drive->{index} / $maxdev);
1364 my $unit = $drive->{index} % $maxdev;
1365 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1367 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1368 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1369 $model = URI
::Escape
::uri_unescape
($model);
1370 $device .= ",model=$model";
1372 } elsif ($drive->{interface
} eq 'sata'){
1373 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1374 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1375 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1376 } elsif ($drive->{interface
} eq 'usb') {
1378 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1380 die "unsupported interface type";
1383 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1388 sub get_initiator_name
{
1391 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1392 while (defined(my $line = <$fh>)) {
1393 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1402 sub print_drive_full
{
1403 my ($storecfg, $vmid, $drive) = @_;
1406 my $volid = $drive->{file
};
1409 if (drive_is_cdrom
($drive)) {
1410 $path = get_iso_path
($storecfg, $vmid, $volid);
1412 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1414 $path = PVE
::Storage
::path
($storecfg, $volid);
1415 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1416 $format = qemu_img_format
($scfg, $volname);
1424 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);
1425 foreach my $o (@qemu_drive_options) {
1426 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1428 if (my $serial = $drive->{serial
}) {
1429 $serial = URI
::Escape
::uri_unescape
($serial);
1430 $opts .= ",serial=$serial";
1433 $opts .= ",format=$format" if $format && !$drive->{format
};
1435 foreach my $o (qw(bps bps_rd bps_wr)) {
1436 my $v = $drive->{"m$o"};
1437 $opts .= ",$o=" . int($v*1024*1024) if $v;
1440 my $cache_direct = 0;
1442 if (my $cache = $drive->{cache
}) {
1443 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1444 } elsif (!drive_is_cdrom
($drive)) {
1445 $opts .= ",cache=none";
1449 # aio native works only with O_DIRECT
1450 if (!$drive->{aio
}) {
1452 $opts .= ",aio=native";
1454 $opts .= ",aio=threads";
1458 if (!drive_is_cdrom
($drive)) {
1460 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1461 $detectzeroes = 'off';
1462 } elsif ($drive->{discard
}) {
1463 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1465 # This used to be our default with discard not being specified:
1466 $detectzeroes = 'on';
1468 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1471 my $pathinfo = $path ?
"file=$path," : '';
1473 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1476 sub print_netdevice_full
{
1477 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1479 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1481 my $device = $net->{model
};
1482 if ($net->{model
} eq 'virtio') {
1483 $device = 'virtio-net-pci';
1486 my $pciaddr = print_pci_addr
("$netid", $bridges);
1487 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1488 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1489 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1490 my $vectors = $net->{queues
} * 2 + 2;
1491 $tmpstr .= ",vectors=$vectors,mq=on";
1493 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1495 if ($use_old_bios_files) {
1497 if ($device eq 'virtio-net-pci') {
1498 $romfile = 'pxe-virtio.rom';
1499 } elsif ($device eq 'e1000') {
1500 $romfile = 'pxe-e1000.rom';
1501 } elsif ($device eq 'ne2k') {
1502 $romfile = 'pxe-ne2k_pci.rom';
1503 } elsif ($device eq 'pcnet') {
1504 $romfile = 'pxe-pcnet.rom';
1505 } elsif ($device eq 'rtl8139') {
1506 $romfile = 'pxe-rtl8139.rom';
1508 $tmpstr .= ",romfile=$romfile" if $romfile;
1514 sub print_netdev_full
{
1515 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1518 if ($netid =~ m/^net(\d+)$/) {
1522 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1524 my $ifname = "tap${vmid}i$i";
1526 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1527 die "interface name '$ifname' is too long (max 15 character)\n"
1528 if length($ifname) >= 16;
1530 my $vhostparam = '';
1531 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1533 my $vmname = $conf->{name
} || "vm$vmid";
1536 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1538 if ($net->{bridge
}) {
1539 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1541 $netdev = "type=user,id=$netid,hostname=$vmname";
1544 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1549 sub drive_is_cdrom
{
1552 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1556 sub parse_number_sets
{
1559 foreach my $part (split(/;/, $set)) {
1560 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1561 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1562 push @$res, [ $1, $2 ];
1564 die "invalid range: $part\n";
1573 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1574 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1575 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1582 return undef if !$value;
1585 my @list = split(/,/, $value);
1589 foreach my $kv (@list) {
1591 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1594 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1597 my $pcidevices = lspci
($2);
1598 $res->{pciid
} = $pcidevices->{$2};
1600 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1601 $res->{rombar
} = $1;
1602 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1603 $res->{'x-vga'} = $1;
1604 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1605 $res->{pcie
} = 1 if $1 == 1;
1607 warn "unknown hostpci setting '$kv'\n";
1611 return undef if !$found;
1616 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1620 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1625 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
() if !defined($res->{macaddr
});
1632 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1635 sub add_random_macs
{
1636 my ($settings) = @_;
1638 foreach my $opt (keys %$settings) {
1639 next if $opt !~ m/^net(\d+)$/;
1640 my $net = parse_net
($settings->{$opt});
1642 $settings->{$opt} = print_net
($net);
1646 sub vm_is_volid_owner
{
1647 my ($storecfg, $vmid, $volid) = @_;
1649 if ($volid !~ m
|^/|) {
1651 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1652 if ($owner && ($owner == $vmid)) {
1660 sub split_flagged_list
{
1661 my $text = shift || '';
1662 $text =~ s/[,;]/ /g;
1664 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1667 sub join_flagged_list
{
1668 my ($how, $lst) = @_;
1669 join $how, map { $lst->{$_} . $_ } keys %$lst;
1672 sub vmconfig_delete_pending_option
{
1673 my ($conf, $key, $force) = @_;
1675 delete $conf->{pending
}->{$key};
1676 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1677 $pending_delete_hash->{$key} = $force ?
'!' : '';
1678 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1681 sub vmconfig_undelete_pending_option
{
1682 my ($conf, $key) = @_;
1684 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1685 delete $pending_delete_hash->{$key};
1687 if (%$pending_delete_hash) {
1688 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1690 delete $conf->{pending
}->{delete};
1694 sub vmconfig_register_unused_drive
{
1695 my ($storecfg, $vmid, $conf, $drive) = @_;
1697 if (!drive_is_cdrom
($drive)) {
1698 my $volid = $drive->{file
};
1699 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1700 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1705 sub vmconfig_cleanup_pending
{
1708 # remove pending changes when nothing changed
1710 foreach my $opt (keys %{$conf->{pending
}}) {
1711 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1713 delete $conf->{pending
}->{$opt};
1717 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1718 my $pending_delete_hash = {};
1719 while (my ($opt, $force) = each %$current_delete_hash) {
1720 if (defined($conf->{$opt})) {
1721 $pending_delete_hash->{$opt} = $force;
1727 if (%$pending_delete_hash) {
1728 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1730 delete $conf->{pending
}->{delete};
1736 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1740 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1741 format_description
=> 'UUID',
1747 format_description
=> 'str',
1753 format_description
=> 'str',
1759 format_description
=> 'name',
1765 format_description
=> 'name',
1771 format_description
=> 'str',
1777 format_description
=> 'str',
1785 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1792 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1795 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1797 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1798 sub verify_bootdisk
{
1799 my ($value, $noerr) = @_;
1801 return $value if is_valid_drivename
($value);
1803 return undef if $noerr;
1805 die "invalid boot disk '$value'\n";
1808 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1810 my ($value, $noerr) = @_;
1812 return $value if parse_net
($value);
1814 return undef if $noerr;
1816 die "unable to parse network options\n";
1819 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1820 sub verify_hostpci
{
1821 my ($value, $noerr) = @_;
1823 return $value if parse_hostpci
($value);
1825 return undef if $noerr;
1827 die "unable to parse pci id\n";
1830 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1831 sub verify_watchdog
{
1832 my ($value, $noerr) = @_;
1834 return $value if parse_watchdog
($value);
1836 return undef if $noerr;
1838 die "unable to parse watchdog options\n";
1841 sub parse_watchdog
{
1844 return undef if !$value;
1848 foreach my $p (split(/,/, $value)) {
1849 next if $p =~ m/^\s*$/;
1851 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1853 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1854 $res->{action
} = $2;
1863 sub parse_usb_device
{
1866 return undef if !$value;
1869 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1870 $res->{vendorid
} = $2;
1871 $res->{productid
} = $4;
1872 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1873 $res->{hostbus
} = $1;
1874 $res->{hostport
} = $2;
1875 } elsif ($value =~ m/^spice$/i) {
1884 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1885 sub verify_usb_device
{
1886 my ($value, $noerr) = @_;
1888 return $value if parse_usb_device
($value);
1890 return undef if $noerr;
1892 die "unable to parse usb device\n";
1895 # add JSON properties for create and set function
1896 sub json_config_properties
{
1899 foreach my $opt (keys %$confdesc) {
1900 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1901 $prop->{$opt} = $confdesc->{$opt};
1908 my ($key, $value) = @_;
1910 die "unknown setting '$key'\n" if !$confdesc->{$key};
1912 my $type = $confdesc->{$key}->{type
};
1914 if (!defined($value)) {
1915 die "got undefined value\n";
1918 if ($value =~ m/[\n\r]/) {
1919 die "property contains a line feed\n";
1922 if ($type eq 'boolean') {
1923 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1924 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1925 die "type check ('boolean') failed - got '$value'\n";
1926 } elsif ($type eq 'integer') {
1927 return int($1) if $value =~ m/^(\d+)$/;
1928 die "type check ('integer') failed - got '$value'\n";
1929 } elsif ($type eq 'number') {
1930 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1931 die "type check ('number') failed - got '$value'\n";
1932 } elsif ($type eq 'string') {
1933 if (my $fmt = $confdesc->{$key}->{format
}) {
1934 if ($fmt eq 'pve-qm-drive') {
1935 # special case - we need to pass $key to parse_drive()
1936 my $drive = parse_drive
($key, $value);
1937 return $value if $drive;
1938 die "unable to parse drive options\n";
1940 PVE
::JSONSchema
::check_format
($fmt, $value);
1943 $value =~ s/^\"(.*)\"$/$1/;
1946 die "internal error"
1950 sub check_iommu_support
{
1951 #fixme : need to check IOMMU support
1952 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1962 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1963 utime undef, undef, $conf;
1967 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1969 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1971 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1973 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1975 # only remove disks owned by this VM
1976 foreach_drive
($conf, sub {
1977 my ($ds, $drive) = @_;
1979 return if drive_is_cdrom
($drive);
1981 my $volid = $drive->{file
};
1983 return if !$volid || $volid =~ m
|^/|;
1985 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1986 return if !$path || !$owner || ($owner != $vmid);
1988 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1991 if ($keep_empty_config) {
1992 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1997 # also remove unused disk
1999 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2002 PVE
::Storage
::foreach_volid
($dl, sub {
2003 my ($volid, $sid, $volname, $d) = @_;
2004 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2013 sub parse_vm_config
{
2014 my ($filename, $raw) = @_;
2016 return undef if !defined($raw);
2019 digest
=> Digest
::SHA
::sha1_hex
($raw),
2024 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2025 || die "got strange filename '$filename'";
2033 my @lines = split(/\n/, $raw);
2034 foreach my $line (@lines) {
2035 next if $line =~ m/^\s*$/;
2037 if ($line =~ m/^\[PENDING\]\s*$/i) {
2038 $section = 'pending';
2039 if (defined($descr)) {
2041 $conf->{description
} = $descr;
2044 $conf = $res->{$section} = {};
2047 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2049 if (defined($descr)) {
2051 $conf->{description
} = $descr;
2054 $conf = $res->{snapshots
}->{$section} = {};
2058 if ($line =~ m/^\#(.*)\s*$/) {
2059 $descr = '' if !defined($descr);
2060 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2064 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2065 $descr = '' if !defined($descr);
2066 $descr .= PVE
::Tools
::decode_text
($2);
2067 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2068 $conf->{snapstate
} = $1;
2069 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2072 $conf->{$key} = $value;
2073 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2075 if ($section eq 'pending') {
2076 $conf->{delete} = $value; # we parse this later
2078 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2080 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2083 eval { $value = check_type
($key, $value); };
2085 warn "vm $vmid - unable to parse value of '$key' - $@";
2087 my $fmt = $confdesc->{$key}->{format
};
2088 if ($fmt && $fmt eq 'pve-qm-drive') {
2089 my $v = parse_drive
($key, $value);
2090 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2091 $v->{file
} = $volid;
2092 $value = print_drive
($vmid, $v);
2094 warn "vm $vmid - unable to parse value of '$key'\n";
2099 if ($key eq 'cdrom') {
2100 $conf->{ide2
} = $value;
2102 $conf->{$key} = $value;
2108 if (defined($descr)) {
2110 $conf->{description
} = $descr;
2112 delete $res->{snapstate
}; # just to be sure
2117 sub write_vm_config
{
2118 my ($filename, $conf) = @_;
2120 delete $conf->{snapstate
}; # just to be sure
2122 if ($conf->{cdrom
}) {
2123 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2124 $conf->{ide2
} = $conf->{cdrom
};
2125 delete $conf->{cdrom
};
2128 # we do not use 'smp' any longer
2129 if ($conf->{sockets
}) {
2130 delete $conf->{smp
};
2131 } elsif ($conf->{smp
}) {
2132 $conf->{sockets
} = $conf->{smp
};
2133 delete $conf->{cores
};
2134 delete $conf->{smp
};
2137 my $used_volids = {};
2139 my $cleanup_config = sub {
2140 my ($cref, $pending, $snapname) = @_;
2142 foreach my $key (keys %$cref) {
2143 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2144 $key eq 'snapstate' || $key eq 'pending';
2145 my $value = $cref->{$key};
2146 if ($key eq 'delete') {
2147 die "propertry 'delete' is only allowed in [PENDING]\n"
2149 # fixme: check syntax?
2152 eval { $value = check_type
($key, $value); };
2153 die "unable to parse value of '$key' - $@" if $@;
2155 $cref->{$key} = $value;
2157 if (!$snapname && is_valid_drivename
($key)) {
2158 my $drive = parse_drive
($key, $value);
2159 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2164 &$cleanup_config($conf);
2166 &$cleanup_config($conf->{pending
}, 1);
2168 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2169 die "internal error" if $snapname eq 'pending';
2170 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2173 # remove 'unusedX' settings if we re-add a volume
2174 foreach my $key (keys %$conf) {
2175 my $value = $conf->{$key};
2176 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2177 delete $conf->{$key};
2181 my $generate_raw_config = sub {
2182 my ($conf, $pending) = @_;
2186 # add description as comment to top of file
2187 if (defined(my $descr = $conf->{description
})) {
2189 foreach my $cl (split(/\n/, $descr)) {
2190 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2193 $raw .= "#\n" if $pending;
2197 foreach my $key (sort keys %$conf) {
2198 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2199 $raw .= "$key: $conf->{$key}\n";
2204 my $raw = &$generate_raw_config($conf);
2206 if (scalar(keys %{$conf->{pending
}})){
2207 $raw .= "\n[PENDING]\n";
2208 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2211 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2212 $raw .= "\n[$snapname]\n";
2213 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2223 # we use static defaults from our JSON schema configuration
2224 foreach my $key (keys %$confdesc) {
2225 if (defined(my $default = $confdesc->{$key}->{default})) {
2226 $res->{$key} = $default;
2230 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2231 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2237 my $vmlist = PVE
::Cluster
::get_vmlist
();
2239 return $res if !$vmlist || !$vmlist->{ids
};
2240 my $ids = $vmlist->{ids
};
2242 foreach my $vmid (keys %$ids) {
2243 my $d = $ids->{$vmid};
2244 next if !$d->{node
} || $d->{node
} ne $nodename;
2245 next if !$d->{type
} || $d->{type
} ne 'qemu';
2246 $res->{$vmid}->{exists} = 1;
2251 # test if VM uses local resources (to prevent migration)
2252 sub check_local_resources
{
2253 my ($conf, $noerr) = @_;
2257 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2258 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2260 foreach my $k (keys %$conf) {
2261 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2262 # sockets are safe: they will recreated be on the target side post-migrate
2263 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2264 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2267 die "VM uses local resources\n" if $loc_res && !$noerr;
2272 # check if used storages are available on all nodes (use by migrate)
2273 sub check_storage_availability
{
2274 my ($storecfg, $conf, $node) = @_;
2276 foreach_drive
($conf, sub {
2277 my ($ds, $drive) = @_;
2279 my $volid = $drive->{file
};
2282 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2285 # check if storage is available on both nodes
2286 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2287 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2291 # list nodes where all VM images are available (used by has_feature API)
2293 my ($conf, $storecfg) = @_;
2295 my $nodelist = PVE
::Cluster
::get_nodelist
();
2296 my $nodehash = { map { $_ => 1 } @$nodelist };
2297 my $nodename = PVE
::INotify
::nodename
();
2299 foreach_drive
($conf, sub {
2300 my ($ds, $drive) = @_;
2302 my $volid = $drive->{file
};
2305 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2307 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2308 if ($scfg->{disable
}) {
2310 } elsif (my $avail = $scfg->{nodes
}) {
2311 foreach my $node (keys %$nodehash) {
2312 delete $nodehash->{$node} if !$avail->{$node};
2314 } elsif (!$scfg->{shared
}) {
2315 foreach my $node (keys %$nodehash) {
2316 delete $nodehash->{$node} if $node ne $nodename
2326 my ($pidfile, $pid) = @_;
2328 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2332 return undef if !$line;
2333 my @param = split(/\0/, $line);
2335 my $cmd = $param[0];
2336 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2338 for (my $i = 0; $i < scalar (@param); $i++) {
2341 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2342 my $p = $param[$i+1];
2343 return 1 if $p && ($p eq $pidfile);
2352 my ($vmid, $nocheck, $node) = @_;
2354 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2356 die "unable to find configuration file for VM $vmid - no such machine\n"
2357 if !$nocheck && ! -f
$filename;
2359 my $pidfile = pidfile_name
($vmid);
2361 if (my $fd = IO
::File-
>new("<$pidfile")) {
2366 my $mtime = $st->mtime;
2367 if ($mtime > time()) {
2368 warn "file '$filename' modified in future\n";
2371 if ($line =~ m/^(\d+)$/) {
2373 if (check_cmdline
($pidfile, $pid)) {
2374 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2386 my $vzlist = config_list
();
2388 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2390 while (defined(my $de = $fd->read)) {
2391 next if $de !~ m/^(\d+)\.pid$/;
2393 next if !defined($vzlist->{$vmid});
2394 if (my $pid = check_running
($vmid)) {
2395 $vzlist->{$vmid}->{pid
} = $pid;
2403 my ($storecfg, $conf) = @_;
2405 my $bootdisk = $conf->{bootdisk
};
2406 return undef if !$bootdisk;
2407 return undef if !is_valid_drivename
($bootdisk);
2409 return undef if !$conf->{$bootdisk};
2411 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2412 return undef if !defined($drive);
2414 return undef if drive_is_cdrom
($drive);
2416 my $volid = $drive->{file
};
2417 return undef if !$volid;
2419 return $drive->{size
};
2422 my $last_proc_pid_stat;
2424 # get VM status information
2425 # This must be fast and should not block ($full == false)
2426 # We only query KVM using QMP if $full == true (this can be slow)
2428 my ($opt_vmid, $full) = @_;
2432 my $storecfg = PVE
::Storage
::config
();
2434 my $list = vzlist
();
2435 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2437 my $cpucount = $cpuinfo->{cpus
} || 1;
2439 foreach my $vmid (keys %$list) {
2440 next if $opt_vmid && ($vmid ne $opt_vmid);
2442 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2443 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2446 $d->{pid
} = $list->{$vmid}->{pid
};
2448 # fixme: better status?
2449 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2451 my $size = disksize
($storecfg, $conf);
2452 if (defined($size)) {
2453 $d->{disk
} = 0; # no info available
2454 $d->{maxdisk
} = $size;
2460 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2461 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2462 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2464 $d->{name
} = $conf->{name
} || "VM $vmid";
2465 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2467 if ($conf->{balloon
}) {
2468 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2469 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2480 $d->{diskwrite
} = 0;
2482 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2487 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2488 foreach my $dev (keys %$netdev) {
2489 next if $dev !~ m/^tap([1-9]\d*)i/;
2491 my $d = $res->{$vmid};
2494 $d->{netout
} += $netdev->{$dev}->{receive
};
2495 $d->{netin
} += $netdev->{$dev}->{transmit
};
2498 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2499 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2504 my $ctime = gettimeofday
;
2506 foreach my $vmid (keys %$list) {
2508 my $d = $res->{$vmid};
2509 my $pid = $d->{pid
};
2512 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2513 next if !$pstat; # not running
2515 my $used = $pstat->{utime} + $pstat->{stime
};
2517 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2519 if ($pstat->{vsize
}) {
2520 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2523 my $old = $last_proc_pid_stat->{$pid};
2525 $last_proc_pid_stat->{$pid} = {
2533 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2535 if ($dtime > 1000) {
2536 my $dutime = $used - $old->{used
};
2538 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2539 $last_proc_pid_stat->{$pid} = {
2545 $d->{cpu
} = $old->{cpu
};
2549 return $res if !$full;
2551 my $qmpclient = PVE
::QMPClient-
>new();
2553 my $ballooncb = sub {
2554 my ($vmid, $resp) = @_;
2556 my $info = $resp->{'return'};
2557 return if !$info->{max_mem
};
2559 my $d = $res->{$vmid};
2561 # use memory assigned to VM
2562 $d->{maxmem
} = $info->{max_mem
};
2563 $d->{balloon
} = $info->{actual
};
2565 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2566 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2567 $d->{freemem
} = $info->{free_mem
};
2570 $d->{ballooninfo
} = $info;
2573 my $blockstatscb = sub {
2574 my ($vmid, $resp) = @_;
2575 my $data = $resp->{'return'} || [];
2576 my $totalrdbytes = 0;
2577 my $totalwrbytes = 0;
2579 for my $blockstat (@$data) {
2580 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2581 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2583 $blockstat->{device
} =~ s/drive-//;
2584 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2586 $res->{$vmid}->{diskread
} = $totalrdbytes;
2587 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2590 my $statuscb = sub {
2591 my ($vmid, $resp) = @_;
2593 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2594 # this fails if ballon driver is not loaded, so this must be
2595 # the last commnand (following command are aborted if this fails).
2596 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2598 my $status = 'unknown';
2599 if (!defined($status = $resp->{'return'}->{status
})) {
2600 warn "unable to get VM status\n";
2604 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2607 foreach my $vmid (keys %$list) {
2608 next if $opt_vmid && ($vmid ne $opt_vmid);
2609 next if !$res->{$vmid}->{pid
}; # not running
2610 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2613 $qmpclient->queue_execute(undef, 1);
2615 foreach my $vmid (keys %$list) {
2616 next if $opt_vmid && ($vmid ne $opt_vmid);
2617 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2624 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2627 my $current_size = 1024;
2628 my $dimm_size = 512;
2629 return if $current_size == $memory;
2631 for (my $j = 0; $j < 8; $j++) {
2632 for (my $i = 0; $i < 32; $i++) {
2633 my $name = "dimm${dimm_id}";
2635 my $numanode = $i % $sockets;
2636 $current_size += $dimm_size;
2637 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2638 return $current_size if $current_size >= $memory;
2644 sub foreach_reverse_dimm
{
2645 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2648 my $current_size = 4177920;
2649 my $dimm_size = 65536;
2650 return if $current_size == $memory;
2652 for (my $j = 0; $j < 8; $j++) {
2653 for (my $i = 0; $i < 32; $i++) {
2654 my $name = "dimm${dimm_id}";
2656 my $numanode = $i % $sockets;
2657 $current_size -= $dimm_size;
2658 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2659 return $current_size if $current_size <= $memory;
2666 my ($conf, $func) = @_;
2668 foreach my $ds (valid_drive_names
()) {
2669 next if !defined($conf->{$ds});
2671 my $drive = parse_drive
($ds, $conf->{$ds});
2674 &$func($ds, $drive);
2679 my ($conf, $func) = @_;
2683 my $test_volid = sub {
2684 my ($volid, $is_cdrom) = @_;
2688 $volhash->{$volid} = $is_cdrom || 0;
2691 foreach_drive
($conf, sub {
2692 my ($ds, $drive) = @_;
2693 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2696 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2697 my $snap = $conf->{snapshots
}->{$snapname};
2698 &$test_volid($snap->{vmstate
}, 0);
2699 foreach_drive
($snap, sub {
2700 my ($ds, $drive) = @_;
2701 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2705 foreach my $volid (keys %$volhash) {
2706 &$func($volid, $volhash->{$volid});
2710 sub vga_conf_has_spice
{
2713 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2718 sub config_to_command
{
2719 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2722 my $globalFlags = [];
2723 my $machineFlags = [];
2729 my $kvmver = kvm_user_version
();
2730 my $vernum = 0; # unknown
2731 my $ostype = $conf->{ostype
};
2732 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2733 $vernum = $1*1000000+$2*1000;
2734 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2735 $vernum = $1*1000000+$2*1000+$3;
2738 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2740 my $have_ovz = -f
'/proc/vz/vestat';
2742 my $q35 = machine_type_is_q35
($conf);
2743 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2744 my $machine_type = $forcemachine || $conf->{machine
};
2745 my $use_old_bios_files = undef;
2746 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2748 my $cpuunits = defined($conf->{cpuunits
}) ?
2749 $conf->{cpuunits
} : $defaults->{cpuunits
};
2751 push @$cmd, '/usr/bin/systemd-run';
2752 push @$cmd, '--scope';
2753 push @$cmd, '--slice', "qemu";
2754 push @$cmd, '--unit', $vmid;
2755 # set KillMode=none, so that systemd don't kill those scopes
2756 # at shutdown (pve-manager service should stop the VMs instead)
2757 push @$cmd, '-p', "KillMode=none";
2758 push @$cmd, '-p', "CPUShares=$cpuunits";
2759 if ($conf->{cpulimit
}) {
2760 my $cpulimit = int($conf->{cpulimit
} * 100);
2761 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2764 push @$cmd, '/usr/bin/kvm';
2766 push @$cmd, '-id', $vmid;
2770 my $qmpsocket = qmp_socket
($vmid);
2771 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2772 push @$cmd, '-mon', "chardev=qmp,mode=control";
2775 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2777 push @$cmd, '-daemonize';
2779 if ($conf->{smbios1
}) {
2780 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2783 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2784 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2785 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2786 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2787 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2788 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2789 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2793 # the q35 chipset support native usb2, so we enable usb controller
2794 # by default for this machine type
2795 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2797 $pciaddr = print_pci_addr
("piix3", $bridges);
2798 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2801 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2802 next if !$conf->{"usb$i"};
2803 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2804 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2807 # include usb device config
2808 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2811 # add usb3 controller if needed
2814 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2815 next if !$conf->{"usb$i"};
2816 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2817 next if !$d || !$d->{usb3
};
2821 $pciaddr = print_pci_addr
("xhci", $bridges);
2822 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2824 my $vga = $conf->{vga
};
2826 my $qxlnum = vga_conf_has_spice
($vga);
2827 $vga = 'qxl' if $qxlnum;
2830 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2831 $conf->{ostype
} eq 'win7' ||
2832 $conf->{ostype
} eq 'w2k8')) {
2839 # enable absolute mouse coordinates (needed by vnc)
2841 if (defined($conf->{tablet
})) {
2842 $tablet = $conf->{tablet
};
2844 $tablet = $defaults->{tablet
};
2845 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2846 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2849 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2853 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2854 my $d = parse_hostpci
($conf->{"hostpci$i"});
2857 my $pcie = $d->{pcie
};
2859 die "q35 machine model is not enabled" if !$q35;
2860 $pciaddr = print_pcie_addr
("hostpci$i");
2862 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2865 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2866 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2867 if ($xvga && $xvga ne '') {
2870 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2871 push @$cpuFlags , 'hv_vendor_id=proxmox';
2873 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2877 my $pcidevices = $d->{pciid
};
2878 my $multifunction = 1 if @$pcidevices > 1;
2881 foreach my $pcidevice (@$pcidevices) {
2883 my $id = "hostpci$i";
2884 $id .= ".$j" if $multifunction;
2885 my $addr = $pciaddr;
2886 $addr .= ".$j" if $multifunction;
2887 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2890 $devicestr .= "$rombar$xvga";
2891 $devicestr .= ",multifunction=on" if $multifunction;
2894 push @$devices, '-device', $devicestr;
2900 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2901 next if !$conf->{"usb$i"};
2902 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2905 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2907 if (defined($d->{usb3
}) && $d->{usb3
}) {
2908 $usbbus = ',bus=xhci.0';
2911 if (defined($d->{host
})) {
2912 $d = parse_usb_device
($d->{host
});
2913 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2914 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2915 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2916 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2917 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2918 # usb redir support for spice, currently no usb3
2919 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2920 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2926 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2927 if (my $path = $conf->{"serial$i"}) {
2928 if ($path eq 'socket') {
2929 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2930 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2931 push @$devices, '-device', "isa-serial,chardev=serial$i";
2933 die "no such serial device\n" if ! -c
$path;
2934 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2935 push @$devices, '-device', "isa-serial,chardev=serial$i";
2941 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2942 if (my $path = $conf->{"parallel$i"}) {
2943 die "no such parallel device\n" if ! -c
$path;
2944 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2945 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2946 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2950 my $vmname = $conf->{name
} || "vm$vmid";
2952 push @$cmd, '-name', $vmname;
2955 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2956 $sockets = $conf->{sockets
} if $conf->{sockets
};
2958 my $cores = $conf->{cores
} || 1;
2960 my $maxcpus = $sockets * $cores;
2962 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2964 my $allowed_vcpus = $cpuinfo->{cpus
};
2966 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2967 if ($allowed_vcpus < $maxcpus);
2969 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2971 push @$cmd, '-nodefaults';
2973 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2975 my $bootindex_hash = {};
2977 foreach my $o (split(//, $bootorder)) {
2978 $bootindex_hash->{$o} = $i*100;
2982 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2984 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2986 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2988 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2990 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2991 my $socket = vnc_socket
($vmid);
2992 push @$cmd, '-vnc', "unix:$socket,x509,password";
2994 push @$cmd, '-nographic';
2998 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3000 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3001 my $useLocaltime = $conf->{localtime};
3004 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3006 if ($ostype =~ m/^w/) { # windows
3007 $useLocaltime = 1 if !defined($conf->{localtime});
3009 # use time drift fix when acpi is enabled
3010 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3011 $tdf = 1 if !defined($conf->{tdf
});
3015 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3016 $ostype eq 'wvista') {
3017 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3018 push @$cmd, '-no-hpet';
3019 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3020 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3021 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3022 push @$cpuFlags , 'hv_time' if !$nokvm;
3025 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3029 if ($ostype eq 'win7' || $ostype eq 'win8') {
3030 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3034 push @$rtcFlags, 'driftfix=slew' if $tdf;
3037 push @$machineFlags, 'accel=tcg';
3039 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3042 if ($machine_type) {
3043 push @$machineFlags, "type=${machine_type}";
3046 if ($conf->{startdate
}) {
3047 push @$rtcFlags, "base=$conf->{startdate}";
3048 } elsif ($useLocaltime) {
3049 push @$rtcFlags, 'base=localtime';
3052 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3053 if (my $cputype = $conf->{cpu
}) {
3054 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3055 or die "Cannot parse cpu description: $cputype\n";
3056 $cpu = $cpuconf->{cputype
};
3057 $kvm_off = 1 if $cpuconf->{hidden
};
3060 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3062 push @$cpuFlags , '-x2apic'
3063 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3065 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3067 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3069 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3071 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3072 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3075 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3077 push @$cpuFlags, 'kvm=off' if $kvm_off;
3079 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3081 push @$cmd, '-cpu', $cpu;
3083 my $memory = $conf->{memory
} || $defaults->{memory
};
3084 my $static_memory = 0;
3085 my $dimm_memory = 0;
3087 if ($hotplug_features->{memory
}) {
3088 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3089 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3090 $static_memory = $STATICMEM;
3091 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3092 $dimm_memory = $memory - $static_memory;
3093 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3097 $static_memory = $memory;
3098 push @$cmd, '-m', $static_memory;
3101 if ($conf->{numa
}) {
3103 my $numa_totalmemory = undef;
3104 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3105 next if !$conf->{"numa$i"};
3106 my $numa = parse_numa
($conf->{"numa$i"});
3109 die "missing numa node$i memory value\n" if !$numa->{memory
};
3110 my $numa_memory = $numa->{memory
};
3111 $numa_totalmemory += $numa_memory;
3112 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3115 my $cpulists = $numa->{cpus
};
3116 die "missing numa node$i cpus\n" if !defined($cpulists);
3117 my $cpus = join(',', map {
3118 my ($start, $end) = @$_;
3119 defined($end) ?
"$start-$end" : $start
3123 my $hostnodelists = $numa->{hostnodes
};
3124 if (defined($hostnodelists)) {
3126 foreach my $hostnoderange (@$hostnodelists) {
3127 my ($start, $end) = @$hostnoderange;
3128 $hostnodes .= ',' if $hostnodes;
3129 $hostnodes .= $start;
3130 $hostnodes .= "-$end" if defined($end);
3132 for (my $i = $start; $i <= $end; ++$i ) {
3133 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3138 my $policy = $numa->{policy
};
3139 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3140 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3143 push @$cmd, '-object', $numa_object;
3144 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3147 die "total memory for NUMA nodes must be equal to vm static memory\n"
3148 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3150 #if no custom tology, we split memory and cores across numa nodes
3151 if(!$numa_totalmemory) {
3153 my $numa_memory = ($static_memory / $sockets) . "M";
3155 for (my $i = 0; $i < $sockets; $i++) {
3157 my $cpustart = ($cores * $i);
3158 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3159 my $cpus = $cpustart;
3160 $cpus .= "-$cpuend" if $cpuend;
3162 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3163 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3168 if ($hotplug_features->{memory
}) {
3169 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3170 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3171 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3172 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3174 #if dimm_memory is not aligned to dimm map
3175 if($current_size > $memory) {
3176 $conf->{memory
} = $current_size;
3177 PVE
::QemuConfig-
>write_config($vmid, $conf);
3182 push @$cmd, '-S' if $conf->{freeze
};
3184 # set keyboard layout
3185 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3186 push @$cmd, '-k', $kb if $kb;
3189 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3190 #push @$cmd, '-soundhw', 'es1370';
3191 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3193 if($conf->{agent
}) {
3194 my $qgasocket = qmp_socket
($vmid, 1);
3195 my $pciaddr = print_pci_addr
("qga0", $bridges);
3196 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3197 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3198 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3205 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3206 for(my $i = 1; $i < $qxlnum; $i++){
3207 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3208 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3211 # assume other OS works like Linux
3212 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3213 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3217 my $pciaddr = print_pci_addr
("spice", $bridges);
3219 my $nodename = PVE
::INotify
::nodename
();
3220 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3221 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3223 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3225 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3226 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3227 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3230 # enable balloon by default, unless explicitly disabled
3231 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3232 $pciaddr = print_pci_addr
("balloon0", $bridges);
3233 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3236 if ($conf->{watchdog
}) {
3237 my $wdopts = parse_watchdog
($conf->{watchdog
});
3238 $pciaddr = print_pci_addr
("watchdog", $bridges);
3239 my $watchdog = $wdopts->{model
} || 'i6300esb';
3240 push @$devices, '-device', "$watchdog$pciaddr";
3241 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3245 my $scsicontroller = {};
3246 my $ahcicontroller = {};
3247 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3249 # Add iscsi initiator name if available
3250 if (my $initiator = get_initiator_name
()) {
3251 push @$devices, '-iscsi', "initiator-name=$initiator";
3254 foreach_drive
($conf, sub {
3255 my ($ds, $drive) = @_;
3257 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3258 push @$vollist, $drive->{file
};
3261 $use_virtio = 1 if $ds =~ m/^virtio/;
3263 if (drive_is_cdrom
($drive)) {
3264 if ($bootindex_hash->{d
}) {
3265 $drive->{bootindex
} = $bootindex_hash->{d
};
3266 $bootindex_hash->{d
} += 1;
3269 if ($bootindex_hash->{c
}) {
3270 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3271 $bootindex_hash->{c
} += 1;
3275 if($drive->{interface
} eq 'virtio'){
3276 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3279 if ($drive->{interface
} eq 'scsi') {
3281 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3283 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3284 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3287 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3288 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3289 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3293 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3294 $queues = ",num_queues=$drive->{queues}";
3297 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3298 $scsicontroller->{$controller}=1;
3301 if ($drive->{interface
} eq 'sata') {
3302 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3303 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3304 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3305 $ahcicontroller->{$controller}=1;
3308 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3309 push @$devices, '-drive',$drive_cmd;
3310 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3313 for (my $i = 0; $i < $MAX_NETS; $i++) {
3314 next if !$conf->{"net$i"};
3315 my $d = parse_net
($conf->{"net$i"});
3318 $use_virtio = 1 if $d->{model
} eq 'virtio';
3320 if ($bootindex_hash->{n
}) {
3321 $d->{bootindex
} = $bootindex_hash->{n
};
3322 $bootindex_hash->{n
} += 1;
3325 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3326 push @$devices, '-netdev', $netdevfull;
3328 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3329 push @$devices, '-device', $netdevicefull;
3334 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3339 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3341 while (my ($k, $v) = each %$bridges) {
3342 $pciaddr = print_pci_addr
("pci.$k");
3343 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3348 if ($conf->{args
}) {
3349 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3353 push @$cmd, @$devices;
3354 push @$cmd, '-rtc', join(',', @$rtcFlags)
3355 if scalar(@$rtcFlags);
3356 push @$cmd, '-machine', join(',', @$machineFlags)
3357 if scalar(@$machineFlags);
3358 push @$cmd, '-global', join(',', @$globalFlags)
3359 if scalar(@$globalFlags);
3361 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3366 return "${var_run_tmpdir}/$vmid.vnc";
3372 my $res = vm_mon_cmd
($vmid, 'query-spice');
3374 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3378 my ($vmid, $qga) = @_;
3379 my $sockettype = $qga ?
'qga' : 'qmp';
3380 return "${var_run_tmpdir}/$vmid.$sockettype";
3385 return "${var_run_tmpdir}/$vmid.pid";
3388 sub vm_devices_list
{
3391 my $res = vm_mon_cmd
($vmid, 'query-pci');
3393 foreach my $pcibus (@$res) {
3394 foreach my $device (@{$pcibus->{devices
}}) {
3395 next if !$device->{'qdev_id'};
3396 if ($device->{'pci_bridge'}) {
3397 $devices->{$device->{'qdev_id'}} = 1;
3398 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3399 next if !$bridge_device->{'qdev_id'};
3400 $devices->{$bridge_device->{'qdev_id'}} = 1;
3401 $devices->{$device->{'qdev_id'}}++;
3404 $devices->{$device->{'qdev_id'}} = 1;
3409 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3410 foreach my $block (@$resblock) {
3411 if($block->{device
} =~ m/^drive-(\S+)/){
3416 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3417 foreach my $mice (@$resmice) {
3418 if ($mice->{name
} eq 'QEMU HID Tablet') {
3419 $devices->{tablet
} = 1;
3428 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3430 my $q35 = machine_type_is_q35
($conf);
3432 my $devices_list = vm_devices_list
($vmid);
3433 return 1 if defined($devices_list->{$deviceid});
3435 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3437 if ($deviceid eq 'tablet') {
3439 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3441 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3443 qemu_iothread_add
($vmid, $deviceid, $device);
3445 qemu_driveadd
($storecfg, $vmid, $device);
3446 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3448 qemu_deviceadd
($vmid, $devicefull);
3449 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3451 eval { qemu_drivedel
($vmid, $deviceid); };
3456 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3459 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3460 my $pciaddr = print_pci_addr
($deviceid);
3461 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3463 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3465 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3466 qemu_iothread_add
($vmid, $deviceid, $device);
3467 $devicefull .= ",iothread=iothread-$deviceid";
3470 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3471 $devicefull .= ",num_queues=$device->{queues}";
3474 qemu_deviceadd
($vmid, $devicefull);
3475 qemu_deviceaddverify
($vmid, $deviceid);
3477 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3479 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3480 qemu_driveadd
($storecfg, $vmid, $device);
3482 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3483 eval { qemu_deviceadd
($vmid, $devicefull); };
3485 eval { qemu_drivedel
($vmid, $deviceid); };
3490 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3492 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3494 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3495 my $use_old_bios_files = undef;
3496 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3498 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3499 qemu_deviceadd
($vmid, $netdevicefull);
3500 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3502 eval { qemu_netdevdel
($vmid, $deviceid); };
3507 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3510 my $pciaddr = print_pci_addr
($deviceid);
3511 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3513 qemu_deviceadd
($vmid, $devicefull);
3514 qemu_deviceaddverify
($vmid, $deviceid);
3517 die "can't hotplug device '$deviceid'\n";
3523 # fixme: this should raise exceptions on error!
3524 sub vm_deviceunplug
{
3525 my ($vmid, $conf, $deviceid) = @_;
3527 my $devices_list = vm_devices_list
($vmid);
3528 return 1 if !defined($devices_list->{$deviceid});
3530 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3532 if ($deviceid eq 'tablet') {
3534 qemu_devicedel
($vmid, $deviceid);
3536 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3538 qemu_devicedel
($vmid, $deviceid);
3539 qemu_devicedelverify
($vmid, $deviceid);
3540 qemu_drivedel
($vmid, $deviceid);
3541 qemu_iothread_del
($conf, $vmid, $deviceid);
3543 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3545 qemu_devicedel
($vmid, $deviceid);
3546 qemu_devicedelverify
($vmid, $deviceid);
3547 qemu_iothread_del
($conf, $vmid, $deviceid);
3549 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3551 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3552 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3553 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3555 qemu_devicedel
($vmid, $deviceid);
3556 qemu_drivedel
($vmid, $deviceid);
3557 qemu_deletescsihw
($conf, $vmid, $deviceid);
3559 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3561 qemu_devicedel
($vmid, $deviceid);
3562 qemu_devicedelverify
($vmid, $deviceid);
3563 qemu_netdevdel
($vmid, $deviceid);
3566 die "can't unplug device '$deviceid'\n";
3572 sub qemu_deviceadd
{
3573 my ($vmid, $devicefull) = @_;
3575 $devicefull = "driver=".$devicefull;
3576 my %options = split(/[=,]/, $devicefull);
3578 vm_mon_cmd
($vmid, "device_add" , %options);
3581 sub qemu_devicedel
{
3582 my ($vmid, $deviceid) = @_;
3584 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3587 sub qemu_iothread_add
{
3588 my($vmid, $deviceid, $device) = @_;
3590 if ($device->{iothread
}) {
3591 my $iothreads = vm_iothreads_list
($vmid);
3592 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3596 sub qemu_iothread_del
{
3597 my($conf, $vmid, $deviceid) = @_;
3599 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3600 if ($device->{iothread
}) {
3601 my $iothreads = vm_iothreads_list
($vmid);
3602 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3606 sub qemu_objectadd
{
3607 my($vmid, $objectid, $qomtype) = @_;
3609 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3614 sub qemu_objectdel
{
3615 my($vmid, $objectid) = @_;
3617 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3623 my ($storecfg, $vmid, $device) = @_;
3625 my $drive = print_drive_full
($storecfg, $vmid, $device);
3626 $drive =~ s/\\/\\\\/g;
3627 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3629 # If the command succeeds qemu prints: "OK
"
3630 return 1 if $ret =~ m/OK/s;
3632 die "adding drive failed
: $ret\n";
3636 my($vmid, $deviceid) = @_;
3638 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3641 return 1 if $ret eq "";
3643 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3644 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3646 die "deleting drive
$deviceid failed
: $ret\n";
3649 sub qemu_deviceaddverify {
3650 my ($vmid, $deviceid) = @_;
3652 for (my $i = 0; $i <= 5; $i++) {
3653 my $devices_list = vm_devices_list($vmid);
3654 return 1 if defined($devices_list->{$deviceid});
3658 die "error on hotplug device
'$deviceid'\n";
3662 sub qemu_devicedelverify {
3663 my ($vmid, $deviceid) = @_;
3665 # need to verify that the device is correctly removed as device_del
3666 # is async and empty return is not reliable
3668 for (my $i = 0; $i <= 5; $i++) {
3669 my $devices_list = vm_devices_list($vmid);
3670 return 1 if !defined($devices_list->{$deviceid});
3674 die "error on hot-unplugging device
'$deviceid'\n";
3677 sub qemu_findorcreatescsihw {
3678 my ($storecfg, $conf, $vmid, $device) = @_;
3680 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3682 my $scsihwid="$controller_prefix$controller";
3683 my $devices_list = vm_devices_list($vmid);
3685 if(!defined($devices_list->{$scsihwid})) {
3686 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3692 sub qemu_deletescsihw {
3693 my ($conf, $vmid, $opt) = @_;
3695 my $device = parse_drive($opt, $conf->{$opt});
3697 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3698 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3702 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3704 my $devices_list = vm_devices_list($vmid);
3705 foreach my $opt (keys %{$devices_list}) {
3706 if (PVE::QemuServer::is_valid_drivename($opt)) {
3707 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3708 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3714 my $scsihwid="scsihw
$controller";
3716 vm_deviceunplug($vmid, $conf, $scsihwid);
3721 sub qemu_add_pci_bridge {
3722 my ($storecfg, $conf, $vmid, $device) = @_;
3728 print_pci_addr($device, $bridges);
3730 while (my ($k, $v) = each %$bridges) {
3733 return 1 if !defined($bridgeid) || $bridgeid < 1;
3735 my $bridge = "pci
.$bridgeid";
3736 my $devices_list = vm_devices_list($vmid);
3738 if (!defined($devices_list->{$bridge})) {
3739 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3745 sub qemu_set_link_status {
3746 my ($vmid, $device, $up) = @_;
3748 vm_mon_cmd($vmid, "set_link
", name => $device,
3749 up => $up ? JSON::true : JSON::false);
3752 sub qemu_netdevadd {
3753 my ($vmid, $conf, $device, $deviceid) = @_;
3755 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3756 my %options = split(/[=,]/, $netdev);
3758 vm_mon_cmd($vmid, "netdev_add
", %options);
3762 sub qemu_netdevdel {
3763 my ($vmid, $deviceid) = @_;
3765 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3768 sub qemu_cpu_hotplug {
3769 my ($vmid, $conf, $vcpus) = @_;
3772 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3773 $sockets = $conf->{sockets} if $conf->{sockets};
3774 my $cores = $conf->{cores} || 1;
3775 my $maxcpus = $sockets * $cores;
3777 $vcpus = $maxcpus if !$vcpus;
3779 die "you can
't add more vcpus than maxcpus\n"
3780 if $vcpus > $maxcpus;
3782 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3783 die "online cpu unplug is not yet possible\n"
3784 if $vcpus < $currentvcpus;
3786 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3787 die "vcpus in running vm is different than configuration\n"
3788 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3790 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3791 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3795 sub qemu_memory_hotplug {
3796 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3798 return $value if !check_running($vmid);
3800 my $memory = $conf->{memory} || $defaults->{memory};
3801 $value = $defaults->{memory} if !$value;
3802 return $value if $value == $memory;
3804 my $static_memory = $STATICMEM;
3805 my $dimm_memory = $memory - $static_memory;
3807 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3808 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3812 $sockets = $conf->{sockets} if $conf->{sockets};
3814 if($value > $memory) {
3816 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3817 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3819 return if $current_size <= $conf->{memory};
3821 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3823 eval { qemu_objectdel($vmid, "mem-
$name"); };
3827 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3829 eval { qemu_objectdel($vmid, "mem-
$name"); };
3832 #update conf after each succesful module hotplug
3833 $conf->{memory} = $current_size;
3834 PVE::QemuConfig->write_config($vmid, $conf);
3839 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3840 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3842 return if $current_size >= $conf->{memory};
3843 print "try to unplug memory dimm
$name\n";
3847 eval { qemu_devicedel($vmid, $name) };
3849 my $dimm_list = qemu_dimm_list($vmid);
3850 last if !$dimm_list->{$name};
3851 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3855 #update conf after each succesful module unplug
3856 $conf->{memory} = $current_size;
3858 eval { qemu_objectdel($vmid, "mem-
$name"); };
3859 PVE::QemuConfig->write_config($vmid, $conf);
3864 sub qemu_dimm_list {
3867 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3870 foreach my $dimm (@$dimmarray) {
3872 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3873 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3874 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3875 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3876 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3881 sub qemu_block_set_io_throttle {
3882 my ($vmid, $deviceid,
3883 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3884 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3886 return if !check_running($vmid) ;
3888 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3890 bps_rd => int($bps_rd),
3891 bps_wr => int($bps_wr),
3893 iops_rd => int($iops_rd),
3894 iops_wr => int($iops_wr),
3895 bps_max => int($bps_max),
3896 bps_rd_max => int($bps_rd_max),
3897 bps_wr_max => int($bps_wr_max),
3898 iops_max => int($iops_max),
3899 iops_rd_max => int($iops_rd_max),
3900 iops_wr_max => int($iops_wr_max)
3905 # old code, only used to shutdown old VM after update
3907 my ($fh, $timeout) = @_;
3909 my $sel = new IO::Select;
3916 while (scalar (@ready = $sel->can_read($timeout))) {
3918 if ($count = $fh->sysread($buf, 8192)) {
3919 if ($buf =~ /^(.*)\(qemu\) $/s) {
3926 if (!defined($count)) {
3933 die "monitor
read timeout
\n" if !scalar(@ready);
3938 # old code, only used to shutdown old VM after update
3939 sub vm_monitor_command {
3940 my ($vmid, $cmdstr, $nocheck) = @_;
3945 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3947 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3949 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3950 die "unable to
connect to VM
$vmid socket - $!\n";
3954 # hack: migrate sometime blocks the monitor (when migrate_downtime
3956 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3957 $timeout = 60*60; # 1 hour
3961 my $data = __read_avail($sock, $timeout);
3963 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3964 die "got unexpected qemu monitor banner
\n";
3967 my $sel = new IO::Select;
3970 if (!scalar(my @ready = $sel->can_write($timeout))) {
3971 die "monitor
write error
- timeout
";
3974 my $fullcmd = "$cmdstr\r";
3976 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3979 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3980 die "monitor
write error
- $!";
3983 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3987 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3988 $timeout = 60*60; # 1 hour
3989 } elsif ($cmdstr =~ m/^(eject|change)/) {
3990 $timeout = 60; # note: cdrom mount command is slow
3992 if ($res = __read_avail($sock, $timeout)) {
3994 my @lines = split("\r?
\n", $res);
3996 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3998 $res = join("\n", @lines);
4006 syslog("err
", "VM
$vmid monitor command failed
- $err");
4013 sub qemu_block_resize {
4014 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4016 my $running = check_running($vmid);
4018 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4020 return if !$running;
4022 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4026 sub qemu_volume_snapshot {
4027 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4029 my $running = check_running($vmid);
4031 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4032 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4034 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4038 sub qemu_volume_snapshot_delete {
4039 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4041 my $running = check_running($vmid);
4043 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4045 return if !$running;
4047 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4050 sub set_migration_caps {
4056 "auto-converge
" => 1,
4058 "x-rdma-pin-all
" => 0,
4063 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4065 for my $supported_capability (@$supported_capabilities) {
4067 capability => $supported_capability->{capability},
4068 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4072 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4075 my $fast_plug_option = {
4084 # hotplug changes in [PENDING]
4085 # $selection hash can be used to only apply specified options, for
4086 # example: { cores => 1 } (only apply changed 'cores')
4087 # $errors ref is used to return error messages
4088 sub vmconfig_hotplug_pending {
4089 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4091 my $defaults = load_defaults();
4093 # commit values which do not have any impact on running VM first
4094 # Note: those option cannot raise errors, we we do not care about
4095 # $selection and always apply them.
4097 my $add_error = sub {
4098 my ($opt, $msg) = @_;
4099 $errors->{$opt} = "hotplug problem
- $msg";
4103 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4104 if ($fast_plug_option->{$opt}) {
4105 $conf->{$opt} = $conf->{pending}->{$opt};
4106 delete $conf->{pending}->{$opt};
4112 PVE::QemuConfig->write_config($vmid, $conf);
4113 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4116 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4118 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4119 while (my ($opt, $force) = each %$pending_delete_hash) {
4120 next if $selection && !$selection->{$opt};
4122 if ($opt eq 'hotplug') {
4123 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4124 } elsif ($opt eq 'tablet') {
4125 die "skip
\n" if !$hotplug_features->{usb};
4126 if ($defaults->{tablet}) {
4127 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4129 vm_deviceunplug($vmid, $conf, $opt);
4131 } elsif ($opt eq 'vcpus') {
4132 die "skip
\n" if !$hotplug_features->{cpu};
4133 qemu_cpu_hotplug($vmid, $conf, undef);
4134 } elsif ($opt eq 'balloon') {
4135 # enable balloon device is not hotpluggable
4136 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4137 } elsif ($fast_plug_option->{$opt}) {
4139 } elsif ($opt =~ m/^net(\d+)$/) {
4140 die "skip
\n" if !$hotplug_features->{network};
4141 vm_deviceunplug($vmid, $conf, $opt);
4142 } elsif (is_valid_drivename($opt)) {
4143 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4144 vm_deviceunplug($vmid, $conf, $opt);
4145 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4146 } elsif ($opt =~ m/^memory$/) {
4147 die "skip
\n" if !$hotplug_features->{memory};
4148 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4149 } elsif ($opt eq 'cpuunits') {
4150 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4151 } elsif ($opt eq 'cpulimit') {
4152 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4158 &$add_error($opt, $err) if $err ne "skip
\n";
4160 # save new config if hotplug was successful
4161 delete $conf->{$opt};
4162 vmconfig_undelete_pending_option($conf, $opt);
4163 PVE::QemuConfig->write_config($vmid, $conf);
4164 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4168 foreach my $opt (keys %{$conf->{pending}}) {
4169 next if $selection && !$selection->{$opt};
4170 my $value = $conf->{pending}->{$opt};
4172 if ($opt eq 'hotplug') {
4173 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4174 } elsif ($opt eq 'tablet') {
4175 die "skip
\n" if !$hotplug_features->{usb};
4177 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4178 } elsif ($value == 0) {
4179 vm_deviceunplug($vmid, $conf, $opt);
4181 } elsif ($opt eq 'vcpus') {
4182 die "skip
\n" if !$hotplug_features->{cpu};
4183 qemu_cpu_hotplug($vmid, $conf, $value);
4184 } elsif ($opt eq 'balloon') {
4185 # enable/disable balloning device is not hotpluggable
4186 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4187 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4188 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4190 # allow manual ballooning if shares is set to zero
4191 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4192 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4193 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4195 } elsif ($opt =~ m/^net(\d+)$/) {
4196 # some changes can be done without hotplug
4197 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4198 $vmid, $opt, $value);
4199 } elsif (is_valid_drivename($opt)) {
4200 # some changes can be done without hotplug
4201 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4202 $vmid, $opt, $value, 1);
4203 } elsif ($opt =~ m/^memory$/) { #dimms
4204 die "skip
\n" if !$hotplug_features->{memory};
4205 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4206 } elsif ($opt eq 'cpuunits') {
4207 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4208 } elsif ($opt eq 'cpulimit') {
4209 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4210 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4212 die "skip
\n"; # skip non-hot-pluggable options
4216 &$add_error($opt, $err) if $err ne "skip
\n";
4218 # save new config if hotplug was successful
4219 $conf->{$opt} = $value;
4220 delete $conf->{pending}->{$opt};
4221 PVE::QemuConfig->write_config($vmid, $conf);
4222 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4227 sub try_deallocate_drive {
4228 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4230 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4231 my $volid = $drive->{file};
4232 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4233 my $sid = PVE::Storage::parse_volume_id($volid);
4234 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4236 # check if the disk is really unused
4237 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4238 if is_volume_in_use($storecfg, $conf, $key, $volid);
4239 PVE::Storage::vdisk_free($storecfg, $volid);
4242 # If vm is not owner of this disk remove from config
4250 sub vmconfig_delete_or_detach_drive {
4251 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4253 my $drive = parse_drive($opt, $conf->{$opt});
4255 my $rpcenv = PVE::RPCEnvironment::get();
4256 my $authuser = $rpcenv->get_user();
4259 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4260 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4262 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4266 sub vmconfig_apply_pending {
4267 my ($vmid, $conf, $storecfg) = @_;
4271 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4272 while (my ($opt, $force) = each %$pending_delete_hash) {
4273 die "internal error
" if $opt =~ m/^unused/;
4274 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4275 if (!defined($conf->{$opt})) {
4276 vmconfig_undelete_pending_option($conf, $opt);
4277 PVE::QemuConfig->write_config($vmid, $conf);
4278 } elsif (is_valid_drivename($opt)) {
4279 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4280 vmconfig_undelete_pending_option($conf, $opt);
4281 delete $conf->{$opt};
4282 PVE::QemuConfig->write_config($vmid, $conf);
4284 vmconfig_undelete_pending_option($conf, $opt);
4285 delete $conf->{$opt};
4286 PVE::QemuConfig->write_config($vmid, $conf);
4290 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4292 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4293 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4295 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4296 # skip if nothing changed
4297 } elsif (is_valid_drivename($opt)) {
4298 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4299 if defined($conf->{$opt});
4300 $conf->{$opt} = $conf->{pending}->{$opt};
4302 $conf->{$opt} = $conf->{pending}->{$opt};
4305 delete $conf->{pending}->{$opt};
4306 PVE::QemuConfig->write_config($vmid, $conf);
4310 my $safe_num_ne = sub {
4313 return 0 if !defined($a) && !defined($b);
4314 return 1 if !defined($a);
4315 return 1 if !defined($b);
4320 my $safe_string_ne = sub {
4323 return 0 if !defined($a) && !defined($b);
4324 return 1 if !defined($a);
4325 return 1 if !defined($b);
4330 sub vmconfig_update_net {
4331 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4333 my $newnet = parse_net($value);
4335 if ($conf->{$opt}) {
4336 my $oldnet = parse_net($conf->{$opt});
4338 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4339 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4340 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4341 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4343 # for non online change, we try to hot-unplug
4344 die "skip
\n" if !$hotplug;
4345 vm_deviceunplug($vmid, $conf, $opt);
4348 die "internal error
" if $opt !~ m/net(\d+)/;
4349 my $iface = "tap
${vmid
}i
$1";
4351 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4352 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4353 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4354 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4355 PVE::Network::tap_unplug($iface);
4356 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4357 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4358 # Rate can be applied on its own but any change above needs to
4359 # include the rate in tap_plug since OVS resets everything.
4360 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4363 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4364 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4372 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4378 sub vmconfig_update_disk {
4379 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4381 # fixme: do we need force?
4383 my $drive = parse_drive($opt, $value);
4385 if ($conf->{$opt}) {
4387 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4389 my $media = $drive->{media} || 'disk';
4390 my $oldmedia = $old_drive->{media} || 'disk';
4391 die "unable to change media type
\n" if $media ne $oldmedia;
4393 if (!drive_is_cdrom($old_drive)) {
4395 if ($drive->{file} ne $old_drive->{file}) {
4397 die "skip
\n" if !$hotplug;
4399 # unplug and register as unused
4400 vm_deviceunplug($vmid, $conf, $opt);
4401 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4404 # update existing disk
4406 # skip non hotpluggable value
4407 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4408 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4409 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4410 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4415 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4416 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4417 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4418 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4419 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4420 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4421 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4422 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4423 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4424 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4425 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4426 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4428 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4429 ($drive->{mbps} || 0)*1024*1024,
4430 ($drive->{mbps_rd} || 0)*1024*1024,
4431 ($drive->{mbps_wr} || 0)*1024*1024,
4432 $drive->{iops} || 0,
4433 $drive->{iops_rd} || 0,
4434 $drive->{iops_wr} || 0,
4435 ($drive->{mbps_max} || 0)*1024*1024,
4436 ($drive->{mbps_rd_max} || 0)*1024*1024,
4437 ($drive->{mbps_wr_max} || 0)*1024*1024,
4438 $drive->{iops_max} || 0,
4439 $drive->{iops_rd_max} || 0,
4440 $drive->{iops_wr_max} || 0);
4449 if ($drive->{file} eq 'none') {
4450 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4452 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4453 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4454 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4462 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4464 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4465 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4469 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4470 $forcemachine, $spice_ticket) = @_;
4472 PVE::QemuConfig->lock_config($vmid, sub {
4473 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4475 die "you can
't start a vm if it's a template
\n" if PVE::QemuConfig->is_template($conf);
4477 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4479 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4481 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4482 vmconfig_apply_pending($vmid, $conf, $storecfg);
4483 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4486 my $defaults = load_defaults();
4488 # set environment variable useful inside network script
4489 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4491 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4493 my $migrate_port = 0;
4496 if ($statefile eq 'tcp') {
4497 my $localip = "localhost
";
4498 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4499 my $nodename = PVE::INotify::nodename();
4500 if ($datacenterconf->{migration_unsecure}) {
4501 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4502 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4504 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4505 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4506 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4507 push @$cmd, '-incoming', $migrate_uri;
4510 push @$cmd, '-loadstate', $statefile;
4517 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4518 my $d = parse_hostpci($conf->{"hostpci
$i"});
4520 my $pcidevices = $d->{pciid};
4521 foreach my $pcidevice (@$pcidevices) {
4522 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4524 my $info = pci_device_info("0000:$pciid");
4525 die "IOMMU
not present
\n" if !check_iommu_support();
4526 die "no pci device info
for device
'$pciid'\n" if !$info;
4527 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4528 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4532 PVE::Storage::activate_volumes($storecfg, $vollist);
4534 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4538 # deactivate volumes if start fails
4539 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4540 die "start failed
: $err";
4543 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4545 if ($statefile && $statefile ne 'tcp') {
4546 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4550 if ($migratedfrom) {
4553 set_migration_caps($vmid);
4558 print "spice listens on port
$spice_port\n";
4559 if ($spice_ticket) {
4560 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4561 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4567 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4568 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4569 if $conf->{balloon};
4572 foreach my $opt (keys %$conf) {
4573 next if $opt !~ m/^net\d+$/;
4574 my $nicconf = parse_net($conf->{$opt});
4575 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4579 vm_mon_cmd_nocheck($vmid, 'qom-set',
4580 path => "machine
/peripheral/balloon0
",
4581 property => "guest-stats-polling-interval
",
4582 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4588 my ($vmid, $execute, %params) = @_;
4590 my $cmd = { execute => $execute, arguments => \%params };
4591 vm_qmp_command($vmid, $cmd);
4594 sub vm_mon_cmd_nocheck {
4595 my ($vmid, $execute, %params) = @_;
4597 my $cmd = { execute => $execute, arguments => \%params };
4598 vm_qmp_command($vmid, $cmd, 1);
4601 sub vm_qmp_command {
4602 my ($vmid, $cmd, $nocheck) = @_;
4607 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4608 $timeout = $cmd->{arguments}->{timeout};
4609 delete $cmd->{arguments}->{timeout};
4613 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4614 my $sname = qmp_socket($vmid);
4615 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4616 my $qmpclient = PVE::QMPClient->new();
4618 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4619 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4620 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4621 if scalar(%{$cmd->{arguments}});
4622 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4624 die "unable to open monitor socket\n";
4628 syslog("err", "VM $vmid qmp command failed - $err");
4635 sub vm_human_monitor_command {
4636 my ($vmid, $cmdline) = @_;
4641 execute => 'human-monitor-command
',
4642 arguments => { 'command-line
' => $cmdline},
4645 return vm_qmp_command($vmid, $cmd);
4648 sub vm_commandline {
4649 my ($storecfg, $vmid) = @_;
4651 my $conf = PVE::QemuConfig->load_config($vmid);
4653 my $defaults = load_defaults();
4655 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4657 return join(' ', @$cmd);
4661 my ($vmid, $skiplock) = @_;
4663 PVE::QemuConfig->lock_config($vmid, sub {
4665 my $conf = PVE::QemuConfig->load_config($vmid);
4667 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4669 vm_mon_cmd($vmid, "system_reset");
4673 sub get_vm_volumes {
4677 foreach_volid($conf, sub {
4678 my ($volid, $is_cdrom) = @_;
4680 return if $volid =~ m|^/|;
4682 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4685 push @$vollist, $volid;
4691 sub vm_stop_cleanup {
4692 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4697 my $vollist = get_vm_volumes($conf);
4698 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4701 foreach my $ext (qw(mon qmp pid vnc qga)) {
4702 unlink "/var/run/qemu-server/${vmid}.$ext";
4705 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4707 warn $@ if $@; # avoid errors - just warn
4710 # Note: use $nockeck to skip tests if VM configuration file exists.
4711 # We need that when migration VMs to other nodes (files already moved)
4712 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4714 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4716 $force = 1 if !defined($force) && !$shutdown;
4719 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4720 kill 15, $pid if $pid;
4721 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4722 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4726 PVE
::QemuConfig-
>lock_config($vmid, sub {
4728 my $pid = check_running
($vmid, $nocheck);
4733 $conf = PVE
::QemuConfig-
>load_config($vmid);
4734 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4735 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4736 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4737 $timeout = $opts->{down
} if $opts->{down
};
4741 $timeout = 60 if !defined($timeout);
4745 if (defined($conf) && $conf->{agent
}) {
4746 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4748 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4751 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4758 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4763 if ($count >= $timeout) {
4765 warn "VM still running - terminating now with SIGTERM\n";
4768 die "VM quit/powerdown failed - got timeout\n";
4771 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4776 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4779 die "VM quit/powerdown failed\n";
4787 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4792 if ($count >= $timeout) {
4793 warn "VM still running - terminating now with SIGKILL\n";
4798 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4803 my ($vmid, $skiplock) = @_;
4805 PVE
::QemuConfig-
>lock_config($vmid, sub {
4807 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4809 PVE
::QemuConfig-
>check_lock($conf)
4810 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4812 vm_mon_cmd
($vmid, "stop");
4817 my ($vmid, $skiplock, $nocheck) = @_;
4819 PVE
::QemuConfig-
>lock_config($vmid, sub {
4823 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4825 PVE
::QemuConfig-
>check_lock($conf)
4826 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4828 vm_mon_cmd
($vmid, "cont");
4831 vm_mon_cmd_nocheck
($vmid, "cont");
4837 my ($vmid, $skiplock, $key) = @_;
4839 PVE
::QemuConfig-
>lock_config($vmid, sub {
4841 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4843 # there is no qmp command, so we use the human monitor command
4844 vm_human_monitor_command
($vmid, "sendkey $key");
4849 my ($storecfg, $vmid, $skiplock) = @_;
4851 PVE
::QemuConfig-
>lock_config($vmid, sub {
4853 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4855 if (!check_running
($vmid)) {
4856 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4858 die "VM $vmid is running - destroy failed\n";
4866 my ($filename, $buf) = @_;
4868 my $fh = IO
::File-
>new($filename, "w");
4869 return undef if !$fh;
4871 my $res = print $fh $buf;
4878 sub pci_device_info
{
4883 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4884 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4886 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4887 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4889 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4890 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4892 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4893 return undef if !defined($product) || $product !~ s/^0x//;
4898 product
=> $product,
4904 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4913 my $name = $dev->{name
};
4915 my $fn = "$pcisysfs/devices/$name/reset";
4917 return file_write
($fn, "1");
4920 sub pci_dev_bind_to_vfio
{
4923 my $name = $dev->{name
};
4925 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4927 if (!-d
$vfio_basedir) {
4928 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4930 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4932 my $testdir = "$vfio_basedir/$name";
4933 return 1 if -d
$testdir;
4935 my $data = "$dev->{vendor} $dev->{product}";
4936 return undef if !file_write
("$vfio_basedir/new_id", $data);
4938 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4939 if (!file_write
($fn, $name)) {
4940 return undef if -f
$fn;
4943 $fn = "$vfio_basedir/bind";
4944 if (! -d
$testdir) {
4945 return undef if !file_write
($fn, $name);
4951 sub pci_dev_group_bind_to_vfio
{
4954 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4956 if (!-d
$vfio_basedir) {
4957 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4959 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4961 # get IOMMU group devices
4962 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4963 my @devs = grep /^0000:/, readdir($D);
4966 foreach my $pciid (@devs) {
4967 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4969 # pci bridges, switches or root ports are not supported
4970 # they have a pci_bus subdirectory so skip them
4971 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4973 my $info = pci_device_info
($1);
4974 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4980 sub print_pci_addr
{
4981 my ($id, $bridges) = @_;
4985 piix3
=> { bus
=> 0, addr
=> 1 },
4986 #addr2 : first videocard
4987 balloon0
=> { bus
=> 0, addr
=> 3 },
4988 watchdog
=> { bus
=> 0, addr
=> 4 },
4989 scsihw0
=> { bus
=> 0, addr
=> 5 },
4990 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4991 scsihw1
=> { bus
=> 0, addr
=> 6 },
4992 ahci0
=> { bus
=> 0, addr
=> 7 },
4993 qga0
=> { bus
=> 0, addr
=> 8 },
4994 spice
=> { bus
=> 0, addr
=> 9 },
4995 virtio0
=> { bus
=> 0, addr
=> 10 },
4996 virtio1
=> { bus
=> 0, addr
=> 11 },
4997 virtio2
=> { bus
=> 0, addr
=> 12 },
4998 virtio3
=> { bus
=> 0, addr
=> 13 },
4999 virtio4
=> { bus
=> 0, addr
=> 14 },
5000 virtio5
=> { bus
=> 0, addr
=> 15 },
5001 hostpci0
=> { bus
=> 0, addr
=> 16 },
5002 hostpci1
=> { bus
=> 0, addr
=> 17 },
5003 net0
=> { bus
=> 0, addr
=> 18 },
5004 net1
=> { bus
=> 0, addr
=> 19 },
5005 net2
=> { bus
=> 0, addr
=> 20 },
5006 net3
=> { bus
=> 0, addr
=> 21 },
5007 net4
=> { bus
=> 0, addr
=> 22 },
5008 net5
=> { bus
=> 0, addr
=> 23 },
5009 vga1
=> { bus
=> 0, addr
=> 24 },
5010 vga2
=> { bus
=> 0, addr
=> 25 },
5011 vga3
=> { bus
=> 0, addr
=> 26 },
5012 hostpci2
=> { bus
=> 0, addr
=> 27 },
5013 hostpci3
=> { bus
=> 0, addr
=> 28 },
5014 #addr29 : usb-host (pve-usb.cfg)
5015 'pci.1' => { bus
=> 0, addr
=> 30 },
5016 'pci.2' => { bus
=> 0, addr
=> 31 },
5017 'net6' => { bus
=> 1, addr
=> 1 },
5018 'net7' => { bus
=> 1, addr
=> 2 },
5019 'net8' => { bus
=> 1, addr
=> 3 },
5020 'net9' => { bus
=> 1, addr
=> 4 },
5021 'net10' => { bus
=> 1, addr
=> 5 },
5022 'net11' => { bus
=> 1, addr
=> 6 },
5023 'net12' => { bus
=> 1, addr
=> 7 },
5024 'net13' => { bus
=> 1, addr
=> 8 },
5025 'net14' => { bus
=> 1, addr
=> 9 },
5026 'net15' => { bus
=> 1, addr
=> 10 },
5027 'net16' => { bus
=> 1, addr
=> 11 },
5028 'net17' => { bus
=> 1, addr
=> 12 },
5029 'net18' => { bus
=> 1, addr
=> 13 },
5030 'net19' => { bus
=> 1, addr
=> 14 },
5031 'net20' => { bus
=> 1, addr
=> 15 },
5032 'net21' => { bus
=> 1, addr
=> 16 },
5033 'net22' => { bus
=> 1, addr
=> 17 },
5034 'net23' => { bus
=> 1, addr
=> 18 },
5035 'net24' => { bus
=> 1, addr
=> 19 },
5036 'net25' => { bus
=> 1, addr
=> 20 },
5037 'net26' => { bus
=> 1, addr
=> 21 },
5038 'net27' => { bus
=> 1, addr
=> 22 },
5039 'net28' => { bus
=> 1, addr
=> 23 },
5040 'net29' => { bus
=> 1, addr
=> 24 },
5041 'net30' => { bus
=> 1, addr
=> 25 },
5042 'net31' => { bus
=> 1, addr
=> 26 },
5043 'xhci' => { bus
=> 1, addr
=> 27 },
5044 'virtio6' => { bus
=> 2, addr
=> 1 },
5045 'virtio7' => { bus
=> 2, addr
=> 2 },
5046 'virtio8' => { bus
=> 2, addr
=> 3 },
5047 'virtio9' => { bus
=> 2, addr
=> 4 },
5048 'virtio10' => { bus
=> 2, addr
=> 5 },
5049 'virtio11' => { bus
=> 2, addr
=> 6 },
5050 'virtio12' => { bus
=> 2, addr
=> 7 },
5051 'virtio13' => { bus
=> 2, addr
=> 8 },
5052 'virtio14' => { bus
=> 2, addr
=> 9 },
5053 'virtio15' => { bus
=> 2, addr
=> 10 },
5054 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5055 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5056 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5057 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5058 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5059 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5060 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5061 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5062 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5063 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5064 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5065 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5066 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5067 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5068 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5069 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5070 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5071 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5072 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5073 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5074 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5075 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5076 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5077 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5078 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5079 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5080 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5081 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5082 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5083 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5084 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5088 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5089 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5090 my $bus = $devices->{$id}->{bus
};
5091 $res = ",bus=pci.$bus,addr=$addr";
5092 $bridges->{$bus} = 1 if $bridges;
5098 sub print_pcie_addr
{
5103 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5104 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5105 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5106 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5109 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5110 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5111 my $bus = $devices->{$id}->{bus
};
5112 $res = ",bus=$bus,addr=$addr";
5118 # vzdump restore implementaion
5120 sub tar_archive_read_firstfile
{
5121 my $archive = shift;
5123 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5125 # try to detect archive type first
5126 my $pid = open (TMP
, "tar tf '$archive'|") ||
5127 die "unable to open file '$archive'\n";
5128 my $firstfile = <TMP
>;
5132 die "ERROR: archive contaions no data\n" if !$firstfile;
5138 sub tar_restore_cleanup
{
5139 my ($storecfg, $statfile) = @_;
5141 print STDERR
"starting cleanup\n";
5143 if (my $fd = IO
::File-
>new($statfile, "r")) {
5144 while (defined(my $line = <$fd>)) {
5145 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5148 if ($volid =~ m
|^/|) {
5149 unlink $volid || die 'unlink failed\n';
5151 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5153 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5155 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5157 print STDERR
"unable to parse line in statfile - $line";
5164 sub restore_archive
{
5165 my ($archive, $vmid, $user, $opts) = @_;
5167 my $format = $opts->{format
};
5170 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5171 $format = 'tar' if !$format;
5173 } elsif ($archive =~ m/\.tar$/) {
5174 $format = 'tar' if !$format;
5175 } elsif ($archive =~ m/.tar.lzo$/) {
5176 $format = 'tar' if !$format;
5178 } elsif ($archive =~ m/\.vma$/) {
5179 $format = 'vma' if !$format;
5180 } elsif ($archive =~ m/\.vma\.gz$/) {
5181 $format = 'vma' if !$format;
5183 } elsif ($archive =~ m/\.vma\.lzo$/) {
5184 $format = 'vma' if !$format;
5187 $format = 'vma' if !$format; # default
5190 # try to detect archive format
5191 if ($format eq 'tar') {
5192 return restore_tar_archive
($archive, $vmid, $user, $opts);
5194 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5198 sub restore_update_config_line
{
5199 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5201 return if $line =~ m/^\#qmdump\#/;
5202 return if $line =~ m/^\#vzdump\#/;
5203 return if $line =~ m/^lock:/;
5204 return if $line =~ m/^unused\d+:/;
5205 return if $line =~ m/^parent:/;
5206 return if $line =~ m/^template:/; # restored VM is never a template
5208 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5209 # try to convert old 1.X settings
5210 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5211 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5212 my ($model, $macaddr) = split(/\=/, $devconfig);
5213 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5216 bridge
=> "vmbr$ind",
5217 macaddr
=> $macaddr,
5219 my $netstr = print_net
($net);
5221 print $outfd "net$cookie->{netcount}: $netstr\n";
5222 $cookie->{netcount
}++;
5224 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5225 my ($id, $netstr) = ($1, $2);
5226 my $net = parse_net
($netstr);
5227 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5228 $netstr = print_net
($net);
5229 print $outfd "$id: $netstr\n";
5230 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5233 my $di = parse_drive
($virtdev, $value);
5234 if (defined($di->{backup
}) && !$di->{backup
}) {
5235 print $outfd "#$line";
5236 } elsif ($map->{$virtdev}) {
5237 delete $di->{format
}; # format can change on restore
5238 $di->{file
} = $map->{$virtdev};
5239 $value = print_drive
($vmid, $di);
5240 print $outfd "$virtdev: $value\n";
5250 my ($cfg, $vmid) = @_;
5252 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5254 my $volid_hash = {};
5255 foreach my $storeid (keys %$info) {
5256 foreach my $item (@{$info->{$storeid}}) {
5257 next if !($item->{volid
} && $item->{size
});
5258 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5259 $volid_hash->{$item->{volid
}} = $item;
5266 sub is_volume_in_use
{
5267 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5269 my $path = PVE
::Storage
::path
($storecfg, $volid);
5271 my $scan_config = sub {
5272 my ($cref, $snapname) = @_;
5274 foreach my $key (keys %$cref) {
5275 my $value = $cref->{$key};
5276 if (is_valid_drivename
($key)) {
5277 next if $skip_drive && $key eq $skip_drive;
5278 my $drive = parse_drive
($key, $value);
5279 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5280 return 1 if $volid eq $drive->{file
};
5281 if ($drive->{file
} =~ m!^/!) {
5282 return 1 if $drive->{file
} eq $path;
5284 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5286 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5288 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5296 return 1 if &$scan_config($conf);
5300 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5301 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5307 sub update_disksize
{
5308 my ($vmid, $conf, $volid_hash) = @_;
5314 # Note: it is allowed to define multiple storages with same path (alias), so
5315 # we need to check both 'volid' and real 'path' (two different volid can point
5316 # to the same path).
5321 foreach my $opt (keys %$conf) {
5322 if (is_valid_drivename
($opt)) {
5323 my $drive = parse_drive
($opt, $conf->{$opt});
5324 my $volid = $drive->{file
};
5327 $used->{$volid} = 1;
5328 if ($volid_hash->{$volid} &&
5329 (my $path = $volid_hash->{$volid}->{path
})) {
5330 $usedpath->{$path} = 1;
5333 next if drive_is_cdrom
($drive);
5334 next if !$volid_hash->{$volid};
5336 $drive->{size
} = $volid_hash->{$volid}->{size
};
5337 my $new = print_drive
($vmid, $drive);
5338 if ($new ne $conf->{$opt}) {
5340 $conf->{$opt} = $new;
5345 # remove 'unusedX' entry if volume is used
5346 foreach my $opt (keys %$conf) {
5347 next if $opt !~ m/^unused\d+$/;
5348 my $volid = $conf->{$opt};
5349 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5350 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5352 delete $conf->{$opt};
5356 foreach my $volid (sort keys %$volid_hash) {
5357 next if $volid =~ m/vm-$vmid-state-/;
5358 next if $used->{$volid};
5359 my $path = $volid_hash->{$volid}->{path
};
5360 next if !$path; # just to be sure
5361 next if $usedpath->{$path};
5363 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5364 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5371 my ($vmid, $nolock) = @_;
5373 my $cfg = PVE
::Storage
::config
();
5375 my $volid_hash = scan_volids
($cfg, $vmid);
5377 my $updatefn = sub {
5380 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5382 PVE
::QemuConfig-
>check_lock($conf);
5385 foreach my $volid (keys %$volid_hash) {
5386 my $info = $volid_hash->{$volid};
5387 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5390 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5392 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5395 if (defined($vmid)) {
5399 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5402 my $vmlist = config_list
();
5403 foreach my $vmid (keys %$vmlist) {
5407 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5413 sub restore_vma_archive
{
5414 my ($archive, $vmid, $user, $opts, $comp) = @_;
5416 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5417 my $readfrom = $archive;
5422 my $qarchive = PVE
::Tools
::shellquote
($archive);
5423 if ($comp eq 'gzip') {
5424 $uncomp = "zcat $qarchive|";
5425 } elsif ($comp eq 'lzop') {
5426 $uncomp = "lzop -d -c $qarchive|";
5428 die "unknown compression method '$comp'\n";
5433 my $tmpdir = "/var/tmp/vzdumptmp$$";
5436 # disable interrupts (always do cleanups)
5437 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5438 warn "got interrupt - ignored\n";
5441 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5442 POSIX
::mkfifo
($mapfifo, 0600);
5445 my $openfifo = sub {
5446 open($fifofh, '>', $mapfifo) || die $!;
5449 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5456 my $rpcenv = PVE
::RPCEnvironment
::get
();
5458 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5459 my $tmpfn = "$conffile.$$.tmp";
5461 # Note: $oldconf is undef if VM does not exists
5462 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5463 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5465 my $print_devmap = sub {
5466 my $virtdev_hash = {};
5468 my $cfgfn = "$tmpdir/qemu-server.conf";
5470 # we can read the config - that is already extracted
5471 my $fh = IO
::File-
>new($cfgfn, "r") ||
5472 "unable to read qemu-server.conf - $!\n";
5474 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5476 my $pve_firewall_dir = '/etc/pve/firewall';
5477 mkdir $pve_firewall_dir; # make sure the dir exists
5478 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5481 while (defined(my $line = <$fh>)) {
5482 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5483 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5484 die "archive does not contain data for drive '$virtdev'\n"
5485 if !$devinfo->{$devname};
5486 if (defined($opts->{storage
})) {
5487 $storeid = $opts->{storage
} || 'local';
5488 } elsif (!$storeid) {
5491 $format = 'raw' if !$format;
5492 $devinfo->{$devname}->{devname
} = $devname;
5493 $devinfo->{$devname}->{virtdev
} = $virtdev;
5494 $devinfo->{$devname}->{format
} = $format;
5495 $devinfo->{$devname}->{storeid
} = $storeid;
5497 # check permission on storage
5498 my $pool = $opts->{pool
}; # todo: do we need that?
5499 if ($user ne 'root@pam') {
5500 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5503 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5507 foreach my $devname (keys %$devinfo) {
5508 die "found no device mapping information for device '$devname'\n"
5509 if !$devinfo->{$devname}->{virtdev
};
5512 my $cfg = PVE
::Storage
::config
();
5514 # create empty/temp config
5516 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5517 foreach_drive
($oldconf, sub {
5518 my ($ds, $drive) = @_;
5520 return if drive_is_cdrom
($drive);
5522 my $volid = $drive->{file
};
5524 return if !$volid || $volid =~ m
|^/|;
5526 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5527 return if !$path || !$owner || ($owner != $vmid);
5529 # Note: only delete disk we want to restore
5530 # other volumes will become unused
5531 if ($virtdev_hash->{$ds}) {
5532 PVE
::Storage
::vdisk_free
($cfg, $volid);
5536 # delete vmstate files
5537 # since after the restore we have no snapshots anymore
5538 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5539 my $snap = $oldconf->{snapshots
}->{$snapname};
5540 if ($snap->{vmstate
}) {
5541 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5550 foreach my $virtdev (sort keys %$virtdev_hash) {
5551 my $d = $virtdev_hash->{$virtdev};
5552 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5553 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5555 # test if requested format is supported
5556 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5557 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5558 $d->{format
} = $defFormat if !$supported;
5560 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5561 $d->{format
}, undef, $alloc_size);
5562 print STDERR
"new volume ID is '$volid'\n";
5563 $d->{volid
} = $volid;
5564 my $path = PVE
::Storage
::path
($cfg, $volid);
5566 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5568 my $write_zeros = 1;
5569 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5573 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5575 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5576 $map->{$virtdev} = $volid;
5579 $fh->seek(0, 0) || die "seek failed - $!\n";
5581 my $outfd = new IO
::File
($tmpfn, "w") ||
5582 die "unable to write config for VM $vmid\n";
5584 my $cookie = { netcount
=> 0 };
5585 while (defined(my $line = <$fh>)) {
5586 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5595 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5596 die "interrupted by signal\n";
5598 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5600 $oldtimeout = alarm($timeout);
5607 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5608 my ($dev_id, $size, $devname) = ($1, $2, $3);
5609 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5610 } elsif ($line =~ m/^CTIME: /) {
5611 # we correctly received the vma config, so we can disable
5612 # the timeout now for disk allocation (set to 10 minutes, so
5613 # that we always timeout if something goes wrong)
5616 print $fifofh "done\n";
5617 my $tmp = $oldtimeout || 0;
5618 $oldtimeout = undef;
5624 print "restore vma archive: $cmd\n";
5625 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5629 alarm($oldtimeout) if $oldtimeout;
5632 foreach my $devname (keys %$devinfo) {
5633 my $volid = $devinfo->{$devname}->{volid
};
5634 push @$vollist, $volid if $volid;
5637 my $cfg = PVE
::Storage
::config
();
5638 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5646 foreach my $devname (keys %$devinfo) {
5647 my $volid = $devinfo->{$devname}->{volid
};
5650 if ($volid =~ m
|^/|) {
5651 unlink $volid || die 'unlink failed\n';
5653 PVE
::Storage
::vdisk_free
($cfg, $volid);
5655 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5657 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5664 rename($tmpfn, $conffile) ||
5665 die "unable to commit configuration file '$conffile'\n";
5667 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5669 eval { rescan
($vmid, 1); };
5673 sub restore_tar_archive
{
5674 my ($archive, $vmid, $user, $opts) = @_;
5676 if ($archive ne '-') {
5677 my $firstfile = tar_archive_read_firstfile
($archive);
5678 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5679 if $firstfile ne 'qemu-server.conf';
5682 my $storecfg = PVE
::Storage
::config
();
5684 # destroy existing data - keep empty config
5685 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5686 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5688 my $tocmd = "/usr/lib/qemu-server/qmextract";
5690 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5691 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5692 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5693 $tocmd .= ' --info' if $opts->{info
};
5695 # tar option "xf" does not autodetect compression when read from STDIN,
5696 # so we pipe to zcat
5697 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5698 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5700 my $tmpdir = "/var/tmp/vzdumptmp$$";
5703 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5704 local $ENV{VZDUMP_VMID
} = $vmid;
5705 local $ENV{VZDUMP_USER
} = $user;
5707 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5708 my $tmpfn = "$conffile.$$.tmp";
5710 # disable interrupts (always do cleanups)
5711 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5712 print STDERR
"got interrupt - ignored\n";
5717 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5718 die "interrupted by signal\n";
5721 if ($archive eq '-') {
5722 print "extracting archive from STDIN\n";
5723 run_command
($cmd, input
=> "<&STDIN");
5725 print "extracting archive '$archive'\n";
5729 return if $opts->{info
};
5733 my $statfile = "$tmpdir/qmrestore.stat";
5734 if (my $fd = IO
::File-
>new($statfile, "r")) {
5735 while (defined (my $line = <$fd>)) {
5736 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5737 $map->{$1} = $2 if $1;
5739 print STDERR
"unable to parse line in statfile - $line\n";
5745 my $confsrc = "$tmpdir/qemu-server.conf";
5747 my $srcfd = new IO
::File
($confsrc, "r") ||
5748 die "unable to open file '$confsrc'\n";
5750 my $outfd = new IO
::File
($tmpfn, "w") ||
5751 die "unable to write config for VM $vmid\n";
5753 my $cookie = { netcount
=> 0 };
5754 while (defined (my $line = <$srcfd>)) {
5755 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5767 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5774 rename $tmpfn, $conffile ||
5775 die "unable to commit configuration file '$conffile'\n";
5777 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5779 eval { rescan
($vmid, 1); };
5783 sub foreach_writable_storage
{
5784 my ($conf, $func) = @_;
5788 foreach my $ds (keys %$conf) {
5789 next if !is_valid_drivename
($ds);
5791 my $drive = parse_drive
($ds, $conf->{$ds});
5793 next if drive_is_cdrom
($drive);
5795 my $volid = $drive->{file
};
5797 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5798 $sidhash->{$sid} = $sid if $sid;
5801 foreach my $sid (sort keys %$sidhash) {
5806 sub do_snapshots_with_qemu
{
5807 my ($storecfg, $volid) = @_;
5809 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5811 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5812 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5816 if ($volid =~ m/\.(qcow2|qed)$/){
5823 sub qga_check_running
{
5826 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5828 warn "Qemu Guest Agent are not running - $@";
5834 sub template_create
{
5835 my ($vmid, $conf, $disk) = @_;
5837 my $storecfg = PVE
::Storage
::config
();
5839 foreach_drive
($conf, sub {
5840 my ($ds, $drive) = @_;
5842 return if drive_is_cdrom
($drive);
5843 return if $disk && $ds ne $disk;
5845 my $volid = $drive->{file
};
5846 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5848 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5849 $drive->{file
} = $voliddst;
5850 $conf->{$ds} = print_drive
($vmid, $drive);
5851 PVE
::QemuConfig-
>write_config($vmid, $conf);
5855 sub qemu_img_convert
{
5856 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5858 my $storecfg = PVE
::Storage
::config
();
5859 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5860 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5862 if ($src_storeid && $dst_storeid) {
5864 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5866 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5867 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5869 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5870 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5872 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5873 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5876 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5877 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5878 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5879 if ($is_zero_initialized) {
5880 push @$cmd, "zeroinit:$dst_path";
5882 push @$cmd, $dst_path;
5887 if($line =~ m/\((\S+)\/100\
%\)/){
5889 my $transferred = int($size * $percent / 100);
5890 my $remaining = $size - $transferred;
5892 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5897 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5899 die "copy failed: $err" if $err;
5903 sub qemu_img_format
{
5904 my ($scfg, $volname) = @_;
5906 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5913 sub qemu_drive_mirror
{
5914 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5916 my $storecfg = PVE
::Storage
::config
();
5917 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5919 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5921 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5923 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5925 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5927 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5928 $opts->{format
} = $format if $format;
5930 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5933 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5935 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5936 my $stat = @$stats[0];
5937 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5938 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5940 my $busy = $stat->{busy
};
5941 my $ready = $stat->{ready
};
5943 if (my $total = $stat->{len
}) {
5944 my $transferred = $stat->{offset
} || 0;
5945 my $remaining = $total - $transferred;
5946 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5948 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5952 if ($stat->{ready
} eq 'true') {
5954 last if $vmiddst != $vmid;
5956 # try to switch the disk if source and destination are on the same guest
5957 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5959 die $@ if $@ !~ m/cannot be completed/;
5968 my $cancel_job = sub {
5969 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5971 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5972 my $stat = @$stats[0];
5979 eval { &$cancel_job(); };
5980 die "mirroring error: $err";
5983 if ($vmiddst != $vmid) {
5984 # if we clone a disk for a new target vm, we don't switch the disk
5985 &$cancel_job(); # so we call block-job-cancel
5990 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5991 $newvmid, $storage, $format, $full, $newvollist) = @_;
5996 print "create linked clone of drive $drivename ($drive->{file})\n";
5997 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5998 push @$newvollist, $newvolid;
6000 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6001 $storeid = $storage if $storage;
6003 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6005 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6006 $format = qemu_img_format
($scfg, $volname);
6009 # test if requested format is supported - else use default
6010 my $supported = grep { $_ eq $format } @$validFormats;
6011 $format = $defFormat if !$supported;
6013 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6015 print "create full clone of drive $drivename ($drive->{file})\n";
6016 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6017 push @$newvollist, $newvolid;
6019 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6021 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6022 if (!$running || $snapname) {
6023 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6025 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
6029 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6032 $disk->{format
} = undef;
6033 $disk->{file
} = $newvolid;
6034 $disk->{size
} = $size;
6039 # this only works if VM is running
6040 sub get_current_qemu_machine
{
6043 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6044 my $res = vm_qmp_command
($vmid, $cmd);
6046 my ($current, $default);
6047 foreach my $e (@$res) {
6048 $default = $e->{name
} if $e->{'is-default'};
6049 $current = $e->{name
} if $e->{'is-current'};
6052 # fallback to the default machine if current is not supported by qemu
6053 return $current || $default || 'pc';
6056 sub qemu_machine_feature_enabled
{
6057 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6062 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6064 $current_major = $3;
6065 $current_minor = $4;
6067 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6069 $current_major = $1;
6070 $current_minor = $2;
6073 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6078 sub qemu_machine_pxe
{
6079 my ($vmid, $conf, $machine) = @_;
6081 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6083 foreach my $opt (keys %$conf) {
6084 next if $opt !~ m/^net(\d+)$/;
6085 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6087 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6088 return $machine.".pxe" if $romfile =~ m/pxe/;
6095 sub qemu_use_old_bios_files
{
6096 my ($machine_type) = @_;
6098 return if !$machine_type;
6100 my $use_old_bios_files = undef;
6102 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6104 $use_old_bios_files = 1;
6106 my $kvmver = kvm_user_version
();
6107 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6108 # load new efi bios files on migration. So this hack is required to allow
6109 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6110 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6111 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6114 return ($use_old_bios_files, $machine_type);
6121 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6122 my (undef, $id, $function) = @_;
6123 my $res = { id
=> $id, function
=> $function};
6124 push @{$devices->{$id}}, $res;
6130 sub vm_iothreads_list
{
6133 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6136 foreach my $iothread (@$res) {
6137 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6144 my ($conf, $drive) = @_;
6148 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6150 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6156 my $controller = int($drive->{index} / $maxdev);
6157 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6159 return ($maxdev, $controller, $controller_prefix);
6162 # bash completion helper
6164 sub complete_backup_archives
{
6165 my ($cmdname, $pname, $cvalue) = @_;
6167 my $cfg = PVE
::Storage
::config
();
6171 if ($cvalue =~ m/^([^:]+):/) {
6175 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6178 foreach my $id (keys %$data) {
6179 foreach my $item (@{$data->{$id}}) {
6180 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6181 push @$res, $item->{volid
} if defined($item->{volid
});
6188 my $complete_vmid_full = sub {
6191 my $idlist = vmstatus
();
6195 foreach my $id (keys %$idlist) {
6196 my $d = $idlist->{$id};
6197 if (defined($running)) {
6198 next if $d->{template
};
6199 next if $running && $d->{status
} ne 'running';
6200 next if !$running && $d->{status
} eq 'running';
6209 return &$complete_vmid_full();
6212 sub complete_vmid_stopped
{
6213 return &$complete_vmid_full(0);
6216 sub complete_vmid_running
{
6217 return &$complete_vmid_full(1);
6220 sub complete_storage
{
6222 my $cfg = PVE
::Storage
::config
();
6223 my $ids = $cfg->{ids
};
6226 foreach my $sid (keys %$ids) {
6227 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6228 next if !$ids->{$sid}->{content
}->{images
};