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 PVE
::QemuServer
::PCI
qw(print_pci_addr print_pcie_addr);
34 use PVE
::QemuServer
::Memory
;
35 use Time
::HiRes
qw(gettimeofday);
36 use File
::Copy
qw(copy);
39 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
41 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
43 # Note about locking: we use flock on the config file protect
44 # against concurent actions.
45 # Aditionaly, we have a 'lock' setting in the config file. This
46 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
47 # allowed when such lock is set. But you can ignore this kind of
48 # lock with the --skiplock flag.
50 cfs_register_file
('/qemu-server/',
54 PVE
::JSONSchema
::register_standard_option
('skiplock', {
55 description
=> "Ignore locks - only root is allowed to use this option.",
60 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
61 description
=> "Some command save/restore state from this location.",
67 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
68 description
=> "The name of the snapshot.",
69 type
=> 'string', format
=> 'pve-configid',
73 #no warnings 'redefine';
76 my ($controller, $vmid, $option, $value) = @_;
78 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
79 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
83 my $nodename = PVE
::INotify
::nodename
();
85 mkdir "/etc/pve/nodes/$nodename";
86 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
89 my $var_run_tmpdir = "/var/run/qemu-server";
90 mkdir $var_run_tmpdir;
92 my $lock_dir = "/var/lock/qemu-server";
95 my $pcisysfs = "/sys/bus/pci";
97 my $cpu_vendor_list = {
99 486 => 'GenuineIntel',
100 pentium
=> 'GenuineIntel',
101 pentium2
=> 'GenuineIntel',
102 pentium3
=> 'GenuineIntel',
103 coreduo
=> 'GenuineIntel',
104 core2duo
=> 'GenuineIntel',
105 Conroe
=> 'GenuineIntel',
106 Penryn
=> 'GenuineIntel',
107 Nehalem
=> 'GenuineIntel',
108 Westmere
=> 'GenuineIntel',
109 SandyBridge
=> 'GenuineIntel',
110 IvyBridge
=> 'GenuineIntel',
111 Haswell
=> 'GenuineIntel',
112 'Haswell-noTSX' => 'GenuineIntel',
113 Broadwell
=> 'GenuineIntel',
114 'Broadwell-noTSX' => 'GenuineIntel',
117 athlon
=> 'AuthenticAMD',
118 phenom
=> 'AuthenticAMD',
119 Opteron_G1
=> 'AuthenticAMD',
120 Opteron_G2
=> 'AuthenticAMD',
121 Opteron_G3
=> 'AuthenticAMD',
122 Opteron_G4
=> 'AuthenticAMD',
123 Opteron_G5
=> 'AuthenticAMD',
125 # generic types, use vendor from host node
135 description
=> "Emulated CPU type.",
137 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
138 format_description
=> 'cputype',
143 description
=> "Do not identify as a KVM virtual machine.",
154 enum
=> [qw(i6300esb ib700)],
155 description
=> "Watchdog type to emulate.",
156 default => 'i6300esb',
161 enum
=> [qw(reset shutdown poweroff pause debug none)],
162 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
166 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
172 description
=> "Specifies whether a VM will be started during system bootup.",
178 description
=> "Automatic restart after crash (currently ignored).",
183 type
=> 'string', format
=> 'pve-hotplug-features',
184 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'.",
185 default => 'network,disk,usb',
190 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
196 description
=> "Lock/unlock the VM.",
197 enum
=> [qw(migrate backup snapshot rollback)],
202 description
=> "Limit of CPU usage.",
203 verbose_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.",
211 description
=> "CPU weight for a VM.",
212 verbose_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.",
220 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
227 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
233 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",
241 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.",
242 enum
=> PVE
::Tools
::kvmkeymaplist
(),
247 type
=> 'string', format
=> 'dns-name',
248 description
=> "Set a name for the VM. Only used on the configuration web interface.",
253 description
=> "SCSI controller model",
254 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
260 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
265 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
266 description
=> "Specify guest operating system.",
267 verbose_description
=> <<EODESC,
268 Specify guest operating system. This is used to enable special
269 optimization/features for specific operating systems:
272 other;; unspecified OS
273 wxp;; Microsoft Windows XP
274 w2k;; Microsoft Windows 2000
275 w2k3;; Microsoft Windows 2003
276 w2k8;; Microsoft Windows 2008
277 wvista;; Microsoft Windows Vista
278 win7;; Microsoft Windows 7
279 win8;; Microsoft Windows 8/2012
280 l24;; Linux 2.4 Kernel
281 l26;; Linux 2.6/3.X Kernel
282 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
288 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
289 pattern
=> '[acdn]{1,4}',
294 type
=> 'string', format
=> 'pve-qm-bootdisk',
295 description
=> "Enable booting from specified disk.",
296 pattern
=> '(ide|sata|scsi|virtio)\d+',
301 description
=> "The number of CPUs. Please use option -sockets instead.",
308 description
=> "The number of CPU sockets.",
315 description
=> "The number of cores per socket.",
322 description
=> "Enable/disable NUMA.",
328 description
=> "Enable/disable hugepages memory.",
329 enum
=> [qw(any 2 1024)],
334 description
=> "Number of hotplugged vcpus.",
341 description
=> "Enable/disable ACPI.",
347 description
=> "Enable/disable Qemu GuestAgent.",
353 description
=> "Enable/disable KVM hardware virtualization.",
359 description
=> "Enable/disable time drift fix.",
365 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
370 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
375 description
=> "Select the VGA type.",
376 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
377 " modes (>= 1280x1024x16) then you should use the options " .
378 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
379 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
380 "display sever. For win* OS you can select how many independent " .
381 "displays you want, Linux guests can add displays them self. " .
382 "You can also run without any graphic card, using a serial device" .
384 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
388 type
=> 'string', format
=> 'pve-qm-watchdog',
389 description
=> "Create a virtual hardware watchdog device.",
390 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
391 " (by a guest action), the watchdog must be periodically polled " .
392 "by an agent inside the guest or else the watchdog will reset " .
393 "the guest (or execute the respective action specified)",
398 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
399 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'.",
400 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
403 startup
=> get_standard_option
('pve-startup-order'),
407 description
=> "Enable/disable Template.",
413 description
=> "Arbitrary arguments passed to kvm.",
414 verbose_description
=> <<EODESCR,
415 Arbitrary arguments passed to kvm, for example:
417 args: -no-reboot -no-hpet
419 NOTE: this option is for experts only.
426 description
=> "Enable/disable the USB tablet device.",
427 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
428 "usually needed to allow absolute mouse positioning with VNC. " .
429 "Else the mouse runs out of sync with normal VNC clients. " .
430 "If you're running lots of console-only guests on one host, " .
431 "you may consider disabling this to save some context switches. " .
432 "This is turned off by default if you use spice (-vga=qxl).",
437 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
441 migrate_downtime
=> {
444 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
450 type
=> 'string', format
=> 'pve-qm-drive',
451 typetext
=> 'volume',
452 description
=> "This is an alias for option -ide2",
456 description
=> "Emulated CPU type.",
460 parent
=> get_standard_option
('pve-snapshot-name', {
462 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
466 description
=> "Timestamp for snapshots.",
472 type
=> 'string', format
=> 'pve-volume-id',
473 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
476 description
=> "Specific the Qemu machine type.",
478 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
483 description
=> "Specify SMBIOS type 1 fields.",
484 type
=> 'string', format
=> 'pve-qm-smbios1',
491 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
497 enum
=> [ qw(seabios ovmf) ],
498 description
=> "Select BIOS implementation.",
499 default => 'seabios',
503 # what about other qemu settings ?
505 #machine => 'string',
518 ##soundhw => 'string',
520 while (my ($k, $v) = each %$confdesc) {
521 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
524 my $MAX_IDE_DISKS = 4;
525 my $MAX_SCSI_DISKS = 14;
526 my $MAX_VIRTIO_DISKS = 16;
527 my $MAX_SATA_DISKS = 6;
528 my $MAX_USB_DEVICES = 5;
530 my $MAX_UNUSED_DISKS = 8;
531 my $MAX_HOSTPCI_DEVICES = 4;
532 my $MAX_SERIAL_PORTS = 4;
533 my $MAX_PARALLEL_PORTS = 3;
539 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
540 description
=> "CPUs accessing this NUMA node.",
541 format_description
=> "id[-id];...",
545 description
=> "Amount of memory this NUMA node provides.",
550 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
551 description
=> "Host NUMA nodes to use.",
552 format_description
=> "id[-id];...",
557 enum
=> [qw(preferred bind interleave)],
558 description
=> "NUMA allocation policy.",
562 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
565 type
=> 'string', format
=> $numa_fmt,
566 description
=> "NUMA topology.",
568 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
570 for (my $i = 0; $i < $MAX_NUMA; $i++) {
571 $confdesc->{"numa$i"} = $numadesc;
574 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
575 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
576 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
577 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
579 my $net_fmt_bridge_descr = <<__EOD__;
580 Bridge to attach the network device to. The Proxmox VE standard bridge
583 If you do not specify a bridge, we create a kvm user (NATed) network
584 device, which provides DHCP and DNS services. The following addresses
591 The DHCP server assign addresses to the guest starting from 10.0.2.15.
597 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
598 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
599 format_description
=> "XX:XX:XX:XX:XX:XX",
604 description
=> "Network Card Model. The 'virtio' model provides the best performance with very low CPU overhead. If your guest does not support this driver, it is usually best to use 'e1000'.",
605 format_description
=> 'model',
606 enum
=> $nic_model_list,
609 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
612 description
=> $net_fmt_bridge_descr,
613 format_description
=> 'bridge',
618 minimum
=> 0, maximum
=> 16,
619 description
=> 'Number of packet queues to be used on the device.',
625 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
630 minimum
=> 1, maximum
=> 4094,
631 description
=> 'VLAN tag to apply to packets on this interface.',
636 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
637 description
=> 'VLAN trunks to pass through this interface.',
638 format_description
=> 'vlanid[;vlanid...]',
643 description
=> 'Whether this interface should be protected by the firewall.',
648 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
655 type
=> 'string', format
=> $net_fmt,
656 description
=> "Specify network devices.",
659 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
661 for (my $i = 0; $i < $MAX_NETS; $i++) {
662 $confdesc->{"net$i"} = $netdesc;
665 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
666 sub verify_volume_id_or_qm_path
{
667 my ($volid, $noerr) = @_;
669 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
673 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
674 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
676 return undef if $noerr;
684 my %drivedesc_base = (
685 volume
=> { alias
=> 'file' },
688 format
=> 'pve-volume-id-or-qm-path',
690 format_description
=> 'volume',
691 description
=> "The drive's backing volume.",
695 enum
=> [qw(cdrom disk)],
696 description
=> "The drive's media type.",
702 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
707 description
=> "Force the drive's physical geometry to have a specific head count.",
712 description
=> "Force the drive's physical geometry to have a specific sector count.",
717 enum
=> [qw(none lba auto)],
718 description
=> "Force disk geometry bios translation mode.",
723 description
=> "Whether the drive should be included when making snapshots.",
728 enum
=> [qw(none writethrough writeback unsafe directsync)],
729 description
=> "The drive's cache mode",
734 format_description
=> 'image format',
735 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
736 description
=> "The drive's backing file's data format.",
741 format
=> 'disk-size',
742 format_description
=> 'DiskSize',
743 description
=> "Disk size. This is purely informational and has no effect.",
748 description
=> "Whether the drive should be included when making backups.",
753 enum
=> [qw(enospc ignore report stop)],
754 description
=> 'Write error action.',
759 enum
=> [qw(native threads)],
760 description
=> 'AIO type to use.',
765 enum
=> [qw(ignore on)],
766 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
771 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
776 format
=> 'urlencoded',
777 format_description
=> 'serial',
778 maxLength
=> 20*3, # *3 since it's %xx url enoded
779 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
787 enum
=> [qw(ignore report stop)],
788 description
=> 'Read error action.',
793 my %iothread_fmt = ( iothread
=> {
795 description
=> "Whether to use iothreads for this drive",
802 format
=> 'urlencoded',
803 format_description
=> 'model',
804 maxLength
=> 40*3, # *3 since it's %xx url enoded
805 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
813 description
=> "Number of queues.",
819 my $add_throttle_desc = sub {
820 my ($key, $type, $what, $unit, $longunit) = @_;
821 $drivedesc_base{$key} = {
823 format_description
=> $unit,
824 description
=> "Maximum $what speed in $longunit per second.",
828 # throughput: (leaky bucket)
829 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
830 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
831 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
832 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
833 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
834 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
835 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
836 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
837 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
839 # pools: (pool of IO before throttling starts taking effect)
840 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
841 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
842 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
843 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
844 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
845 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
855 type
=> 'string', format
=> $ide_fmt,
856 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
858 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
867 type
=> 'string', format
=> $scsi_fmt,
868 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
870 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
878 type
=> 'string', format
=> $sata_fmt,
879 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
881 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
890 type
=> 'string', format
=> $virtio_fmt,
891 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
893 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
906 type
=> 'string', format
=> 'pve-qm-usb-device',
907 format_description
=> 'HOSTUSBDEVICE|spice',
908 description
=> <<EODESCR,
909 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
911 'bus-port(.port)*' (decimal numbers) or
912 'vendor_id:product_id' (hexadeciaml numbers) or
915 You can use the 'lsusb -t' command to list existing usb devices.
917 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
919 The value 'spice' can be used to add a usb redirection devices for spice.
925 description
=> "Specifies whether if given host option is a USB3 device or port (this does currently not work reliably with spice redirection and is then ignored).",
932 type
=> 'string', format
=> $usb_fmt,
933 description
=> "Configure an USB device (n is 0 to 4).",
935 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
937 # NOTE: the match-groups of this regex are used in parse_hostpci
938 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
943 pattern
=> qr/$PCIRE(;$PCIRE)*/,
944 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
945 description
=> <<EODESCR,
946 Host PCI device pass through. The PCI ID of a host's PCI device or a list
947 of PCI virtual functions of the host. HOSTPCIID syntax is:
949 'bus:dev.func' (hexadecimal numbers)
951 You can us the 'lspci' command to list existing PCI devices.
956 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
962 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
968 description
=> "Enable vfio-vga device support.",
973 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
977 type
=> 'string', format
=> 'pve-qm-hostpci',
978 description
=> "Map host PCI devices into guest.",
979 verbose_description
=> <<EODESCR,
980 Map host PCI devices into guest.
982 NOTE: This option allows direct access to host hardware. So it is no longer
983 possible to migrate such machines - use with special care.
985 CAUTION: Experimental! User reported problems with this option.
988 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
993 pattern
=> '(/dev/.+|socket)',
994 description
=> "Create a serial device inside the VM (n is 0 to 3)",
995 verbose_description
=> <<EODESCR,
996 Create a serial device inside the VM (n is 0 to 3), and pass through a
997 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
998 host side (use 'qm terminal' to open a terminal connection).
1000 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1002 CAUTION: Experimental! User reported problems with this option.
1009 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1010 description
=> "Map host parallel devices (n is 0 to 2).",
1011 verbose_description
=> <<EODESCR,
1012 Map host parallel devices (n is 0 to 2).
1014 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1016 CAUTION: Experimental! User reported problems with this option.
1020 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1021 $confdesc->{"parallel$i"} = $paralleldesc;
1024 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1025 $confdesc->{"serial$i"} = $serialdesc;
1028 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1029 $confdesc->{"hostpci$i"} = $hostpcidesc;
1032 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1033 $drivename_hash->{"ide$i"} = 1;
1034 $confdesc->{"ide$i"} = $idedesc;
1037 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1038 $drivename_hash->{"sata$i"} = 1;
1039 $confdesc->{"sata$i"} = $satadesc;
1042 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1043 $drivename_hash->{"scsi$i"} = 1;
1044 $confdesc->{"scsi$i"} = $scsidesc ;
1047 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1048 $drivename_hash->{"virtio$i"} = 1;
1049 $confdesc->{"virtio$i"} = $virtiodesc;
1052 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1053 $confdesc->{"usb$i"} = $usbdesc;
1058 type
=> 'string', format
=> 'pve-volume-id',
1059 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1062 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1063 $confdesc->{"unused$i"} = $unuseddesc;
1066 my $kvm_api_version = 0;
1070 return $kvm_api_version if $kvm_api_version;
1072 my $fh = IO
::File-
>new("</dev/kvm") ||
1075 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1076 $kvm_api_version = $v;
1081 return $kvm_api_version;
1084 my $kvm_user_version;
1086 sub kvm_user_version
{
1088 return $kvm_user_version if $kvm_user_version;
1090 $kvm_user_version = 'unknown';
1094 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1095 $kvm_user_version = $2;
1099 eval { run_command
("kvm -version", outfunc
=> $code); };
1102 return $kvm_user_version;
1106 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1108 sub valid_drive_names
{
1109 # order is important - used to autoselect boot disk
1110 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1111 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1112 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1113 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1116 sub is_valid_drivename
{
1119 return defined($drivename_hash->{$dev});
1124 return defined($confdesc->{$key});
1128 return $nic_model_list;
1131 sub os_list_description
{
1135 wxp
=> 'Windows XP',
1136 w2k
=> 'Windows 2000',
1137 w2k3
=>, 'Windows 2003',
1138 w2k8
=> 'Windows 2008',
1139 wvista
=> 'Windows Vista',
1140 win7
=> 'Windows 7',
1141 win8
=> 'Windows 8/2012',
1149 sub get_cdrom_path
{
1151 return $cdrom_path if $cdrom_path;
1153 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1154 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1155 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1159 my ($storecfg, $vmid, $cdrom) = @_;
1161 if ($cdrom eq 'cdrom') {
1162 return get_cdrom_path
();
1163 } elsif ($cdrom eq 'none') {
1165 } elsif ($cdrom =~ m
|^/|) {
1168 return PVE
::Storage
::path
($storecfg, $cdrom);
1172 # try to convert old style file names to volume IDs
1173 sub filename_to_volume_id
{
1174 my ($vmid, $file, $media) = @_;
1176 if (!($file eq 'none' || $file eq 'cdrom' ||
1177 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1179 return undef if $file =~ m
|/|;
1181 if ($media && $media eq 'cdrom') {
1182 $file = "local:iso/$file";
1184 $file = "local:$vmid/$file";
1191 sub verify_media_type
{
1192 my ($opt, $vtype, $media) = @_;
1197 if ($media eq 'disk') {
1199 } elsif ($media eq 'cdrom') {
1202 die "internal error";
1205 return if ($vtype eq $etype);
1207 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1210 sub cleanup_drive_path
{
1211 my ($opt, $storecfg, $drive) = @_;
1213 # try to convert filesystem paths to volume IDs
1215 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1216 ($drive->{file
} !~ m
|^/dev/.+|) &&
1217 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1218 ($drive->{file
} !~ m/^\d+$/)) {
1219 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1220 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1221 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1222 verify_media_type
($opt, $vtype, $drive->{media
});
1223 $drive->{file
} = $volid;
1226 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1229 sub parse_hotplug_features
{
1234 return $res if $data eq '0';
1236 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1238 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1239 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1242 die "invalid hotplug feature '$feature'\n";
1248 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1249 sub pve_verify_hotplug_features
{
1250 my ($value, $noerr) = @_;
1252 return $value if parse_hotplug_features
($value);
1254 return undef if $noerr;
1256 die "unable to parse hotplug option\n";
1259 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1260 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1261 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1262 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1263 # [,iothread=on][,serial=serial][,model=model]
1266 my ($key, $data) = @_;
1268 my ($interface, $index);
1270 if ($key =~ m/^([^\d]+)(\d+)$/) {
1277 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1278 : $confdesc->{$key}->{format
};
1280 warn "invalid drive key: $key\n";
1283 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1284 return undef if !$res;
1285 $res->{interface
} = $interface;
1286 $res->{index} = $index;
1289 foreach my $opt (qw(bps bps_rd bps_wr)) {
1290 if (my $bps = defined(delete $res->{$opt})) {
1291 if (defined($res->{"m$opt"})) {
1292 warn "both $opt and m$opt specified\n";
1296 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1299 return undef if $error;
1301 return undef if $res->{mbps_rd
} && $res->{mbps
};
1302 return undef if $res->{mbps_wr
} && $res->{mbps
};
1303 return undef if $res->{iops_rd
} && $res->{iops
};
1304 return undef if $res->{iops_wr
} && $res->{iops
};
1306 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1307 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1308 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1309 return undef if $res->{interface
} eq 'virtio';
1312 if (my $size = $res->{size
}) {
1313 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1320 my ($vmid, $drive) = @_;
1321 my $data = { %$drive };
1322 delete $data->{$_} for qw(index interface);
1323 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1327 my($fh, $noerr) = @_;
1330 my $SG_GET_VERSION_NUM = 0x2282;
1332 my $versionbuf = "\x00" x
8;
1333 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1335 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1338 my $version = unpack("I", $versionbuf);
1339 if ($version < 30000) {
1340 die "scsi generic interface too old\n" if !$noerr;
1344 my $buf = "\x00" x
36;
1345 my $sensebuf = "\x00" x
8;
1346 my $cmd = pack("C x3 C x1", 0x12, 36);
1348 # see /usr/include/scsi/sg.h
1349 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";
1351 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1352 length($sensebuf), 0, length($buf), $buf,
1353 $cmd, $sensebuf, 6000);
1355 $ret = ioctl($fh, $SG_IO, $packet);
1357 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1361 my @res = unpack($sg_io_hdr_t, $packet);
1362 if ($res[17] || $res[18]) {
1363 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1368 (my $byte0, my $byte1, $res->{vendor
},
1369 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1371 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1372 $res->{type
} = $byte0 & 31;
1380 my $fh = IO
::File-
>new("+<$path") || return undef;
1381 my $res = scsi_inquiry
($fh, 1);
1387 sub machine_type_is_q35
{
1390 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1393 sub print_tabletdevice_full
{
1396 my $q35 = machine_type_is_q35
($conf);
1398 # we use uhci for old VMs because tablet driver was buggy in older qemu
1399 my $usbbus = $q35 ?
"ehci" : "uhci";
1401 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1404 sub print_drivedevice_full
{
1405 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1410 if ($drive->{interface
} eq 'virtio') {
1411 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1412 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1413 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1414 } elsif ($drive->{interface
} eq 'scsi') {
1416 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1417 my $unit = $drive->{index} % $maxdev;
1418 my $devicetype = 'hd';
1420 if (drive_is_cdrom
($drive)) {
1423 if ($drive->{file
} =~ m
|^/|) {
1424 $path = $drive->{file
};
1425 if (my $info = path_is_scsi
($path)) {
1426 if ($info->{type
} == 0) {
1427 $devicetype = 'block';
1428 } elsif ($info->{type
} == 1) { # tape
1429 $devicetype = 'generic';
1433 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1436 if($path =~ m/^iscsi\:\/\
//){
1437 $devicetype = 'generic';
1441 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1442 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1444 $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}";
1447 } elsif ($drive->{interface
} eq 'ide'){
1449 my $controller = int($drive->{index} / $maxdev);
1450 my $unit = $drive->{index} % $maxdev;
1451 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1453 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1454 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1455 $model = URI
::Escape
::uri_unescape
($model);
1456 $device .= ",model=$model";
1458 } elsif ($drive->{interface
} eq 'sata'){
1459 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1460 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1461 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1462 } elsif ($drive->{interface
} eq 'usb') {
1464 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1466 die "unsupported interface type";
1469 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1474 sub get_initiator_name
{
1477 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1478 while (defined(my $line = <$fh>)) {
1479 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1488 sub print_drive_full
{
1489 my ($storecfg, $vmid, $drive) = @_;
1492 my $volid = $drive->{file
};
1495 if (drive_is_cdrom
($drive)) {
1496 $path = get_iso_path
($storecfg, $vmid, $volid);
1498 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1500 $path = PVE
::Storage
::path
($storecfg, $volid);
1501 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1502 $format = qemu_img_format
($scfg, $volname);
1510 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);
1511 foreach my $o (@qemu_drive_options) {
1512 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1514 if (my $serial = $drive->{serial
}) {
1515 $serial = URI
::Escape
::uri_unescape
($serial);
1516 $opts .= ",serial=$serial";
1519 $opts .= ",format=$format" if $format && !$drive->{format
};
1521 foreach my $o (qw(bps bps_rd bps_wr)) {
1522 my $v = $drive->{"m$o"};
1523 $opts .= ",$o=" . int($v*1024*1024) if $v;
1526 my $cache_direct = 0;
1528 if (my $cache = $drive->{cache
}) {
1529 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1530 } elsif (!drive_is_cdrom
($drive)) {
1531 $opts .= ",cache=none";
1535 # aio native works only with O_DIRECT
1536 if (!$drive->{aio
}) {
1538 $opts .= ",aio=native";
1540 $opts .= ",aio=threads";
1544 if (!drive_is_cdrom
($drive)) {
1546 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1547 $detectzeroes = 'off';
1548 } elsif ($drive->{discard
}) {
1549 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1551 # This used to be our default with discard not being specified:
1552 $detectzeroes = 'on';
1554 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1557 my $pathinfo = $path ?
"file=$path," : '';
1559 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1562 sub print_netdevice_full
{
1563 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1565 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1567 my $device = $net->{model
};
1568 if ($net->{model
} eq 'virtio') {
1569 $device = 'virtio-net-pci';
1572 my $pciaddr = print_pci_addr
("$netid", $bridges);
1573 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1574 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1575 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1576 my $vectors = $net->{queues
} * 2 + 2;
1577 $tmpstr .= ",vectors=$vectors,mq=on";
1579 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1581 if ($use_old_bios_files) {
1583 if ($device eq 'virtio-net-pci') {
1584 $romfile = 'pxe-virtio.rom';
1585 } elsif ($device eq 'e1000') {
1586 $romfile = 'pxe-e1000.rom';
1587 } elsif ($device eq 'ne2k') {
1588 $romfile = 'pxe-ne2k_pci.rom';
1589 } elsif ($device eq 'pcnet') {
1590 $romfile = 'pxe-pcnet.rom';
1591 } elsif ($device eq 'rtl8139') {
1592 $romfile = 'pxe-rtl8139.rom';
1594 $tmpstr .= ",romfile=$romfile" if $romfile;
1600 sub print_netdev_full
{
1601 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1604 if ($netid =~ m/^net(\d+)$/) {
1608 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1610 my $ifname = "tap${vmid}i$i";
1612 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1613 die "interface name '$ifname' is too long (max 15 character)\n"
1614 if length($ifname) >= 16;
1616 my $vhostparam = '';
1617 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1619 my $vmname = $conf->{name
} || "vm$vmid";
1622 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1624 if ($net->{bridge
}) {
1625 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1627 $netdev = "type=user,id=$netid,hostname=$vmname";
1630 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1635 sub drive_is_cdrom
{
1638 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1642 sub parse_number_sets
{
1645 foreach my $part (split(/;/, $set)) {
1646 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1647 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1648 push @$res, [ $1, $2 ];
1650 die "invalid range: $part\n";
1659 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1660 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1661 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1668 return undef if !$value;
1670 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1672 my @idlist = split(/;/, $res->{host
});
1673 delete $res->{host
};
1674 foreach my $id (@idlist) {
1675 if ($id =~ /^$PCIRE$/) {
1676 push @{$res->{pciid
}}, { id
=> $1, function
=> ($2//'0') };
1678 # should have been caught by parse_property_string already
1679 die "failed to parse PCI id: $id\n";
1685 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1689 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1694 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
() if !defined($res->{macaddr
});
1701 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1704 sub add_random_macs
{
1705 my ($settings) = @_;
1707 foreach my $opt (keys %$settings) {
1708 next if $opt !~ m/^net(\d+)$/;
1709 my $net = parse_net
($settings->{$opt});
1711 $settings->{$opt} = print_net
($net);
1715 sub vm_is_volid_owner
{
1716 my ($storecfg, $vmid, $volid) = @_;
1718 if ($volid !~ m
|^/|) {
1720 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1721 if ($owner && ($owner == $vmid)) {
1729 sub split_flagged_list
{
1730 my $text = shift || '';
1731 $text =~ s/[,;]/ /g;
1733 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1736 sub join_flagged_list
{
1737 my ($how, $lst) = @_;
1738 join $how, map { $lst->{$_} . $_ } keys %$lst;
1741 sub vmconfig_delete_pending_option
{
1742 my ($conf, $key, $force) = @_;
1744 delete $conf->{pending
}->{$key};
1745 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1746 $pending_delete_hash->{$key} = $force ?
'!' : '';
1747 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1750 sub vmconfig_undelete_pending_option
{
1751 my ($conf, $key) = @_;
1753 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1754 delete $pending_delete_hash->{$key};
1756 if (%$pending_delete_hash) {
1757 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1759 delete $conf->{pending
}->{delete};
1763 sub vmconfig_register_unused_drive
{
1764 my ($storecfg, $vmid, $conf, $drive) = @_;
1766 if (!drive_is_cdrom
($drive)) {
1767 my $volid = $drive->{file
};
1768 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1769 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1774 sub vmconfig_cleanup_pending
{
1777 # remove pending changes when nothing changed
1779 foreach my $opt (keys %{$conf->{pending
}}) {
1780 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1782 delete $conf->{pending
}->{$opt};
1786 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1787 my $pending_delete_hash = {};
1788 while (my ($opt, $force) = each %$current_delete_hash) {
1789 if (defined($conf->{$opt})) {
1790 $pending_delete_hash->{$opt} = $force;
1796 if (%$pending_delete_hash) {
1797 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1799 delete $conf->{pending
}->{delete};
1805 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1809 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1810 format_description
=> 'UUID',
1811 description
=> "Set SMBIOS1 UUID.",
1817 format_description
=> 'string',
1818 description
=> "Set SMBIOS1 version.",
1824 format_description
=> 'string',
1825 description
=> "Set SMBIOS1 serial number.",
1831 format_description
=> 'string',
1832 description
=> "Set SMBIOS1 manufacturer.",
1838 format_description
=> 'string',
1839 description
=> "Set SMBIOS1 product ID.",
1845 format_description
=> 'string',
1846 description
=> "Set SMBIOS1 SKU string.",
1852 format_description
=> 'string',
1853 description
=> "Set SMBIOS1 family string.",
1861 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1868 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1871 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1873 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1874 sub verify_bootdisk
{
1875 my ($value, $noerr) = @_;
1877 return $value if is_valid_drivename
($value);
1879 return undef if $noerr;
1881 die "invalid boot disk '$value'\n";
1884 sub parse_watchdog
{
1887 return undef if !$value;
1889 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1894 sub parse_usb_device
{
1897 return undef if !$value;
1900 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1901 $res->{vendorid
} = $2;
1902 $res->{productid
} = $4;
1903 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1904 $res->{hostbus
} = $1;
1905 $res->{hostport
} = $2;
1906 } elsif ($value =~ m/^spice$/i) {
1915 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1916 sub verify_usb_device
{
1917 my ($value, $noerr) = @_;
1919 return $value if parse_usb_device
($value);
1921 return undef if $noerr;
1923 die "unable to parse usb device\n";
1926 # add JSON properties for create and set function
1927 sub json_config_properties
{
1930 foreach my $opt (keys %$confdesc) {
1931 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1932 $prop->{$opt} = $confdesc->{$opt};
1939 my ($key, $value) = @_;
1941 die "unknown setting '$key'\n" if !$confdesc->{$key};
1943 my $type = $confdesc->{$key}->{type
};
1945 if (!defined($value)) {
1946 die "got undefined value\n";
1949 if ($value =~ m/[\n\r]/) {
1950 die "property contains a line feed\n";
1953 if ($type eq 'boolean') {
1954 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1955 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1956 die "type check ('boolean') failed - got '$value'\n";
1957 } elsif ($type eq 'integer') {
1958 return int($1) if $value =~ m/^(\d+)$/;
1959 die "type check ('integer') failed - got '$value'\n";
1960 } elsif ($type eq 'number') {
1961 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1962 die "type check ('number') failed - got '$value'\n";
1963 } elsif ($type eq 'string') {
1964 if (my $fmt = $confdesc->{$key}->{format
}) {
1965 if ($fmt eq 'pve-qm-drive') {
1966 # special case - we need to pass $key to parse_drive()
1967 my $drive = parse_drive
($key, $value);
1968 return $value if $drive;
1969 die "unable to parse drive options\n";
1971 PVE
::JSONSchema
::check_format
($fmt, $value);
1974 $value =~ s/^\"(.*)\"$/$1/;
1977 die "internal error"
1981 sub check_iommu_support
{
1982 #fixme : need to check IOMMU support
1983 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1993 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1994 utime undef, undef, $conf;
1998 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2000 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2002 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2004 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2006 # only remove disks owned by this VM
2007 foreach_drive
($conf, sub {
2008 my ($ds, $drive) = @_;
2010 return if drive_is_cdrom
($drive);
2012 my $volid = $drive->{file
};
2014 return if !$volid || $volid =~ m
|^/|;
2016 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2017 return if !$path || !$owner || ($owner != $vmid);
2019 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2022 if ($keep_empty_config) {
2023 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2028 # also remove unused disk
2030 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2033 PVE
::Storage
::foreach_volid
($dl, sub {
2034 my ($volid, $sid, $volname, $d) = @_;
2035 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2044 sub parse_vm_config
{
2045 my ($filename, $raw) = @_;
2047 return undef if !defined($raw);
2050 digest
=> Digest
::SHA
::sha1_hex
($raw),
2055 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2056 || die "got strange filename '$filename'";
2064 my @lines = split(/\n/, $raw);
2065 foreach my $line (@lines) {
2066 next if $line =~ m/^\s*$/;
2068 if ($line =~ m/^\[PENDING\]\s*$/i) {
2069 $section = 'pending';
2070 if (defined($descr)) {
2072 $conf->{description
} = $descr;
2075 $conf = $res->{$section} = {};
2078 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2080 if (defined($descr)) {
2082 $conf->{description
} = $descr;
2085 $conf = $res->{snapshots
}->{$section} = {};
2089 if ($line =~ m/^\#(.*)\s*$/) {
2090 $descr = '' if !defined($descr);
2091 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2095 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2096 $descr = '' if !defined($descr);
2097 $descr .= PVE
::Tools
::decode_text
($2);
2098 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2099 $conf->{snapstate
} = $1;
2100 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2103 $conf->{$key} = $value;
2104 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2106 if ($section eq 'pending') {
2107 $conf->{delete} = $value; # we parse this later
2109 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2111 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2114 eval { $value = check_type
($key, $value); };
2116 warn "vm $vmid - unable to parse value of '$key' - $@";
2118 my $fmt = $confdesc->{$key}->{format
};
2119 if ($fmt && $fmt eq 'pve-qm-drive') {
2120 my $v = parse_drive
($key, $value);
2121 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2122 $v->{file
} = $volid;
2123 $value = print_drive
($vmid, $v);
2125 warn "vm $vmid - unable to parse value of '$key'\n";
2130 if ($key eq 'cdrom') {
2131 $conf->{ide2
} = $value;
2133 $conf->{$key} = $value;
2139 if (defined($descr)) {
2141 $conf->{description
} = $descr;
2143 delete $res->{snapstate
}; # just to be sure
2148 sub write_vm_config
{
2149 my ($filename, $conf) = @_;
2151 delete $conf->{snapstate
}; # just to be sure
2153 if ($conf->{cdrom
}) {
2154 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2155 $conf->{ide2
} = $conf->{cdrom
};
2156 delete $conf->{cdrom
};
2159 # we do not use 'smp' any longer
2160 if ($conf->{sockets
}) {
2161 delete $conf->{smp
};
2162 } elsif ($conf->{smp
}) {
2163 $conf->{sockets
} = $conf->{smp
};
2164 delete $conf->{cores
};
2165 delete $conf->{smp
};
2168 my $used_volids = {};
2170 my $cleanup_config = sub {
2171 my ($cref, $pending, $snapname) = @_;
2173 foreach my $key (keys %$cref) {
2174 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2175 $key eq 'snapstate' || $key eq 'pending';
2176 my $value = $cref->{$key};
2177 if ($key eq 'delete') {
2178 die "propertry 'delete' is only allowed in [PENDING]\n"
2180 # fixme: check syntax?
2183 eval { $value = check_type
($key, $value); };
2184 die "unable to parse value of '$key' - $@" if $@;
2186 $cref->{$key} = $value;
2188 if (!$snapname && is_valid_drivename
($key)) {
2189 my $drive = parse_drive
($key, $value);
2190 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2195 &$cleanup_config($conf);
2197 &$cleanup_config($conf->{pending
}, 1);
2199 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2200 die "internal error" if $snapname eq 'pending';
2201 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2204 # remove 'unusedX' settings if we re-add a volume
2205 foreach my $key (keys %$conf) {
2206 my $value = $conf->{$key};
2207 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2208 delete $conf->{$key};
2212 my $generate_raw_config = sub {
2213 my ($conf, $pending) = @_;
2217 # add description as comment to top of file
2218 if (defined(my $descr = $conf->{description
})) {
2220 foreach my $cl (split(/\n/, $descr)) {
2221 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2224 $raw .= "#\n" if $pending;
2228 foreach my $key (sort keys %$conf) {
2229 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2230 $raw .= "$key: $conf->{$key}\n";
2235 my $raw = &$generate_raw_config($conf);
2237 if (scalar(keys %{$conf->{pending
}})){
2238 $raw .= "\n[PENDING]\n";
2239 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2242 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2243 $raw .= "\n[$snapname]\n";
2244 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2254 # we use static defaults from our JSON schema configuration
2255 foreach my $key (keys %$confdesc) {
2256 if (defined(my $default = $confdesc->{$key}->{default})) {
2257 $res->{$key} = $default;
2261 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2262 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2268 my $vmlist = PVE
::Cluster
::get_vmlist
();
2270 return $res if !$vmlist || !$vmlist->{ids
};
2271 my $ids = $vmlist->{ids
};
2273 foreach my $vmid (keys %$ids) {
2274 my $d = $ids->{$vmid};
2275 next if !$d->{node
} || $d->{node
} ne $nodename;
2276 next if !$d->{type
} || $d->{type
} ne 'qemu';
2277 $res->{$vmid}->{exists} = 1;
2282 # test if VM uses local resources (to prevent migration)
2283 sub check_local_resources
{
2284 my ($conf, $noerr) = @_;
2288 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2289 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2291 foreach my $k (keys %$conf) {
2292 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2293 # sockets are safe: they will recreated be on the target side post-migrate
2294 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2295 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2298 die "VM uses local resources\n" if $loc_res && !$noerr;
2303 # check if used storages are available on all nodes (use by migrate)
2304 sub check_storage_availability
{
2305 my ($storecfg, $conf, $node) = @_;
2307 foreach_drive
($conf, sub {
2308 my ($ds, $drive) = @_;
2310 my $volid = $drive->{file
};
2313 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2316 # check if storage is available on both nodes
2317 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2318 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2322 # list nodes where all VM images are available (used by has_feature API)
2324 my ($conf, $storecfg) = @_;
2326 my $nodelist = PVE
::Cluster
::get_nodelist
();
2327 my $nodehash = { map { $_ => 1 } @$nodelist };
2328 my $nodename = PVE
::INotify
::nodename
();
2330 foreach_drive
($conf, sub {
2331 my ($ds, $drive) = @_;
2333 my $volid = $drive->{file
};
2336 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2338 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2339 if ($scfg->{disable
}) {
2341 } elsif (my $avail = $scfg->{nodes
}) {
2342 foreach my $node (keys %$nodehash) {
2343 delete $nodehash->{$node} if !$avail->{$node};
2345 } elsif (!$scfg->{shared
}) {
2346 foreach my $node (keys %$nodehash) {
2347 delete $nodehash->{$node} if $node ne $nodename
2357 my ($pidfile, $pid) = @_;
2359 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2363 return undef if !$line;
2364 my @param = split(/\0/, $line);
2366 my $cmd = $param[0];
2367 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2369 for (my $i = 0; $i < scalar (@param); $i++) {
2372 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2373 my $p = $param[$i+1];
2374 return 1 if $p && ($p eq $pidfile);
2383 my ($vmid, $nocheck, $node) = @_;
2385 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2387 die "unable to find configuration file for VM $vmid - no such machine\n"
2388 if !$nocheck && ! -f
$filename;
2390 my $pidfile = pidfile_name
($vmid);
2392 if (my $fd = IO
::File-
>new("<$pidfile")) {
2397 my $mtime = $st->mtime;
2398 if ($mtime > time()) {
2399 warn "file '$filename' modified in future\n";
2402 if ($line =~ m/^(\d+)$/) {
2404 if (check_cmdline
($pidfile, $pid)) {
2405 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2417 my $vzlist = config_list
();
2419 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2421 while (defined(my $de = $fd->read)) {
2422 next if $de !~ m/^(\d+)\.pid$/;
2424 next if !defined($vzlist->{$vmid});
2425 if (my $pid = check_running
($vmid)) {
2426 $vzlist->{$vmid}->{pid
} = $pid;
2434 my ($storecfg, $conf) = @_;
2436 my $bootdisk = $conf->{bootdisk
};
2437 return undef if !$bootdisk;
2438 return undef if !is_valid_drivename
($bootdisk);
2440 return undef if !$conf->{$bootdisk};
2442 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2443 return undef if !defined($drive);
2445 return undef if drive_is_cdrom
($drive);
2447 my $volid = $drive->{file
};
2448 return undef if !$volid;
2450 return $drive->{size
};
2453 my $last_proc_pid_stat;
2455 # get VM status information
2456 # This must be fast and should not block ($full == false)
2457 # We only query KVM using QMP if $full == true (this can be slow)
2459 my ($opt_vmid, $full) = @_;
2463 my $storecfg = PVE
::Storage
::config
();
2465 my $list = vzlist
();
2466 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2468 my $cpucount = $cpuinfo->{cpus
} || 1;
2470 foreach my $vmid (keys %$list) {
2471 next if $opt_vmid && ($vmid ne $opt_vmid);
2473 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2474 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2477 $d->{pid
} = $list->{$vmid}->{pid
};
2479 # fixme: better status?
2480 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2482 my $size = disksize
($storecfg, $conf);
2483 if (defined($size)) {
2484 $d->{disk
} = 0; # no info available
2485 $d->{maxdisk
} = $size;
2491 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2492 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2493 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2495 $d->{name
} = $conf->{name
} || "VM $vmid";
2496 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2498 if ($conf->{balloon
}) {
2499 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2500 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2511 $d->{diskwrite
} = 0;
2513 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2518 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2519 foreach my $dev (keys %$netdev) {
2520 next if $dev !~ m/^tap([1-9]\d*)i/;
2522 my $d = $res->{$vmid};
2525 $d->{netout
} += $netdev->{$dev}->{receive
};
2526 $d->{netin
} += $netdev->{$dev}->{transmit
};
2529 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2530 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2535 my $ctime = gettimeofday
;
2537 foreach my $vmid (keys %$list) {
2539 my $d = $res->{$vmid};
2540 my $pid = $d->{pid
};
2543 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2544 next if !$pstat; # not running
2546 my $used = $pstat->{utime} + $pstat->{stime
};
2548 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2550 if ($pstat->{vsize
}) {
2551 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2554 my $old = $last_proc_pid_stat->{$pid};
2556 $last_proc_pid_stat->{$pid} = {
2564 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2566 if ($dtime > 1000) {
2567 my $dutime = $used - $old->{used
};
2569 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2570 $last_proc_pid_stat->{$pid} = {
2576 $d->{cpu
} = $old->{cpu
};
2580 return $res if !$full;
2582 my $qmpclient = PVE
::QMPClient-
>new();
2584 my $ballooncb = sub {
2585 my ($vmid, $resp) = @_;
2587 my $info = $resp->{'return'};
2588 return if !$info->{max_mem
};
2590 my $d = $res->{$vmid};
2592 # use memory assigned to VM
2593 $d->{maxmem
} = $info->{max_mem
};
2594 $d->{balloon
} = $info->{actual
};
2596 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2597 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2598 $d->{freemem
} = $info->{free_mem
};
2601 $d->{ballooninfo
} = $info;
2604 my $blockstatscb = sub {
2605 my ($vmid, $resp) = @_;
2606 my $data = $resp->{'return'} || [];
2607 my $totalrdbytes = 0;
2608 my $totalwrbytes = 0;
2610 for my $blockstat (@$data) {
2611 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2612 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2614 $blockstat->{device
} =~ s/drive-//;
2615 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2617 $res->{$vmid}->{diskread
} = $totalrdbytes;
2618 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2621 my $statuscb = sub {
2622 my ($vmid, $resp) = @_;
2624 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2625 # this fails if ballon driver is not loaded, so this must be
2626 # the last commnand (following command are aborted if this fails).
2627 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2629 my $status = 'unknown';
2630 if (!defined($status = $resp->{'return'}->{status
})) {
2631 warn "unable to get VM status\n";
2635 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2638 foreach my $vmid (keys %$list) {
2639 next if $opt_vmid && ($vmid ne $opt_vmid);
2640 next if !$res->{$vmid}->{pid
}; # not running
2641 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2644 $qmpclient->queue_execute(undef, 1);
2646 foreach my $vmid (keys %$list) {
2647 next if $opt_vmid && ($vmid ne $opt_vmid);
2648 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2655 my ($conf, $func, @param) = @_;
2657 foreach my $ds (valid_drive_names
()) {
2658 next if !defined($conf->{$ds});
2660 my $drive = parse_drive
($ds, $conf->{$ds});
2663 &$func($ds, $drive, @param);
2668 my ($conf, $func, @param) = @_;
2672 my $test_volid = sub {
2673 my ($volid, $is_cdrom) = @_;
2677 $volhash->{$volid} = $is_cdrom || 0;
2680 foreach_drive
($conf, sub {
2681 my ($ds, $drive) = @_;
2682 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2685 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2686 my $snap = $conf->{snapshots
}->{$snapname};
2687 &$test_volid($snap->{vmstate
}, 0);
2688 foreach_drive
($snap, sub {
2689 my ($ds, $drive) = @_;
2690 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2694 foreach my $volid (keys %$volhash) {
2695 &$func($volid, $volhash->{$volid}, @param);
2699 sub vga_conf_has_spice
{
2702 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2707 sub config_to_command
{
2708 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2711 my $globalFlags = [];
2712 my $machineFlags = [];
2718 my $kvmver = kvm_user_version
();
2719 my $vernum = 0; # unknown
2720 my $ostype = $conf->{ostype
};
2721 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2722 $vernum = $1*1000000+$2*1000;
2723 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2724 $vernum = $1*1000000+$2*1000+$3;
2727 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2729 my $have_ovz = -f
'/proc/vz/vestat';
2731 my $q35 = machine_type_is_q35
($conf);
2732 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2733 my $machine_type = $forcemachine || $conf->{machine
};
2734 my $use_old_bios_files = undef;
2735 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2737 my $cpuunits = defined($conf->{cpuunits
}) ?
2738 $conf->{cpuunits
} : $defaults->{cpuunits
};
2740 push @$cmd, '/usr/bin/kvm';
2742 push @$cmd, '-id', $vmid;
2746 my $qmpsocket = qmp_socket
($vmid);
2747 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2748 push @$cmd, '-mon', "chardev=qmp,mode=control";
2751 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2753 push @$cmd, '-daemonize';
2755 if ($conf->{smbios1
}) {
2756 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2759 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2760 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2761 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2762 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2763 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2764 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2765 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2769 # the q35 chipset support native usb2, so we enable usb controller
2770 # by default for this machine type
2771 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2773 $pciaddr = print_pci_addr
("piix3", $bridges);
2774 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2777 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2778 next if !$conf->{"usb$i"};
2779 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2780 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2783 # include usb device config
2784 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2787 # add usb3 controller if needed
2790 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2791 next if !$conf->{"usb$i"};
2792 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2793 next if !$d || !$d->{usb3
};
2797 $pciaddr = print_pci_addr
("xhci", $bridges);
2798 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2800 my $vga = $conf->{vga
};
2802 my $qxlnum = vga_conf_has_spice
($vga);
2803 $vga = 'qxl' if $qxlnum;
2806 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2807 $conf->{ostype
} eq 'win7' ||
2808 $conf->{ostype
} eq 'w2k8')) {
2815 # enable absolute mouse coordinates (needed by vnc)
2817 if (defined($conf->{tablet
})) {
2818 $tablet = $conf->{tablet
};
2820 $tablet = $defaults->{tablet
};
2821 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2822 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2825 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2829 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2830 my $d = parse_hostpci
($conf->{"hostpci$i"});
2833 my $pcie = $d->{pcie
};
2835 die "q35 machine model is not enabled" if !$q35;
2836 $pciaddr = print_pcie_addr
("hostpci$i");
2838 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2841 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2843 if ($d->{'x-vga'}) {
2844 $xvga = ',x-vga=on';
2847 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2848 push @$cpuFlags , 'hv_vendor_id=proxmox';
2850 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2854 my $pcidevices = $d->{pciid
};
2855 my $multifunction = 1 if @$pcidevices > 1;
2858 foreach my $pcidevice (@$pcidevices) {
2860 my $id = "hostpci$i";
2861 $id .= ".$j" if $multifunction;
2862 my $addr = $pciaddr;
2863 $addr .= ".$j" if $multifunction;
2864 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2867 $devicestr .= "$rombar$xvga";
2868 $devicestr .= ",multifunction=on" if $multifunction;
2871 push @$devices, '-device', $devicestr;
2877 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2878 next if !$conf->{"usb$i"};
2879 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2882 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2884 if (defined($d->{usb3
}) && $d->{usb3
}) {
2885 $usbbus = ',bus=xhci.0';
2888 if (defined($d->{host
})) {
2889 $d = parse_usb_device
($d->{host
});
2890 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2891 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2892 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2893 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2894 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2895 # usb redir support for spice, currently no usb3
2896 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2897 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2903 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2904 if (my $path = $conf->{"serial$i"}) {
2905 if ($path eq 'socket') {
2906 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2907 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2908 push @$devices, '-device', "isa-serial,chardev=serial$i";
2910 die "no such serial device\n" if ! -c
$path;
2911 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2912 push @$devices, '-device', "isa-serial,chardev=serial$i";
2918 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2919 if (my $path = $conf->{"parallel$i"}) {
2920 die "no such parallel device\n" if ! -c
$path;
2921 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2922 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2923 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2927 my $vmname = $conf->{name
} || "vm$vmid";
2929 push @$cmd, '-name', $vmname;
2932 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2933 $sockets = $conf->{sockets
} if $conf->{sockets
};
2935 my $cores = $conf->{cores
} || 1;
2937 my $maxcpus = $sockets * $cores;
2939 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2941 my $allowed_vcpus = $cpuinfo->{cpus
};
2943 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2944 if ($allowed_vcpus < $maxcpus);
2946 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2948 push @$cmd, '-nodefaults';
2950 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2952 my $bootindex_hash = {};
2954 foreach my $o (split(//, $bootorder)) {
2955 $bootindex_hash->{$o} = $i*100;
2959 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2961 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2963 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2965 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2967 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2968 my $socket = vnc_socket
($vmid);
2969 push @$cmd, '-vnc', "unix:$socket,x509,password";
2971 push @$cmd, '-nographic';
2975 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2977 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2978 my $useLocaltime = $conf->{localtime};
2981 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2983 if ($ostype =~ m/^w/) { # windows
2984 $useLocaltime = 1 if !defined($conf->{localtime});
2986 # use time drift fix when acpi is enabled
2987 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2988 $tdf = 1 if !defined($conf->{tdf
});
2992 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2993 $ostype eq 'wvista') {
2994 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2995 push @$cmd, '-no-hpet';
2996 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2997 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2998 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2999 push @$cpuFlags , 'hv_time' if !$nokvm;
3001 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
3002 push @$cpuFlags , 'hv_reset' if !$nokvm;
3003 push @$cpuFlags , 'hv_vpindex' if !$nokvm;
3004 push @$cpuFlags , 'hv_runtime' if !$nokvm;
3008 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3012 if ($ostype eq 'win7' || $ostype eq 'win8') {
3013 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3017 push @$rtcFlags, 'driftfix=slew' if $tdf;
3020 push @$machineFlags, 'accel=tcg';
3022 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3025 if ($machine_type) {
3026 push @$machineFlags, "type=${machine_type}";
3029 if ($conf->{startdate
}) {
3030 push @$rtcFlags, "base=$conf->{startdate}";
3031 } elsif ($useLocaltime) {
3032 push @$rtcFlags, 'base=localtime';
3035 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3036 if (my $cputype = $conf->{cpu
}) {
3037 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3038 or die "Cannot parse cpu description: $cputype\n";
3039 $cpu = $cpuconf->{cputype
};
3040 $kvm_off = 1 if $cpuconf->{hidden
};
3043 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3045 push @$cpuFlags , '-x2apic'
3046 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3048 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3050 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3052 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3054 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3055 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3058 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3060 push @$cpuFlags, 'kvm=off' if $kvm_off;
3062 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3063 die "internal error"; # should not happen
3065 push @$cpuFlags, "vendor=${cpu_vendor}"
3066 if $cpu_vendor ne 'default';
3068 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3070 push @$cmd, '-cpu', $cpu;
3072 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3074 push @$cmd, '-S' if $conf->{freeze
};
3076 # set keyboard layout
3077 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3078 push @$cmd, '-k', $kb if $kb;
3081 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3082 #push @$cmd, '-soundhw', 'es1370';
3083 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3085 if($conf->{agent
}) {
3086 my $qgasocket = qmp_socket
($vmid, 1);
3087 my $pciaddr = print_pci_addr
("qga0", $bridges);
3088 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3089 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3090 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3097 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3098 for(my $i = 1; $i < $qxlnum; $i++){
3099 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3100 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3103 # assume other OS works like Linux
3104 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3105 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3109 my $pciaddr = print_pci_addr
("spice", $bridges);
3111 my $nodename = PVE
::INotify
::nodename
();
3112 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3113 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3115 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3117 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3118 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3119 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3122 # enable balloon by default, unless explicitly disabled
3123 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3124 $pciaddr = print_pci_addr
("balloon0", $bridges);
3125 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3128 if ($conf->{watchdog
}) {
3129 my $wdopts = parse_watchdog
($conf->{watchdog
});
3130 $pciaddr = print_pci_addr
("watchdog", $bridges);
3131 my $watchdog = $wdopts->{model
} || 'i6300esb';
3132 push @$devices, '-device', "$watchdog$pciaddr";
3133 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3137 my $scsicontroller = {};
3138 my $ahcicontroller = {};
3139 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3141 # Add iscsi initiator name if available
3142 if (my $initiator = get_initiator_name
()) {
3143 push @$devices, '-iscsi', "initiator-name=$initiator";
3146 foreach_drive
($conf, sub {
3147 my ($ds, $drive) = @_;
3149 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3150 push @$vollist, $drive->{file
};
3153 $use_virtio = 1 if $ds =~ m/^virtio/;
3155 if (drive_is_cdrom
($drive)) {
3156 if ($bootindex_hash->{d
}) {
3157 $drive->{bootindex
} = $bootindex_hash->{d
};
3158 $bootindex_hash->{d
} += 1;
3161 if ($bootindex_hash->{c
}) {
3162 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3163 $bootindex_hash->{c
} += 1;
3167 if($drive->{interface
} eq 'virtio'){
3168 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3171 if ($drive->{interface
} eq 'scsi') {
3173 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3175 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3176 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3179 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3180 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3181 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3182 } elsif ($drive->{iothread
}) {
3183 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3187 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3188 $queues = ",num_queues=$drive->{queues}";
3191 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3192 $scsicontroller->{$controller}=1;
3195 if ($drive->{interface
} eq 'sata') {
3196 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3197 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3198 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3199 $ahcicontroller->{$controller}=1;
3202 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3203 push @$devices, '-drive',$drive_cmd;
3204 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3207 for (my $i = 0; $i < $MAX_NETS; $i++) {
3208 next if !$conf->{"net$i"};
3209 my $d = parse_net
($conf->{"net$i"});
3212 $use_virtio = 1 if $d->{model
} eq 'virtio';
3214 if ($bootindex_hash->{n
}) {
3215 $d->{bootindex
} = $bootindex_hash->{n
};
3216 $bootindex_hash->{n
} += 1;
3219 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3220 push @$devices, '-netdev', $netdevfull;
3222 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3223 push @$devices, '-device', $netdevicefull;
3228 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3233 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3235 while (my ($k, $v) = each %$bridges) {
3236 $pciaddr = print_pci_addr
("pci.$k");
3237 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3242 if ($conf->{args
}) {
3243 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3247 push @$cmd, @$devices;
3248 push @$cmd, '-rtc', join(',', @$rtcFlags)
3249 if scalar(@$rtcFlags);
3250 push @$cmd, '-machine', join(',', @$machineFlags)
3251 if scalar(@$machineFlags);
3252 push @$cmd, '-global', join(',', @$globalFlags)
3253 if scalar(@$globalFlags);
3255 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3260 return "${var_run_tmpdir}/$vmid.vnc";
3266 my $res = vm_mon_cmd
($vmid, 'query-spice');
3268 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3272 my ($vmid, $qga) = @_;
3273 my $sockettype = $qga ?
'qga' : 'qmp';
3274 return "${var_run_tmpdir}/$vmid.$sockettype";
3279 return "${var_run_tmpdir}/$vmid.pid";
3282 sub vm_devices_list
{
3285 my $res = vm_mon_cmd
($vmid, 'query-pci');
3287 foreach my $pcibus (@$res) {
3288 foreach my $device (@{$pcibus->{devices
}}) {
3289 next if !$device->{'qdev_id'};
3290 if ($device->{'pci_bridge'}) {
3291 $devices->{$device->{'qdev_id'}} = 1;
3292 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3293 next if !$bridge_device->{'qdev_id'};
3294 $devices->{$bridge_device->{'qdev_id'}} = 1;
3295 $devices->{$device->{'qdev_id'}}++;
3298 $devices->{$device->{'qdev_id'}} = 1;
3303 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3304 foreach my $block (@$resblock) {
3305 if($block->{device
} =~ m/^drive-(\S+)/){
3310 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3311 foreach my $mice (@$resmice) {
3312 if ($mice->{name
} eq 'QEMU HID Tablet') {
3313 $devices->{tablet
} = 1;
3322 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3324 my $q35 = machine_type_is_q35
($conf);
3326 my $devices_list = vm_devices_list
($vmid);
3327 return 1 if defined($devices_list->{$deviceid});
3329 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3331 if ($deviceid eq 'tablet') {
3333 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3335 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3337 qemu_iothread_add
($vmid, $deviceid, $device);
3339 qemu_driveadd
($storecfg, $vmid, $device);
3340 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3342 qemu_deviceadd
($vmid, $devicefull);
3343 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3345 eval { qemu_drivedel
($vmid, $deviceid); };
3350 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3353 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3354 my $pciaddr = print_pci_addr
($deviceid);
3355 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3357 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3359 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3360 qemu_iothread_add
($vmid, $deviceid, $device);
3361 $devicefull .= ",iothread=iothread-$deviceid";
3364 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3365 $devicefull .= ",num_queues=$device->{queues}";
3368 qemu_deviceadd
($vmid, $devicefull);
3369 qemu_deviceaddverify
($vmid, $deviceid);
3371 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3373 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3374 qemu_driveadd
($storecfg, $vmid, $device);
3376 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3377 eval { qemu_deviceadd
($vmid, $devicefull); };
3379 eval { qemu_drivedel
($vmid, $deviceid); };
3384 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3386 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3388 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3389 my $use_old_bios_files = undef;
3390 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3392 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3393 qemu_deviceadd
($vmid, $netdevicefull);
3394 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3396 eval { qemu_netdevdel
($vmid, $deviceid); };
3401 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3404 my $pciaddr = print_pci_addr
($deviceid);
3405 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3407 qemu_deviceadd
($vmid, $devicefull);
3408 qemu_deviceaddverify
($vmid, $deviceid);
3411 die "can't hotplug device '$deviceid'\n";
3417 # fixme: this should raise exceptions on error!
3418 sub vm_deviceunplug
{
3419 my ($vmid, $conf, $deviceid) = @_;
3421 my $devices_list = vm_devices_list
($vmid);
3422 return 1 if !defined($devices_list->{$deviceid});
3424 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3426 if ($deviceid eq 'tablet') {
3428 qemu_devicedel
($vmid, $deviceid);
3430 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3432 qemu_devicedel
($vmid, $deviceid);
3433 qemu_devicedelverify
($vmid, $deviceid);
3434 qemu_drivedel
($vmid, $deviceid);
3435 qemu_iothread_del
($conf, $vmid, $deviceid);
3437 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3439 qemu_devicedel
($vmid, $deviceid);
3440 qemu_devicedelverify
($vmid, $deviceid);
3441 qemu_iothread_del
($conf, $vmid, $deviceid);
3443 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3445 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3446 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3447 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3449 qemu_devicedel
($vmid, $deviceid);
3450 qemu_drivedel
($vmid, $deviceid);
3451 qemu_deletescsihw
($conf, $vmid, $deviceid);
3453 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3455 qemu_devicedel
($vmid, $deviceid);
3456 qemu_devicedelverify
($vmid, $deviceid);
3457 qemu_netdevdel
($vmid, $deviceid);
3460 die "can't unplug device '$deviceid'\n";
3466 sub qemu_deviceadd
{
3467 my ($vmid, $devicefull) = @_;
3469 $devicefull = "driver=".$devicefull;
3470 my %options = split(/[=,]/, $devicefull);
3472 vm_mon_cmd
($vmid, "device_add" , %options);
3475 sub qemu_devicedel
{
3476 my ($vmid, $deviceid) = @_;
3478 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3481 sub qemu_iothread_add
{
3482 my($vmid, $deviceid, $device) = @_;
3484 if ($device->{iothread
}) {
3485 my $iothreads = vm_iothreads_list
($vmid);
3486 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3490 sub qemu_iothread_del
{
3491 my($conf, $vmid, $deviceid) = @_;
3493 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3494 if ($device->{iothread
}) {
3495 my $iothreads = vm_iothreads_list
($vmid);
3496 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3500 sub qemu_objectadd
{
3501 my($vmid, $objectid, $qomtype) = @_;
3503 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3508 sub qemu_objectdel
{
3509 my($vmid, $objectid) = @_;
3511 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3517 my ($storecfg, $vmid, $device) = @_;
3519 my $drive = print_drive_full
($storecfg, $vmid, $device);
3520 $drive =~ s/\\/\\\\/g;
3521 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3523 # If the command succeeds qemu prints: "OK
"
3524 return 1 if $ret =~ m/OK/s;
3526 die "adding drive failed
: $ret\n";
3530 my($vmid, $deviceid) = @_;
3532 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3535 return 1 if $ret eq "";
3537 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3538 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3540 die "deleting drive
$deviceid failed
: $ret\n";
3543 sub qemu_deviceaddverify {
3544 my ($vmid, $deviceid) = @_;
3546 for (my $i = 0; $i <= 5; $i++) {
3547 my $devices_list = vm_devices_list($vmid);
3548 return 1 if defined($devices_list->{$deviceid});
3552 die "error on hotplug device
'$deviceid'\n";
3556 sub qemu_devicedelverify {
3557 my ($vmid, $deviceid) = @_;
3559 # need to verify that the device is correctly removed as device_del
3560 # is async and empty return is not reliable
3562 for (my $i = 0; $i <= 5; $i++) {
3563 my $devices_list = vm_devices_list($vmid);
3564 return 1 if !defined($devices_list->{$deviceid});
3568 die "error on hot-unplugging device
'$deviceid'\n";
3571 sub qemu_findorcreatescsihw {
3572 my ($storecfg, $conf, $vmid, $device) = @_;
3574 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3576 my $scsihwid="$controller_prefix$controller";
3577 my $devices_list = vm_devices_list($vmid);
3579 if(!defined($devices_list->{$scsihwid})) {
3580 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3586 sub qemu_deletescsihw {
3587 my ($conf, $vmid, $opt) = @_;
3589 my $device = parse_drive($opt, $conf->{$opt});
3591 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3592 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3596 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3598 my $devices_list = vm_devices_list($vmid);
3599 foreach my $opt (keys %{$devices_list}) {
3600 if (PVE::QemuServer::is_valid_drivename($opt)) {
3601 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3602 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3608 my $scsihwid="scsihw
$controller";
3610 vm_deviceunplug($vmid, $conf, $scsihwid);
3615 sub qemu_add_pci_bridge {
3616 my ($storecfg, $conf, $vmid, $device) = @_;
3622 print_pci_addr($device, $bridges);
3624 while (my ($k, $v) = each %$bridges) {
3627 return 1 if !defined($bridgeid) || $bridgeid < 1;
3629 my $bridge = "pci
.$bridgeid";
3630 my $devices_list = vm_devices_list($vmid);
3632 if (!defined($devices_list->{$bridge})) {
3633 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3639 sub qemu_set_link_status {
3640 my ($vmid, $device, $up) = @_;
3642 vm_mon_cmd($vmid, "set_link
", name => $device,
3643 up => $up ? JSON::true : JSON::false);
3646 sub qemu_netdevadd {
3647 my ($vmid, $conf, $device, $deviceid) = @_;
3649 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3650 my %options = split(/[=,]/, $netdev);
3652 vm_mon_cmd($vmid, "netdev_add
", %options);
3656 sub qemu_netdevdel {
3657 my ($vmid, $deviceid) = @_;
3659 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3662 sub qemu_cpu_hotplug {
3663 my ($vmid, $conf, $vcpus) = @_;
3666 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3667 $sockets = $conf->{sockets} if $conf->{sockets};
3668 my $cores = $conf->{cores} || 1;
3669 my $maxcpus = $sockets * $cores;
3671 $vcpus = $maxcpus if !$vcpus;
3673 die "you can
't add more vcpus than maxcpus\n"
3674 if $vcpus > $maxcpus;
3676 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3677 die "online cpu unplug is not yet possible\n"
3678 if $vcpus < $currentvcpus;
3680 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3681 die "vcpus in running vm is different than configuration\n"
3682 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3684 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3685 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3689 sub qemu_block_set_io_throttle {
3690 my ($vmid, $deviceid,
3691 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3692 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3694 return if !check_running($vmid) ;
3696 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3698 bps_rd => int($bps_rd),
3699 bps_wr => int($bps_wr),
3701 iops_rd => int($iops_rd),
3702 iops_wr => int($iops_wr),
3703 bps_max => int($bps_max),
3704 bps_rd_max => int($bps_rd_max),
3705 bps_wr_max => int($bps_wr_max),
3706 iops_max => int($iops_max),
3707 iops_rd_max => int($iops_rd_max),
3708 iops_wr_max => int($iops_wr_max)
3713 # old code, only used to shutdown old VM after update
3715 my ($fh, $timeout) = @_;
3717 my $sel = new IO::Select;
3724 while (scalar (@ready = $sel->can_read($timeout))) {
3726 if ($count = $fh->sysread($buf, 8192)) {
3727 if ($buf =~ /^(.*)\(qemu\) $/s) {
3734 if (!defined($count)) {
3741 die "monitor read timeout\n" if !scalar(@ready);
3746 # old code, only used to shutdown old VM after update
3747 sub vm_monitor_command {
3748 my ($vmid, $cmdstr, $nocheck) = @_;
3753 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3755 my $sname = "${var_run_tmpdir}/$vmid.mon";
3757 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3758 die "unable to connect to VM $vmid socket - $!\n";
3762 # hack: migrate sometime blocks the monitor (when migrate_downtime
3764 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3765 $timeout = 60*60; # 1 hour
3769 my $data = __read_avail($sock, $timeout);
3771 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3772 die "got unexpected qemu monitor banner\n";
3775 my $sel = new IO::Select;
3778 if (!scalar(my @ready = $sel->can_write($timeout))) {
3779 die "monitor write error - timeout";
3782 my $fullcmd = "$cmdstr\r";
3784 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3787 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3788 die "monitor write error - $!";
3791 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3795 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3796 $timeout = 60*60; # 1 hour
3797 } elsif ($cmdstr =~ m/^(eject|change)/) {
3798 $timeout = 60; # note: cdrom mount command is slow
3800 if ($res = __read_avail($sock, $timeout)) {
3802 my @lines = split("\r?\n", $res);
3804 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3806 $res = join("\n", @lines);
3814 syslog("err", "VM $vmid monitor command failed - $err");
3821 sub qemu_block_resize {
3822 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3824 my $running = check_running($vmid);
3826 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3828 return if !$running;
3830 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3834 sub qemu_volume_snapshot {
3835 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3837 my $running = check_running($vmid);
3839 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3840 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3842 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3846 sub qemu_volume_snapshot_delete {
3847 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3849 my $running = check_running($vmid);
3851 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3853 return if !$running;
3855 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
3858 sub set_migration_caps {
3864 "auto-converge" => 1,
3866 "x-rdma-pin-all" => 0,
3871 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
3873 for my $supported_capability (@$supported_capabilities) {
3875 capability => $supported_capability->{capability},
3876 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3880 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
3883 my $fast_plug_option = {
3892 # hotplug changes in [PENDING]
3893 # $selection hash can be used to only apply specified options, for
3894 # example: { cores => 1 } (only apply changed 'cores
')
3895 # $errors ref is used to return error messages
3896 sub vmconfig_hotplug_pending {
3897 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3899 my $defaults = load_defaults();
3901 # commit values which do not have any impact on running VM first
3902 # Note: those option cannot raise errors, we we do not care about
3903 # $selection and always apply them.
3905 my $add_error = sub {
3906 my ($opt, $msg) = @_;
3907 $errors->{$opt} = "hotplug problem - $msg";
3911 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3912 if ($fast_plug_option->{$opt}) {
3913 $conf->{$opt} = $conf->{pending}->{$opt};
3914 delete $conf->{pending}->{$opt};
3920 PVE::QemuConfig->write_config($vmid, $conf);
3921 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3924 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3926 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3927 while (my ($opt, $force) = each %$pending_delete_hash) {
3928 next if $selection && !$selection->{$opt};
3930 if ($opt eq 'hotplug
') {
3931 die "skip\n" if ($conf->{hotplug} =~ /memory/);
3932 } elsif ($opt eq 'tablet
') {
3933 die "skip\n" if !$hotplug_features->{usb};
3934 if ($defaults->{tablet}) {
3935 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3937 vm_deviceunplug($vmid, $conf, $opt);
3939 } elsif ($opt eq 'vcpus
') {
3940 die "skip\n" if !$hotplug_features->{cpu};
3941 qemu_cpu_hotplug($vmid, $conf, undef);
3942 } elsif ($opt eq 'balloon
') {
3943 # enable balloon device is not hotpluggable
3944 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
3945 } elsif ($fast_plug_option->{$opt}) {
3947 } elsif ($opt =~ m/^net(\d+)$/) {
3948 die "skip\n" if !$hotplug_features->{network};
3949 vm_deviceunplug($vmid, $conf, $opt);
3950 } elsif (is_valid_drivename($opt)) {
3951 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3952 vm_deviceunplug($vmid, $conf, $opt);
3953 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3954 } elsif ($opt =~ m/^memory$/) {
3955 die "skip\n" if !$hotplug_features->{memory};
3956 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3957 } elsif ($opt eq 'cpuunits
') {
3958 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
3959 } elsif ($opt eq 'cpulimit
') {
3960 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
3966 &$add_error($opt, $err) if $err ne "skip\n";
3968 # save new config if hotplug was successful
3969 delete $conf->{$opt};
3970 vmconfig_undelete_pending_option($conf, $opt);
3971 PVE::QemuConfig->write_config($vmid, $conf);
3972 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3976 foreach my $opt (keys %{$conf->{pending}}) {
3977 next if $selection && !$selection->{$opt};
3978 my $value = $conf->{pending}->{$opt};
3980 if ($opt eq 'hotplug
') {
3981 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3982 } elsif ($opt eq 'tablet
') {
3983 die "skip\n" if !$hotplug_features->{usb};
3985 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3986 } elsif ($value == 0) {
3987 vm_deviceunplug($vmid, $conf, $opt);
3989 } elsif ($opt eq 'vcpus
') {
3990 die "skip\n" if !$hotplug_features->{cpu};
3991 qemu_cpu_hotplug($vmid, $conf, $value);
3992 } elsif ($opt eq 'balloon
') {
3993 # enable/disable balloning device is not hotpluggable
3994 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3995 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3996 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
3998 # allow manual ballooning if shares is set to zero
3999 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4000 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4001 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4003 } elsif ($opt =~ m/^net(\d+)$/) {
4004 # some changes can be done without hotplug
4005 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4006 $vmid, $opt, $value);
4007 } elsif (is_valid_drivename($opt)) {
4008 # some changes can be done without hotplug
4009 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4010 $vmid, $opt, $value, 1);
4011 } elsif ($opt =~ m/^memory$/) { #dimms
4012 die "skip\n" if !$hotplug_features->{memory};
4013 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4014 } elsif ($opt eq 'cpuunits
') {
4015 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4016 } elsif ($opt eq 'cpulimit
') {
4017 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4018 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4020 die "skip\n"; # skip non-hot-pluggable options
4024 &$add_error($opt, $err) if $err ne "skip\n";
4026 # save new config if hotplug was successful
4027 $conf->{$opt} = $value;
4028 delete $conf->{pending}->{$opt};
4029 PVE::QemuConfig->write_config($vmid, $conf);
4030 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4035 sub try_deallocate_drive {
4036 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4038 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4039 my $volid = $drive->{file};
4040 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4041 my $sid = PVE::Storage::parse_volume_id($volid);
4042 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4044 # check if the disk is really unused
4045 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4046 if is_volume_in_use($storecfg, $conf, $key, $volid);
4047 PVE::Storage::vdisk_free($storecfg, $volid);
4050 # If vm is not owner of this disk remove from config
4058 sub vmconfig_delete_or_detach_drive {
4059 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4061 my $drive = parse_drive($opt, $conf->{$opt});
4063 my $rpcenv = PVE::RPCEnvironment::get();
4064 my $authuser = $rpcenv->get_user();
4067 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4068 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4070 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4074 sub vmconfig_apply_pending {
4075 my ($vmid, $conf, $storecfg) = @_;
4079 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4080 while (my ($opt, $force) = each %$pending_delete_hash) {
4081 die "internal error" if $opt =~ m/^unused/;
4082 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4083 if (!defined($conf->{$opt})) {
4084 vmconfig_undelete_pending_option($conf, $opt);
4085 PVE::QemuConfig->write_config($vmid, $conf);
4086 } elsif (is_valid_drivename($opt)) {
4087 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4088 vmconfig_undelete_pending_option($conf, $opt);
4089 delete $conf->{$opt};
4090 PVE::QemuConfig->write_config($vmid, $conf);
4092 vmconfig_undelete_pending_option($conf, $opt);
4093 delete $conf->{$opt};
4094 PVE::QemuConfig->write_config($vmid, $conf);
4098 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4100 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4101 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4103 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4104 # skip if nothing changed
4105 } elsif (is_valid_drivename($opt)) {
4106 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4107 if defined($conf->{$opt});
4108 $conf->{$opt} = $conf->{pending}->{$opt};
4110 $conf->{$opt} = $conf->{pending}->{$opt};
4113 delete $conf->{pending}->{$opt};
4114 PVE::QemuConfig->write_config($vmid, $conf);
4118 my $safe_num_ne = sub {
4121 return 0 if !defined($a) && !defined($b);
4122 return 1 if !defined($a);
4123 return 1 if !defined($b);
4128 my $safe_string_ne = sub {
4131 return 0 if !defined($a) && !defined($b);
4132 return 1 if !defined($a);
4133 return 1 if !defined($b);
4138 sub vmconfig_update_net {
4139 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4141 my $newnet = parse_net($value);
4143 if ($conf->{$opt}) {
4144 my $oldnet = parse_net($conf->{$opt});
4146 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4147 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4148 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4149 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4151 # for non online change, we try to hot-unplug
4152 die "skip\n" if !$hotplug;
4153 vm_deviceunplug($vmid, $conf, $opt);
4156 die "internal error" if $opt !~ m/net(\d+)/;
4157 my $iface = "tap${vmid}i$1";
4159 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4160 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4161 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4162 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4163 PVE::Network::tap_unplug($iface);
4164 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4165 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4166 # Rate can be applied on its own but any change above needs to
4167 # include the rate in tap_plug since OVS resets everything.
4168 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4171 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4172 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4180 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4186 sub vmconfig_update_disk {
4187 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4189 # fixme: do we need force?
4191 my $drive = parse_drive($opt, $value);
4193 if ($conf->{$opt}) {
4195 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4197 my $media = $drive->{media} || 'disk
';
4198 my $oldmedia = $old_drive->{media} || 'disk
';
4199 die "unable to change media type\n" if $media ne $oldmedia;
4201 if (!drive_is_cdrom($old_drive)) {
4203 if ($drive->{file} ne $old_drive->{file}) {
4205 die "skip\n" if !$hotplug;
4207 # unplug and register as unused
4208 vm_deviceunplug($vmid, $conf, $opt);
4209 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4212 # update existing disk
4214 # skip non hotpluggable value
4215 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4216 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4217 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4218 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4223 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4224 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4225 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4226 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4227 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4228 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4229 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4230 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4231 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4232 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4233 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4234 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4236 qemu_block_set_io_throttle($vmid,"drive-$opt",
4237 ($drive->{mbps} || 0)*1024*1024,
4238 ($drive->{mbps_rd} || 0)*1024*1024,
4239 ($drive->{mbps_wr} || 0)*1024*1024,
4240 $drive->{iops} || 0,
4241 $drive->{iops_rd} || 0,
4242 $drive->{iops_wr} || 0,
4243 ($drive->{mbps_max} || 0)*1024*1024,
4244 ($drive->{mbps_rd_max} || 0)*1024*1024,
4245 ($drive->{mbps_wr_max} || 0)*1024*1024,
4246 $drive->{iops_max} || 0,
4247 $drive->{iops_rd_max} || 0,
4248 $drive->{iops_wr_max} || 0);
4257 if ($drive->{file} eq 'none
') {
4258 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4260 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4261 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4262 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4270 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4272 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4273 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4277 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4278 $forcemachine, $spice_ticket) = @_;
4280 PVE::QemuConfig->lock_config($vmid, sub {
4281 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4283 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4285 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4287 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4289 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4290 vmconfig_apply_pending($vmid, $conf, $storecfg);
4291 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4294 my $defaults = load_defaults();
4296 # set environment variable useful inside network script
4297 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4299 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4301 my $migrate_port = 0;
4304 if ($statefile eq 'tcp
') {
4305 my $localip = "localhost";
4306 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4307 my $nodename = PVE::INotify::nodename();
4308 if ($datacenterconf->{migration_unsecure}) {
4309 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4310 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4312 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4313 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4314 $migrate_uri = "tcp:${localip}:${migrate_port}";
4315 push @$cmd, '-incoming
', $migrate_uri;
4318 } elsif ($statefile eq 'unix
') {
4319 # should be default for secure migrations as a ssh TCP forward
4320 # tunnel is not deterministic reliable ready and fails regurarly
4321 # to set up in time, so use UNIX socket forwards
4322 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4323 unlink $socket_addr;
4325 $migrate_uri = "unix:$socket_addr";
4327 push @$cmd, '-incoming
', $migrate_uri;
4331 push @$cmd, '-loadstate
', $statefile;
4338 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4339 my $d = parse_hostpci($conf->{"hostpci$i"});
4341 my $pcidevices = $d->{pciid};
4342 foreach my $pcidevice (@$pcidevices) {
4343 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4345 my $info = pci_device_info("0000:$pciid");
4346 die "IOMMU not present\n" if !check_iommu_support();
4347 die "no pci device info for device '$pciid'\n" if !$info;
4348 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4349 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4353 PVE::Storage::activate_volumes($storecfg, $vollist);
4355 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4357 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4358 eval { run_command($cmd); };
4361 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4362 : $defaults->{cpuunits};
4364 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4367 Slice => 'qemu
.slice
',
4369 CPUShares => $cpuunits
4372 if (my $cpulimit = $conf->{cpulimit}) {
4373 $properties{CPUQuota} = int($cpulimit * 100);
4375 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4377 if ($conf->{hugepages}) {
4380 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4381 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4383 PVE::QemuServer::Memory::hugepages_mount();
4384 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4387 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4388 run_command($cmd, %run_params);
4392 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4396 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4398 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4402 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4403 run_command($cmd, %run_params);
4408 # deactivate volumes if start fails
4409 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4410 die "start failed: $err";
4413 print "migration listens on $migrate_uri\n" if $migrate_uri;
4415 if ($statefile && $statefile ne 'tcp
') {
4416 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4420 if ($migratedfrom) {
4423 set_migration_caps($vmid);
4428 print "spice listens on port $spice_port\n";
4429 if ($spice_ticket) {
4430 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4431 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4437 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4438 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4439 if $conf->{balloon};
4442 foreach my $opt (keys %$conf) {
4443 next if $opt !~ m/^net\d+$/;
4444 my $nicconf = parse_net($conf->{$opt});
4445 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4449 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4450 path => "machine/peripheral/balloon0",
4451 property => "guest-stats-polling-interval",
4452 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4458 my ($vmid, $execute, %params) = @_;
4460 my $cmd = { execute => $execute, arguments => \%params };
4461 vm_qmp_command($vmid, $cmd);
4464 sub vm_mon_cmd_nocheck {
4465 my ($vmid, $execute, %params) = @_;
4467 my $cmd = { execute => $execute, arguments => \%params };
4468 vm_qmp_command($vmid, $cmd, 1);
4471 sub vm_qmp_command {
4472 my ($vmid, $cmd, $nocheck) = @_;
4477 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4478 $timeout = $cmd->{arguments}->{timeout};
4479 delete $cmd->{arguments}->{timeout};
4483 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4484 my $sname = qmp_socket($vmid);
4485 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4486 my $qmpclient = PVE::QMPClient->new();
4488 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4489 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4490 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4491 if scalar(%{$cmd->{arguments}});
4492 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4494 die "unable to
open monitor
socket\n";
4498 syslog("err
", "VM
$vmid qmp command failed
- $err");
4505 sub vm_human_monitor_command {
4506 my ($vmid, $cmdline) = @_;
4511 execute => 'human-monitor-command',
4512 arguments => { 'command-line' => $cmdline},
4515 return vm_qmp_command($vmid, $cmd);
4518 sub vm_commandline {
4519 my ($storecfg, $vmid) = @_;
4521 my $conf = PVE::QemuConfig->load_config($vmid);
4523 my $defaults = load_defaults();
4525 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4527 return join(' ', @$cmd);
4531 my ($vmid, $skiplock) = @_;
4533 PVE::QemuConfig->lock_config($vmid, sub {
4535 my $conf = PVE::QemuConfig->load_config($vmid);
4537 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4539 vm_mon_cmd($vmid, "system_reset
");
4543 sub get_vm_volumes {
4547 foreach_volid($conf, sub {
4548 my ($volid, $is_cdrom) = @_;
4550 return if $volid =~ m|^/|;
4552 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4555 push @$vollist, $volid;
4561 sub vm_stop_cleanup {
4562 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4567 my $vollist = get_vm_volumes($conf);
4568 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4571 foreach my $ext (qw(mon qmp pid vnc qga)) {
4572 unlink "/var/run/qemu-server/${vmid}.$ext";
4575 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4577 warn $@ if $@; # avoid errors - just warn
4580 # Note: use $nockeck to skip tests if VM configuration file exists.
4581 # We need that when migration VMs to other nodes (files already moved)
4582 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4584 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4586 $force = 1 if !defined($force) && !$shutdown;
4589 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4590 kill 15, $pid if $pid;
4591 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4592 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4596 PVE
::QemuConfig-
>lock_config($vmid, sub {
4598 my $pid = check_running
($vmid, $nocheck);
4603 $conf = PVE
::QemuConfig-
>load_config($vmid);
4604 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4605 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4606 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4607 $timeout = $opts->{down
} if $opts->{down
};
4611 $timeout = 60 if !defined($timeout);
4615 if (defined($conf) && $conf->{agent
}) {
4616 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4618 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4621 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4628 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4633 if ($count >= $timeout) {
4635 warn "VM still running - terminating now with SIGTERM\n";
4638 die "VM quit/powerdown failed - got timeout\n";
4641 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4646 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4649 die "VM quit/powerdown failed\n";
4657 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4662 if ($count >= $timeout) {
4663 warn "VM still running - terminating now with SIGKILL\n";
4668 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4673 my ($vmid, $skiplock) = @_;
4675 PVE
::QemuConfig-
>lock_config($vmid, sub {
4677 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4679 PVE
::QemuConfig-
>check_lock($conf)
4680 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4682 vm_mon_cmd
($vmid, "stop");
4687 my ($vmid, $skiplock, $nocheck) = @_;
4689 PVE
::QemuConfig-
>lock_config($vmid, sub {
4693 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4695 PVE
::QemuConfig-
>check_lock($conf)
4696 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4698 vm_mon_cmd
($vmid, "cont");
4701 vm_mon_cmd_nocheck
($vmid, "cont");
4707 my ($vmid, $skiplock, $key) = @_;
4709 PVE
::QemuConfig-
>lock_config($vmid, sub {
4711 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4713 # there is no qmp command, so we use the human monitor command
4714 vm_human_monitor_command
($vmid, "sendkey $key");
4719 my ($storecfg, $vmid, $skiplock) = @_;
4721 PVE
::QemuConfig-
>lock_config($vmid, sub {
4723 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4725 if (!check_running
($vmid)) {
4726 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4728 die "VM $vmid is running - destroy failed\n";
4736 my ($filename, $buf) = @_;
4738 my $fh = IO
::File-
>new($filename, "w");
4739 return undef if !$fh;
4741 my $res = print $fh $buf;
4748 sub pci_device_info
{
4753 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4754 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4756 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4757 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4759 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4760 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4762 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4763 return undef if !defined($product) || $product !~ s/^0x//;
4768 product
=> $product,
4774 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4783 my $name = $dev->{name
};
4785 my $fn = "$pcisysfs/devices/$name/reset";
4787 return file_write
($fn, "1");
4790 sub pci_dev_bind_to_vfio
{
4793 my $name = $dev->{name
};
4795 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4797 if (!-d
$vfio_basedir) {
4798 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4800 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4802 my $testdir = "$vfio_basedir/$name";
4803 return 1 if -d
$testdir;
4805 my $data = "$dev->{vendor} $dev->{product}";
4806 return undef if !file_write
("$vfio_basedir/new_id", $data);
4808 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4809 if (!file_write
($fn, $name)) {
4810 return undef if -f
$fn;
4813 $fn = "$vfio_basedir/bind";
4814 if (! -d
$testdir) {
4815 return undef if !file_write
($fn, $name);
4821 sub pci_dev_group_bind_to_vfio
{
4824 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4826 if (!-d
$vfio_basedir) {
4827 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4829 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4831 # get IOMMU group devices
4832 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4833 my @devs = grep /^0000:/, readdir($D);
4836 foreach my $pciid (@devs) {
4837 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4839 # pci bridges, switches or root ports are not supported
4840 # they have a pci_bus subdirectory so skip them
4841 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4843 my $info = pci_device_info
($1);
4844 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4850 # vzdump restore implementaion
4852 sub tar_archive_read_firstfile
{
4853 my $archive = shift;
4855 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4857 # try to detect archive type first
4858 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
4859 die "unable to open file '$archive'\n";
4860 my $firstfile = <$fh>;
4864 die "ERROR: archive contaions no data\n" if !$firstfile;
4870 sub tar_restore_cleanup
{
4871 my ($storecfg, $statfile) = @_;
4873 print STDERR
"starting cleanup\n";
4875 if (my $fd = IO
::File-
>new($statfile, "r")) {
4876 while (defined(my $line = <$fd>)) {
4877 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4880 if ($volid =~ m
|^/|) {
4881 unlink $volid || die 'unlink failed\n';
4883 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4885 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4887 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4889 print STDERR
"unable to parse line in statfile - $line";
4896 sub restore_archive
{
4897 my ($archive, $vmid, $user, $opts) = @_;
4899 my $format = $opts->{format
};
4902 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4903 $format = 'tar' if !$format;
4905 } elsif ($archive =~ m/\.tar$/) {
4906 $format = 'tar' if !$format;
4907 } elsif ($archive =~ m/.tar.lzo$/) {
4908 $format = 'tar' if !$format;
4910 } elsif ($archive =~ m/\.vma$/) {
4911 $format = 'vma' if !$format;
4912 } elsif ($archive =~ m/\.vma\.gz$/) {
4913 $format = 'vma' if !$format;
4915 } elsif ($archive =~ m/\.vma\.lzo$/) {
4916 $format = 'vma' if !$format;
4919 $format = 'vma' if !$format; # default
4922 # try to detect archive format
4923 if ($format eq 'tar') {
4924 return restore_tar_archive
($archive, $vmid, $user, $opts);
4926 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4930 sub restore_update_config_line
{
4931 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4933 return if $line =~ m/^\#qmdump\#/;
4934 return if $line =~ m/^\#vzdump\#/;
4935 return if $line =~ m/^lock:/;
4936 return if $line =~ m/^unused\d+:/;
4937 return if $line =~ m/^parent:/;
4938 return if $line =~ m/^template:/; # restored VM is never a template
4940 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4941 # try to convert old 1.X settings
4942 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4943 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4944 my ($model, $macaddr) = split(/\=/, $devconfig);
4945 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4948 bridge
=> "vmbr$ind",
4949 macaddr
=> $macaddr,
4951 my $netstr = print_net
($net);
4953 print $outfd "net$cookie->{netcount}: $netstr\n";
4954 $cookie->{netcount
}++;
4956 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4957 my ($id, $netstr) = ($1, $2);
4958 my $net = parse_net
($netstr);
4959 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4960 $netstr = print_net
($net);
4961 print $outfd "$id: $netstr\n";
4962 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
4965 my $di = parse_drive
($virtdev, $value);
4966 if (defined($di->{backup
}) && !$di->{backup
}) {
4967 print $outfd "#$line";
4968 } elsif ($map->{$virtdev}) {
4969 delete $di->{format
}; # format can change on restore
4970 $di->{file
} = $map->{$virtdev};
4971 $value = print_drive
($vmid, $di);
4972 print $outfd "$virtdev: $value\n";
4982 my ($cfg, $vmid) = @_;
4984 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
4986 my $volid_hash = {};
4987 foreach my $storeid (keys %$info) {
4988 foreach my $item (@{$info->{$storeid}}) {
4989 next if !($item->{volid
} && $item->{size
});
4990 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
4991 $volid_hash->{$item->{volid
}} = $item;
4998 sub is_volume_in_use
{
4999 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5001 my $path = PVE
::Storage
::path
($storecfg, $volid);
5003 my $scan_config = sub {
5004 my ($cref, $snapname) = @_;
5006 foreach my $key (keys %$cref) {
5007 my $value = $cref->{$key};
5008 if (is_valid_drivename
($key)) {
5009 next if $skip_drive && $key eq $skip_drive;
5010 my $drive = parse_drive
($key, $value);
5011 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5012 return 1 if $volid eq $drive->{file
};
5013 if ($drive->{file
} =~ m!^/!) {
5014 return 1 if $drive->{file
} eq $path;
5016 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5018 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5020 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5028 return 1 if &$scan_config($conf);
5032 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5033 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5039 sub update_disksize
{
5040 my ($vmid, $conf, $volid_hash) = @_;
5046 # Note: it is allowed to define multiple storages with same path (alias), so
5047 # we need to check both 'volid' and real 'path' (two different volid can point
5048 # to the same path).
5053 foreach my $opt (keys %$conf) {
5054 if (is_valid_drivename
($opt)) {
5055 my $drive = parse_drive
($opt, $conf->{$opt});
5056 my $volid = $drive->{file
};
5059 $used->{$volid} = 1;
5060 if ($volid_hash->{$volid} &&
5061 (my $path = $volid_hash->{$volid}->{path
})) {
5062 $usedpath->{$path} = 1;
5065 next if drive_is_cdrom
($drive);
5066 next if !$volid_hash->{$volid};
5068 $drive->{size
} = $volid_hash->{$volid}->{size
};
5069 my $new = print_drive
($vmid, $drive);
5070 if ($new ne $conf->{$opt}) {
5072 $conf->{$opt} = $new;
5077 # remove 'unusedX' entry if volume is used
5078 foreach my $opt (keys %$conf) {
5079 next if $opt !~ m/^unused\d+$/;
5080 my $volid = $conf->{$opt};
5081 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5082 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5084 delete $conf->{$opt};
5088 foreach my $volid (sort keys %$volid_hash) {
5089 next if $volid =~ m/vm-$vmid-state-/;
5090 next if $used->{$volid};
5091 my $path = $volid_hash->{$volid}->{path
};
5092 next if !$path; # just to be sure
5093 next if $usedpath->{$path};
5095 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5096 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5103 my ($vmid, $nolock) = @_;
5105 my $cfg = PVE
::Storage
::config
();
5107 my $volid_hash = scan_volids
($cfg, $vmid);
5109 my $updatefn = sub {
5112 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5114 PVE
::QemuConfig-
>check_lock($conf);
5117 foreach my $volid (keys %$volid_hash) {
5118 my $info = $volid_hash->{$volid};
5119 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5122 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5124 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5127 if (defined($vmid)) {
5131 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5134 my $vmlist = config_list
();
5135 foreach my $vmid (keys %$vmlist) {
5139 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5145 sub restore_vma_archive
{
5146 my ($archive, $vmid, $user, $opts, $comp) = @_;
5148 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5149 my $readfrom = $archive;
5154 my $qarchive = PVE
::Tools
::shellquote
($archive);
5155 if ($comp eq 'gzip') {
5156 $uncomp = "zcat $qarchive|";
5157 } elsif ($comp eq 'lzop') {
5158 $uncomp = "lzop -d -c $qarchive|";
5160 die "unknown compression method '$comp'\n";
5165 my $tmpdir = "/var/tmp/vzdumptmp$$";
5168 # disable interrupts (always do cleanups)
5169 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5170 warn "got interrupt - ignored\n";
5173 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5174 POSIX
::mkfifo
($mapfifo, 0600);
5177 my $openfifo = sub {
5178 open($fifofh, '>', $mapfifo) || die $!;
5181 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5188 my $rpcenv = PVE
::RPCEnvironment
::get
();
5190 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5191 my $tmpfn = "$conffile.$$.tmp";
5193 # Note: $oldconf is undef if VM does not exists
5194 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5195 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5197 my $print_devmap = sub {
5198 my $virtdev_hash = {};
5200 my $cfgfn = "$tmpdir/qemu-server.conf";
5202 # we can read the config - that is already extracted
5203 my $fh = IO
::File-
>new($cfgfn, "r") ||
5204 "unable to read qemu-server.conf - $!\n";
5206 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5208 my $pve_firewall_dir = '/etc/pve/firewall';
5209 mkdir $pve_firewall_dir; # make sure the dir exists
5210 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5213 while (defined(my $line = <$fh>)) {
5214 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5215 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5216 die "archive does not contain data for drive '$virtdev'\n"
5217 if !$devinfo->{$devname};
5218 if (defined($opts->{storage
})) {
5219 $storeid = $opts->{storage
} || 'local';
5220 } elsif (!$storeid) {
5223 $format = 'raw' if !$format;
5224 $devinfo->{$devname}->{devname
} = $devname;
5225 $devinfo->{$devname}->{virtdev
} = $virtdev;
5226 $devinfo->{$devname}->{format
} = $format;
5227 $devinfo->{$devname}->{storeid
} = $storeid;
5229 # check permission on storage
5230 my $pool = $opts->{pool
}; # todo: do we need that?
5231 if ($user ne 'root@pam') {
5232 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5235 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5239 foreach my $devname (keys %$devinfo) {
5240 die "found no device mapping information for device '$devname'\n"
5241 if !$devinfo->{$devname}->{virtdev
};
5244 my $cfg = PVE
::Storage
::config
();
5246 # create empty/temp config
5248 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5249 foreach_drive
($oldconf, sub {
5250 my ($ds, $drive) = @_;
5252 return if drive_is_cdrom
($drive);
5254 my $volid = $drive->{file
};
5256 return if !$volid || $volid =~ m
|^/|;
5258 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5259 return if !$path || !$owner || ($owner != $vmid);
5261 # Note: only delete disk we want to restore
5262 # other volumes will become unused
5263 if ($virtdev_hash->{$ds}) {
5264 PVE
::Storage
::vdisk_free
($cfg, $volid);
5268 # delete vmstate files
5269 # since after the restore we have no snapshots anymore
5270 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5271 my $snap = $oldconf->{snapshots
}->{$snapname};
5272 if ($snap->{vmstate
}) {
5273 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5282 foreach my $virtdev (sort keys %$virtdev_hash) {
5283 my $d = $virtdev_hash->{$virtdev};
5284 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5285 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5287 # test if requested format is supported
5288 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5289 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5290 $d->{format
} = $defFormat if !$supported;
5292 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5293 $d->{format
}, undef, $alloc_size);
5294 print STDERR
"new volume ID is '$volid'\n";
5295 $d->{volid
} = $volid;
5296 my $path = PVE
::Storage
::path
($cfg, $volid);
5298 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5300 my $write_zeros = 1;
5301 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5305 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5307 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5308 $map->{$virtdev} = $volid;
5311 $fh->seek(0, 0) || die "seek failed - $!\n";
5313 my $outfd = new IO
::File
($tmpfn, "w") ||
5314 die "unable to write config for VM $vmid\n";
5316 my $cookie = { netcount
=> 0 };
5317 while (defined(my $line = <$fh>)) {
5318 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5327 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5328 die "interrupted by signal\n";
5330 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5332 $oldtimeout = alarm($timeout);
5339 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5340 my ($dev_id, $size, $devname) = ($1, $2, $3);
5341 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5342 } elsif ($line =~ m/^CTIME: /) {
5343 # we correctly received the vma config, so we can disable
5344 # the timeout now for disk allocation (set to 10 minutes, so
5345 # that we always timeout if something goes wrong)
5348 print $fifofh "done\n";
5349 my $tmp = $oldtimeout || 0;
5350 $oldtimeout = undef;
5356 print "restore vma archive: $cmd\n";
5357 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5361 alarm($oldtimeout) if $oldtimeout;
5364 foreach my $devname (keys %$devinfo) {
5365 my $volid = $devinfo->{$devname}->{volid
};
5366 push @$vollist, $volid if $volid;
5369 my $cfg = PVE
::Storage
::config
();
5370 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5378 foreach my $devname (keys %$devinfo) {
5379 my $volid = $devinfo->{$devname}->{volid
};
5382 if ($volid =~ m
|^/|) {
5383 unlink $volid || die 'unlink failed\n';
5385 PVE
::Storage
::vdisk_free
($cfg, $volid);
5387 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5389 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5396 rename($tmpfn, $conffile) ||
5397 die "unable to commit configuration file '$conffile'\n";
5399 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5401 eval { rescan
($vmid, 1); };
5405 sub restore_tar_archive
{
5406 my ($archive, $vmid, $user, $opts) = @_;
5408 if ($archive ne '-') {
5409 my $firstfile = tar_archive_read_firstfile
($archive);
5410 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5411 if $firstfile ne 'qemu-server.conf';
5414 my $storecfg = PVE
::Storage
::config
();
5416 # destroy existing data - keep empty config
5417 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5418 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5420 my $tocmd = "/usr/lib/qemu-server/qmextract";
5422 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5423 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5424 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5425 $tocmd .= ' --info' if $opts->{info
};
5427 # tar option "xf" does not autodetect compression when read from STDIN,
5428 # so we pipe to zcat
5429 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5430 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5432 my $tmpdir = "/var/tmp/vzdumptmp$$";
5435 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5436 local $ENV{VZDUMP_VMID
} = $vmid;
5437 local $ENV{VZDUMP_USER
} = $user;
5439 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5440 my $tmpfn = "$conffile.$$.tmp";
5442 # disable interrupts (always do cleanups)
5443 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5444 print STDERR
"got interrupt - ignored\n";
5449 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5450 die "interrupted by signal\n";
5453 if ($archive eq '-') {
5454 print "extracting archive from STDIN\n";
5455 run_command
($cmd, input
=> "<&STDIN");
5457 print "extracting archive '$archive'\n";
5461 return if $opts->{info
};
5465 my $statfile = "$tmpdir/qmrestore.stat";
5466 if (my $fd = IO
::File-
>new($statfile, "r")) {
5467 while (defined (my $line = <$fd>)) {
5468 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5469 $map->{$1} = $2 if $1;
5471 print STDERR
"unable to parse line in statfile - $line\n";
5477 my $confsrc = "$tmpdir/qemu-server.conf";
5479 my $srcfd = new IO
::File
($confsrc, "r") ||
5480 die "unable to open file '$confsrc'\n";
5482 my $outfd = new IO
::File
($tmpfn, "w") ||
5483 die "unable to write config for VM $vmid\n";
5485 my $cookie = { netcount
=> 0 };
5486 while (defined (my $line = <$srcfd>)) {
5487 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5499 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5506 rename $tmpfn, $conffile ||
5507 die "unable to commit configuration file '$conffile'\n";
5509 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5511 eval { rescan
($vmid, 1); };
5515 sub foreach_writable_storage
{
5516 my ($conf, $func) = @_;
5520 foreach my $ds (keys %$conf) {
5521 next if !is_valid_drivename
($ds);
5523 my $drive = parse_drive
($ds, $conf->{$ds});
5525 next if drive_is_cdrom
($drive);
5527 my $volid = $drive->{file
};
5529 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5530 $sidhash->{$sid} = $sid if $sid;
5533 foreach my $sid (sort keys %$sidhash) {
5538 sub do_snapshots_with_qemu
{
5539 my ($storecfg, $volid) = @_;
5541 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5543 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5544 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5548 if ($volid =~ m/\.(qcow2|qed)$/){
5555 sub qga_check_running
{
5558 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5560 warn "Qemu Guest Agent are not running - $@";
5566 sub template_create
{
5567 my ($vmid, $conf, $disk) = @_;
5569 my $storecfg = PVE
::Storage
::config
();
5571 foreach_drive
($conf, sub {
5572 my ($ds, $drive) = @_;
5574 return if drive_is_cdrom
($drive);
5575 return if $disk && $ds ne $disk;
5577 my $volid = $drive->{file
};
5578 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5580 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5581 $drive->{file
} = $voliddst;
5582 $conf->{$ds} = print_drive
($vmid, $drive);
5583 PVE
::QemuConfig-
>write_config($vmid, $conf);
5587 sub qemu_img_convert
{
5588 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5590 my $storecfg = PVE
::Storage
::config
();
5591 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5592 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5594 if ($src_storeid && $dst_storeid) {
5596 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5598 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5599 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5601 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5602 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5604 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5605 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5608 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5609 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5610 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5611 if ($is_zero_initialized) {
5612 push @$cmd, "zeroinit:$dst_path";
5614 push @$cmd, $dst_path;
5619 if($line =~ m/\((\S+)\/100\
%\)/){
5621 my $transferred = int($size * $percent / 100);
5622 my $remaining = $size - $transferred;
5624 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5629 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5631 die "copy failed: $err" if $err;
5635 sub qemu_img_format
{
5636 my ($scfg, $volname) = @_;
5638 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5645 sub qemu_drive_mirror
{
5646 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5648 my $storecfg = PVE
::Storage
::config
();
5649 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5651 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5653 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5655 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5657 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5659 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5660 $opts->{format
} = $format if $format;
5662 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5664 my $finish_job = sub {
5666 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5667 my $stat = @$stats[0];
5674 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5676 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5677 my $stat = @$stats[0];
5678 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5679 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5681 my $busy = $stat->{busy
};
5682 my $ready = $stat->{ready
};
5684 if (my $total = $stat->{len
}) {
5685 my $transferred = $stat->{offset
} || 0;
5686 my $remaining = $total - $transferred;
5687 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5689 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5693 if ($stat->{ready
} eq 'true') {
5695 last if $vmiddst != $vmid;
5697 # try to switch the disk if source and destination are on the same guest
5698 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5703 die $@ if $@ !~ m/cannot be completed/;
5712 my $cancel_job = sub {
5713 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5718 eval { &$cancel_job(); };
5719 die "mirroring error: $err";
5722 if ($vmiddst != $vmid) {
5723 # if we clone a disk for a new target vm, we don't switch the disk
5724 &$cancel_job(); # so we call block-job-cancel
5729 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5730 $newvmid, $storage, $format, $full, $newvollist) = @_;
5735 print "create linked clone of drive $drivename ($drive->{file})\n";
5736 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5737 push @$newvollist, $newvolid;
5739 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5740 $storeid = $storage if $storage;
5742 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5744 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5745 $format = qemu_img_format
($scfg, $volname);
5748 # test if requested format is supported - else use default
5749 my $supported = grep { $_ eq $format } @$validFormats;
5750 $format = $defFormat if !$supported;
5752 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5754 print "create full clone of drive $drivename ($drive->{file})\n";
5755 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5756 push @$newvollist, $newvolid;
5758 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5760 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5761 if (!$running || $snapname) {
5762 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5764 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5768 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5771 $disk->{format
} = undef;
5772 $disk->{file
} = $newvolid;
5773 $disk->{size
} = $size;
5778 # this only works if VM is running
5779 sub get_current_qemu_machine
{
5782 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5783 my $res = vm_qmp_command
($vmid, $cmd);
5785 my ($current, $default);
5786 foreach my $e (@$res) {
5787 $default = $e->{name
} if $e->{'is-default'};
5788 $current = $e->{name
} if $e->{'is-current'};
5791 # fallback to the default machine if current is not supported by qemu
5792 return $current || $default || 'pc';
5795 sub qemu_machine_feature_enabled
{
5796 my ($machine, $kvmver, $version_major, $version_minor) = @_;
5801 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
5803 $current_major = $3;
5804 $current_minor = $4;
5806 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
5808 $current_major = $1;
5809 $current_minor = $2;
5812 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
5817 sub qemu_machine_pxe
{
5818 my ($vmid, $conf, $machine) = @_;
5820 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
5822 foreach my $opt (keys %$conf) {
5823 next if $opt !~ m/^net(\d+)$/;
5824 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
5826 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
5827 return $machine.".pxe" if $romfile =~ m/pxe/;
5834 sub qemu_use_old_bios_files
{
5835 my ($machine_type) = @_;
5837 return if !$machine_type;
5839 my $use_old_bios_files = undef;
5841 if ($machine_type =~ m/^(\S+)\.pxe$/) {
5843 $use_old_bios_files = 1;
5845 my $kvmver = kvm_user_version
();
5846 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
5847 # load new efi bios files on migration. So this hack is required to allow
5848 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
5849 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
5850 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
5853 return ($use_old_bios_files, $machine_type);
5860 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
5861 my (undef, $id, $function) = @_;
5862 my $res = { id
=> $id, function
=> $function};
5863 push @{$devices->{$id}}, $res;
5869 sub vm_iothreads_list
{
5872 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
5875 foreach my $iothread (@$res) {
5876 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
5883 my ($conf, $drive) = @_;
5887 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
5889 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
5895 my $controller = int($drive->{index} / $maxdev);
5896 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
5898 return ($maxdev, $controller, $controller_prefix);
5901 # bash completion helper
5903 sub complete_backup_archives
{
5904 my ($cmdname, $pname, $cvalue) = @_;
5906 my $cfg = PVE
::Storage
::config
();
5910 if ($cvalue =~ m/^([^:]+):/) {
5914 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
5917 foreach my $id (keys %$data) {
5918 foreach my $item (@{$data->{$id}}) {
5919 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
5920 push @$res, $item->{volid
} if defined($item->{volid
});
5927 my $complete_vmid_full = sub {
5930 my $idlist = vmstatus
();
5934 foreach my $id (keys %$idlist) {
5935 my $d = $idlist->{$id};
5936 if (defined($running)) {
5937 next if $d->{template
};
5938 next if $running && $d->{status
} ne 'running';
5939 next if !$running && $d->{status
} eq 'running';
5948 return &$complete_vmid_full();
5951 sub complete_vmid_stopped
{
5952 return &$complete_vmid_full(0);
5955 sub complete_vmid_running
{
5956 return &$complete_vmid_full(1);
5959 sub complete_storage
{
5961 my $cfg = PVE
::Storage
::config
();
5962 my $ids = $cfg->{ids
};
5965 foreach my $sid (keys %$ids) {
5966 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
5967 next if !$ids->{$sid}->{content
}->{images
};