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
::Memory
;
34 use Time
::HiRes
qw(gettimeofday);
35 use File
::Copy
qw(copy);
38 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
40 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
42 # Note about locking: we use flock on the config file protect
43 # against concurent actions.
44 # Aditionaly, we have a 'lock' setting in the config file. This
45 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
46 # allowed when such lock is set. But you can ignore this kind of
47 # lock with the --skiplock flag.
49 cfs_register_file
('/qemu-server/',
53 PVE
::JSONSchema
::register_standard_option
('skiplock', {
54 description
=> "Ignore locks - only root is allowed to use this option.",
59 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
60 description
=> "Some command save/restore state from this location.",
66 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
67 description
=> "The name of the snapshot.",
68 type
=> 'string', format
=> 'pve-configid',
72 #no warnings 'redefine';
75 my ($controller, $vmid, $option, $value) = @_;
77 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
78 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
82 my $nodename = PVE
::INotify
::nodename
();
84 mkdir "/etc/pve/nodes/$nodename";
85 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
88 my $var_run_tmpdir = "/var/run/qemu-server";
89 mkdir $var_run_tmpdir;
91 my $lock_dir = "/var/lock/qemu-server";
94 my $pcisysfs = "/sys/bus/pci";
96 my $cpu_vendor_list = {
98 486 => 'GenuineIntel',
99 pentium
=> 'GenuineIntel',
100 pentium2
=> 'GenuineIntel',
101 pentium3
=> 'GenuineIntel',
102 coreduo
=> 'GenuineIntel',
103 core2duo
=> 'GenuineIntel',
104 Conroe
=> 'GenuineIntel',
105 Penryn
=> 'GenuineIntel',
106 Nehalem
=> 'GenuineIntel',
107 Westmere
=> 'GenuineIntel',
108 SandyBridge
=> 'GenuineIntel',
109 IvyBridge
=> 'GenuineIntel',
110 Haswell
=> 'GenuineIntel',
111 'Haswell-noTSX' => 'GenuineIntel',
112 Broadwell
=> 'GenuineIntel',
113 'Broadwell-noTSX' => 'GenuineIntel',
116 athlon
=> 'AuthenticAMD',
117 phenom
=> 'AuthenticAMD',
118 Opteron_G1
=> 'AuthenticAMD',
119 Opteron_G2
=> 'AuthenticAMD',
120 Opteron_G3
=> 'AuthenticAMD',
121 Opteron_G4
=> 'AuthenticAMD',
122 Opteron_G5
=> 'AuthenticAMD',
124 # generic types, use vendor from host node
134 description
=> "Emulated CPU type.",
136 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
137 format_description
=> 'cputype',
142 description
=> "Do not identify as a KVM virtual machine.",
153 enum
=> [qw(i6300esb ib700)],
154 description
=> "Watchdog type to emulate.",
155 default => 'i6300esb',
160 enum
=> [qw(reset shutdown poweroff pause debug none)],
161 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
165 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
171 description
=> "Specifies whether a VM will be started during system bootup.",
177 description
=> "Automatic restart after crash (currently ignored).",
182 type
=> 'string', format
=> 'pve-hotplug-features',
183 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'.",
184 default => 'network,disk,usb',
189 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
195 description
=> "Lock/unlock the VM.",
196 enum
=> [qw(migrate backup snapshot rollback)],
201 description
=> "Limit of CPU usage.",
202 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.",
210 description
=> "CPU weight for a VM.",
211 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.",
219 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
226 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
232 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",
240 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.",
241 enum
=> PVE
::Tools
::kvmkeymaplist
(),
246 type
=> 'string', format
=> 'dns-name',
247 description
=> "Set a name for the VM. Only used on the configuration web interface.",
252 description
=> "SCSI controller model",
253 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
259 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
264 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
265 description
=> "Specify guest operating system.",
266 verbose_description
=> <<EODESC,
267 Specify guest operating system. This is used to enable special
268 optimization/features for specific operating systems:
271 other;; unspecified OS
272 wxp;; Microsoft Windows XP
273 w2k;; Microsoft Windows 2000
274 w2k3;; Microsoft Windows 2003
275 w2k8;; Microsoft Windows 2008
276 wvista;; Microsoft Windows Vista
277 win7;; Microsoft Windows 7
278 win8;; Microsoft Windows 8/2012
279 l24;; Linux 2.4 Kernel
280 l26;; Linux 2.6/3.X Kernel
281 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
287 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
288 pattern
=> '[acdn]{1,4}',
293 type
=> 'string', format
=> 'pve-qm-bootdisk',
294 description
=> "Enable booting from specified disk.",
295 pattern
=> '(ide|sata|scsi|virtio)\d+',
300 description
=> "The number of CPUs. Please use option -sockets instead.",
307 description
=> "The number of CPU sockets.",
314 description
=> "The number of cores per socket.",
321 description
=> "Enable/disable NUMA.",
327 description
=> "Enable/disable hugepages memory.",
328 enum
=> [qw(any 2 1024)],
333 description
=> "Number of hotplugged vcpus.",
340 description
=> "Enable/disable ACPI.",
346 description
=> "Enable/disable Qemu GuestAgent.",
352 description
=> "Enable/disable KVM hardware virtualization.",
358 description
=> "Enable/disable time drift fix.",
364 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
369 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
374 description
=> "Select the VGA type.",
375 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
376 " modes (>= 1280x1024x16) then you should use the options " .
377 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
378 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
379 "display sever. For win* OS you can select how many independent " .
380 "displays you want, Linux guests can add displays them self. " .
381 "You can also run without any graphic card, using a serial device" .
383 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
387 type
=> 'string', format
=> 'pve-qm-watchdog',
388 description
=> "Create a virtual hardware watchdog device.",
389 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
390 " (by a guest action), the watchdog must be periodically polled " .
391 "by an agent inside the guest or else the watchdog will reset " .
392 "the guest (or execute the respective action specified)",
397 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
398 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'.",
399 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
402 startup
=> get_standard_option
('pve-startup-order'),
406 description
=> "Enable/disable Template.",
412 description
=> "Arbitrary arguments passed to kvm.",
413 verbose_description
=> <<EODESCR,
414 Arbitrary arguments passed to kvm, for example:
416 args: -no-reboot -no-hpet
418 NOTE: this option is for experts only.
425 description
=> "Enable/disable the USB tablet device.",
426 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
427 "usually needed to allow absolute mouse positioning with VNC. " .
428 "Else the mouse runs out of sync with normal VNC clients. " .
429 "If you're running lots of console-only guests on one host, " .
430 "you may consider disabling this to save some context switches. " .
431 "This is turned off by default if you use spice (-vga=qxl).",
436 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
440 migrate_downtime
=> {
443 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
449 type
=> 'string', format
=> 'pve-qm-drive',
450 typetext
=> 'volume',
451 description
=> "This is an alias for option -ide2",
455 description
=> "Emulated CPU type.",
459 parent
=> get_standard_option
('pve-snapshot-name', {
461 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
465 description
=> "Timestamp for snapshots.",
471 type
=> 'string', format
=> 'pve-volume-id',
472 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
475 description
=> "Specific the Qemu machine type.",
477 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
482 description
=> "Specify SMBIOS type 1 fields.",
483 type
=> 'string', format
=> 'pve-qm-smbios1',
490 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
496 enum
=> [ qw(seabios ovmf) ],
497 description
=> "Select BIOS implementation.",
498 default => 'seabios',
502 # what about other qemu settings ?
504 #machine => 'string',
517 ##soundhw => 'string',
519 while (my ($k, $v) = each %$confdesc) {
520 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
523 my $MAX_IDE_DISKS = 4;
524 my $MAX_SCSI_DISKS = 14;
525 my $MAX_VIRTIO_DISKS = 16;
526 my $MAX_SATA_DISKS = 6;
527 my $MAX_USB_DEVICES = 5;
529 my $MAX_UNUSED_DISKS = 8;
530 my $MAX_HOSTPCI_DEVICES = 4;
531 my $MAX_SERIAL_PORTS = 4;
532 my $MAX_PARALLEL_PORTS = 3;
538 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
539 description
=> "CPUs accessing this NUMA node.",
540 format_description
=> "id[-id];...",
544 description
=> "Amount of memory this NUMA node provides.",
549 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
550 description
=> "Host NUMA nodes to use.",
551 format_description
=> "id[-id];...",
556 enum
=> [qw(preferred bind interleave)],
557 description
=> "NUMA allocation policy.",
561 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
564 type
=> 'string', format
=> $numa_fmt,
565 description
=> "NUMA topology.",
567 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
569 for (my $i = 0; $i < $MAX_NUMA; $i++) {
570 $confdesc->{"numa$i"} = $numadesc;
573 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
574 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
575 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
576 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
578 my $net_fmt_bridge_descr = <<__EOD__;
579 Bridge to attach the network device to. The Proxmox VE standard bridge
582 If you do not specify a bridge, we create a kvm user (NATed) network
583 device, which provides DHCP and DNS services. The following addresses
590 The DHCP server assign addresses to the guest starting from 10.0.2.15.
596 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
597 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
598 format_description
=> "XX:XX:XX:XX:XX:XX",
603 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'.",
604 format_description
=> 'model',
605 enum
=> $nic_model_list,
608 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
611 description
=> $net_fmt_bridge_descr,
612 format_description
=> 'bridge',
617 minimum
=> 0, maximum
=> 16,
618 description
=> 'Number of packet queues to be used on the device.',
624 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
629 minimum
=> 1, maximum
=> 4094,
630 description
=> 'VLAN tag to apply to packets on this interface.',
635 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
636 description
=> 'VLAN trunks to pass through this interface.',
637 format_description
=> 'vlanid[;vlanid...]',
642 description
=> 'Whether this interface should be protected by the firewall.',
647 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
654 type
=> 'string', format
=> $net_fmt,
655 description
=> "Specify network devices.",
658 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
660 for (my $i = 0; $i < $MAX_NETS; $i++) {
661 $confdesc->{"net$i"} = $netdesc;
664 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
665 sub verify_volume_id_or_qm_path
{
666 my ($volid, $noerr) = @_;
668 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
672 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
673 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
675 return undef if $noerr;
683 my %drivedesc_base = (
684 volume
=> { alias
=> 'file' },
687 format
=> 'pve-volume-id-or-qm-path',
689 format_description
=> 'volume',
690 description
=> "The drive's backing volume.",
694 enum
=> [qw(cdrom disk)],
695 description
=> "The drive's media type.",
701 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
706 description
=> "Force the drive's physical geometry to have a specific head count.",
711 description
=> "Force the drive's physical geometry to have a specific sector count.",
716 enum
=> [qw(none lba auto)],
717 description
=> "Force disk geometry bios translation mode.",
722 description
=> "Whether the drive should be included when making snapshots.",
727 enum
=> [qw(none writethrough writeback unsafe directsync)],
728 description
=> "The drive's cache mode",
733 format_description
=> 'image format',
734 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
735 description
=> "The drive's backing file's data format.",
740 format
=> 'disk-size',
741 format_description
=> 'DiskSize',
742 description
=> "Disk size. This is purely informational and has no effect.",
747 description
=> "Whether the drive should be included when making backups.",
752 enum
=> [qw(enospc ignore report stop)],
753 description
=> 'Write error action.',
758 enum
=> [qw(native threads)],
759 description
=> 'AIO type to use.',
764 enum
=> [qw(ignore on)],
765 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
770 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
775 format
=> 'urlencoded',
776 format_description
=> 'serial',
777 maxLength
=> 20*3, # *3 since it's %xx url enoded
778 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
786 enum
=> [qw(ignore report stop)],
787 description
=> 'Read error action.',
792 my %iothread_fmt = ( iothread
=> {
794 description
=> "Whether to use iothreads for this drive",
801 format
=> 'urlencoded',
802 format_description
=> 'model',
803 maxLength
=> 40*3, # *3 since it's %xx url enoded
804 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
812 description
=> "Number of queues.",
818 my $add_throttle_desc = sub {
819 my ($key, $type, $what, $unit, $longunit) = @_;
820 $drivedesc_base{$key} = {
822 format_description
=> $unit,
823 description
=> "Maximum $what speed in $longunit per second.",
827 # throughput: (leaky bucket)
828 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
829 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
830 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
831 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
832 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
833 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
834 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
835 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
836 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
838 # pools: (pool of IO before throttling starts taking effect)
839 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
840 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
841 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
842 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
843 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
844 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
854 type
=> 'string', format
=> $ide_fmt,
855 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
857 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
866 type
=> 'string', format
=> $scsi_fmt,
867 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
869 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
877 type
=> 'string', format
=> $sata_fmt,
878 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
880 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
889 type
=> 'string', format
=> $virtio_fmt,
890 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
892 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
905 type
=> 'string', format
=> 'pve-qm-usb-device',
906 format_description
=> 'HOSTUSBDEVICE|spice',
907 description
=> <<EODESCR,
908 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
910 'bus-port(.port)*' (decimal numbers) or
911 'vendor_id:product_id' (hexadeciaml numbers) or
914 You can use the 'lsusb -t' command to list existing usb devices.
916 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
918 The value 'spice' can be used to add a usb redirection devices for spice.
924 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).",
931 type
=> 'string', format
=> $usb_fmt,
932 description
=> "Configure an USB device (n is 0 to 4).",
934 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
936 # NOTE: the match-groups of this regex are used in parse_hostpci
937 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
942 pattern
=> qr/$PCIRE(;$PCIRE)*/,
943 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
944 description
=> <<EODESCR,
945 Host PCI device pass through. The PCI ID of a host's PCI device or a list
946 of PCI virtual functions of the host. HOSTPCIID syntax is:
948 'bus:dev.func' (hexadecimal numbers)
950 You can us the 'lspci' command to list existing PCI devices.
955 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
961 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
967 description
=> "Enable vfio-vga device support.",
972 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
976 type
=> 'string', format
=> 'pve-qm-hostpci',
977 description
=> "Map host PCI devices into guest.",
978 verbose_description
=> <<EODESCR,
979 Map host PCI devices into guest.
981 NOTE: This option allows direct access to host hardware. So it is no longer
982 possible to migrate such machines - use with special care.
984 CAUTION: Experimental! User reported problems with this option.
987 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
992 pattern
=> '(/dev/.+|socket)',
993 description
=> "Create a serial device inside the VM (n is 0 to 3)",
994 verbose_description
=> <<EODESCR,
995 Create a serial device inside the VM (n is 0 to 3), and pass through a
996 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
997 host side (use 'qm terminal' to open a terminal connection).
999 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1001 CAUTION: Experimental! User reported problems with this option.
1008 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1009 description
=> "Map host parallel devices (n is 0 to 2).",
1010 verbose_description
=> <<EODESCR,
1011 Map host parallel devices (n is 0 to 2).
1013 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1015 CAUTION: Experimental! User reported problems with this option.
1019 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1020 $confdesc->{"parallel$i"} = $paralleldesc;
1023 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1024 $confdesc->{"serial$i"} = $serialdesc;
1027 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1028 $confdesc->{"hostpci$i"} = $hostpcidesc;
1031 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1032 $drivename_hash->{"ide$i"} = 1;
1033 $confdesc->{"ide$i"} = $idedesc;
1036 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1037 $drivename_hash->{"sata$i"} = 1;
1038 $confdesc->{"sata$i"} = $satadesc;
1041 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1042 $drivename_hash->{"scsi$i"} = 1;
1043 $confdesc->{"scsi$i"} = $scsidesc ;
1046 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1047 $drivename_hash->{"virtio$i"} = 1;
1048 $confdesc->{"virtio$i"} = $virtiodesc;
1051 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1052 $confdesc->{"usb$i"} = $usbdesc;
1057 type
=> 'string', format
=> 'pve-volume-id',
1058 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1061 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1062 $confdesc->{"unused$i"} = $unuseddesc;
1065 my $kvm_api_version = 0;
1069 return $kvm_api_version if $kvm_api_version;
1071 my $fh = IO
::File-
>new("</dev/kvm") ||
1074 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1075 $kvm_api_version = $v;
1080 return $kvm_api_version;
1083 my $kvm_user_version;
1085 sub kvm_user_version
{
1087 return $kvm_user_version if $kvm_user_version;
1089 $kvm_user_version = 'unknown';
1093 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1094 $kvm_user_version = $2;
1098 eval { run_command
("kvm -version", outfunc
=> $code); };
1101 return $kvm_user_version;
1105 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1107 sub valid_drive_names
{
1108 # order is important - used to autoselect boot disk
1109 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1110 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1111 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1112 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1115 sub is_valid_drivename
{
1118 return defined($drivename_hash->{$dev});
1123 return defined($confdesc->{$key});
1127 return $nic_model_list;
1130 sub os_list_description
{
1134 wxp
=> 'Windows XP',
1135 w2k
=> 'Windows 2000',
1136 w2k3
=>, 'Windows 2003',
1137 w2k8
=> 'Windows 2008',
1138 wvista
=> 'Windows Vista',
1139 win7
=> 'Windows 7',
1140 win8
=> 'Windows 8/2012',
1148 sub get_cdrom_path
{
1150 return $cdrom_path if $cdrom_path;
1152 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1153 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1154 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1158 my ($storecfg, $vmid, $cdrom) = @_;
1160 if ($cdrom eq 'cdrom') {
1161 return get_cdrom_path
();
1162 } elsif ($cdrom eq 'none') {
1164 } elsif ($cdrom =~ m
|^/|) {
1167 return PVE
::Storage
::path
($storecfg, $cdrom);
1171 # try to convert old style file names to volume IDs
1172 sub filename_to_volume_id
{
1173 my ($vmid, $file, $media) = @_;
1175 if (!($file eq 'none' || $file eq 'cdrom' ||
1176 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1178 return undef if $file =~ m
|/|;
1180 if ($media && $media eq 'cdrom') {
1181 $file = "local:iso/$file";
1183 $file = "local:$vmid/$file";
1190 sub verify_media_type
{
1191 my ($opt, $vtype, $media) = @_;
1196 if ($media eq 'disk') {
1198 } elsif ($media eq 'cdrom') {
1201 die "internal error";
1204 return if ($vtype eq $etype);
1206 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1209 sub cleanup_drive_path
{
1210 my ($opt, $storecfg, $drive) = @_;
1212 # try to convert filesystem paths to volume IDs
1214 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1215 ($drive->{file
} !~ m
|^/dev/.+|) &&
1216 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1217 ($drive->{file
} !~ m/^\d+$/)) {
1218 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1219 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1220 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1221 verify_media_type
($opt, $vtype, $drive->{media
});
1222 $drive->{file
} = $volid;
1225 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1228 sub parse_hotplug_features
{
1233 return $res if $data eq '0';
1235 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1237 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1238 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1241 die "invalid hotplug feature '$feature'\n";
1247 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1248 sub pve_verify_hotplug_features
{
1249 my ($value, $noerr) = @_;
1251 return $value if parse_hotplug_features
($value);
1253 return undef if $noerr;
1255 die "unable to parse hotplug option\n";
1258 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1259 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1260 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1261 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1262 # [,iothread=on][,serial=serial][,model=model]
1265 my ($key, $data) = @_;
1267 my ($interface, $index);
1269 if ($key =~ m/^([^\d]+)(\d+)$/) {
1276 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1277 : $confdesc->{$key}->{format
};
1279 warn "invalid drive key: $key\n";
1282 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1283 return undef if !$res;
1284 $res->{interface
} = $interface;
1285 $res->{index} = $index;
1288 foreach my $opt (qw(bps bps_rd bps_wr)) {
1289 if (my $bps = defined(delete $res->{$opt})) {
1290 if (defined($res->{"m$opt"})) {
1291 warn "both $opt and m$opt specified\n";
1295 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1298 return undef if $error;
1300 return undef if $res->{mbps_rd
} && $res->{mbps
};
1301 return undef if $res->{mbps_wr
} && $res->{mbps
};
1302 return undef if $res->{iops_rd
} && $res->{iops
};
1303 return undef if $res->{iops_wr
} && $res->{iops
};
1305 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1306 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1307 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1308 return undef if $res->{interface
} eq 'virtio';
1311 if (my $size = $res->{size
}) {
1312 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1319 my ($vmid, $drive) = @_;
1320 my $data = { %$drive };
1321 delete $data->{$_} for qw(index interface);
1322 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1326 my($fh, $noerr) = @_;
1329 my $SG_GET_VERSION_NUM = 0x2282;
1331 my $versionbuf = "\x00" x
8;
1332 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1334 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1337 my $version = unpack("I", $versionbuf);
1338 if ($version < 30000) {
1339 die "scsi generic interface too old\n" if !$noerr;
1343 my $buf = "\x00" x
36;
1344 my $sensebuf = "\x00" x
8;
1345 my $cmd = pack("C x3 C x1", 0x12, 36);
1347 # see /usr/include/scsi/sg.h
1348 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";
1350 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1351 length($sensebuf), 0, length($buf), $buf,
1352 $cmd, $sensebuf, 6000);
1354 $ret = ioctl($fh, $SG_IO, $packet);
1356 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1360 my @res = unpack($sg_io_hdr_t, $packet);
1361 if ($res[17] || $res[18]) {
1362 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1367 (my $byte0, my $byte1, $res->{vendor
},
1368 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1370 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1371 $res->{type
} = $byte0 & 31;
1379 my $fh = IO
::File-
>new("+<$path") || return undef;
1380 my $res = scsi_inquiry
($fh, 1);
1386 sub machine_type_is_q35
{
1389 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1392 sub print_tabletdevice_full
{
1395 my $q35 = machine_type_is_q35
($conf);
1397 # we use uhci for old VMs because tablet driver was buggy in older qemu
1398 my $usbbus = $q35 ?
"ehci" : "uhci";
1400 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1403 sub print_drivedevice_full
{
1404 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1409 if ($drive->{interface
} eq 'virtio') {
1410 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1411 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1412 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1413 } elsif ($drive->{interface
} eq 'scsi') {
1415 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1416 my $unit = $drive->{index} % $maxdev;
1417 my $devicetype = 'hd';
1419 if (drive_is_cdrom
($drive)) {
1422 if ($drive->{file
} =~ m
|^/|) {
1423 $path = $drive->{file
};
1424 if (my $info = path_is_scsi
($path)) {
1425 if ($info->{type
} == 0) {
1426 $devicetype = 'block';
1427 } elsif ($info->{type
} == 1) { # tape
1428 $devicetype = 'generic';
1432 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1435 if($path =~ m/^iscsi\:\/\
//){
1436 $devicetype = 'generic';
1440 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1441 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1443 $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}";
1446 } elsif ($drive->{interface
} eq 'ide'){
1448 my $controller = int($drive->{index} / $maxdev);
1449 my $unit = $drive->{index} % $maxdev;
1450 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1452 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1453 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1454 $model = URI
::Escape
::uri_unescape
($model);
1455 $device .= ",model=$model";
1457 } elsif ($drive->{interface
} eq 'sata'){
1458 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1459 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1460 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1461 } elsif ($drive->{interface
} eq 'usb') {
1463 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1465 die "unsupported interface type";
1468 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1473 sub get_initiator_name
{
1476 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1477 while (defined(my $line = <$fh>)) {
1478 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1487 sub print_drive_full
{
1488 my ($storecfg, $vmid, $drive) = @_;
1491 my $volid = $drive->{file
};
1494 if (drive_is_cdrom
($drive)) {
1495 $path = get_iso_path
($storecfg, $vmid, $volid);
1497 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1499 $path = PVE
::Storage
::path
($storecfg, $volid);
1500 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1501 $format = qemu_img_format
($scfg, $volname);
1509 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);
1510 foreach my $o (@qemu_drive_options) {
1511 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1513 if (my $serial = $drive->{serial
}) {
1514 $serial = URI
::Escape
::uri_unescape
($serial);
1515 $opts .= ",serial=$serial";
1518 $opts .= ",format=$format" if $format && !$drive->{format
};
1520 foreach my $o (qw(bps bps_rd bps_wr)) {
1521 my $v = $drive->{"m$o"};
1522 $opts .= ",$o=" . int($v*1024*1024) if $v;
1525 my $cache_direct = 0;
1527 if (my $cache = $drive->{cache
}) {
1528 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1529 } elsif (!drive_is_cdrom
($drive)) {
1530 $opts .= ",cache=none";
1534 # aio native works only with O_DIRECT
1535 if (!$drive->{aio
}) {
1537 $opts .= ",aio=native";
1539 $opts .= ",aio=threads";
1543 if (!drive_is_cdrom
($drive)) {
1545 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1546 $detectzeroes = 'off';
1547 } elsif ($drive->{discard
}) {
1548 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1550 # This used to be our default with discard not being specified:
1551 $detectzeroes = 'on';
1553 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1556 my $pathinfo = $path ?
"file=$path," : '';
1558 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1561 sub print_netdevice_full
{
1562 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1564 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1566 my $device = $net->{model
};
1567 if ($net->{model
} eq 'virtio') {
1568 $device = 'virtio-net-pci';
1571 my $pciaddr = print_pci_addr
("$netid", $bridges);
1572 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1573 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1574 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1575 my $vectors = $net->{queues
} * 2 + 2;
1576 $tmpstr .= ",vectors=$vectors,mq=on";
1578 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1580 if ($use_old_bios_files) {
1582 if ($device eq 'virtio-net-pci') {
1583 $romfile = 'pxe-virtio.rom';
1584 } elsif ($device eq 'e1000') {
1585 $romfile = 'pxe-e1000.rom';
1586 } elsif ($device eq 'ne2k') {
1587 $romfile = 'pxe-ne2k_pci.rom';
1588 } elsif ($device eq 'pcnet') {
1589 $romfile = 'pxe-pcnet.rom';
1590 } elsif ($device eq 'rtl8139') {
1591 $romfile = 'pxe-rtl8139.rom';
1593 $tmpstr .= ",romfile=$romfile" if $romfile;
1599 sub print_netdev_full
{
1600 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1603 if ($netid =~ m/^net(\d+)$/) {
1607 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1609 my $ifname = "tap${vmid}i$i";
1611 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1612 die "interface name '$ifname' is too long (max 15 character)\n"
1613 if length($ifname) >= 16;
1615 my $vhostparam = '';
1616 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1618 my $vmname = $conf->{name
} || "vm$vmid";
1621 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1623 if ($net->{bridge
}) {
1624 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1626 $netdev = "type=user,id=$netid,hostname=$vmname";
1629 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1634 sub drive_is_cdrom
{
1637 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1641 sub parse_number_sets
{
1644 foreach my $part (split(/;/, $set)) {
1645 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1646 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1647 push @$res, [ $1, $2 ];
1649 die "invalid range: $part\n";
1658 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1659 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1660 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1667 return undef if !$value;
1669 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1671 my @idlist = split(/;/, $res->{host
});
1672 delete $res->{host
};
1673 foreach my $id (@idlist) {
1674 if ($id =~ /^$PCIRE$/) {
1675 push @{$res->{pciid
}}, { id
=> $1, function
=> ($2//'0') };
1677 # should have been caught by parse_property_string already
1678 die "failed to parse PCI id: $id\n";
1684 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1688 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1693 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
() if !defined($res->{macaddr
});
1700 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1703 sub add_random_macs
{
1704 my ($settings) = @_;
1706 foreach my $opt (keys %$settings) {
1707 next if $opt !~ m/^net(\d+)$/;
1708 my $net = parse_net
($settings->{$opt});
1710 $settings->{$opt} = print_net
($net);
1714 sub vm_is_volid_owner
{
1715 my ($storecfg, $vmid, $volid) = @_;
1717 if ($volid !~ m
|^/|) {
1719 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1720 if ($owner && ($owner == $vmid)) {
1728 sub split_flagged_list
{
1729 my $text = shift || '';
1730 $text =~ s/[,;]/ /g;
1732 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1735 sub join_flagged_list
{
1736 my ($how, $lst) = @_;
1737 join $how, map { $lst->{$_} . $_ } keys %$lst;
1740 sub vmconfig_delete_pending_option
{
1741 my ($conf, $key, $force) = @_;
1743 delete $conf->{pending
}->{$key};
1744 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1745 $pending_delete_hash->{$key} = $force ?
'!' : '';
1746 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1749 sub vmconfig_undelete_pending_option
{
1750 my ($conf, $key) = @_;
1752 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1753 delete $pending_delete_hash->{$key};
1755 if (%$pending_delete_hash) {
1756 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1758 delete $conf->{pending
}->{delete};
1762 sub vmconfig_register_unused_drive
{
1763 my ($storecfg, $vmid, $conf, $drive) = @_;
1765 if (!drive_is_cdrom
($drive)) {
1766 my $volid = $drive->{file
};
1767 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1768 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1773 sub vmconfig_cleanup_pending
{
1776 # remove pending changes when nothing changed
1778 foreach my $opt (keys %{$conf->{pending
}}) {
1779 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1781 delete $conf->{pending
}->{$opt};
1785 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1786 my $pending_delete_hash = {};
1787 while (my ($opt, $force) = each %$current_delete_hash) {
1788 if (defined($conf->{$opt})) {
1789 $pending_delete_hash->{$opt} = $force;
1795 if (%$pending_delete_hash) {
1796 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1798 delete $conf->{pending
}->{delete};
1804 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1808 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1809 format_description
=> 'UUID',
1810 description
=> "Set SMBIOS1 UUID.",
1816 format_description
=> 'string',
1817 description
=> "Set SMBIOS1 version.",
1823 format_description
=> 'string',
1824 description
=> "Set SMBIOS1 serial number.",
1830 format_description
=> 'string',
1831 description
=> "Set SMBIOS1 manufacturer.",
1837 format_description
=> 'string',
1838 description
=> "Set SMBIOS1 product ID.",
1844 format_description
=> 'string',
1845 description
=> "Set SMBIOS1 SKU string.",
1851 format_description
=> 'string',
1852 description
=> "Set SMBIOS1 family string.",
1860 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1867 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1870 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1872 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1873 sub verify_bootdisk
{
1874 my ($value, $noerr) = @_;
1876 return $value if is_valid_drivename
($value);
1878 return undef if $noerr;
1880 die "invalid boot disk '$value'\n";
1883 sub parse_watchdog
{
1886 return undef if !$value;
1888 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1893 sub parse_usb_device
{
1896 return undef if !$value;
1899 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1900 $res->{vendorid
} = $2;
1901 $res->{productid
} = $4;
1902 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1903 $res->{hostbus
} = $1;
1904 $res->{hostport
} = $2;
1905 } elsif ($value =~ m/^spice$/i) {
1914 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1915 sub verify_usb_device
{
1916 my ($value, $noerr) = @_;
1918 return $value if parse_usb_device
($value);
1920 return undef if $noerr;
1922 die "unable to parse usb device\n";
1925 # add JSON properties for create and set function
1926 sub json_config_properties
{
1929 foreach my $opt (keys %$confdesc) {
1930 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1931 $prop->{$opt} = $confdesc->{$opt};
1938 my ($key, $value) = @_;
1940 die "unknown setting '$key'\n" if !$confdesc->{$key};
1942 my $type = $confdesc->{$key}->{type
};
1944 if (!defined($value)) {
1945 die "got undefined value\n";
1948 if ($value =~ m/[\n\r]/) {
1949 die "property contains a line feed\n";
1952 if ($type eq 'boolean') {
1953 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1954 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1955 die "type check ('boolean') failed - got '$value'\n";
1956 } elsif ($type eq 'integer') {
1957 return int($1) if $value =~ m/^(\d+)$/;
1958 die "type check ('integer') failed - got '$value'\n";
1959 } elsif ($type eq 'number') {
1960 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1961 die "type check ('number') failed - got '$value'\n";
1962 } elsif ($type eq 'string') {
1963 if (my $fmt = $confdesc->{$key}->{format
}) {
1964 if ($fmt eq 'pve-qm-drive') {
1965 # special case - we need to pass $key to parse_drive()
1966 my $drive = parse_drive
($key, $value);
1967 return $value if $drive;
1968 die "unable to parse drive options\n";
1970 PVE
::JSONSchema
::check_format
($fmt, $value);
1973 $value =~ s/^\"(.*)\"$/$1/;
1976 die "internal error"
1980 sub check_iommu_support
{
1981 #fixme : need to check IOMMU support
1982 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1992 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1993 utime undef, undef, $conf;
1997 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1999 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2001 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2003 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2005 # only remove disks owned by this VM
2006 foreach_drive
($conf, sub {
2007 my ($ds, $drive) = @_;
2009 return if drive_is_cdrom
($drive);
2011 my $volid = $drive->{file
};
2013 return if !$volid || $volid =~ m
|^/|;
2015 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2016 return if !$path || !$owner || ($owner != $vmid);
2018 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2021 if ($keep_empty_config) {
2022 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2027 # also remove unused disk
2029 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2032 PVE
::Storage
::foreach_volid
($dl, sub {
2033 my ($volid, $sid, $volname, $d) = @_;
2034 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2043 sub parse_vm_config
{
2044 my ($filename, $raw) = @_;
2046 return undef if !defined($raw);
2049 digest
=> Digest
::SHA
::sha1_hex
($raw),
2054 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2055 || die "got strange filename '$filename'";
2063 my @lines = split(/\n/, $raw);
2064 foreach my $line (@lines) {
2065 next if $line =~ m/^\s*$/;
2067 if ($line =~ m/^\[PENDING\]\s*$/i) {
2068 $section = 'pending';
2069 if (defined($descr)) {
2071 $conf->{description
} = $descr;
2074 $conf = $res->{$section} = {};
2077 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2079 if (defined($descr)) {
2081 $conf->{description
} = $descr;
2084 $conf = $res->{snapshots
}->{$section} = {};
2088 if ($line =~ m/^\#(.*)\s*$/) {
2089 $descr = '' if !defined($descr);
2090 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2094 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2095 $descr = '' if !defined($descr);
2096 $descr .= PVE
::Tools
::decode_text
($2);
2097 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2098 $conf->{snapstate
} = $1;
2099 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2102 $conf->{$key} = $value;
2103 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2105 if ($section eq 'pending') {
2106 $conf->{delete} = $value; # we parse this later
2108 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2110 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2113 eval { $value = check_type
($key, $value); };
2115 warn "vm $vmid - unable to parse value of '$key' - $@";
2117 my $fmt = $confdesc->{$key}->{format
};
2118 if ($fmt && $fmt eq 'pve-qm-drive') {
2119 my $v = parse_drive
($key, $value);
2120 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2121 $v->{file
} = $volid;
2122 $value = print_drive
($vmid, $v);
2124 warn "vm $vmid - unable to parse value of '$key'\n";
2129 if ($key eq 'cdrom') {
2130 $conf->{ide2
} = $value;
2132 $conf->{$key} = $value;
2138 if (defined($descr)) {
2140 $conf->{description
} = $descr;
2142 delete $res->{snapstate
}; # just to be sure
2147 sub write_vm_config
{
2148 my ($filename, $conf) = @_;
2150 delete $conf->{snapstate
}; # just to be sure
2152 if ($conf->{cdrom
}) {
2153 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2154 $conf->{ide2
} = $conf->{cdrom
};
2155 delete $conf->{cdrom
};
2158 # we do not use 'smp' any longer
2159 if ($conf->{sockets
}) {
2160 delete $conf->{smp
};
2161 } elsif ($conf->{smp
}) {
2162 $conf->{sockets
} = $conf->{smp
};
2163 delete $conf->{cores
};
2164 delete $conf->{smp
};
2167 my $used_volids = {};
2169 my $cleanup_config = sub {
2170 my ($cref, $pending, $snapname) = @_;
2172 foreach my $key (keys %$cref) {
2173 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2174 $key eq 'snapstate' || $key eq 'pending';
2175 my $value = $cref->{$key};
2176 if ($key eq 'delete') {
2177 die "propertry 'delete' is only allowed in [PENDING]\n"
2179 # fixme: check syntax?
2182 eval { $value = check_type
($key, $value); };
2183 die "unable to parse value of '$key' - $@" if $@;
2185 $cref->{$key} = $value;
2187 if (!$snapname && is_valid_drivename
($key)) {
2188 my $drive = parse_drive
($key, $value);
2189 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2194 &$cleanup_config($conf);
2196 &$cleanup_config($conf->{pending
}, 1);
2198 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2199 die "internal error" if $snapname eq 'pending';
2200 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2203 # remove 'unusedX' settings if we re-add a volume
2204 foreach my $key (keys %$conf) {
2205 my $value = $conf->{$key};
2206 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2207 delete $conf->{$key};
2211 my $generate_raw_config = sub {
2212 my ($conf, $pending) = @_;
2216 # add description as comment to top of file
2217 if (defined(my $descr = $conf->{description
})) {
2219 foreach my $cl (split(/\n/, $descr)) {
2220 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2223 $raw .= "#\n" if $pending;
2227 foreach my $key (sort keys %$conf) {
2228 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2229 $raw .= "$key: $conf->{$key}\n";
2234 my $raw = &$generate_raw_config($conf);
2236 if (scalar(keys %{$conf->{pending
}})){
2237 $raw .= "\n[PENDING]\n";
2238 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2241 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2242 $raw .= "\n[$snapname]\n";
2243 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2253 # we use static defaults from our JSON schema configuration
2254 foreach my $key (keys %$confdesc) {
2255 if (defined(my $default = $confdesc->{$key}->{default})) {
2256 $res->{$key} = $default;
2260 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2261 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2267 my $vmlist = PVE
::Cluster
::get_vmlist
();
2269 return $res if !$vmlist || !$vmlist->{ids
};
2270 my $ids = $vmlist->{ids
};
2272 foreach my $vmid (keys %$ids) {
2273 my $d = $ids->{$vmid};
2274 next if !$d->{node
} || $d->{node
} ne $nodename;
2275 next if !$d->{type
} || $d->{type
} ne 'qemu';
2276 $res->{$vmid}->{exists} = 1;
2281 # test if VM uses local resources (to prevent migration)
2282 sub check_local_resources
{
2283 my ($conf, $noerr) = @_;
2287 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2288 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2290 foreach my $k (keys %$conf) {
2291 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2292 # sockets are safe: they will recreated be on the target side post-migrate
2293 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2294 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2297 die "VM uses local resources\n" if $loc_res && !$noerr;
2302 # check if used storages are available on all nodes (use by migrate)
2303 sub check_storage_availability
{
2304 my ($storecfg, $conf, $node) = @_;
2306 foreach_drive
($conf, sub {
2307 my ($ds, $drive) = @_;
2309 my $volid = $drive->{file
};
2312 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2315 # check if storage is available on both nodes
2316 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2317 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2321 # list nodes where all VM images are available (used by has_feature API)
2323 my ($conf, $storecfg) = @_;
2325 my $nodelist = PVE
::Cluster
::get_nodelist
();
2326 my $nodehash = { map { $_ => 1 } @$nodelist };
2327 my $nodename = PVE
::INotify
::nodename
();
2329 foreach_drive
($conf, sub {
2330 my ($ds, $drive) = @_;
2332 my $volid = $drive->{file
};
2335 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2337 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2338 if ($scfg->{disable
}) {
2340 } elsif (my $avail = $scfg->{nodes
}) {
2341 foreach my $node (keys %$nodehash) {
2342 delete $nodehash->{$node} if !$avail->{$node};
2344 } elsif (!$scfg->{shared
}) {
2345 foreach my $node (keys %$nodehash) {
2346 delete $nodehash->{$node} if $node ne $nodename
2356 my ($pidfile, $pid) = @_;
2358 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2362 return undef if !$line;
2363 my @param = split(/\0/, $line);
2365 my $cmd = $param[0];
2366 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2368 for (my $i = 0; $i < scalar (@param); $i++) {
2371 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2372 my $p = $param[$i+1];
2373 return 1 if $p && ($p eq $pidfile);
2382 my ($vmid, $nocheck, $node) = @_;
2384 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2386 die "unable to find configuration file for VM $vmid - no such machine\n"
2387 if !$nocheck && ! -f
$filename;
2389 my $pidfile = pidfile_name
($vmid);
2391 if (my $fd = IO
::File-
>new("<$pidfile")) {
2396 my $mtime = $st->mtime;
2397 if ($mtime > time()) {
2398 warn "file '$filename' modified in future\n";
2401 if ($line =~ m/^(\d+)$/) {
2403 if (check_cmdline
($pidfile, $pid)) {
2404 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2416 my $vzlist = config_list
();
2418 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2420 while (defined(my $de = $fd->read)) {
2421 next if $de !~ m/^(\d+)\.pid$/;
2423 next if !defined($vzlist->{$vmid});
2424 if (my $pid = check_running
($vmid)) {
2425 $vzlist->{$vmid}->{pid
} = $pid;
2433 my ($storecfg, $conf) = @_;
2435 my $bootdisk = $conf->{bootdisk
};
2436 return undef if !$bootdisk;
2437 return undef if !is_valid_drivename
($bootdisk);
2439 return undef if !$conf->{$bootdisk};
2441 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2442 return undef if !defined($drive);
2444 return undef if drive_is_cdrom
($drive);
2446 my $volid = $drive->{file
};
2447 return undef if !$volid;
2449 return $drive->{size
};
2452 my $last_proc_pid_stat;
2454 # get VM status information
2455 # This must be fast and should not block ($full == false)
2456 # We only query KVM using QMP if $full == true (this can be slow)
2458 my ($opt_vmid, $full) = @_;
2462 my $storecfg = PVE
::Storage
::config
();
2464 my $list = vzlist
();
2465 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2467 my $cpucount = $cpuinfo->{cpus
} || 1;
2469 foreach my $vmid (keys %$list) {
2470 next if $opt_vmid && ($vmid ne $opt_vmid);
2472 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2473 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2476 $d->{pid
} = $list->{$vmid}->{pid
};
2478 # fixme: better status?
2479 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2481 my $size = disksize
($storecfg, $conf);
2482 if (defined($size)) {
2483 $d->{disk
} = 0; # no info available
2484 $d->{maxdisk
} = $size;
2490 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2491 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2492 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2494 $d->{name
} = $conf->{name
} || "VM $vmid";
2495 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2497 if ($conf->{balloon
}) {
2498 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2499 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2510 $d->{diskwrite
} = 0;
2512 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2517 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2518 foreach my $dev (keys %$netdev) {
2519 next if $dev !~ m/^tap([1-9]\d*)i/;
2521 my $d = $res->{$vmid};
2524 $d->{netout
} += $netdev->{$dev}->{receive
};
2525 $d->{netin
} += $netdev->{$dev}->{transmit
};
2528 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2529 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2534 my $ctime = gettimeofday
;
2536 foreach my $vmid (keys %$list) {
2538 my $d = $res->{$vmid};
2539 my $pid = $d->{pid
};
2542 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2543 next if !$pstat; # not running
2545 my $used = $pstat->{utime} + $pstat->{stime
};
2547 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2549 if ($pstat->{vsize
}) {
2550 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2553 my $old = $last_proc_pid_stat->{$pid};
2555 $last_proc_pid_stat->{$pid} = {
2563 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2565 if ($dtime > 1000) {
2566 my $dutime = $used - $old->{used
};
2568 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2569 $last_proc_pid_stat->{$pid} = {
2575 $d->{cpu
} = $old->{cpu
};
2579 return $res if !$full;
2581 my $qmpclient = PVE
::QMPClient-
>new();
2583 my $ballooncb = sub {
2584 my ($vmid, $resp) = @_;
2586 my $info = $resp->{'return'};
2587 return if !$info->{max_mem
};
2589 my $d = $res->{$vmid};
2591 # use memory assigned to VM
2592 $d->{maxmem
} = $info->{max_mem
};
2593 $d->{balloon
} = $info->{actual
};
2595 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2596 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2597 $d->{freemem
} = $info->{free_mem
};
2600 $d->{ballooninfo
} = $info;
2603 my $blockstatscb = sub {
2604 my ($vmid, $resp) = @_;
2605 my $data = $resp->{'return'} || [];
2606 my $totalrdbytes = 0;
2607 my $totalwrbytes = 0;
2609 for my $blockstat (@$data) {
2610 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2611 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2613 $blockstat->{device
} =~ s/drive-//;
2614 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2616 $res->{$vmid}->{diskread
} = $totalrdbytes;
2617 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2620 my $statuscb = sub {
2621 my ($vmid, $resp) = @_;
2623 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2624 # this fails if ballon driver is not loaded, so this must be
2625 # the last commnand (following command are aborted if this fails).
2626 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2628 my $status = 'unknown';
2629 if (!defined($status = $resp->{'return'}->{status
})) {
2630 warn "unable to get VM status\n";
2634 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2637 foreach my $vmid (keys %$list) {
2638 next if $opt_vmid && ($vmid ne $opt_vmid);
2639 next if !$res->{$vmid}->{pid
}; # not running
2640 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2643 $qmpclient->queue_execute(undef, 1);
2645 foreach my $vmid (keys %$list) {
2646 next if $opt_vmid && ($vmid ne $opt_vmid);
2647 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2654 my ($conf, $func, @param) = @_;
2656 foreach my $ds (valid_drive_names
()) {
2657 next if !defined($conf->{$ds});
2659 my $drive = parse_drive
($ds, $conf->{$ds});
2662 &$func($ds, $drive, @param);
2667 my ($conf, $func, @param) = @_;
2671 my $test_volid = sub {
2672 my ($volid, $is_cdrom) = @_;
2676 $volhash->{$volid} = $is_cdrom || 0;
2679 foreach_drive
($conf, sub {
2680 my ($ds, $drive) = @_;
2681 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2684 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2685 my $snap = $conf->{snapshots
}->{$snapname};
2686 &$test_volid($snap->{vmstate
}, 0);
2687 foreach_drive
($snap, sub {
2688 my ($ds, $drive) = @_;
2689 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2693 foreach my $volid (keys %$volhash) {
2694 &$func($volid, $volhash->{$volid}, @param);
2698 sub vga_conf_has_spice
{
2701 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2706 sub config_to_command
{
2707 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2710 my $globalFlags = [];
2711 my $machineFlags = [];
2717 my $kvmver = kvm_user_version
();
2718 my $vernum = 0; # unknown
2719 my $ostype = $conf->{ostype
};
2720 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2721 $vernum = $1*1000000+$2*1000;
2722 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2723 $vernum = $1*1000000+$2*1000+$3;
2726 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2728 my $have_ovz = -f
'/proc/vz/vestat';
2730 my $q35 = machine_type_is_q35
($conf);
2731 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2732 my $machine_type = $forcemachine || $conf->{machine
};
2733 my $use_old_bios_files = undef;
2734 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2736 my $cpuunits = defined($conf->{cpuunits
}) ?
2737 $conf->{cpuunits
} : $defaults->{cpuunits
};
2739 push @$cmd, '/usr/bin/kvm';
2741 push @$cmd, '-id', $vmid;
2745 my $qmpsocket = qmp_socket
($vmid);
2746 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2747 push @$cmd, '-mon', "chardev=qmp,mode=control";
2750 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2752 push @$cmd, '-daemonize';
2754 if ($conf->{smbios1
}) {
2755 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2758 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2759 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2760 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2761 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2762 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2763 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2764 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2768 # the q35 chipset support native usb2, so we enable usb controller
2769 # by default for this machine type
2770 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2772 $pciaddr = print_pci_addr
("piix3", $bridges);
2773 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2776 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2777 next if !$conf->{"usb$i"};
2778 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2779 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2782 # include usb device config
2783 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2786 # add usb3 controller if needed
2789 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2790 next if !$conf->{"usb$i"};
2791 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2792 next if !$d || !$d->{usb3
};
2796 $pciaddr = print_pci_addr
("xhci", $bridges);
2797 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2799 my $vga = $conf->{vga
};
2801 my $qxlnum = vga_conf_has_spice
($vga);
2802 $vga = 'qxl' if $qxlnum;
2805 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2806 $conf->{ostype
} eq 'win7' ||
2807 $conf->{ostype
} eq 'w2k8')) {
2814 # enable absolute mouse coordinates (needed by vnc)
2816 if (defined($conf->{tablet
})) {
2817 $tablet = $conf->{tablet
};
2819 $tablet = $defaults->{tablet
};
2820 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2821 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2824 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2828 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2829 my $d = parse_hostpci
($conf->{"hostpci$i"});
2832 my $pcie = $d->{pcie
};
2834 die "q35 machine model is not enabled" if !$q35;
2835 $pciaddr = print_pcie_addr
("hostpci$i");
2837 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2840 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2842 if ($d->{'x-vga'}) {
2843 $xvga = ',x-vga=on';
2846 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2847 push @$cpuFlags , 'hv_vendor_id=proxmox';
2849 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2853 my $pcidevices = $d->{pciid
};
2854 my $multifunction = 1 if @$pcidevices > 1;
2857 foreach my $pcidevice (@$pcidevices) {
2859 my $id = "hostpci$i";
2860 $id .= ".$j" if $multifunction;
2861 my $addr = $pciaddr;
2862 $addr .= ".$j" if $multifunction;
2863 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2866 $devicestr .= "$rombar$xvga";
2867 $devicestr .= ",multifunction=on" if $multifunction;
2870 push @$devices, '-device', $devicestr;
2876 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2877 next if !$conf->{"usb$i"};
2878 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2881 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2883 if (defined($d->{usb3
}) && $d->{usb3
}) {
2884 $usbbus = ',bus=xhci.0';
2887 if (defined($d->{host
})) {
2888 $d = parse_usb_device
($d->{host
});
2889 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2890 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2891 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2892 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2893 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2894 # usb redir support for spice, currently no usb3
2895 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2896 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2902 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2903 if (my $path = $conf->{"serial$i"}) {
2904 if ($path eq 'socket') {
2905 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2906 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2907 push @$devices, '-device', "isa-serial,chardev=serial$i";
2909 die "no such serial device\n" if ! -c
$path;
2910 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2911 push @$devices, '-device', "isa-serial,chardev=serial$i";
2917 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2918 if (my $path = $conf->{"parallel$i"}) {
2919 die "no such parallel device\n" if ! -c
$path;
2920 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2921 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2922 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2926 my $vmname = $conf->{name
} || "vm$vmid";
2928 push @$cmd, '-name', $vmname;
2931 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2932 $sockets = $conf->{sockets
} if $conf->{sockets
};
2934 my $cores = $conf->{cores
} || 1;
2936 my $maxcpus = $sockets * $cores;
2938 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2940 my $allowed_vcpus = $cpuinfo->{cpus
};
2942 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2943 if ($allowed_vcpus < $maxcpus);
2945 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2947 push @$cmd, '-nodefaults';
2949 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2951 my $bootindex_hash = {};
2953 foreach my $o (split(//, $bootorder)) {
2954 $bootindex_hash->{$o} = $i*100;
2958 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2960 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2962 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2964 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2966 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2967 my $socket = vnc_socket
($vmid);
2968 push @$cmd, '-vnc', "unix:$socket,x509,password";
2970 push @$cmd, '-nographic';
2974 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2976 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2977 my $useLocaltime = $conf->{localtime};
2980 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2982 if ($ostype =~ m/^w/) { # windows
2983 $useLocaltime = 1 if !defined($conf->{localtime});
2985 # use time drift fix when acpi is enabled
2986 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2987 $tdf = 1 if !defined($conf->{tdf
});
2991 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2992 $ostype eq 'wvista') {
2993 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2994 push @$cmd, '-no-hpet';
2995 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2996 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2997 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2998 push @$cpuFlags , 'hv_time' if !$nokvm;
3000 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
3001 push @$cpuFlags , 'hv_reset' if !$nokvm;
3002 push @$cpuFlags , 'hv_vpindex' if !$nokvm;
3003 push @$cpuFlags , 'hv_runtime' if !$nokvm;
3007 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3011 if ($ostype eq 'win7' || $ostype eq 'win8') {
3012 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3016 push @$rtcFlags, 'driftfix=slew' if $tdf;
3019 push @$machineFlags, 'accel=tcg';
3021 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3024 if ($machine_type) {
3025 push @$machineFlags, "type=${machine_type}";
3028 if ($conf->{startdate
}) {
3029 push @$rtcFlags, "base=$conf->{startdate}";
3030 } elsif ($useLocaltime) {
3031 push @$rtcFlags, 'base=localtime';
3034 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3035 if (my $cputype = $conf->{cpu
}) {
3036 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3037 or die "Cannot parse cpu description: $cputype\n";
3038 $cpu = $cpuconf->{cputype
};
3039 $kvm_off = 1 if $cpuconf->{hidden
};
3042 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3044 push @$cpuFlags , '-x2apic'
3045 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3047 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3049 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3051 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3053 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3054 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3057 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3059 push @$cpuFlags, 'kvm=off' if $kvm_off;
3061 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3062 die "internal error"; # should not happen
3064 push @$cpuFlags, "vendor=${cpu_vendor}"
3065 if $cpu_vendor ne 'default';
3067 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3069 push @$cmd, '-cpu', $cpu;
3071 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3073 push @$cmd, '-S' if $conf->{freeze
};
3075 # set keyboard layout
3076 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3077 push @$cmd, '-k', $kb if $kb;
3080 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3081 #push @$cmd, '-soundhw', 'es1370';
3082 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3084 if($conf->{agent
}) {
3085 my $qgasocket = qmp_socket
($vmid, 1);
3086 my $pciaddr = print_pci_addr
("qga0", $bridges);
3087 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3088 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3089 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3096 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3097 for(my $i = 1; $i < $qxlnum; $i++){
3098 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3099 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3102 # assume other OS works like Linux
3103 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3104 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3108 my $pciaddr = print_pci_addr
("spice", $bridges);
3110 my $nodename = PVE
::INotify
::nodename
();
3111 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3112 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3114 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3116 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3117 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3118 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3121 # enable balloon by default, unless explicitly disabled
3122 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3123 $pciaddr = print_pci_addr
("balloon0", $bridges);
3124 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3127 if ($conf->{watchdog
}) {
3128 my $wdopts = parse_watchdog
($conf->{watchdog
});
3129 $pciaddr = print_pci_addr
("watchdog", $bridges);
3130 my $watchdog = $wdopts->{model
} || 'i6300esb';
3131 push @$devices, '-device', "$watchdog$pciaddr";
3132 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3136 my $scsicontroller = {};
3137 my $ahcicontroller = {};
3138 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3140 # Add iscsi initiator name if available
3141 if (my $initiator = get_initiator_name
()) {
3142 push @$devices, '-iscsi', "initiator-name=$initiator";
3145 foreach_drive
($conf, sub {
3146 my ($ds, $drive) = @_;
3148 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3149 push @$vollist, $drive->{file
};
3152 $use_virtio = 1 if $ds =~ m/^virtio/;
3154 if (drive_is_cdrom
($drive)) {
3155 if ($bootindex_hash->{d
}) {
3156 $drive->{bootindex
} = $bootindex_hash->{d
};
3157 $bootindex_hash->{d
} += 1;
3160 if ($bootindex_hash->{c
}) {
3161 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3162 $bootindex_hash->{c
} += 1;
3166 if($drive->{interface
} eq 'virtio'){
3167 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3170 if ($drive->{interface
} eq 'scsi') {
3172 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3174 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3175 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3178 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3179 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3180 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3181 } elsif ($drive->{iothread
}) {
3182 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3186 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3187 $queues = ",num_queues=$drive->{queues}";
3190 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3191 $scsicontroller->{$controller}=1;
3194 if ($drive->{interface
} eq 'sata') {
3195 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3196 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3197 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3198 $ahcicontroller->{$controller}=1;
3201 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3202 push @$devices, '-drive',$drive_cmd;
3203 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3206 for (my $i = 0; $i < $MAX_NETS; $i++) {
3207 next if !$conf->{"net$i"};
3208 my $d = parse_net
($conf->{"net$i"});
3211 $use_virtio = 1 if $d->{model
} eq 'virtio';
3213 if ($bootindex_hash->{n
}) {
3214 $d->{bootindex
} = $bootindex_hash->{n
};
3215 $bootindex_hash->{n
} += 1;
3218 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3219 push @$devices, '-netdev', $netdevfull;
3221 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3222 push @$devices, '-device', $netdevicefull;
3227 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3232 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3234 while (my ($k, $v) = each %$bridges) {
3235 $pciaddr = print_pci_addr
("pci.$k");
3236 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3241 if ($conf->{args
}) {
3242 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3246 push @$cmd, @$devices;
3247 push @$cmd, '-rtc', join(',', @$rtcFlags)
3248 if scalar(@$rtcFlags);
3249 push @$cmd, '-machine', join(',', @$machineFlags)
3250 if scalar(@$machineFlags);
3251 push @$cmd, '-global', join(',', @$globalFlags)
3252 if scalar(@$globalFlags);
3254 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3259 return "${var_run_tmpdir}/$vmid.vnc";
3265 my $res = vm_mon_cmd
($vmid, 'query-spice');
3267 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3271 my ($vmid, $qga) = @_;
3272 my $sockettype = $qga ?
'qga' : 'qmp';
3273 return "${var_run_tmpdir}/$vmid.$sockettype";
3278 return "${var_run_tmpdir}/$vmid.pid";
3281 sub vm_devices_list
{
3284 my $res = vm_mon_cmd
($vmid, 'query-pci');
3286 foreach my $pcibus (@$res) {
3287 foreach my $device (@{$pcibus->{devices
}}) {
3288 next if !$device->{'qdev_id'};
3289 if ($device->{'pci_bridge'}) {
3290 $devices->{$device->{'qdev_id'}} = 1;
3291 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3292 next if !$bridge_device->{'qdev_id'};
3293 $devices->{$bridge_device->{'qdev_id'}} = 1;
3294 $devices->{$device->{'qdev_id'}}++;
3297 $devices->{$device->{'qdev_id'}} = 1;
3302 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3303 foreach my $block (@$resblock) {
3304 if($block->{device
} =~ m/^drive-(\S+)/){
3309 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3310 foreach my $mice (@$resmice) {
3311 if ($mice->{name
} eq 'QEMU HID Tablet') {
3312 $devices->{tablet
} = 1;
3321 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3323 my $q35 = machine_type_is_q35
($conf);
3325 my $devices_list = vm_devices_list
($vmid);
3326 return 1 if defined($devices_list->{$deviceid});
3328 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3330 if ($deviceid eq 'tablet') {
3332 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3334 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3336 qemu_iothread_add
($vmid, $deviceid, $device);
3338 qemu_driveadd
($storecfg, $vmid, $device);
3339 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3341 qemu_deviceadd
($vmid, $devicefull);
3342 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3344 eval { qemu_drivedel
($vmid, $deviceid); };
3349 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3352 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3353 my $pciaddr = print_pci_addr
($deviceid);
3354 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3356 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3358 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3359 qemu_iothread_add
($vmid, $deviceid, $device);
3360 $devicefull .= ",iothread=iothread-$deviceid";
3363 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3364 $devicefull .= ",num_queues=$device->{queues}";
3367 qemu_deviceadd
($vmid, $devicefull);
3368 qemu_deviceaddverify
($vmid, $deviceid);
3370 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3372 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3373 qemu_driveadd
($storecfg, $vmid, $device);
3375 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3376 eval { qemu_deviceadd
($vmid, $devicefull); };
3378 eval { qemu_drivedel
($vmid, $deviceid); };
3383 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3385 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3387 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3388 my $use_old_bios_files = undef;
3389 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3391 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3392 qemu_deviceadd
($vmid, $netdevicefull);
3393 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3395 eval { qemu_netdevdel
($vmid, $deviceid); };
3400 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3403 my $pciaddr = print_pci_addr
($deviceid);
3404 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3406 qemu_deviceadd
($vmid, $devicefull);
3407 qemu_deviceaddverify
($vmid, $deviceid);
3410 die "can't hotplug device '$deviceid'\n";
3416 # fixme: this should raise exceptions on error!
3417 sub vm_deviceunplug
{
3418 my ($vmid, $conf, $deviceid) = @_;
3420 my $devices_list = vm_devices_list
($vmid);
3421 return 1 if !defined($devices_list->{$deviceid});
3423 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3425 if ($deviceid eq 'tablet') {
3427 qemu_devicedel
($vmid, $deviceid);
3429 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3431 qemu_devicedel
($vmid, $deviceid);
3432 qemu_devicedelverify
($vmid, $deviceid);
3433 qemu_drivedel
($vmid, $deviceid);
3434 qemu_iothread_del
($conf, $vmid, $deviceid);
3436 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3438 qemu_devicedel
($vmid, $deviceid);
3439 qemu_devicedelverify
($vmid, $deviceid);
3440 qemu_iothread_del
($conf, $vmid, $deviceid);
3442 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3444 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3445 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3446 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3448 qemu_devicedel
($vmid, $deviceid);
3449 qemu_drivedel
($vmid, $deviceid);
3450 qemu_deletescsihw
($conf, $vmid, $deviceid);
3452 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3454 qemu_devicedel
($vmid, $deviceid);
3455 qemu_devicedelverify
($vmid, $deviceid);
3456 qemu_netdevdel
($vmid, $deviceid);
3459 die "can't unplug device '$deviceid'\n";
3465 sub qemu_deviceadd
{
3466 my ($vmid, $devicefull) = @_;
3468 $devicefull = "driver=".$devicefull;
3469 my %options = split(/[=,]/, $devicefull);
3471 vm_mon_cmd
($vmid, "device_add" , %options);
3474 sub qemu_devicedel
{
3475 my ($vmid, $deviceid) = @_;
3477 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3480 sub qemu_iothread_add
{
3481 my($vmid, $deviceid, $device) = @_;
3483 if ($device->{iothread
}) {
3484 my $iothreads = vm_iothreads_list
($vmid);
3485 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3489 sub qemu_iothread_del
{
3490 my($conf, $vmid, $deviceid) = @_;
3492 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3493 if ($device->{iothread
}) {
3494 my $iothreads = vm_iothreads_list
($vmid);
3495 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3499 sub qemu_objectadd
{
3500 my($vmid, $objectid, $qomtype) = @_;
3502 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3507 sub qemu_objectdel
{
3508 my($vmid, $objectid) = @_;
3510 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3516 my ($storecfg, $vmid, $device) = @_;
3518 my $drive = print_drive_full
($storecfg, $vmid, $device);
3519 $drive =~ s/\\/\\\\/g;
3520 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3522 # If the command succeeds qemu prints: "OK
"
3523 return 1 if $ret =~ m/OK/s;
3525 die "adding drive failed
: $ret\n";
3529 my($vmid, $deviceid) = @_;
3531 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3534 return 1 if $ret eq "";
3536 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3537 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3539 die "deleting drive
$deviceid failed
: $ret\n";
3542 sub qemu_deviceaddverify {
3543 my ($vmid, $deviceid) = @_;
3545 for (my $i = 0; $i <= 5; $i++) {
3546 my $devices_list = vm_devices_list($vmid);
3547 return 1 if defined($devices_list->{$deviceid});
3551 die "error on hotplug device
'$deviceid'\n";
3555 sub qemu_devicedelverify {
3556 my ($vmid, $deviceid) = @_;
3558 # need to verify that the device is correctly removed as device_del
3559 # is async and empty return is not reliable
3561 for (my $i = 0; $i <= 5; $i++) {
3562 my $devices_list = vm_devices_list($vmid);
3563 return 1 if !defined($devices_list->{$deviceid});
3567 die "error on hot-unplugging device
'$deviceid'\n";
3570 sub qemu_findorcreatescsihw {
3571 my ($storecfg, $conf, $vmid, $device) = @_;
3573 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3575 my $scsihwid="$controller_prefix$controller";
3576 my $devices_list = vm_devices_list($vmid);
3578 if(!defined($devices_list->{$scsihwid})) {
3579 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3585 sub qemu_deletescsihw {
3586 my ($conf, $vmid, $opt) = @_;
3588 my $device = parse_drive($opt, $conf->{$opt});
3590 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3591 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3595 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3597 my $devices_list = vm_devices_list($vmid);
3598 foreach my $opt (keys %{$devices_list}) {
3599 if (PVE::QemuServer::is_valid_drivename($opt)) {
3600 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3601 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3607 my $scsihwid="scsihw
$controller";
3609 vm_deviceunplug($vmid, $conf, $scsihwid);
3614 sub qemu_add_pci_bridge {
3615 my ($storecfg, $conf, $vmid, $device) = @_;
3621 print_pci_addr($device, $bridges);
3623 while (my ($k, $v) = each %$bridges) {
3626 return 1 if !defined($bridgeid) || $bridgeid < 1;
3628 my $bridge = "pci
.$bridgeid";
3629 my $devices_list = vm_devices_list($vmid);
3631 if (!defined($devices_list->{$bridge})) {
3632 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3638 sub qemu_set_link_status {
3639 my ($vmid, $device, $up) = @_;
3641 vm_mon_cmd($vmid, "set_link
", name => $device,
3642 up => $up ? JSON::true : JSON::false);
3645 sub qemu_netdevadd {
3646 my ($vmid, $conf, $device, $deviceid) = @_;
3648 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3649 my %options = split(/[=,]/, $netdev);
3651 vm_mon_cmd($vmid, "netdev_add
", %options);
3655 sub qemu_netdevdel {
3656 my ($vmid, $deviceid) = @_;
3658 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3661 sub qemu_cpu_hotplug {
3662 my ($vmid, $conf, $vcpus) = @_;
3665 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3666 $sockets = $conf->{sockets} if $conf->{sockets};
3667 my $cores = $conf->{cores} || 1;
3668 my $maxcpus = $sockets * $cores;
3670 $vcpus = $maxcpus if !$vcpus;
3672 die "you can
't add more vcpus than maxcpus\n"
3673 if $vcpus > $maxcpus;
3675 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3676 die "online cpu unplug is not yet possible\n"
3677 if $vcpus < $currentvcpus;
3679 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3680 die "vcpus in running vm is different than configuration\n"
3681 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3683 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3684 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3688 sub qemu_block_set_io_throttle {
3689 my ($vmid, $deviceid,
3690 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3691 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3693 return if !check_running($vmid) ;
3695 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3697 bps_rd => int($bps_rd),
3698 bps_wr => int($bps_wr),
3700 iops_rd => int($iops_rd),
3701 iops_wr => int($iops_wr),
3702 bps_max => int($bps_max),
3703 bps_rd_max => int($bps_rd_max),
3704 bps_wr_max => int($bps_wr_max),
3705 iops_max => int($iops_max),
3706 iops_rd_max => int($iops_rd_max),
3707 iops_wr_max => int($iops_wr_max)
3712 # old code, only used to shutdown old VM after update
3714 my ($fh, $timeout) = @_;
3716 my $sel = new IO::Select;
3723 while (scalar (@ready = $sel->can_read($timeout))) {
3725 if ($count = $fh->sysread($buf, 8192)) {
3726 if ($buf =~ /^(.*)\(qemu\) $/s) {
3733 if (!defined($count)) {
3740 die "monitor read timeout\n" if !scalar(@ready);
3745 # old code, only used to shutdown old VM after update
3746 sub vm_monitor_command {
3747 my ($vmid, $cmdstr, $nocheck) = @_;
3752 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3754 my $sname = "${var_run_tmpdir}/$vmid.mon";
3756 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3757 die "unable to connect to VM $vmid socket - $!\n";
3761 # hack: migrate sometime blocks the monitor (when migrate_downtime
3763 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3764 $timeout = 60*60; # 1 hour
3768 my $data = __read_avail($sock, $timeout);
3770 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3771 die "got unexpected qemu monitor banner\n";
3774 my $sel = new IO::Select;
3777 if (!scalar(my @ready = $sel->can_write($timeout))) {
3778 die "monitor write error - timeout";
3781 my $fullcmd = "$cmdstr\r";
3783 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3786 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3787 die "monitor write error - $!";
3790 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3794 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3795 $timeout = 60*60; # 1 hour
3796 } elsif ($cmdstr =~ m/^(eject|change)/) {
3797 $timeout = 60; # note: cdrom mount command is slow
3799 if ($res = __read_avail($sock, $timeout)) {
3801 my @lines = split("\r?\n", $res);
3803 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3805 $res = join("\n", @lines);
3813 syslog("err", "VM $vmid monitor command failed - $err");
3820 sub qemu_block_resize {
3821 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3823 my $running = check_running($vmid);
3825 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3827 return if !$running;
3829 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3833 sub qemu_volume_snapshot {
3834 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3836 my $running = check_running($vmid);
3838 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3839 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3841 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3845 sub qemu_volume_snapshot_delete {
3846 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3848 my $running = check_running($vmid);
3850 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3852 return if !$running;
3854 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
3857 sub set_migration_caps {
3863 "auto-converge" => 1,
3865 "x-rdma-pin-all" => 0,
3870 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
3872 for my $supported_capability (@$supported_capabilities) {
3874 capability => $supported_capability->{capability},
3875 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3879 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
3882 my $fast_plug_option = {
3891 # hotplug changes in [PENDING]
3892 # $selection hash can be used to only apply specified options, for
3893 # example: { cores => 1 } (only apply changed 'cores
')
3894 # $errors ref is used to return error messages
3895 sub vmconfig_hotplug_pending {
3896 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3898 my $defaults = load_defaults();
3900 # commit values which do not have any impact on running VM first
3901 # Note: those option cannot raise errors, we we do not care about
3902 # $selection and always apply them.
3904 my $add_error = sub {
3905 my ($opt, $msg) = @_;
3906 $errors->{$opt} = "hotplug problem - $msg";
3910 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3911 if ($fast_plug_option->{$opt}) {
3912 $conf->{$opt} = $conf->{pending}->{$opt};
3913 delete $conf->{pending}->{$opt};
3919 PVE::QemuConfig->write_config($vmid, $conf);
3920 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3923 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3925 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3926 while (my ($opt, $force) = each %$pending_delete_hash) {
3927 next if $selection && !$selection->{$opt};
3929 if ($opt eq 'hotplug
') {
3930 die "skip\n" if ($conf->{hotplug} =~ /memory/);
3931 } elsif ($opt eq 'tablet
') {
3932 die "skip\n" if !$hotplug_features->{usb};
3933 if ($defaults->{tablet}) {
3934 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3936 vm_deviceunplug($vmid, $conf, $opt);
3938 } elsif ($opt eq 'vcpus
') {
3939 die "skip\n" if !$hotplug_features->{cpu};
3940 qemu_cpu_hotplug($vmid, $conf, undef);
3941 } elsif ($opt eq 'balloon
') {
3942 # enable balloon device is not hotpluggable
3943 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
3944 } elsif ($fast_plug_option->{$opt}) {
3946 } elsif ($opt =~ m/^net(\d+)$/) {
3947 die "skip\n" if !$hotplug_features->{network};
3948 vm_deviceunplug($vmid, $conf, $opt);
3949 } elsif (is_valid_drivename($opt)) {
3950 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3951 vm_deviceunplug($vmid, $conf, $opt);
3952 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3953 } elsif ($opt =~ m/^memory$/) {
3954 die "skip\n" if !$hotplug_features->{memory};
3955 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3956 } elsif ($opt eq 'cpuunits
') {
3957 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
3958 } elsif ($opt eq 'cpulimit
') {
3959 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
3965 &$add_error($opt, $err) if $err ne "skip\n";
3967 # save new config if hotplug was successful
3968 delete $conf->{$opt};
3969 vmconfig_undelete_pending_option($conf, $opt);
3970 PVE::QemuConfig->write_config($vmid, $conf);
3971 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3975 foreach my $opt (keys %{$conf->{pending}}) {
3976 next if $selection && !$selection->{$opt};
3977 my $value = $conf->{pending}->{$opt};
3979 if ($opt eq 'hotplug
') {
3980 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3981 } elsif ($opt eq 'tablet
') {
3982 die "skip\n" if !$hotplug_features->{usb};
3984 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3985 } elsif ($value == 0) {
3986 vm_deviceunplug($vmid, $conf, $opt);
3988 } elsif ($opt eq 'vcpus
') {
3989 die "skip\n" if !$hotplug_features->{cpu};
3990 qemu_cpu_hotplug($vmid, $conf, $value);
3991 } elsif ($opt eq 'balloon
') {
3992 # enable/disable balloning device is not hotpluggable
3993 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3994 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3995 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
3997 # allow manual ballooning if shares is set to zero
3998 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3999 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4000 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4002 } elsif ($opt =~ m/^net(\d+)$/) {
4003 # some changes can be done without hotplug
4004 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4005 $vmid, $opt, $value);
4006 } elsif (is_valid_drivename($opt)) {
4007 # some changes can be done without hotplug
4008 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4009 $vmid, $opt, $value, 1);
4010 } elsif ($opt =~ m/^memory$/) { #dimms
4011 die "skip\n" if !$hotplug_features->{memory};
4012 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4013 } elsif ($opt eq 'cpuunits
') {
4014 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4015 } elsif ($opt eq 'cpulimit
') {
4016 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4017 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4019 die "skip\n"; # skip non-hot-pluggable options
4023 &$add_error($opt, $err) if $err ne "skip\n";
4025 # save new config if hotplug was successful
4026 $conf->{$opt} = $value;
4027 delete $conf->{pending}->{$opt};
4028 PVE::QemuConfig->write_config($vmid, $conf);
4029 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4034 sub try_deallocate_drive {
4035 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4037 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4038 my $volid = $drive->{file};
4039 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4040 my $sid = PVE::Storage::parse_volume_id($volid);
4041 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4043 # check if the disk is really unused
4044 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4045 if is_volume_in_use($storecfg, $conf, $key, $volid);
4046 PVE::Storage::vdisk_free($storecfg, $volid);
4049 # If vm is not owner of this disk remove from config
4057 sub vmconfig_delete_or_detach_drive {
4058 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4060 my $drive = parse_drive($opt, $conf->{$opt});
4062 my $rpcenv = PVE::RPCEnvironment::get();
4063 my $authuser = $rpcenv->get_user();
4066 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4067 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4069 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4073 sub vmconfig_apply_pending {
4074 my ($vmid, $conf, $storecfg) = @_;
4078 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4079 while (my ($opt, $force) = each %$pending_delete_hash) {
4080 die "internal error" if $opt =~ m/^unused/;
4081 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4082 if (!defined($conf->{$opt})) {
4083 vmconfig_undelete_pending_option($conf, $opt);
4084 PVE::QemuConfig->write_config($vmid, $conf);
4085 } elsif (is_valid_drivename($opt)) {
4086 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4087 vmconfig_undelete_pending_option($conf, $opt);
4088 delete $conf->{$opt};
4089 PVE::QemuConfig->write_config($vmid, $conf);
4091 vmconfig_undelete_pending_option($conf, $opt);
4092 delete $conf->{$opt};
4093 PVE::QemuConfig->write_config($vmid, $conf);
4097 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4099 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4100 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4102 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4103 # skip if nothing changed
4104 } elsif (is_valid_drivename($opt)) {
4105 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4106 if defined($conf->{$opt});
4107 $conf->{$opt} = $conf->{pending}->{$opt};
4109 $conf->{$opt} = $conf->{pending}->{$opt};
4112 delete $conf->{pending}->{$opt};
4113 PVE::QemuConfig->write_config($vmid, $conf);
4117 my $safe_num_ne = sub {
4120 return 0 if !defined($a) && !defined($b);
4121 return 1 if !defined($a);
4122 return 1 if !defined($b);
4127 my $safe_string_ne = sub {
4130 return 0 if !defined($a) && !defined($b);
4131 return 1 if !defined($a);
4132 return 1 if !defined($b);
4137 sub vmconfig_update_net {
4138 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4140 my $newnet = parse_net($value);
4142 if ($conf->{$opt}) {
4143 my $oldnet = parse_net($conf->{$opt});
4145 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4146 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4147 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4148 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4150 # for non online change, we try to hot-unplug
4151 die "skip\n" if !$hotplug;
4152 vm_deviceunplug($vmid, $conf, $opt);
4155 die "internal error" if $opt !~ m/net(\d+)/;
4156 my $iface = "tap${vmid}i$1";
4158 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4159 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4160 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4161 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4162 PVE::Network::tap_unplug($iface);
4163 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4164 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4165 # Rate can be applied on its own but any change above needs to
4166 # include the rate in tap_plug since OVS resets everything.
4167 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4170 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4171 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4179 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4185 sub vmconfig_update_disk {
4186 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4188 # fixme: do we need force?
4190 my $drive = parse_drive($opt, $value);
4192 if ($conf->{$opt}) {
4194 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4196 my $media = $drive->{media} || 'disk
';
4197 my $oldmedia = $old_drive->{media} || 'disk
';
4198 die "unable to change media type\n" if $media ne $oldmedia;
4200 if (!drive_is_cdrom($old_drive)) {
4202 if ($drive->{file} ne $old_drive->{file}) {
4204 die "skip\n" if !$hotplug;
4206 # unplug and register as unused
4207 vm_deviceunplug($vmid, $conf, $opt);
4208 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4211 # update existing disk
4213 # skip non hotpluggable value
4214 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4215 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4216 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4217 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4222 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4223 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4224 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4225 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4226 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4227 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4228 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4229 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4230 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4231 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4232 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4233 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4235 qemu_block_set_io_throttle($vmid,"drive-$opt",
4236 ($drive->{mbps} || 0)*1024*1024,
4237 ($drive->{mbps_rd} || 0)*1024*1024,
4238 ($drive->{mbps_wr} || 0)*1024*1024,
4239 $drive->{iops} || 0,
4240 $drive->{iops_rd} || 0,
4241 $drive->{iops_wr} || 0,
4242 ($drive->{mbps_max} || 0)*1024*1024,
4243 ($drive->{mbps_rd_max} || 0)*1024*1024,
4244 ($drive->{mbps_wr_max} || 0)*1024*1024,
4245 $drive->{iops_max} || 0,
4246 $drive->{iops_rd_max} || 0,
4247 $drive->{iops_wr_max} || 0);
4256 if ($drive->{file} eq 'none
') {
4257 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4259 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4260 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4261 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4269 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4271 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4272 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4276 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4277 $forcemachine, $spice_ticket) = @_;
4279 PVE::QemuConfig->lock_config($vmid, sub {
4280 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4282 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4284 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4286 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4288 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4289 vmconfig_apply_pending($vmid, $conf, $storecfg);
4290 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4293 my $defaults = load_defaults();
4295 # set environment variable useful inside network script
4296 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4298 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4300 my $migrate_port = 0;
4303 if ($statefile eq 'tcp
') {
4304 my $localip = "localhost";
4305 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4306 my $nodename = PVE::INotify::nodename();
4307 if ($datacenterconf->{migration_unsecure}) {
4308 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4309 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4311 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4312 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4313 $migrate_uri = "tcp:${localip}:${migrate_port}";
4314 push @$cmd, '-incoming
', $migrate_uri;
4317 } elsif ($statefile eq 'unix
') {
4318 # should be default for secure migrations as a ssh TCP forward
4319 # tunnel is not deterministic reliable ready and fails regurarly
4320 # to set up in time, so use UNIX socket forwards
4321 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4322 unlink $socket_addr;
4324 $migrate_uri = "unix:$socket_addr";
4326 push @$cmd, '-incoming
', $migrate_uri;
4330 push @$cmd, '-loadstate
', $statefile;
4337 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4338 my $d = parse_hostpci($conf->{"hostpci$i"});
4340 my $pcidevices = $d->{pciid};
4341 foreach my $pcidevice (@$pcidevices) {
4342 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4344 my $info = pci_device_info("0000:$pciid");
4345 die "IOMMU not present\n" if !check_iommu_support();
4346 die "no pci device info for device '$pciid'\n" if !$info;
4347 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4348 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4352 PVE::Storage::activate_volumes($storecfg, $vollist);
4354 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4356 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4357 eval { run_command($cmd); };
4360 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4361 : $defaults->{cpuunits};
4363 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4366 Slice => 'qemu
.slice
',
4368 CPUShares => $cpuunits
4371 if (my $cpulimit = $conf->{cpulimit}) {
4372 $properties{CPUQuota} = int($cpulimit * 100);
4374 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4376 if ($conf->{hugepages}) {
4379 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4380 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4382 PVE::QemuServer::Memory::hugepages_mount();
4383 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4386 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4387 run_command($cmd, %run_params);
4391 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4395 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4397 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4401 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4402 run_command($cmd, %run_params);
4407 # deactivate volumes if start fails
4408 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4409 die "start failed: $err";
4412 print "migration listens on $migrate_uri\n" if $migrate_uri;
4414 if ($statefile && $statefile ne 'tcp
') {
4415 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4419 if ($migratedfrom) {
4422 set_migration_caps($vmid);
4427 print "spice listens on port $spice_port\n";
4428 if ($spice_ticket) {
4429 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4430 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4436 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4437 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4438 if $conf->{balloon};
4441 foreach my $opt (keys %$conf) {
4442 next if $opt !~ m/^net\d+$/;
4443 my $nicconf = parse_net($conf->{$opt});
4444 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4448 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4449 path => "machine/peripheral/balloon0",
4450 property => "guest-stats-polling-interval",
4451 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4457 my ($vmid, $execute, %params) = @_;
4459 my $cmd = { execute => $execute, arguments => \%params };
4460 vm_qmp_command($vmid, $cmd);
4463 sub vm_mon_cmd_nocheck {
4464 my ($vmid, $execute, %params) = @_;
4466 my $cmd = { execute => $execute, arguments => \%params };
4467 vm_qmp_command($vmid, $cmd, 1);
4470 sub vm_qmp_command {
4471 my ($vmid, $cmd, $nocheck) = @_;
4476 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4477 $timeout = $cmd->{arguments}->{timeout};
4478 delete $cmd->{arguments}->{timeout};
4482 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4483 my $sname = qmp_socket($vmid);
4484 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4485 my $qmpclient = PVE::QMPClient->new();
4487 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4488 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4489 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4490 if scalar(%{$cmd->{arguments}});
4491 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4493 die "unable to
open monitor
socket\n";
4497 syslog("err
", "VM
$vmid qmp command failed
- $err");
4504 sub vm_human_monitor_command {
4505 my ($vmid, $cmdline) = @_;
4510 execute => 'human-monitor-command',
4511 arguments => { 'command-line' => $cmdline},
4514 return vm_qmp_command($vmid, $cmd);
4517 sub vm_commandline {
4518 my ($storecfg, $vmid) = @_;
4520 my $conf = PVE::QemuConfig->load_config($vmid);
4522 my $defaults = load_defaults();
4524 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4526 return join(' ', @$cmd);
4530 my ($vmid, $skiplock) = @_;
4532 PVE::QemuConfig->lock_config($vmid, sub {
4534 my $conf = PVE::QemuConfig->load_config($vmid);
4536 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4538 vm_mon_cmd($vmid, "system_reset
");
4542 sub get_vm_volumes {
4546 foreach_volid($conf, sub {
4547 my ($volid, $is_cdrom) = @_;
4549 return if $volid =~ m|^/|;
4551 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4554 push @$vollist, $volid;
4560 sub vm_stop_cleanup {
4561 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4566 my $vollist = get_vm_volumes($conf);
4567 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4570 foreach my $ext (qw(mon qmp pid vnc qga)) {
4571 unlink "/var/run/qemu-server/${vmid}.$ext";
4574 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4576 warn $@ if $@; # avoid errors - just warn
4579 # Note: use $nockeck to skip tests if VM configuration file exists.
4580 # We need that when migration VMs to other nodes (files already moved)
4581 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4583 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4585 $force = 1 if !defined($force) && !$shutdown;
4588 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4589 kill 15, $pid if $pid;
4590 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4591 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4595 PVE
::QemuConfig-
>lock_config($vmid, sub {
4597 my $pid = check_running
($vmid, $nocheck);
4602 $conf = PVE
::QemuConfig-
>load_config($vmid);
4603 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4604 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4605 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4606 $timeout = $opts->{down
} if $opts->{down
};
4610 $timeout = 60 if !defined($timeout);
4614 if (defined($conf) && $conf->{agent
}) {
4615 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4617 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4620 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4627 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4632 if ($count >= $timeout) {
4634 warn "VM still running - terminating now with SIGTERM\n";
4637 die "VM quit/powerdown failed - got timeout\n";
4640 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4645 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4648 die "VM quit/powerdown failed\n";
4656 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4661 if ($count >= $timeout) {
4662 warn "VM still running - terminating now with SIGKILL\n";
4667 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4672 my ($vmid, $skiplock) = @_;
4674 PVE
::QemuConfig-
>lock_config($vmid, sub {
4676 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4678 PVE
::QemuConfig-
>check_lock($conf)
4679 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4681 vm_mon_cmd
($vmid, "stop");
4686 my ($vmid, $skiplock, $nocheck) = @_;
4688 PVE
::QemuConfig-
>lock_config($vmid, sub {
4692 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4694 PVE
::QemuConfig-
>check_lock($conf)
4695 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4697 vm_mon_cmd
($vmid, "cont");
4700 vm_mon_cmd_nocheck
($vmid, "cont");
4706 my ($vmid, $skiplock, $key) = @_;
4708 PVE
::QemuConfig-
>lock_config($vmid, sub {
4710 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4712 # there is no qmp command, so we use the human monitor command
4713 vm_human_monitor_command
($vmid, "sendkey $key");
4718 my ($storecfg, $vmid, $skiplock) = @_;
4720 PVE
::QemuConfig-
>lock_config($vmid, sub {
4722 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4724 if (!check_running
($vmid)) {
4725 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4727 die "VM $vmid is running - destroy failed\n";
4735 my ($filename, $buf) = @_;
4737 my $fh = IO
::File-
>new($filename, "w");
4738 return undef if !$fh;
4740 my $res = print $fh $buf;
4747 sub pci_device_info
{
4752 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4753 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4755 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4756 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4758 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4759 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4761 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4762 return undef if !defined($product) || $product !~ s/^0x//;
4767 product
=> $product,
4773 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4782 my $name = $dev->{name
};
4784 my $fn = "$pcisysfs/devices/$name/reset";
4786 return file_write
($fn, "1");
4789 sub pci_dev_bind_to_vfio
{
4792 my $name = $dev->{name
};
4794 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4796 if (!-d
$vfio_basedir) {
4797 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4799 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4801 my $testdir = "$vfio_basedir/$name";
4802 return 1 if -d
$testdir;
4804 my $data = "$dev->{vendor} $dev->{product}";
4805 return undef if !file_write
("$vfio_basedir/new_id", $data);
4807 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4808 if (!file_write
($fn, $name)) {
4809 return undef if -f
$fn;
4812 $fn = "$vfio_basedir/bind";
4813 if (! -d
$testdir) {
4814 return undef if !file_write
($fn, $name);
4820 sub pci_dev_group_bind_to_vfio
{
4823 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4825 if (!-d
$vfio_basedir) {
4826 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4828 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4830 # get IOMMU group devices
4831 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4832 my @devs = grep /^0000:/, readdir($D);
4835 foreach my $pciid (@devs) {
4836 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4838 # pci bridges, switches or root ports are not supported
4839 # they have a pci_bus subdirectory so skip them
4840 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4842 my $info = pci_device_info
($1);
4843 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4849 sub print_pci_addr
{
4850 my ($id, $bridges) = @_;
4854 piix3
=> { bus
=> 0, addr
=> 1 },
4855 #addr2 : first videocard
4856 balloon0
=> { bus
=> 0, addr
=> 3 },
4857 watchdog
=> { bus
=> 0, addr
=> 4 },
4858 scsihw0
=> { bus
=> 0, addr
=> 5 },
4859 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4860 scsihw1
=> { bus
=> 0, addr
=> 6 },
4861 ahci0
=> { bus
=> 0, addr
=> 7 },
4862 qga0
=> { bus
=> 0, addr
=> 8 },
4863 spice
=> { bus
=> 0, addr
=> 9 },
4864 virtio0
=> { bus
=> 0, addr
=> 10 },
4865 virtio1
=> { bus
=> 0, addr
=> 11 },
4866 virtio2
=> { bus
=> 0, addr
=> 12 },
4867 virtio3
=> { bus
=> 0, addr
=> 13 },
4868 virtio4
=> { bus
=> 0, addr
=> 14 },
4869 virtio5
=> { bus
=> 0, addr
=> 15 },
4870 hostpci0
=> { bus
=> 0, addr
=> 16 },
4871 hostpci1
=> { bus
=> 0, addr
=> 17 },
4872 net0
=> { bus
=> 0, addr
=> 18 },
4873 net1
=> { bus
=> 0, addr
=> 19 },
4874 net2
=> { bus
=> 0, addr
=> 20 },
4875 net3
=> { bus
=> 0, addr
=> 21 },
4876 net4
=> { bus
=> 0, addr
=> 22 },
4877 net5
=> { bus
=> 0, addr
=> 23 },
4878 vga1
=> { bus
=> 0, addr
=> 24 },
4879 vga2
=> { bus
=> 0, addr
=> 25 },
4880 vga3
=> { bus
=> 0, addr
=> 26 },
4881 hostpci2
=> { bus
=> 0, addr
=> 27 },
4882 hostpci3
=> { bus
=> 0, addr
=> 28 },
4883 #addr29 : usb-host (pve-usb.cfg)
4884 'pci.1' => { bus
=> 0, addr
=> 30 },
4885 'pci.2' => { bus
=> 0, addr
=> 31 },
4886 'net6' => { bus
=> 1, addr
=> 1 },
4887 'net7' => { bus
=> 1, addr
=> 2 },
4888 'net8' => { bus
=> 1, addr
=> 3 },
4889 'net9' => { bus
=> 1, addr
=> 4 },
4890 'net10' => { bus
=> 1, addr
=> 5 },
4891 'net11' => { bus
=> 1, addr
=> 6 },
4892 'net12' => { bus
=> 1, addr
=> 7 },
4893 'net13' => { bus
=> 1, addr
=> 8 },
4894 'net14' => { bus
=> 1, addr
=> 9 },
4895 'net15' => { bus
=> 1, addr
=> 10 },
4896 'net16' => { bus
=> 1, addr
=> 11 },
4897 'net17' => { bus
=> 1, addr
=> 12 },
4898 'net18' => { bus
=> 1, addr
=> 13 },
4899 'net19' => { bus
=> 1, addr
=> 14 },
4900 'net20' => { bus
=> 1, addr
=> 15 },
4901 'net21' => { bus
=> 1, addr
=> 16 },
4902 'net22' => { bus
=> 1, addr
=> 17 },
4903 'net23' => { bus
=> 1, addr
=> 18 },
4904 'net24' => { bus
=> 1, addr
=> 19 },
4905 'net25' => { bus
=> 1, addr
=> 20 },
4906 'net26' => { bus
=> 1, addr
=> 21 },
4907 'net27' => { bus
=> 1, addr
=> 22 },
4908 'net28' => { bus
=> 1, addr
=> 23 },
4909 'net29' => { bus
=> 1, addr
=> 24 },
4910 'net30' => { bus
=> 1, addr
=> 25 },
4911 'net31' => { bus
=> 1, addr
=> 26 },
4912 'xhci' => { bus
=> 1, addr
=> 27 },
4913 'virtio6' => { bus
=> 2, addr
=> 1 },
4914 'virtio7' => { bus
=> 2, addr
=> 2 },
4915 'virtio8' => { bus
=> 2, addr
=> 3 },
4916 'virtio9' => { bus
=> 2, addr
=> 4 },
4917 'virtio10' => { bus
=> 2, addr
=> 5 },
4918 'virtio11' => { bus
=> 2, addr
=> 6 },
4919 'virtio12' => { bus
=> 2, addr
=> 7 },
4920 'virtio13' => { bus
=> 2, addr
=> 8 },
4921 'virtio14' => { bus
=> 2, addr
=> 9 },
4922 'virtio15' => { bus
=> 2, addr
=> 10 },
4923 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4924 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4925 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4926 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4927 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4928 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4929 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4930 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4931 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4932 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4933 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4934 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4935 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4936 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4937 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4938 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4939 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4940 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4941 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4942 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4943 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4944 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4945 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4946 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4947 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4948 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4949 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4950 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4951 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4952 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4953 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4957 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4958 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4959 my $bus = $devices->{$id}->{bus
};
4960 $res = ",bus=pci.$bus,addr=$addr";
4961 $bridges->{$bus} = 1 if $bridges;
4967 sub print_pcie_addr
{
4972 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4973 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4974 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4975 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4978 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4979 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4980 my $bus = $devices->{$id}->{bus
};
4981 $res = ",bus=$bus,addr=$addr";
4987 # vzdump restore implementaion
4989 sub tar_archive_read_firstfile
{
4990 my $archive = shift;
4992 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4994 # try to detect archive type first
4995 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
4996 die "unable to open file '$archive'\n";
4997 my $firstfile = <$fh>;
5001 die "ERROR: archive contaions no data\n" if !$firstfile;
5007 sub tar_restore_cleanup
{
5008 my ($storecfg, $statfile) = @_;
5010 print STDERR
"starting cleanup\n";
5012 if (my $fd = IO
::File-
>new($statfile, "r")) {
5013 while (defined(my $line = <$fd>)) {
5014 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5017 if ($volid =~ m
|^/|) {
5018 unlink $volid || die 'unlink failed\n';
5020 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5022 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5024 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5026 print STDERR
"unable to parse line in statfile - $line";
5033 sub restore_archive
{
5034 my ($archive, $vmid, $user, $opts) = @_;
5036 my $format = $opts->{format
};
5039 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5040 $format = 'tar' if !$format;
5042 } elsif ($archive =~ m/\.tar$/) {
5043 $format = 'tar' if !$format;
5044 } elsif ($archive =~ m/.tar.lzo$/) {
5045 $format = 'tar' if !$format;
5047 } elsif ($archive =~ m/\.vma$/) {
5048 $format = 'vma' if !$format;
5049 } elsif ($archive =~ m/\.vma\.gz$/) {
5050 $format = 'vma' if !$format;
5052 } elsif ($archive =~ m/\.vma\.lzo$/) {
5053 $format = 'vma' if !$format;
5056 $format = 'vma' if !$format; # default
5059 # try to detect archive format
5060 if ($format eq 'tar') {
5061 return restore_tar_archive
($archive, $vmid, $user, $opts);
5063 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5067 sub restore_update_config_line
{
5068 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5070 return if $line =~ m/^\#qmdump\#/;
5071 return if $line =~ m/^\#vzdump\#/;
5072 return if $line =~ m/^lock:/;
5073 return if $line =~ m/^unused\d+:/;
5074 return if $line =~ m/^parent:/;
5075 return if $line =~ m/^template:/; # restored VM is never a template
5077 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5078 # try to convert old 1.X settings
5079 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5080 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5081 my ($model, $macaddr) = split(/\=/, $devconfig);
5082 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5085 bridge
=> "vmbr$ind",
5086 macaddr
=> $macaddr,
5088 my $netstr = print_net
($net);
5090 print $outfd "net$cookie->{netcount}: $netstr\n";
5091 $cookie->{netcount
}++;
5093 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5094 my ($id, $netstr) = ($1, $2);
5095 my $net = parse_net
($netstr);
5096 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5097 $netstr = print_net
($net);
5098 print $outfd "$id: $netstr\n";
5099 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5102 my $di = parse_drive
($virtdev, $value);
5103 if (defined($di->{backup
}) && !$di->{backup
}) {
5104 print $outfd "#$line";
5105 } elsif ($map->{$virtdev}) {
5106 delete $di->{format
}; # format can change on restore
5107 $di->{file
} = $map->{$virtdev};
5108 $value = print_drive
($vmid, $di);
5109 print $outfd "$virtdev: $value\n";
5119 my ($cfg, $vmid) = @_;
5121 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5123 my $volid_hash = {};
5124 foreach my $storeid (keys %$info) {
5125 foreach my $item (@{$info->{$storeid}}) {
5126 next if !($item->{volid
} && $item->{size
});
5127 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5128 $volid_hash->{$item->{volid
}} = $item;
5135 sub is_volume_in_use
{
5136 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5138 my $path = PVE
::Storage
::path
($storecfg, $volid);
5140 my $scan_config = sub {
5141 my ($cref, $snapname) = @_;
5143 foreach my $key (keys %$cref) {
5144 my $value = $cref->{$key};
5145 if (is_valid_drivename
($key)) {
5146 next if $skip_drive && $key eq $skip_drive;
5147 my $drive = parse_drive
($key, $value);
5148 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5149 return 1 if $volid eq $drive->{file
};
5150 if ($drive->{file
} =~ m!^/!) {
5151 return 1 if $drive->{file
} eq $path;
5153 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5155 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5157 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5165 return 1 if &$scan_config($conf);
5169 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5170 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5176 sub update_disksize
{
5177 my ($vmid, $conf, $volid_hash) = @_;
5183 # Note: it is allowed to define multiple storages with same path (alias), so
5184 # we need to check both 'volid' and real 'path' (two different volid can point
5185 # to the same path).
5190 foreach my $opt (keys %$conf) {
5191 if (is_valid_drivename
($opt)) {
5192 my $drive = parse_drive
($opt, $conf->{$opt});
5193 my $volid = $drive->{file
};
5196 $used->{$volid} = 1;
5197 if ($volid_hash->{$volid} &&
5198 (my $path = $volid_hash->{$volid}->{path
})) {
5199 $usedpath->{$path} = 1;
5202 next if drive_is_cdrom
($drive);
5203 next if !$volid_hash->{$volid};
5205 $drive->{size
} = $volid_hash->{$volid}->{size
};
5206 my $new = print_drive
($vmid, $drive);
5207 if ($new ne $conf->{$opt}) {
5209 $conf->{$opt} = $new;
5214 # remove 'unusedX' entry if volume is used
5215 foreach my $opt (keys %$conf) {
5216 next if $opt !~ m/^unused\d+$/;
5217 my $volid = $conf->{$opt};
5218 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5219 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5221 delete $conf->{$opt};
5225 foreach my $volid (sort keys %$volid_hash) {
5226 next if $volid =~ m/vm-$vmid-state-/;
5227 next if $used->{$volid};
5228 my $path = $volid_hash->{$volid}->{path
};
5229 next if !$path; # just to be sure
5230 next if $usedpath->{$path};
5232 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5233 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5240 my ($vmid, $nolock) = @_;
5242 my $cfg = PVE
::Storage
::config
();
5244 my $volid_hash = scan_volids
($cfg, $vmid);
5246 my $updatefn = sub {
5249 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5251 PVE
::QemuConfig-
>check_lock($conf);
5254 foreach my $volid (keys %$volid_hash) {
5255 my $info = $volid_hash->{$volid};
5256 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5259 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5261 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5264 if (defined($vmid)) {
5268 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5271 my $vmlist = config_list
();
5272 foreach my $vmid (keys %$vmlist) {
5276 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5282 sub restore_vma_archive
{
5283 my ($archive, $vmid, $user, $opts, $comp) = @_;
5285 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5286 my $readfrom = $archive;
5291 my $qarchive = PVE
::Tools
::shellquote
($archive);
5292 if ($comp eq 'gzip') {
5293 $uncomp = "zcat $qarchive|";
5294 } elsif ($comp eq 'lzop') {
5295 $uncomp = "lzop -d -c $qarchive|";
5297 die "unknown compression method '$comp'\n";
5302 my $tmpdir = "/var/tmp/vzdumptmp$$";
5305 # disable interrupts (always do cleanups)
5306 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5307 warn "got interrupt - ignored\n";
5310 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5311 POSIX
::mkfifo
($mapfifo, 0600);
5314 my $openfifo = sub {
5315 open($fifofh, '>', $mapfifo) || die $!;
5318 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5325 my $rpcenv = PVE
::RPCEnvironment
::get
();
5327 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5328 my $tmpfn = "$conffile.$$.tmp";
5330 # Note: $oldconf is undef if VM does not exists
5331 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5332 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5334 my $print_devmap = sub {
5335 my $virtdev_hash = {};
5337 my $cfgfn = "$tmpdir/qemu-server.conf";
5339 # we can read the config - that is already extracted
5340 my $fh = IO
::File-
>new($cfgfn, "r") ||
5341 "unable to read qemu-server.conf - $!\n";
5343 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5345 my $pve_firewall_dir = '/etc/pve/firewall';
5346 mkdir $pve_firewall_dir; # make sure the dir exists
5347 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5350 while (defined(my $line = <$fh>)) {
5351 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5352 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5353 die "archive does not contain data for drive '$virtdev'\n"
5354 if !$devinfo->{$devname};
5355 if (defined($opts->{storage
})) {
5356 $storeid = $opts->{storage
} || 'local';
5357 } elsif (!$storeid) {
5360 $format = 'raw' if !$format;
5361 $devinfo->{$devname}->{devname
} = $devname;
5362 $devinfo->{$devname}->{virtdev
} = $virtdev;
5363 $devinfo->{$devname}->{format
} = $format;
5364 $devinfo->{$devname}->{storeid
} = $storeid;
5366 # check permission on storage
5367 my $pool = $opts->{pool
}; # todo: do we need that?
5368 if ($user ne 'root@pam') {
5369 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5372 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5376 foreach my $devname (keys %$devinfo) {
5377 die "found no device mapping information for device '$devname'\n"
5378 if !$devinfo->{$devname}->{virtdev
};
5381 my $cfg = PVE
::Storage
::config
();
5383 # create empty/temp config
5385 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5386 foreach_drive
($oldconf, sub {
5387 my ($ds, $drive) = @_;
5389 return if drive_is_cdrom
($drive);
5391 my $volid = $drive->{file
};
5393 return if !$volid || $volid =~ m
|^/|;
5395 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5396 return if !$path || !$owner || ($owner != $vmid);
5398 # Note: only delete disk we want to restore
5399 # other volumes will become unused
5400 if ($virtdev_hash->{$ds}) {
5401 PVE
::Storage
::vdisk_free
($cfg, $volid);
5405 # delete vmstate files
5406 # since after the restore we have no snapshots anymore
5407 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5408 my $snap = $oldconf->{snapshots
}->{$snapname};
5409 if ($snap->{vmstate
}) {
5410 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5419 foreach my $virtdev (sort keys %$virtdev_hash) {
5420 my $d = $virtdev_hash->{$virtdev};
5421 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5422 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5424 # test if requested format is supported
5425 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5426 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5427 $d->{format
} = $defFormat if !$supported;
5429 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5430 $d->{format
}, undef, $alloc_size);
5431 print STDERR
"new volume ID is '$volid'\n";
5432 $d->{volid
} = $volid;
5433 my $path = PVE
::Storage
::path
($cfg, $volid);
5435 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5437 my $write_zeros = 1;
5438 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5442 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5444 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5445 $map->{$virtdev} = $volid;
5448 $fh->seek(0, 0) || die "seek failed - $!\n";
5450 my $outfd = new IO
::File
($tmpfn, "w") ||
5451 die "unable to write config for VM $vmid\n";
5453 my $cookie = { netcount
=> 0 };
5454 while (defined(my $line = <$fh>)) {
5455 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5464 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5465 die "interrupted by signal\n";
5467 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5469 $oldtimeout = alarm($timeout);
5476 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5477 my ($dev_id, $size, $devname) = ($1, $2, $3);
5478 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5479 } elsif ($line =~ m/^CTIME: /) {
5480 # we correctly received the vma config, so we can disable
5481 # the timeout now for disk allocation (set to 10 minutes, so
5482 # that we always timeout if something goes wrong)
5485 print $fifofh "done\n";
5486 my $tmp = $oldtimeout || 0;
5487 $oldtimeout = undef;
5493 print "restore vma archive: $cmd\n";
5494 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5498 alarm($oldtimeout) if $oldtimeout;
5501 foreach my $devname (keys %$devinfo) {
5502 my $volid = $devinfo->{$devname}->{volid
};
5503 push @$vollist, $volid if $volid;
5506 my $cfg = PVE
::Storage
::config
();
5507 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5515 foreach my $devname (keys %$devinfo) {
5516 my $volid = $devinfo->{$devname}->{volid
};
5519 if ($volid =~ m
|^/|) {
5520 unlink $volid || die 'unlink failed\n';
5522 PVE
::Storage
::vdisk_free
($cfg, $volid);
5524 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5526 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5533 rename($tmpfn, $conffile) ||
5534 die "unable to commit configuration file '$conffile'\n";
5536 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5538 eval { rescan
($vmid, 1); };
5542 sub restore_tar_archive
{
5543 my ($archive, $vmid, $user, $opts) = @_;
5545 if ($archive ne '-') {
5546 my $firstfile = tar_archive_read_firstfile
($archive);
5547 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5548 if $firstfile ne 'qemu-server.conf';
5551 my $storecfg = PVE
::Storage
::config
();
5553 # destroy existing data - keep empty config
5554 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5555 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5557 my $tocmd = "/usr/lib/qemu-server/qmextract";
5559 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5560 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5561 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5562 $tocmd .= ' --info' if $opts->{info
};
5564 # tar option "xf" does not autodetect compression when read from STDIN,
5565 # so we pipe to zcat
5566 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5567 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5569 my $tmpdir = "/var/tmp/vzdumptmp$$";
5572 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5573 local $ENV{VZDUMP_VMID
} = $vmid;
5574 local $ENV{VZDUMP_USER
} = $user;
5576 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5577 my $tmpfn = "$conffile.$$.tmp";
5579 # disable interrupts (always do cleanups)
5580 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5581 print STDERR
"got interrupt - ignored\n";
5586 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5587 die "interrupted by signal\n";
5590 if ($archive eq '-') {
5591 print "extracting archive from STDIN\n";
5592 run_command
($cmd, input
=> "<&STDIN");
5594 print "extracting archive '$archive'\n";
5598 return if $opts->{info
};
5602 my $statfile = "$tmpdir/qmrestore.stat";
5603 if (my $fd = IO
::File-
>new($statfile, "r")) {
5604 while (defined (my $line = <$fd>)) {
5605 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5606 $map->{$1} = $2 if $1;
5608 print STDERR
"unable to parse line in statfile - $line\n";
5614 my $confsrc = "$tmpdir/qemu-server.conf";
5616 my $srcfd = new IO
::File
($confsrc, "r") ||
5617 die "unable to open file '$confsrc'\n";
5619 my $outfd = new IO
::File
($tmpfn, "w") ||
5620 die "unable to write config for VM $vmid\n";
5622 my $cookie = { netcount
=> 0 };
5623 while (defined (my $line = <$srcfd>)) {
5624 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5636 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5643 rename $tmpfn, $conffile ||
5644 die "unable to commit configuration file '$conffile'\n";
5646 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5648 eval { rescan
($vmid, 1); };
5652 sub foreach_writable_storage
{
5653 my ($conf, $func) = @_;
5657 foreach my $ds (keys %$conf) {
5658 next if !is_valid_drivename
($ds);
5660 my $drive = parse_drive
($ds, $conf->{$ds});
5662 next if drive_is_cdrom
($drive);
5664 my $volid = $drive->{file
};
5666 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5667 $sidhash->{$sid} = $sid if $sid;
5670 foreach my $sid (sort keys %$sidhash) {
5675 sub do_snapshots_with_qemu
{
5676 my ($storecfg, $volid) = @_;
5678 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5680 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5681 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5685 if ($volid =~ m/\.(qcow2|qed)$/){
5692 sub qga_check_running
{
5695 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5697 warn "Qemu Guest Agent are not running - $@";
5703 sub template_create
{
5704 my ($vmid, $conf, $disk) = @_;
5706 my $storecfg = PVE
::Storage
::config
();
5708 foreach_drive
($conf, sub {
5709 my ($ds, $drive) = @_;
5711 return if drive_is_cdrom
($drive);
5712 return if $disk && $ds ne $disk;
5714 my $volid = $drive->{file
};
5715 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5717 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5718 $drive->{file
} = $voliddst;
5719 $conf->{$ds} = print_drive
($vmid, $drive);
5720 PVE
::QemuConfig-
>write_config($vmid, $conf);
5724 sub qemu_img_convert
{
5725 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5727 my $storecfg = PVE
::Storage
::config
();
5728 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5729 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5731 if ($src_storeid && $dst_storeid) {
5733 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5735 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5736 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5738 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5739 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5741 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5742 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5745 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5746 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5747 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5748 if ($is_zero_initialized) {
5749 push @$cmd, "zeroinit:$dst_path";
5751 push @$cmd, $dst_path;
5756 if($line =~ m/\((\S+)\/100\
%\)/){
5758 my $transferred = int($size * $percent / 100);
5759 my $remaining = $size - $transferred;
5761 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5766 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5768 die "copy failed: $err" if $err;
5772 sub qemu_img_format
{
5773 my ($scfg, $volname) = @_;
5775 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5782 sub qemu_drive_mirror
{
5783 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5785 my $storecfg = PVE
::Storage
::config
();
5786 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5788 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5790 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5792 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5794 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5796 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5797 $opts->{format
} = $format if $format;
5799 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5801 my $finish_job = sub {
5803 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5804 my $stat = @$stats[0];
5811 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5813 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5814 my $stat = @$stats[0];
5815 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5816 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5818 my $busy = $stat->{busy
};
5819 my $ready = $stat->{ready
};
5821 if (my $total = $stat->{len
}) {
5822 my $transferred = $stat->{offset
} || 0;
5823 my $remaining = $total - $transferred;
5824 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5826 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5830 if ($stat->{ready
} eq 'true') {
5832 last if $vmiddst != $vmid;
5834 # try to switch the disk if source and destination are on the same guest
5835 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5840 die $@ if $@ !~ m/cannot be completed/;
5849 my $cancel_job = sub {
5850 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5855 eval { &$cancel_job(); };
5856 die "mirroring error: $err";
5859 if ($vmiddst != $vmid) {
5860 # if we clone a disk for a new target vm, we don't switch the disk
5861 &$cancel_job(); # so we call block-job-cancel
5866 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5867 $newvmid, $storage, $format, $full, $newvollist) = @_;
5872 print "create linked clone of drive $drivename ($drive->{file})\n";
5873 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5874 push @$newvollist, $newvolid;
5876 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5877 $storeid = $storage if $storage;
5879 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5881 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5882 $format = qemu_img_format
($scfg, $volname);
5885 # test if requested format is supported - else use default
5886 my $supported = grep { $_ eq $format } @$validFormats;
5887 $format = $defFormat if !$supported;
5889 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5891 print "create full clone of drive $drivename ($drive->{file})\n";
5892 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5893 push @$newvollist, $newvolid;
5895 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5897 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5898 if (!$running || $snapname) {
5899 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5901 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5905 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5908 $disk->{format
} = undef;
5909 $disk->{file
} = $newvolid;
5910 $disk->{size
} = $size;
5915 # this only works if VM is running
5916 sub get_current_qemu_machine
{
5919 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5920 my $res = vm_qmp_command
($vmid, $cmd);
5922 my ($current, $default);
5923 foreach my $e (@$res) {
5924 $default = $e->{name
} if $e->{'is-default'};
5925 $current = $e->{name
} if $e->{'is-current'};
5928 # fallback to the default machine if current is not supported by qemu
5929 return $current || $default || 'pc';
5932 sub qemu_machine_feature_enabled
{
5933 my ($machine, $kvmver, $version_major, $version_minor) = @_;
5938 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
5940 $current_major = $3;
5941 $current_minor = $4;
5943 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
5945 $current_major = $1;
5946 $current_minor = $2;
5949 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
5954 sub qemu_machine_pxe
{
5955 my ($vmid, $conf, $machine) = @_;
5957 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
5959 foreach my $opt (keys %$conf) {
5960 next if $opt !~ m/^net(\d+)$/;
5961 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
5963 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
5964 return $machine.".pxe" if $romfile =~ m/pxe/;
5971 sub qemu_use_old_bios_files
{
5972 my ($machine_type) = @_;
5974 return if !$machine_type;
5976 my $use_old_bios_files = undef;
5978 if ($machine_type =~ m/^(\S+)\.pxe$/) {
5980 $use_old_bios_files = 1;
5982 my $kvmver = kvm_user_version
();
5983 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
5984 # load new efi bios files on migration. So this hack is required to allow
5985 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
5986 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
5987 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
5990 return ($use_old_bios_files, $machine_type);
5997 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
5998 my (undef, $id, $function) = @_;
5999 my $res = { id
=> $id, function
=> $function};
6000 push @{$devices->{$id}}, $res;
6006 sub vm_iothreads_list
{
6009 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6012 foreach my $iothread (@$res) {
6013 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6020 my ($conf, $drive) = @_;
6024 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6026 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6032 my $controller = int($drive->{index} / $maxdev);
6033 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6035 return ($maxdev, $controller, $controller_prefix);
6038 # bash completion helper
6040 sub complete_backup_archives
{
6041 my ($cmdname, $pname, $cvalue) = @_;
6043 my $cfg = PVE
::Storage
::config
();
6047 if ($cvalue =~ m/^([^:]+):/) {
6051 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6054 foreach my $id (keys %$data) {
6055 foreach my $item (@{$data->{$id}}) {
6056 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6057 push @$res, $item->{volid
} if defined($item->{volid
});
6064 my $complete_vmid_full = sub {
6067 my $idlist = vmstatus
();
6071 foreach my $id (keys %$idlist) {
6072 my $d = $idlist->{$id};
6073 if (defined($running)) {
6074 next if $d->{template
};
6075 next if $running && $d->{status
} ne 'running';
6076 next if !$running && $d->{status
} eq 'running';
6085 return &$complete_vmid_full();
6088 sub complete_vmid_stopped
{
6089 return &$complete_vmid_full(0);
6092 sub complete_vmid_running
{
6093 return &$complete_vmid_full(1);
6096 sub complete_storage
{
6098 my $cfg = PVE
::Storage
::config
();
6099 my $ids = $cfg->{ids
};
6102 foreach my $sid (keys %$ids) {
6103 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6104 next if !$ids->{$sid}->{content
}->{images
};