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
=> "Number of hotplugged vcpus.",
334 description
=> "Enable/disable ACPI.",
340 description
=> "Enable/disable Qemu GuestAgent.",
346 description
=> "Enable/disable KVM hardware virtualization.",
352 description
=> "Enable/disable time drift fix.",
358 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
363 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
368 description
=> "Select the VGA type.",
369 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
370 " modes (>= 1280x1024x16) then you should use the options " .
371 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
372 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
373 "display sever. For win* OS you can select how many independent " .
374 "displays you want, Linux guests can add displays them self. " .
375 "You can also run without any graphic card, using a serial device" .
377 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
381 type
=> 'string', format
=> 'pve-qm-watchdog',
382 description
=> "Create a virtual hardware watchdog device.",
383 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
384 " (by a guest action), the watchdog must be periodically polled " .
385 "by an agent inside the guest or else the watchdog will reset " .
386 "the guest (or execute the respective action specified)",
391 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
392 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'.",
393 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
396 startup
=> get_standard_option
('pve-startup-order'),
400 description
=> "Enable/disable Template.",
406 description
=> "Arbitrary arguments passed to kvm.",
407 verbose_description
=> <<EODESCR,
408 Arbitrary arguments passed to kvm, for example:
410 args: -no-reboot -no-hpet
412 NOTE: this option is for experts only.
419 description
=> "Enable/disable the USB tablet device.",
420 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
421 "usually needed to allow absolute mouse positioning with VNC. " .
422 "Else the mouse runs out of sync with normal VNC clients. " .
423 "If you're running lots of console-only guests on one host, " .
424 "you may consider disabling this to save some context switches. " .
425 "This is turned off by default if you use spice (-vga=qxl).",
430 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
434 migrate_downtime
=> {
437 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
443 type
=> 'string', format
=> 'pve-qm-drive',
444 typetext
=> 'volume',
445 description
=> "This is an alias for option -ide2",
449 description
=> "Emulated CPU type.",
453 parent
=> get_standard_option
('pve-snapshot-name', {
455 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
459 description
=> "Timestamp for snapshots.",
465 type
=> 'string', format
=> 'pve-volume-id',
466 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
469 description
=> "Specific the Qemu machine type.",
471 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
476 description
=> "Specify SMBIOS type 1 fields.",
477 type
=> 'string', format
=> 'pve-qm-smbios1',
484 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
490 enum
=> [ qw(seabios ovmf) ],
491 description
=> "Select BIOS implementation.",
492 default => 'seabios',
496 # what about other qemu settings ?
498 #machine => 'string',
511 ##soundhw => 'string',
513 while (my ($k, $v) = each %$confdesc) {
514 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
517 my $MAX_IDE_DISKS = 4;
518 my $MAX_SCSI_DISKS = 14;
519 my $MAX_VIRTIO_DISKS = 16;
520 my $MAX_SATA_DISKS = 6;
521 my $MAX_USB_DEVICES = 5;
523 my $MAX_UNUSED_DISKS = 8;
524 my $MAX_HOSTPCI_DEVICES = 4;
525 my $MAX_SERIAL_PORTS = 4;
526 my $MAX_PARALLEL_PORTS = 3;
532 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
533 description
=> "CPUs accessing this NUMA node.",
534 format_description
=> "id[-id];...",
538 description
=> "Amount of memory this NUMA node provides.",
543 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
544 description
=> "Host NUMA nodes to use.",
545 format_description
=> "id[-id];...",
550 enum
=> [qw(preferred bind interleave)],
551 description
=> "NUMA allocation policy.",
555 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
558 type
=> 'string', format
=> $numa_fmt,
559 description
=> "NUMA topology.",
561 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
563 for (my $i = 0; $i < $MAX_NUMA; $i++) {
564 $confdesc->{"numa$i"} = $numadesc;
567 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
568 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
569 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
570 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
572 my $net_fmt_bridge_descr = <<__EOD__;
573 Bridge to attach the network device to. The Proxmox VE standard bridge
576 If you do not specify a bridge, we create a kvm user (NATed) network
577 device, which provides DHCP and DNS services. The following addresses
584 The DHCP server assign addresses to the guest starting from 10.0.2.15.
590 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
591 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
592 format_description
=> "XX:XX:XX:XX:XX:XX",
597 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'.",
598 format_description
=> 'model',
599 enum
=> $nic_model_list,
602 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
605 description
=> $net_fmt_bridge_descr,
606 format_description
=> 'bridge',
611 minimum
=> 0, maximum
=> 16,
612 description
=> 'Number of packet queues to be used on the device.',
618 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
623 minimum
=> 1, maximum
=> 4094,
624 description
=> 'VLAN tag to apply to packets on this interface.',
629 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
630 description
=> 'VLAN trunks to pass through this interface.',
631 format_description
=> 'vlanid[;vlanid...]',
636 description
=> 'Whether this interface should be protected by the firewall.',
641 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
648 type
=> 'string', format
=> $net_fmt,
649 description
=> "Specify network devices.",
652 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
654 for (my $i = 0; $i < $MAX_NETS; $i++) {
655 $confdesc->{"net$i"} = $netdesc;
658 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
659 sub verify_volume_id_or_qm_path
{
660 my ($volid, $noerr) = @_;
662 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
666 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
667 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
669 return undef if $noerr;
677 my %drivedesc_base = (
678 volume
=> { alias
=> 'file' },
681 format
=> 'pve-volume-id-or-qm-path',
683 format_description
=> 'volume',
684 description
=> "The drive's backing volume.",
688 enum
=> [qw(cdrom disk)],
689 description
=> "The drive's media type.",
695 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
700 description
=> "Force the drive's physical geometry to have a specific head count.",
705 description
=> "Force the drive's physical geometry to have a specific sector count.",
710 enum
=> [qw(none lba auto)],
711 description
=> "Force disk geometry bios translation mode.",
716 description
=> "Whether the drive should be included when making snapshots.",
721 enum
=> [qw(none writethrough writeback unsafe directsync)],
722 description
=> "The drive's cache mode",
727 format_description
=> 'image format',
728 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
729 description
=> "The drive's backing file's data format.",
734 format
=> 'disk-size',
735 format_description
=> 'DiskSize',
736 description
=> "Disk size. This is purely informational and has no effect.",
741 description
=> "Whether the drive should be included when making backups.",
746 enum
=> [qw(enospc ignore report stop)],
747 description
=> 'Write error action.',
752 enum
=> [qw(native threads)],
753 description
=> 'AIO type to use.',
758 enum
=> [qw(ignore on)],
759 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
764 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
769 format
=> 'urlencoded',
770 format_description
=> 'serial',
771 maxLength
=> 20*3, # *3 since it's %xx url enoded
772 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
780 enum
=> [qw(ignore report stop)],
781 description
=> 'Read error action.',
786 my %iothread_fmt = ( iothread
=> {
788 description
=> "Whether to use iothreads for this drive",
795 format
=> 'urlencoded',
796 format_description
=> 'model',
797 maxLength
=> 40*3, # *3 since it's %xx url enoded
798 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
806 description
=> "Number of queues.",
812 my $add_throttle_desc = sub {
813 my ($key, $type, $what, $unit, $longunit) = @_;
814 $drivedesc_base{$key} = {
816 format_description
=> $unit,
817 description
=> "Maximum $what speed in $longunit per second.",
821 # throughput: (leaky bucket)
822 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
823 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
824 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
825 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
826 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
827 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
828 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
829 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
830 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
832 # pools: (pool of IO before throttling starts taking effect)
833 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
834 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
835 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
836 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
837 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
838 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
848 type
=> 'string', format
=> $ide_fmt,
849 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
851 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
860 type
=> 'string', format
=> $scsi_fmt,
861 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
863 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
871 type
=> 'string', format
=> $sata_fmt,
872 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
874 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
883 type
=> 'string', format
=> $virtio_fmt,
884 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
886 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
899 type
=> 'string', format
=> 'pve-qm-usb-device',
900 format_description
=> 'HOSTUSBDEVICE|spice',
901 description
=> <<EODESCR,
902 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
904 'bus-port(.port)*' (decimal numbers) or
905 'vendor_id:product_id' (hexadeciaml numbers) or
908 You can use the 'lsusb -t' command to list existing usb devices.
910 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
912 The value 'spice' can be used to add a usb redirection devices for spice.
918 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).",
925 type
=> 'string', format
=> $usb_fmt,
926 description
=> "Configure an USB device (n is 0 to 4).",
928 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
930 # NOTE: the match-groups of this regex are used in parse_hostpci
931 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
936 pattern
=> qr/$PCIRE(;$PCIRE)*/,
937 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
938 description
=> <<EODESCR,
939 Host PCI device pass through. The PCI ID of a host's PCI device or a list
940 of PCI virtual functions of the host. HOSTPCIID syntax is:
942 'bus:dev.func' (hexadecimal numbers)
944 You can us the 'lspci' command to list existing PCI devices.
949 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
955 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
961 description
=> "Enable vfio-vga device support.",
966 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
970 type
=> 'string', format
=> 'pve-qm-hostpci',
971 description
=> "Map host PCI devices into guest.",
972 verbose_description
=> <<EODESCR,
973 Map host PCI devices into guest.
975 NOTE: This option allows direct access to host hardware. So it is no longer
976 possible to migrate such machines - use with special care.
978 CAUTION: Experimental! User reported problems with this option.
981 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
986 pattern
=> '(/dev/.+|socket)',
987 description
=> "Create a serial device inside the VM (n is 0 to 3)",
988 verbose_description
=> <<EODESCR,
989 Create a serial device inside the VM (n is 0 to 3), and pass through a
990 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
991 host side (use 'qm terminal' to open a terminal connection).
993 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
995 CAUTION: Experimental! User reported problems with this option.
1002 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1003 description
=> "Map host parallel devices (n is 0 to 2).",
1004 verbose_description
=> <<EODESCR,
1005 Map host parallel devices (n is 0 to 2).
1007 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1009 CAUTION: Experimental! User reported problems with this option.
1013 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1014 $confdesc->{"parallel$i"} = $paralleldesc;
1017 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1018 $confdesc->{"serial$i"} = $serialdesc;
1021 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1022 $confdesc->{"hostpci$i"} = $hostpcidesc;
1025 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1026 $drivename_hash->{"ide$i"} = 1;
1027 $confdesc->{"ide$i"} = $idedesc;
1030 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1031 $drivename_hash->{"sata$i"} = 1;
1032 $confdesc->{"sata$i"} = $satadesc;
1035 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1036 $drivename_hash->{"scsi$i"} = 1;
1037 $confdesc->{"scsi$i"} = $scsidesc ;
1040 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1041 $drivename_hash->{"virtio$i"} = 1;
1042 $confdesc->{"virtio$i"} = $virtiodesc;
1045 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1046 $confdesc->{"usb$i"} = $usbdesc;
1051 type
=> 'string', format
=> 'pve-volume-id',
1052 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1055 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1056 $confdesc->{"unused$i"} = $unuseddesc;
1059 my $kvm_api_version = 0;
1063 return $kvm_api_version if $kvm_api_version;
1065 my $fh = IO
::File-
>new("</dev/kvm") ||
1068 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1069 $kvm_api_version = $v;
1074 return $kvm_api_version;
1077 my $kvm_user_version;
1079 sub kvm_user_version
{
1081 return $kvm_user_version if $kvm_user_version;
1083 $kvm_user_version = 'unknown';
1087 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1088 $kvm_user_version = $2;
1092 eval { run_command
("kvm -version", outfunc
=> $code); };
1095 return $kvm_user_version;
1099 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1101 sub valid_drive_names
{
1102 # order is important - used to autoselect boot disk
1103 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1104 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1105 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1106 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1109 sub is_valid_drivename
{
1112 return defined($drivename_hash->{$dev});
1117 return defined($confdesc->{$key});
1121 return $nic_model_list;
1124 sub os_list_description
{
1128 wxp
=> 'Windows XP',
1129 w2k
=> 'Windows 2000',
1130 w2k3
=>, 'Windows 2003',
1131 w2k8
=> 'Windows 2008',
1132 wvista
=> 'Windows Vista',
1133 win7
=> 'Windows 7',
1134 win8
=> 'Windows 8/2012',
1142 sub get_cdrom_path
{
1144 return $cdrom_path if $cdrom_path;
1146 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1147 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1148 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1152 my ($storecfg, $vmid, $cdrom) = @_;
1154 if ($cdrom eq 'cdrom') {
1155 return get_cdrom_path
();
1156 } elsif ($cdrom eq 'none') {
1158 } elsif ($cdrom =~ m
|^/|) {
1161 return PVE
::Storage
::path
($storecfg, $cdrom);
1165 # try to convert old style file names to volume IDs
1166 sub filename_to_volume_id
{
1167 my ($vmid, $file, $media) = @_;
1169 if (!($file eq 'none' || $file eq 'cdrom' ||
1170 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1172 return undef if $file =~ m
|/|;
1174 if ($media && $media eq 'cdrom') {
1175 $file = "local:iso/$file";
1177 $file = "local:$vmid/$file";
1184 sub verify_media_type
{
1185 my ($opt, $vtype, $media) = @_;
1190 if ($media eq 'disk') {
1192 } elsif ($media eq 'cdrom') {
1195 die "internal error";
1198 return if ($vtype eq $etype);
1200 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1203 sub cleanup_drive_path
{
1204 my ($opt, $storecfg, $drive) = @_;
1206 # try to convert filesystem paths to volume IDs
1208 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1209 ($drive->{file
} !~ m
|^/dev/.+|) &&
1210 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1211 ($drive->{file
} !~ m/^\d+$/)) {
1212 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1213 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1214 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1215 verify_media_type
($opt, $vtype, $drive->{media
});
1216 $drive->{file
} = $volid;
1219 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1222 sub parse_hotplug_features
{
1227 return $res if $data eq '0';
1229 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1231 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1232 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1235 die "invalid hotplug feature '$feature'\n";
1241 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1242 sub pve_verify_hotplug_features
{
1243 my ($value, $noerr) = @_;
1245 return $value if parse_hotplug_features
($value);
1247 return undef if $noerr;
1249 die "unable to parse hotplug option\n";
1252 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1253 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1254 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1255 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1256 # [,iothread=on][,serial=serial][,model=model]
1259 my ($key, $data) = @_;
1261 my ($interface, $index);
1263 if ($key =~ m/^([^\d]+)(\d+)$/) {
1270 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1271 : $confdesc->{$key}->{format
};
1273 warn "invalid drive key: $key\n";
1276 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1277 return undef if !$res;
1278 $res->{interface
} = $interface;
1279 $res->{index} = $index;
1282 foreach my $opt (qw(bps bps_rd bps_wr)) {
1283 if (my $bps = defined(delete $res->{$opt})) {
1284 if (defined($res->{"m$opt"})) {
1285 warn "both $opt and m$opt specified\n";
1289 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1292 return undef if $error;
1294 return undef if $res->{mbps_rd
} && $res->{mbps
};
1295 return undef if $res->{mbps_wr
} && $res->{mbps
};
1296 return undef if $res->{iops_rd
} && $res->{iops
};
1297 return undef if $res->{iops_wr
} && $res->{iops
};
1299 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1300 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1301 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1302 return undef if $res->{interface
} eq 'virtio';
1305 if (my $size = $res->{size
}) {
1306 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1313 my ($vmid, $drive) = @_;
1314 my $data = { %$drive };
1315 delete $data->{$_} for qw(index interface);
1316 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1320 my($fh, $noerr) = @_;
1323 my $SG_GET_VERSION_NUM = 0x2282;
1325 my $versionbuf = "\x00" x
8;
1326 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1328 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1331 my $version = unpack("I", $versionbuf);
1332 if ($version < 30000) {
1333 die "scsi generic interface too old\n" if !$noerr;
1337 my $buf = "\x00" x
36;
1338 my $sensebuf = "\x00" x
8;
1339 my $cmd = pack("C x3 C x1", 0x12, 36);
1341 # see /usr/include/scsi/sg.h
1342 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";
1344 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1345 length($sensebuf), 0, length($buf), $buf,
1346 $cmd, $sensebuf, 6000);
1348 $ret = ioctl($fh, $SG_IO, $packet);
1350 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1354 my @res = unpack($sg_io_hdr_t, $packet);
1355 if ($res[17] || $res[18]) {
1356 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1361 (my $byte0, my $byte1, $res->{vendor
},
1362 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1364 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1365 $res->{type
} = $byte0 & 31;
1373 my $fh = IO
::File-
>new("+<$path") || return undef;
1374 my $res = scsi_inquiry
($fh, 1);
1380 sub machine_type_is_q35
{
1383 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1386 sub print_tabletdevice_full
{
1389 my $q35 = machine_type_is_q35
($conf);
1391 # we use uhci for old VMs because tablet driver was buggy in older qemu
1392 my $usbbus = $q35 ?
"ehci" : "uhci";
1394 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1397 sub print_drivedevice_full
{
1398 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1403 if ($drive->{interface
} eq 'virtio') {
1404 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1405 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1406 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1407 } elsif ($drive->{interface
} eq 'scsi') {
1409 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1410 my $unit = $drive->{index} % $maxdev;
1411 my $devicetype = 'hd';
1413 if (drive_is_cdrom
($drive)) {
1416 if ($drive->{file
} =~ m
|^/|) {
1417 $path = $drive->{file
};
1418 if (my $info = path_is_scsi
($path)) {
1419 if ($info->{type
} == 0) {
1420 $devicetype = 'block';
1421 } elsif ($info->{type
} == 1) { # tape
1422 $devicetype = 'generic';
1426 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1429 if($path =~ m/^iscsi\:\/\
//){
1430 $devicetype = 'generic';
1434 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1435 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1437 $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}";
1440 } elsif ($drive->{interface
} eq 'ide'){
1442 my $controller = int($drive->{index} / $maxdev);
1443 my $unit = $drive->{index} % $maxdev;
1444 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1446 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1447 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1448 $model = URI
::Escape
::uri_unescape
($model);
1449 $device .= ",model=$model";
1451 } elsif ($drive->{interface
} eq 'sata'){
1452 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1453 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1454 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1455 } elsif ($drive->{interface
} eq 'usb') {
1457 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1459 die "unsupported interface type";
1462 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1467 sub get_initiator_name
{
1470 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1471 while (defined(my $line = <$fh>)) {
1472 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1481 sub print_drive_full
{
1482 my ($storecfg, $vmid, $drive) = @_;
1485 my $volid = $drive->{file
};
1488 if (drive_is_cdrom
($drive)) {
1489 $path = get_iso_path
($storecfg, $vmid, $volid);
1491 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1493 $path = PVE
::Storage
::path
($storecfg, $volid);
1494 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1495 $format = qemu_img_format
($scfg, $volname);
1503 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);
1504 foreach my $o (@qemu_drive_options) {
1505 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1507 if (my $serial = $drive->{serial
}) {
1508 $serial = URI
::Escape
::uri_unescape
($serial);
1509 $opts .= ",serial=$serial";
1512 $opts .= ",format=$format" if $format && !$drive->{format
};
1514 foreach my $o (qw(bps bps_rd bps_wr)) {
1515 my $v = $drive->{"m$o"};
1516 $opts .= ",$o=" . int($v*1024*1024) if $v;
1519 my $cache_direct = 0;
1521 if (my $cache = $drive->{cache
}) {
1522 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1523 } elsif (!drive_is_cdrom
($drive)) {
1524 $opts .= ",cache=none";
1528 # aio native works only with O_DIRECT
1529 if (!$drive->{aio
}) {
1531 $opts .= ",aio=native";
1533 $opts .= ",aio=threads";
1537 if (!drive_is_cdrom
($drive)) {
1539 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1540 $detectzeroes = 'off';
1541 } elsif ($drive->{discard
}) {
1542 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1544 # This used to be our default with discard not being specified:
1545 $detectzeroes = 'on';
1547 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1550 my $pathinfo = $path ?
"file=$path," : '';
1552 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1555 sub print_netdevice_full
{
1556 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1558 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1560 my $device = $net->{model
};
1561 if ($net->{model
} eq 'virtio') {
1562 $device = 'virtio-net-pci';
1565 my $pciaddr = print_pci_addr
("$netid", $bridges);
1566 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1567 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1568 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1569 my $vectors = $net->{queues
} * 2 + 2;
1570 $tmpstr .= ",vectors=$vectors,mq=on";
1572 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1574 if ($use_old_bios_files) {
1576 if ($device eq 'virtio-net-pci') {
1577 $romfile = 'pxe-virtio.rom';
1578 } elsif ($device eq 'e1000') {
1579 $romfile = 'pxe-e1000.rom';
1580 } elsif ($device eq 'ne2k') {
1581 $romfile = 'pxe-ne2k_pci.rom';
1582 } elsif ($device eq 'pcnet') {
1583 $romfile = 'pxe-pcnet.rom';
1584 } elsif ($device eq 'rtl8139') {
1585 $romfile = 'pxe-rtl8139.rom';
1587 $tmpstr .= ",romfile=$romfile" if $romfile;
1593 sub print_netdev_full
{
1594 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1597 if ($netid =~ m/^net(\d+)$/) {
1601 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1603 my $ifname = "tap${vmid}i$i";
1605 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1606 die "interface name '$ifname' is too long (max 15 character)\n"
1607 if length($ifname) >= 16;
1609 my $vhostparam = '';
1610 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1612 my $vmname = $conf->{name
} || "vm$vmid";
1615 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1617 if ($net->{bridge
}) {
1618 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1620 $netdev = "type=user,id=$netid,hostname=$vmname";
1623 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1628 sub drive_is_cdrom
{
1631 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1635 sub parse_number_sets
{
1638 foreach my $part (split(/;/, $set)) {
1639 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1640 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1641 push @$res, [ $1, $2 ];
1643 die "invalid range: $part\n";
1652 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1653 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1654 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1661 return undef if !$value;
1663 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1665 my @idlist = split(/;/, $res->{host
});
1666 delete $res->{host
};
1667 foreach my $id (@idlist) {
1668 if ($id =~ /^$PCIRE$/) {
1669 push @{$res->{pciid
}}, { id
=> $1, function
=> ($2//'0') };
1671 # should have been caught by parse_property_string already
1672 die "failed to parse PCI id: $id\n";
1678 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1682 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1687 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
() if !defined($res->{macaddr
});
1694 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1697 sub add_random_macs
{
1698 my ($settings) = @_;
1700 foreach my $opt (keys %$settings) {
1701 next if $opt !~ m/^net(\d+)$/;
1702 my $net = parse_net
($settings->{$opt});
1704 $settings->{$opt} = print_net
($net);
1708 sub vm_is_volid_owner
{
1709 my ($storecfg, $vmid, $volid) = @_;
1711 if ($volid !~ m
|^/|) {
1713 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1714 if ($owner && ($owner == $vmid)) {
1722 sub split_flagged_list
{
1723 my $text = shift || '';
1724 $text =~ s/[,;]/ /g;
1726 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1729 sub join_flagged_list
{
1730 my ($how, $lst) = @_;
1731 join $how, map { $lst->{$_} . $_ } keys %$lst;
1734 sub vmconfig_delete_pending_option
{
1735 my ($conf, $key, $force) = @_;
1737 delete $conf->{pending
}->{$key};
1738 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1739 $pending_delete_hash->{$key} = $force ?
'!' : '';
1740 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1743 sub vmconfig_undelete_pending_option
{
1744 my ($conf, $key) = @_;
1746 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1747 delete $pending_delete_hash->{$key};
1749 if (%$pending_delete_hash) {
1750 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1752 delete $conf->{pending
}->{delete};
1756 sub vmconfig_register_unused_drive
{
1757 my ($storecfg, $vmid, $conf, $drive) = @_;
1759 if (!drive_is_cdrom
($drive)) {
1760 my $volid = $drive->{file
};
1761 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1762 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1767 sub vmconfig_cleanup_pending
{
1770 # remove pending changes when nothing changed
1772 foreach my $opt (keys %{$conf->{pending
}}) {
1773 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1775 delete $conf->{pending
}->{$opt};
1779 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1780 my $pending_delete_hash = {};
1781 while (my ($opt, $force) = each %$current_delete_hash) {
1782 if (defined($conf->{$opt})) {
1783 $pending_delete_hash->{$opt} = $force;
1789 if (%$pending_delete_hash) {
1790 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1792 delete $conf->{pending
}->{delete};
1798 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1802 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1803 format_description
=> 'UUID',
1804 description
=> "Set SMBIOS1 UUID.",
1810 format_description
=> 'string',
1811 description
=> "Set SMBIOS1 version.",
1817 format_description
=> 'string',
1818 description
=> "Set SMBIOS1 serial number.",
1824 format_description
=> 'string',
1825 description
=> "Set SMBIOS1 manufacturer.",
1831 format_description
=> 'string',
1832 description
=> "Set SMBIOS1 product ID.",
1838 format_description
=> 'string',
1839 description
=> "Set SMBIOS1 SKU string.",
1845 format_description
=> 'string',
1846 description
=> "Set SMBIOS1 family string.",
1854 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1861 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1864 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1866 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1867 sub verify_bootdisk
{
1868 my ($value, $noerr) = @_;
1870 return $value if is_valid_drivename
($value);
1872 return undef if $noerr;
1874 die "invalid boot disk '$value'\n";
1877 sub parse_watchdog
{
1880 return undef if !$value;
1882 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1887 sub parse_usb_device
{
1890 return undef if !$value;
1893 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1894 $res->{vendorid
} = $2;
1895 $res->{productid
} = $4;
1896 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1897 $res->{hostbus
} = $1;
1898 $res->{hostport
} = $2;
1899 } elsif ($value =~ m/^spice$/i) {
1908 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1909 sub verify_usb_device
{
1910 my ($value, $noerr) = @_;
1912 return $value if parse_usb_device
($value);
1914 return undef if $noerr;
1916 die "unable to parse usb device\n";
1919 # add JSON properties for create and set function
1920 sub json_config_properties
{
1923 foreach my $opt (keys %$confdesc) {
1924 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1925 $prop->{$opt} = $confdesc->{$opt};
1932 my ($key, $value) = @_;
1934 die "unknown setting '$key'\n" if !$confdesc->{$key};
1936 my $type = $confdesc->{$key}->{type
};
1938 if (!defined($value)) {
1939 die "got undefined value\n";
1942 if ($value =~ m/[\n\r]/) {
1943 die "property contains a line feed\n";
1946 if ($type eq 'boolean') {
1947 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1948 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1949 die "type check ('boolean') failed - got '$value'\n";
1950 } elsif ($type eq 'integer') {
1951 return int($1) if $value =~ m/^(\d+)$/;
1952 die "type check ('integer') failed - got '$value'\n";
1953 } elsif ($type eq 'number') {
1954 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1955 die "type check ('number') failed - got '$value'\n";
1956 } elsif ($type eq 'string') {
1957 if (my $fmt = $confdesc->{$key}->{format
}) {
1958 if ($fmt eq 'pve-qm-drive') {
1959 # special case - we need to pass $key to parse_drive()
1960 my $drive = parse_drive
($key, $value);
1961 return $value if $drive;
1962 die "unable to parse drive options\n";
1964 PVE
::JSONSchema
::check_format
($fmt, $value);
1967 $value =~ s/^\"(.*)\"$/$1/;
1970 die "internal error"
1974 sub check_iommu_support
{
1975 #fixme : need to check IOMMU support
1976 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1986 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1987 utime undef, undef, $conf;
1991 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1993 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1995 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1997 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1999 # only remove disks owned by this VM
2000 foreach_drive
($conf, sub {
2001 my ($ds, $drive) = @_;
2003 return if drive_is_cdrom
($drive);
2005 my $volid = $drive->{file
};
2007 return if !$volid || $volid =~ m
|^/|;
2009 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2010 return if !$path || !$owner || ($owner != $vmid);
2012 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2015 if ($keep_empty_config) {
2016 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2021 # also remove unused disk
2023 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2026 PVE
::Storage
::foreach_volid
($dl, sub {
2027 my ($volid, $sid, $volname, $d) = @_;
2028 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2037 sub parse_vm_config
{
2038 my ($filename, $raw) = @_;
2040 return undef if !defined($raw);
2043 digest
=> Digest
::SHA
::sha1_hex
($raw),
2048 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2049 || die "got strange filename '$filename'";
2057 my @lines = split(/\n/, $raw);
2058 foreach my $line (@lines) {
2059 next if $line =~ m/^\s*$/;
2061 if ($line =~ m/^\[PENDING\]\s*$/i) {
2062 $section = 'pending';
2063 if (defined($descr)) {
2065 $conf->{description
} = $descr;
2068 $conf = $res->{$section} = {};
2071 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2073 if (defined($descr)) {
2075 $conf->{description
} = $descr;
2078 $conf = $res->{snapshots
}->{$section} = {};
2082 if ($line =~ m/^\#(.*)\s*$/) {
2083 $descr = '' if !defined($descr);
2084 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2088 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2089 $descr = '' if !defined($descr);
2090 $descr .= PVE
::Tools
::decode_text
($2);
2091 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2092 $conf->{snapstate
} = $1;
2093 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2096 $conf->{$key} = $value;
2097 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2099 if ($section eq 'pending') {
2100 $conf->{delete} = $value; # we parse this later
2102 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2104 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2107 eval { $value = check_type
($key, $value); };
2109 warn "vm $vmid - unable to parse value of '$key' - $@";
2111 my $fmt = $confdesc->{$key}->{format
};
2112 if ($fmt && $fmt eq 'pve-qm-drive') {
2113 my $v = parse_drive
($key, $value);
2114 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2115 $v->{file
} = $volid;
2116 $value = print_drive
($vmid, $v);
2118 warn "vm $vmid - unable to parse value of '$key'\n";
2123 if ($key eq 'cdrom') {
2124 $conf->{ide2
} = $value;
2126 $conf->{$key} = $value;
2132 if (defined($descr)) {
2134 $conf->{description
} = $descr;
2136 delete $res->{snapstate
}; # just to be sure
2141 sub write_vm_config
{
2142 my ($filename, $conf) = @_;
2144 delete $conf->{snapstate
}; # just to be sure
2146 if ($conf->{cdrom
}) {
2147 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2148 $conf->{ide2
} = $conf->{cdrom
};
2149 delete $conf->{cdrom
};
2152 # we do not use 'smp' any longer
2153 if ($conf->{sockets
}) {
2154 delete $conf->{smp
};
2155 } elsif ($conf->{smp
}) {
2156 $conf->{sockets
} = $conf->{smp
};
2157 delete $conf->{cores
};
2158 delete $conf->{smp
};
2161 my $used_volids = {};
2163 my $cleanup_config = sub {
2164 my ($cref, $pending, $snapname) = @_;
2166 foreach my $key (keys %$cref) {
2167 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2168 $key eq 'snapstate' || $key eq 'pending';
2169 my $value = $cref->{$key};
2170 if ($key eq 'delete') {
2171 die "propertry 'delete' is only allowed in [PENDING]\n"
2173 # fixme: check syntax?
2176 eval { $value = check_type
($key, $value); };
2177 die "unable to parse value of '$key' - $@" if $@;
2179 $cref->{$key} = $value;
2181 if (!$snapname && is_valid_drivename
($key)) {
2182 my $drive = parse_drive
($key, $value);
2183 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2188 &$cleanup_config($conf);
2190 &$cleanup_config($conf->{pending
}, 1);
2192 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2193 die "internal error" if $snapname eq 'pending';
2194 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2197 # remove 'unusedX' settings if we re-add a volume
2198 foreach my $key (keys %$conf) {
2199 my $value = $conf->{$key};
2200 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2201 delete $conf->{$key};
2205 my $generate_raw_config = sub {
2206 my ($conf, $pending) = @_;
2210 # add description as comment to top of file
2211 if (defined(my $descr = $conf->{description
})) {
2213 foreach my $cl (split(/\n/, $descr)) {
2214 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2217 $raw .= "#\n" if $pending;
2221 foreach my $key (sort keys %$conf) {
2222 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2223 $raw .= "$key: $conf->{$key}\n";
2228 my $raw = &$generate_raw_config($conf);
2230 if (scalar(keys %{$conf->{pending
}})){
2231 $raw .= "\n[PENDING]\n";
2232 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2235 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2236 $raw .= "\n[$snapname]\n";
2237 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2247 # we use static defaults from our JSON schema configuration
2248 foreach my $key (keys %$confdesc) {
2249 if (defined(my $default = $confdesc->{$key}->{default})) {
2250 $res->{$key} = $default;
2254 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2255 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2261 my $vmlist = PVE
::Cluster
::get_vmlist
();
2263 return $res if !$vmlist || !$vmlist->{ids
};
2264 my $ids = $vmlist->{ids
};
2266 foreach my $vmid (keys %$ids) {
2267 my $d = $ids->{$vmid};
2268 next if !$d->{node
} || $d->{node
} ne $nodename;
2269 next if !$d->{type
} || $d->{type
} ne 'qemu';
2270 $res->{$vmid}->{exists} = 1;
2275 # test if VM uses local resources (to prevent migration)
2276 sub check_local_resources
{
2277 my ($conf, $noerr) = @_;
2281 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2282 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2284 foreach my $k (keys %$conf) {
2285 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2286 # sockets are safe: they will recreated be on the target side post-migrate
2287 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2288 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2291 die "VM uses local resources\n" if $loc_res && !$noerr;
2296 # check if used storages are available on all nodes (use by migrate)
2297 sub check_storage_availability
{
2298 my ($storecfg, $conf, $node) = @_;
2300 foreach_drive
($conf, sub {
2301 my ($ds, $drive) = @_;
2303 my $volid = $drive->{file
};
2306 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2309 # check if storage is available on both nodes
2310 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2311 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2315 # list nodes where all VM images are available (used by has_feature API)
2317 my ($conf, $storecfg) = @_;
2319 my $nodelist = PVE
::Cluster
::get_nodelist
();
2320 my $nodehash = { map { $_ => 1 } @$nodelist };
2321 my $nodename = PVE
::INotify
::nodename
();
2323 foreach_drive
($conf, sub {
2324 my ($ds, $drive) = @_;
2326 my $volid = $drive->{file
};
2329 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2331 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2332 if ($scfg->{disable
}) {
2334 } elsif (my $avail = $scfg->{nodes
}) {
2335 foreach my $node (keys %$nodehash) {
2336 delete $nodehash->{$node} if !$avail->{$node};
2338 } elsif (!$scfg->{shared
}) {
2339 foreach my $node (keys %$nodehash) {
2340 delete $nodehash->{$node} if $node ne $nodename
2350 my ($pidfile, $pid) = @_;
2352 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2356 return undef if !$line;
2357 my @param = split(/\0/, $line);
2359 my $cmd = $param[0];
2360 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2362 for (my $i = 0; $i < scalar (@param); $i++) {
2365 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2366 my $p = $param[$i+1];
2367 return 1 if $p && ($p eq $pidfile);
2376 my ($vmid, $nocheck, $node) = @_;
2378 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2380 die "unable to find configuration file for VM $vmid - no such machine\n"
2381 if !$nocheck && ! -f
$filename;
2383 my $pidfile = pidfile_name
($vmid);
2385 if (my $fd = IO
::File-
>new("<$pidfile")) {
2390 my $mtime = $st->mtime;
2391 if ($mtime > time()) {
2392 warn "file '$filename' modified in future\n";
2395 if ($line =~ m/^(\d+)$/) {
2397 if (check_cmdline
($pidfile, $pid)) {
2398 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2410 my $vzlist = config_list
();
2412 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2414 while (defined(my $de = $fd->read)) {
2415 next if $de !~ m/^(\d+)\.pid$/;
2417 next if !defined($vzlist->{$vmid});
2418 if (my $pid = check_running
($vmid)) {
2419 $vzlist->{$vmid}->{pid
} = $pid;
2427 my ($storecfg, $conf) = @_;
2429 my $bootdisk = $conf->{bootdisk
};
2430 return undef if !$bootdisk;
2431 return undef if !is_valid_drivename
($bootdisk);
2433 return undef if !$conf->{$bootdisk};
2435 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2436 return undef if !defined($drive);
2438 return undef if drive_is_cdrom
($drive);
2440 my $volid = $drive->{file
};
2441 return undef if !$volid;
2443 return $drive->{size
};
2446 my $last_proc_pid_stat;
2448 # get VM status information
2449 # This must be fast and should not block ($full == false)
2450 # We only query KVM using QMP if $full == true (this can be slow)
2452 my ($opt_vmid, $full) = @_;
2456 my $storecfg = PVE
::Storage
::config
();
2458 my $list = vzlist
();
2459 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2461 my $cpucount = $cpuinfo->{cpus
} || 1;
2463 foreach my $vmid (keys %$list) {
2464 next if $opt_vmid && ($vmid ne $opt_vmid);
2466 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2467 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2470 $d->{pid
} = $list->{$vmid}->{pid
};
2472 # fixme: better status?
2473 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2475 my $size = disksize
($storecfg, $conf);
2476 if (defined($size)) {
2477 $d->{disk
} = 0; # no info available
2478 $d->{maxdisk
} = $size;
2484 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2485 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2486 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2488 $d->{name
} = $conf->{name
} || "VM $vmid";
2489 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2491 if ($conf->{balloon
}) {
2492 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2493 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2504 $d->{diskwrite
} = 0;
2506 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2511 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2512 foreach my $dev (keys %$netdev) {
2513 next if $dev !~ m/^tap([1-9]\d*)i/;
2515 my $d = $res->{$vmid};
2518 $d->{netout
} += $netdev->{$dev}->{receive
};
2519 $d->{netin
} += $netdev->{$dev}->{transmit
};
2522 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2523 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2528 my $ctime = gettimeofday
;
2530 foreach my $vmid (keys %$list) {
2532 my $d = $res->{$vmid};
2533 my $pid = $d->{pid
};
2536 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2537 next if !$pstat; # not running
2539 my $used = $pstat->{utime} + $pstat->{stime
};
2541 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2543 if ($pstat->{vsize
}) {
2544 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2547 my $old = $last_proc_pid_stat->{$pid};
2549 $last_proc_pid_stat->{$pid} = {
2557 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2559 if ($dtime > 1000) {
2560 my $dutime = $used - $old->{used
};
2562 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2563 $last_proc_pid_stat->{$pid} = {
2569 $d->{cpu
} = $old->{cpu
};
2573 return $res if !$full;
2575 my $qmpclient = PVE
::QMPClient-
>new();
2577 my $ballooncb = sub {
2578 my ($vmid, $resp) = @_;
2580 my $info = $resp->{'return'};
2581 return if !$info->{max_mem
};
2583 my $d = $res->{$vmid};
2585 # use memory assigned to VM
2586 $d->{maxmem
} = $info->{max_mem
};
2587 $d->{balloon
} = $info->{actual
};
2589 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2590 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2591 $d->{freemem
} = $info->{free_mem
};
2594 $d->{ballooninfo
} = $info;
2597 my $blockstatscb = sub {
2598 my ($vmid, $resp) = @_;
2599 my $data = $resp->{'return'} || [];
2600 my $totalrdbytes = 0;
2601 my $totalwrbytes = 0;
2603 for my $blockstat (@$data) {
2604 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2605 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2607 $blockstat->{device
} =~ s/drive-//;
2608 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2610 $res->{$vmid}->{diskread
} = $totalrdbytes;
2611 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2614 my $statuscb = sub {
2615 my ($vmid, $resp) = @_;
2617 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2618 # this fails if ballon driver is not loaded, so this must be
2619 # the last commnand (following command are aborted if this fails).
2620 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2622 my $status = 'unknown';
2623 if (!defined($status = $resp->{'return'}->{status
})) {
2624 warn "unable to get VM status\n";
2628 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2631 foreach my $vmid (keys %$list) {
2632 next if $opt_vmid && ($vmid ne $opt_vmid);
2633 next if !$res->{$vmid}->{pid
}; # not running
2634 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2637 $qmpclient->queue_execute(undef, 1);
2639 foreach my $vmid (keys %$list) {
2640 next if $opt_vmid && ($vmid ne $opt_vmid);
2641 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2648 my ($conf, $func) = @_;
2650 foreach my $ds (valid_drive_names
()) {
2651 next if !defined($conf->{$ds});
2653 my $drive = parse_drive
($ds, $conf->{$ds});
2656 &$func($ds, $drive);
2661 my ($conf, $func) = @_;
2665 my $test_volid = sub {
2666 my ($volid, $is_cdrom) = @_;
2670 $volhash->{$volid} = $is_cdrom || 0;
2673 foreach_drive
($conf, sub {
2674 my ($ds, $drive) = @_;
2675 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2678 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2679 my $snap = $conf->{snapshots
}->{$snapname};
2680 &$test_volid($snap->{vmstate
}, 0);
2681 foreach_drive
($snap, sub {
2682 my ($ds, $drive) = @_;
2683 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2687 foreach my $volid (keys %$volhash) {
2688 &$func($volid, $volhash->{$volid});
2692 sub vga_conf_has_spice
{
2695 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2700 sub config_to_command
{
2701 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2704 my $globalFlags = [];
2705 my $machineFlags = [];
2711 my $kvmver = kvm_user_version
();
2712 my $vernum = 0; # unknown
2713 my $ostype = $conf->{ostype
};
2714 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2715 $vernum = $1*1000000+$2*1000;
2716 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2717 $vernum = $1*1000000+$2*1000+$3;
2720 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2722 my $have_ovz = -f
'/proc/vz/vestat';
2724 my $q35 = machine_type_is_q35
($conf);
2725 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2726 my $machine_type = $forcemachine || $conf->{machine
};
2727 my $use_old_bios_files = undef;
2728 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2730 my $cpuunits = defined($conf->{cpuunits
}) ?
2731 $conf->{cpuunits
} : $defaults->{cpuunits
};
2733 push @$cmd, '/usr/bin/kvm';
2735 push @$cmd, '-id', $vmid;
2739 my $qmpsocket = qmp_socket
($vmid);
2740 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2741 push @$cmd, '-mon', "chardev=qmp,mode=control";
2744 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2746 push @$cmd, '-daemonize';
2748 if ($conf->{smbios1
}) {
2749 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2752 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2753 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2754 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2755 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2756 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2757 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2758 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2762 # the q35 chipset support native usb2, so we enable usb controller
2763 # by default for this machine type
2764 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2766 $pciaddr = print_pci_addr
("piix3", $bridges);
2767 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2770 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2771 next if !$conf->{"usb$i"};
2772 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2773 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2776 # include usb device config
2777 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2780 # add usb3 controller if needed
2783 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2784 next if !$conf->{"usb$i"};
2785 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2786 next if !$d || !$d->{usb3
};
2790 $pciaddr = print_pci_addr
("xhci", $bridges);
2791 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2793 my $vga = $conf->{vga
};
2795 my $qxlnum = vga_conf_has_spice
($vga);
2796 $vga = 'qxl' if $qxlnum;
2799 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2800 $conf->{ostype
} eq 'win7' ||
2801 $conf->{ostype
} eq 'w2k8')) {
2808 # enable absolute mouse coordinates (needed by vnc)
2810 if (defined($conf->{tablet
})) {
2811 $tablet = $conf->{tablet
};
2813 $tablet = $defaults->{tablet
};
2814 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2815 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2818 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2822 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2823 my $d = parse_hostpci
($conf->{"hostpci$i"});
2826 my $pcie = $d->{pcie
};
2828 die "q35 machine model is not enabled" if !$q35;
2829 $pciaddr = print_pcie_addr
("hostpci$i");
2831 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2834 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2836 if ($d->{'x-vga'}) {
2837 $xvga = ',x-vga=on';
2840 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2841 push @$cpuFlags , 'hv_vendor_id=proxmox';
2843 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2847 my $pcidevices = $d->{pciid
};
2848 my $multifunction = 1 if @$pcidevices > 1;
2851 foreach my $pcidevice (@$pcidevices) {
2853 my $id = "hostpci$i";
2854 $id .= ".$j" if $multifunction;
2855 my $addr = $pciaddr;
2856 $addr .= ".$j" if $multifunction;
2857 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2860 $devicestr .= "$rombar$xvga";
2861 $devicestr .= ",multifunction=on" if $multifunction;
2864 push @$devices, '-device', $devicestr;
2870 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2871 next if !$conf->{"usb$i"};
2872 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2875 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2877 if (defined($d->{usb3
}) && $d->{usb3
}) {
2878 $usbbus = ',bus=xhci.0';
2881 if (defined($d->{host
})) {
2882 $d = parse_usb_device
($d->{host
});
2883 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2884 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2885 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2886 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2887 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2888 # usb redir support for spice, currently no usb3
2889 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2890 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2896 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2897 if (my $path = $conf->{"serial$i"}) {
2898 if ($path eq 'socket') {
2899 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2900 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2901 push @$devices, '-device', "isa-serial,chardev=serial$i";
2903 die "no such serial device\n" if ! -c
$path;
2904 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2905 push @$devices, '-device', "isa-serial,chardev=serial$i";
2911 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2912 if (my $path = $conf->{"parallel$i"}) {
2913 die "no such parallel device\n" if ! -c
$path;
2914 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2915 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2916 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2920 my $vmname = $conf->{name
} || "vm$vmid";
2922 push @$cmd, '-name', $vmname;
2925 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2926 $sockets = $conf->{sockets
} if $conf->{sockets
};
2928 my $cores = $conf->{cores
} || 1;
2930 my $maxcpus = $sockets * $cores;
2932 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2934 my $allowed_vcpus = $cpuinfo->{cpus
};
2936 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2937 if ($allowed_vcpus < $maxcpus);
2939 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2941 push @$cmd, '-nodefaults';
2943 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2945 my $bootindex_hash = {};
2947 foreach my $o (split(//, $bootorder)) {
2948 $bootindex_hash->{$o} = $i*100;
2952 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2954 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2956 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2958 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2960 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2961 my $socket = vnc_socket
($vmid);
2962 push @$cmd, '-vnc', "unix:$socket,x509,password";
2964 push @$cmd, '-nographic';
2968 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2970 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2971 my $useLocaltime = $conf->{localtime};
2974 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2976 if ($ostype =~ m/^w/) { # windows
2977 $useLocaltime = 1 if !defined($conf->{localtime});
2979 # use time drift fix when acpi is enabled
2980 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2981 $tdf = 1 if !defined($conf->{tdf
});
2985 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2986 $ostype eq 'wvista') {
2987 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2988 push @$cmd, '-no-hpet';
2989 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2990 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2991 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2992 push @$cpuFlags , 'hv_time' if !$nokvm;
2994 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
2995 push @$cpuFlags , 'hv_reset' if !$nokvm;
2996 push @$cpuFlags , 'hv_vpindex' if !$nokvm;
2997 push @$cpuFlags , 'hv_runtime' if !$nokvm;
3001 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3005 if ($ostype eq 'win7' || $ostype eq 'win8') {
3006 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3010 push @$rtcFlags, 'driftfix=slew' if $tdf;
3013 push @$machineFlags, 'accel=tcg';
3015 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3018 if ($machine_type) {
3019 push @$machineFlags, "type=${machine_type}";
3022 if ($conf->{startdate
}) {
3023 push @$rtcFlags, "base=$conf->{startdate}";
3024 } elsif ($useLocaltime) {
3025 push @$rtcFlags, 'base=localtime';
3028 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3029 if (my $cputype = $conf->{cpu
}) {
3030 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3031 or die "Cannot parse cpu description: $cputype\n";
3032 $cpu = $cpuconf->{cputype
};
3033 $kvm_off = 1 if $cpuconf->{hidden
};
3036 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3038 push @$cpuFlags , '-x2apic'
3039 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3041 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3043 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3045 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3047 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3048 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3051 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3053 push @$cpuFlags, 'kvm=off' if $kvm_off;
3055 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3056 die "internal error"; # should not happen
3058 push @$cpuFlags, "vendor=${cpu_vendor}"
3059 if $cpu_vendor ne 'default';
3061 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3063 push @$cmd, '-cpu', $cpu;
3065 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3067 push @$cmd, '-S' if $conf->{freeze
};
3069 # set keyboard layout
3070 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3071 push @$cmd, '-k', $kb if $kb;
3074 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3075 #push @$cmd, '-soundhw', 'es1370';
3076 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3078 if($conf->{agent
}) {
3079 my $qgasocket = qmp_socket
($vmid, 1);
3080 my $pciaddr = print_pci_addr
("qga0", $bridges);
3081 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3082 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3083 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3090 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3091 for(my $i = 1; $i < $qxlnum; $i++){
3092 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3093 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3096 # assume other OS works like Linux
3097 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3098 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3102 my $pciaddr = print_pci_addr
("spice", $bridges);
3104 my $nodename = PVE
::INotify
::nodename
();
3105 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3106 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3108 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3110 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3111 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3112 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3115 # enable balloon by default, unless explicitly disabled
3116 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3117 $pciaddr = print_pci_addr
("balloon0", $bridges);
3118 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3121 if ($conf->{watchdog
}) {
3122 my $wdopts = parse_watchdog
($conf->{watchdog
});
3123 $pciaddr = print_pci_addr
("watchdog", $bridges);
3124 my $watchdog = $wdopts->{model
} || 'i6300esb';
3125 push @$devices, '-device', "$watchdog$pciaddr";
3126 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3130 my $scsicontroller = {};
3131 my $ahcicontroller = {};
3132 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3134 # Add iscsi initiator name if available
3135 if (my $initiator = get_initiator_name
()) {
3136 push @$devices, '-iscsi', "initiator-name=$initiator";
3139 foreach_drive
($conf, sub {
3140 my ($ds, $drive) = @_;
3142 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3143 push @$vollist, $drive->{file
};
3146 $use_virtio = 1 if $ds =~ m/^virtio/;
3148 if (drive_is_cdrom
($drive)) {
3149 if ($bootindex_hash->{d
}) {
3150 $drive->{bootindex
} = $bootindex_hash->{d
};
3151 $bootindex_hash->{d
} += 1;
3154 if ($bootindex_hash->{c
}) {
3155 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3156 $bootindex_hash->{c
} += 1;
3160 if($drive->{interface
} eq 'virtio'){
3161 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3164 if ($drive->{interface
} eq 'scsi') {
3166 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3168 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3169 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3172 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3173 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3174 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3175 } elsif ($drive->{iothread
}) {
3176 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3180 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3181 $queues = ",num_queues=$drive->{queues}";
3184 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3185 $scsicontroller->{$controller}=1;
3188 if ($drive->{interface
} eq 'sata') {
3189 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3190 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3191 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3192 $ahcicontroller->{$controller}=1;
3195 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3196 push @$devices, '-drive',$drive_cmd;
3197 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3200 for (my $i = 0; $i < $MAX_NETS; $i++) {
3201 next if !$conf->{"net$i"};
3202 my $d = parse_net
($conf->{"net$i"});
3205 $use_virtio = 1 if $d->{model
} eq 'virtio';
3207 if ($bootindex_hash->{n
}) {
3208 $d->{bootindex
} = $bootindex_hash->{n
};
3209 $bootindex_hash->{n
} += 1;
3212 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3213 push @$devices, '-netdev', $netdevfull;
3215 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3216 push @$devices, '-device', $netdevicefull;
3221 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3226 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3228 while (my ($k, $v) = each %$bridges) {
3229 $pciaddr = print_pci_addr
("pci.$k");
3230 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3235 if ($conf->{args
}) {
3236 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3240 push @$cmd, @$devices;
3241 push @$cmd, '-rtc', join(',', @$rtcFlags)
3242 if scalar(@$rtcFlags);
3243 push @$cmd, '-machine', join(',', @$machineFlags)
3244 if scalar(@$machineFlags);
3245 push @$cmd, '-global', join(',', @$globalFlags)
3246 if scalar(@$globalFlags);
3248 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3253 return "${var_run_tmpdir}/$vmid.vnc";
3259 my $res = vm_mon_cmd
($vmid, 'query-spice');
3261 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3265 my ($vmid, $qga) = @_;
3266 my $sockettype = $qga ?
'qga' : 'qmp';
3267 return "${var_run_tmpdir}/$vmid.$sockettype";
3272 return "${var_run_tmpdir}/$vmid.pid";
3275 sub vm_devices_list
{
3278 my $res = vm_mon_cmd
($vmid, 'query-pci');
3280 foreach my $pcibus (@$res) {
3281 foreach my $device (@{$pcibus->{devices
}}) {
3282 next if !$device->{'qdev_id'};
3283 if ($device->{'pci_bridge'}) {
3284 $devices->{$device->{'qdev_id'}} = 1;
3285 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3286 next if !$bridge_device->{'qdev_id'};
3287 $devices->{$bridge_device->{'qdev_id'}} = 1;
3288 $devices->{$device->{'qdev_id'}}++;
3291 $devices->{$device->{'qdev_id'}} = 1;
3296 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3297 foreach my $block (@$resblock) {
3298 if($block->{device
} =~ m/^drive-(\S+)/){
3303 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3304 foreach my $mice (@$resmice) {
3305 if ($mice->{name
} eq 'QEMU HID Tablet') {
3306 $devices->{tablet
} = 1;
3315 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3317 my $q35 = machine_type_is_q35
($conf);
3319 my $devices_list = vm_devices_list
($vmid);
3320 return 1 if defined($devices_list->{$deviceid});
3322 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3324 if ($deviceid eq 'tablet') {
3326 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3328 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3330 qemu_iothread_add
($vmid, $deviceid, $device);
3332 qemu_driveadd
($storecfg, $vmid, $device);
3333 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3335 qemu_deviceadd
($vmid, $devicefull);
3336 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3338 eval { qemu_drivedel
($vmid, $deviceid); };
3343 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3346 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3347 my $pciaddr = print_pci_addr
($deviceid);
3348 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3350 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3352 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3353 qemu_iothread_add
($vmid, $deviceid, $device);
3354 $devicefull .= ",iothread=iothread-$deviceid";
3357 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3358 $devicefull .= ",num_queues=$device->{queues}";
3361 qemu_deviceadd
($vmid, $devicefull);
3362 qemu_deviceaddverify
($vmid, $deviceid);
3364 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3366 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3367 qemu_driveadd
($storecfg, $vmid, $device);
3369 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3370 eval { qemu_deviceadd
($vmid, $devicefull); };
3372 eval { qemu_drivedel
($vmid, $deviceid); };
3377 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3379 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3381 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3382 my $use_old_bios_files = undef;
3383 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3385 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3386 qemu_deviceadd
($vmid, $netdevicefull);
3387 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3389 eval { qemu_netdevdel
($vmid, $deviceid); };
3394 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3397 my $pciaddr = print_pci_addr
($deviceid);
3398 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3400 qemu_deviceadd
($vmid, $devicefull);
3401 qemu_deviceaddverify
($vmid, $deviceid);
3404 die "can't hotplug device '$deviceid'\n";
3410 # fixme: this should raise exceptions on error!
3411 sub vm_deviceunplug
{
3412 my ($vmid, $conf, $deviceid) = @_;
3414 my $devices_list = vm_devices_list
($vmid);
3415 return 1 if !defined($devices_list->{$deviceid});
3417 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3419 if ($deviceid eq 'tablet') {
3421 qemu_devicedel
($vmid, $deviceid);
3423 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3425 qemu_devicedel
($vmid, $deviceid);
3426 qemu_devicedelverify
($vmid, $deviceid);
3427 qemu_drivedel
($vmid, $deviceid);
3428 qemu_iothread_del
($conf, $vmid, $deviceid);
3430 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3432 qemu_devicedel
($vmid, $deviceid);
3433 qemu_devicedelverify
($vmid, $deviceid);
3434 qemu_iothread_del
($conf, $vmid, $deviceid);
3436 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3438 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3439 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3440 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3442 qemu_devicedel
($vmid, $deviceid);
3443 qemu_drivedel
($vmid, $deviceid);
3444 qemu_deletescsihw
($conf, $vmid, $deviceid);
3446 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3448 qemu_devicedel
($vmid, $deviceid);
3449 qemu_devicedelverify
($vmid, $deviceid);
3450 qemu_netdevdel
($vmid, $deviceid);
3453 die "can't unplug device '$deviceid'\n";
3459 sub qemu_deviceadd
{
3460 my ($vmid, $devicefull) = @_;
3462 $devicefull = "driver=".$devicefull;
3463 my %options = split(/[=,]/, $devicefull);
3465 vm_mon_cmd
($vmid, "device_add" , %options);
3468 sub qemu_devicedel
{
3469 my ($vmid, $deviceid) = @_;
3471 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3474 sub qemu_iothread_add
{
3475 my($vmid, $deviceid, $device) = @_;
3477 if ($device->{iothread
}) {
3478 my $iothreads = vm_iothreads_list
($vmid);
3479 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3483 sub qemu_iothread_del
{
3484 my($conf, $vmid, $deviceid) = @_;
3486 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3487 if ($device->{iothread
}) {
3488 my $iothreads = vm_iothreads_list
($vmid);
3489 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3493 sub qemu_objectadd
{
3494 my($vmid, $objectid, $qomtype) = @_;
3496 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3501 sub qemu_objectdel
{
3502 my($vmid, $objectid) = @_;
3504 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3510 my ($storecfg, $vmid, $device) = @_;
3512 my $drive = print_drive_full
($storecfg, $vmid, $device);
3513 $drive =~ s/\\/\\\\/g;
3514 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3516 # If the command succeeds qemu prints: "OK
"
3517 return 1 if $ret =~ m/OK/s;
3519 die "adding drive failed
: $ret\n";
3523 my($vmid, $deviceid) = @_;
3525 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3528 return 1 if $ret eq "";
3530 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3531 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3533 die "deleting drive
$deviceid failed
: $ret\n";
3536 sub qemu_deviceaddverify {
3537 my ($vmid, $deviceid) = @_;
3539 for (my $i = 0; $i <= 5; $i++) {
3540 my $devices_list = vm_devices_list($vmid);
3541 return 1 if defined($devices_list->{$deviceid});
3545 die "error on hotplug device
'$deviceid'\n";
3549 sub qemu_devicedelverify {
3550 my ($vmid, $deviceid) = @_;
3552 # need to verify that the device is correctly removed as device_del
3553 # is async and empty return is not reliable
3555 for (my $i = 0; $i <= 5; $i++) {
3556 my $devices_list = vm_devices_list($vmid);
3557 return 1 if !defined($devices_list->{$deviceid});
3561 die "error on hot-unplugging device
'$deviceid'\n";
3564 sub qemu_findorcreatescsihw {
3565 my ($storecfg, $conf, $vmid, $device) = @_;
3567 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3569 my $scsihwid="$controller_prefix$controller";
3570 my $devices_list = vm_devices_list($vmid);
3572 if(!defined($devices_list->{$scsihwid})) {
3573 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3579 sub qemu_deletescsihw {
3580 my ($conf, $vmid, $opt) = @_;
3582 my $device = parse_drive($opt, $conf->{$opt});
3584 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3585 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3589 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3591 my $devices_list = vm_devices_list($vmid);
3592 foreach my $opt (keys %{$devices_list}) {
3593 if (PVE::QemuServer::is_valid_drivename($opt)) {
3594 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3595 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3601 my $scsihwid="scsihw
$controller";
3603 vm_deviceunplug($vmid, $conf, $scsihwid);
3608 sub qemu_add_pci_bridge {
3609 my ($storecfg, $conf, $vmid, $device) = @_;
3615 print_pci_addr($device, $bridges);
3617 while (my ($k, $v) = each %$bridges) {
3620 return 1 if !defined($bridgeid) || $bridgeid < 1;
3622 my $bridge = "pci
.$bridgeid";
3623 my $devices_list = vm_devices_list($vmid);
3625 if (!defined($devices_list->{$bridge})) {
3626 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3632 sub qemu_set_link_status {
3633 my ($vmid, $device, $up) = @_;
3635 vm_mon_cmd($vmid, "set_link
", name => $device,
3636 up => $up ? JSON::true : JSON::false);
3639 sub qemu_netdevadd {
3640 my ($vmid, $conf, $device, $deviceid) = @_;
3642 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3643 my %options = split(/[=,]/, $netdev);
3645 vm_mon_cmd($vmid, "netdev_add
", %options);
3649 sub qemu_netdevdel {
3650 my ($vmid, $deviceid) = @_;
3652 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3655 sub qemu_cpu_hotplug {
3656 my ($vmid, $conf, $vcpus) = @_;
3659 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3660 $sockets = $conf->{sockets} if $conf->{sockets};
3661 my $cores = $conf->{cores} || 1;
3662 my $maxcpus = $sockets * $cores;
3664 $vcpus = $maxcpus if !$vcpus;
3666 die "you can
't add more vcpus than maxcpus\n"
3667 if $vcpus > $maxcpus;
3669 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3670 die "online cpu unplug is not yet possible\n"
3671 if $vcpus < $currentvcpus;
3673 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3674 die "vcpus in running vm is different than configuration\n"
3675 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3677 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3678 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3682 sub qemu_block_set_io_throttle {
3683 my ($vmid, $deviceid,
3684 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3685 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3687 return if !check_running($vmid) ;
3689 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3691 bps_rd => int($bps_rd),
3692 bps_wr => int($bps_wr),
3694 iops_rd => int($iops_rd),
3695 iops_wr => int($iops_wr),
3696 bps_max => int($bps_max),
3697 bps_rd_max => int($bps_rd_max),
3698 bps_wr_max => int($bps_wr_max),
3699 iops_max => int($iops_max),
3700 iops_rd_max => int($iops_rd_max),
3701 iops_wr_max => int($iops_wr_max)
3706 # old code, only used to shutdown old VM after update
3708 my ($fh, $timeout) = @_;
3710 my $sel = new IO::Select;
3717 while (scalar (@ready = $sel->can_read($timeout))) {
3719 if ($count = $fh->sysread($buf, 8192)) {
3720 if ($buf =~ /^(.*)\(qemu\) $/s) {
3727 if (!defined($count)) {
3734 die "monitor read timeout\n" if !scalar(@ready);
3739 # old code, only used to shutdown old VM after update
3740 sub vm_monitor_command {
3741 my ($vmid, $cmdstr, $nocheck) = @_;
3746 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3748 my $sname = "${var_run_tmpdir}/$vmid.mon";
3750 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3751 die "unable to connect to VM $vmid socket - $!\n";
3755 # hack: migrate sometime blocks the monitor (when migrate_downtime
3757 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3758 $timeout = 60*60; # 1 hour
3762 my $data = __read_avail($sock, $timeout);
3764 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3765 die "got unexpected qemu monitor banner\n";
3768 my $sel = new IO::Select;
3771 if (!scalar(my @ready = $sel->can_write($timeout))) {
3772 die "monitor write error - timeout";
3775 my $fullcmd = "$cmdstr\r";
3777 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3780 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3781 die "monitor write error - $!";
3784 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3788 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3789 $timeout = 60*60; # 1 hour
3790 } elsif ($cmdstr =~ m/^(eject|change)/) {
3791 $timeout = 60; # note: cdrom mount command is slow
3793 if ($res = __read_avail($sock, $timeout)) {
3795 my @lines = split("\r?\n", $res);
3797 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3799 $res = join("\n", @lines);
3807 syslog("err", "VM $vmid monitor command failed - $err");
3814 sub qemu_block_resize {
3815 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3817 my $running = check_running($vmid);
3819 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3821 return if !$running;
3823 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3827 sub qemu_volume_snapshot {
3828 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3830 my $running = check_running($vmid);
3832 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3833 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3835 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3839 sub qemu_volume_snapshot_delete {
3840 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3842 my $running = check_running($vmid);
3844 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3846 return if !$running;
3848 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
3851 sub set_migration_caps {
3857 "auto-converge" => 1,
3859 "x-rdma-pin-all" => 0,
3864 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
3866 for my $supported_capability (@$supported_capabilities) {
3868 capability => $supported_capability->{capability},
3869 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3873 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
3876 my $fast_plug_option = {
3885 # hotplug changes in [PENDING]
3886 # $selection hash can be used to only apply specified options, for
3887 # example: { cores => 1 } (only apply changed 'cores
')
3888 # $errors ref is used to return error messages
3889 sub vmconfig_hotplug_pending {
3890 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3892 my $defaults = load_defaults();
3894 # commit values which do not have any impact on running VM first
3895 # Note: those option cannot raise errors, we we do not care about
3896 # $selection and always apply them.
3898 my $add_error = sub {
3899 my ($opt, $msg) = @_;
3900 $errors->{$opt} = "hotplug problem - $msg";
3904 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3905 if ($fast_plug_option->{$opt}) {
3906 $conf->{$opt} = $conf->{pending}->{$opt};
3907 delete $conf->{pending}->{$opt};
3913 PVE::QemuConfig->write_config($vmid, $conf);
3914 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3917 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3919 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3920 while (my ($opt, $force) = each %$pending_delete_hash) {
3921 next if $selection && !$selection->{$opt};
3923 if ($opt eq 'hotplug
') {
3924 die "skip\n" if ($conf->{hotplug} =~ /memory/);
3925 } elsif ($opt eq 'tablet
') {
3926 die "skip\n" if !$hotplug_features->{usb};
3927 if ($defaults->{tablet}) {
3928 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3930 vm_deviceunplug($vmid, $conf, $opt);
3932 } elsif ($opt eq 'vcpus
') {
3933 die "skip\n" if !$hotplug_features->{cpu};
3934 qemu_cpu_hotplug($vmid, $conf, undef);
3935 } elsif ($opt eq 'balloon
') {
3936 # enable balloon device is not hotpluggable
3937 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
3938 } elsif ($fast_plug_option->{$opt}) {
3940 } elsif ($opt =~ m/^net(\d+)$/) {
3941 die "skip\n" if !$hotplug_features->{network};
3942 vm_deviceunplug($vmid, $conf, $opt);
3943 } elsif (is_valid_drivename($opt)) {
3944 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3945 vm_deviceunplug($vmid, $conf, $opt);
3946 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3947 } elsif ($opt =~ m/^memory$/) {
3948 die "skip\n" if !$hotplug_features->{memory};
3949 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3950 } elsif ($opt eq 'cpuunits
') {
3951 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
3952 } elsif ($opt eq 'cpulimit
') {
3953 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
3959 &$add_error($opt, $err) if $err ne "skip\n";
3961 # save new config if hotplug was successful
3962 delete $conf->{$opt};
3963 vmconfig_undelete_pending_option($conf, $opt);
3964 PVE::QemuConfig->write_config($vmid, $conf);
3965 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3969 foreach my $opt (keys %{$conf->{pending}}) {
3970 next if $selection && !$selection->{$opt};
3971 my $value = $conf->{pending}->{$opt};
3973 if ($opt eq 'hotplug
') {
3974 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3975 } elsif ($opt eq 'tablet
') {
3976 die "skip\n" if !$hotplug_features->{usb};
3978 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3979 } elsif ($value == 0) {
3980 vm_deviceunplug($vmid, $conf, $opt);
3982 } elsif ($opt eq 'vcpus
') {
3983 die "skip\n" if !$hotplug_features->{cpu};
3984 qemu_cpu_hotplug($vmid, $conf, $value);
3985 } elsif ($opt eq 'balloon
') {
3986 # enable/disable balloning device is not hotpluggable
3987 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3988 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3989 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
3991 # allow manual ballooning if shares is set to zero
3992 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3993 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3994 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
3996 } elsif ($opt =~ m/^net(\d+)$/) {
3997 # some changes can be done without hotplug
3998 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3999 $vmid, $opt, $value);
4000 } elsif (is_valid_drivename($opt)) {
4001 # some changes can be done without hotplug
4002 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4003 $vmid, $opt, $value, 1);
4004 } elsif ($opt =~ m/^memory$/) { #dimms
4005 die "skip\n" if !$hotplug_features->{memory};
4006 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4007 } elsif ($opt eq 'cpuunits
') {
4008 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4009 } elsif ($opt eq 'cpulimit
') {
4010 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4011 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4013 die "skip\n"; # skip non-hot-pluggable options
4017 &$add_error($opt, $err) if $err ne "skip\n";
4019 # save new config if hotplug was successful
4020 $conf->{$opt} = $value;
4021 delete $conf->{pending}->{$opt};
4022 PVE::QemuConfig->write_config($vmid, $conf);
4023 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4028 sub try_deallocate_drive {
4029 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4031 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4032 my $volid = $drive->{file};
4033 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4034 my $sid = PVE::Storage::parse_volume_id($volid);
4035 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4037 # check if the disk is really unused
4038 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4039 if is_volume_in_use($storecfg, $conf, $key, $volid);
4040 PVE::Storage::vdisk_free($storecfg, $volid);
4043 # If vm is not owner of this disk remove from config
4051 sub vmconfig_delete_or_detach_drive {
4052 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4054 my $drive = parse_drive($opt, $conf->{$opt});
4056 my $rpcenv = PVE::RPCEnvironment::get();
4057 my $authuser = $rpcenv->get_user();
4060 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4061 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4063 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4067 sub vmconfig_apply_pending {
4068 my ($vmid, $conf, $storecfg) = @_;
4072 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4073 while (my ($opt, $force) = each %$pending_delete_hash) {
4074 die "internal error" if $opt =~ m/^unused/;
4075 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4076 if (!defined($conf->{$opt})) {
4077 vmconfig_undelete_pending_option($conf, $opt);
4078 PVE::QemuConfig->write_config($vmid, $conf);
4079 } elsif (is_valid_drivename($opt)) {
4080 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4081 vmconfig_undelete_pending_option($conf, $opt);
4082 delete $conf->{$opt};
4083 PVE::QemuConfig->write_config($vmid, $conf);
4085 vmconfig_undelete_pending_option($conf, $opt);
4086 delete $conf->{$opt};
4087 PVE::QemuConfig->write_config($vmid, $conf);
4091 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4093 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4094 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4096 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4097 # skip if nothing changed
4098 } elsif (is_valid_drivename($opt)) {
4099 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4100 if defined($conf->{$opt});
4101 $conf->{$opt} = $conf->{pending}->{$opt};
4103 $conf->{$opt} = $conf->{pending}->{$opt};
4106 delete $conf->{pending}->{$opt};
4107 PVE::QemuConfig->write_config($vmid, $conf);
4111 my $safe_num_ne = sub {
4114 return 0 if !defined($a) && !defined($b);
4115 return 1 if !defined($a);
4116 return 1 if !defined($b);
4121 my $safe_string_ne = sub {
4124 return 0 if !defined($a) && !defined($b);
4125 return 1 if !defined($a);
4126 return 1 if !defined($b);
4131 sub vmconfig_update_net {
4132 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4134 my $newnet = parse_net($value);
4136 if ($conf->{$opt}) {
4137 my $oldnet = parse_net($conf->{$opt});
4139 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4140 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4141 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4142 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4144 # for non online change, we try to hot-unplug
4145 die "skip\n" if !$hotplug;
4146 vm_deviceunplug($vmid, $conf, $opt);
4149 die "internal error" if $opt !~ m/net(\d+)/;
4150 my $iface = "tap${vmid}i$1";
4152 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4153 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4154 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4155 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4156 PVE::Network::tap_unplug($iface);
4157 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4158 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4159 # Rate can be applied on its own but any change above needs to
4160 # include the rate in tap_plug since OVS resets everything.
4161 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4164 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4165 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4173 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4179 sub vmconfig_update_disk {
4180 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4182 # fixme: do we need force?
4184 my $drive = parse_drive($opt, $value);
4186 if ($conf->{$opt}) {
4188 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4190 my $media = $drive->{media} || 'disk
';
4191 my $oldmedia = $old_drive->{media} || 'disk
';
4192 die "unable to change media type\n" if $media ne $oldmedia;
4194 if (!drive_is_cdrom($old_drive)) {
4196 if ($drive->{file} ne $old_drive->{file}) {
4198 die "skip\n" if !$hotplug;
4200 # unplug and register as unused
4201 vm_deviceunplug($vmid, $conf, $opt);
4202 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4205 # update existing disk
4207 # skip non hotpluggable value
4208 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4209 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4210 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4211 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4216 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4217 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4218 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4219 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4220 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4221 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4222 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4223 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4224 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4225 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4226 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4227 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4229 qemu_block_set_io_throttle($vmid,"drive-$opt",
4230 ($drive->{mbps} || 0)*1024*1024,
4231 ($drive->{mbps_rd} || 0)*1024*1024,
4232 ($drive->{mbps_wr} || 0)*1024*1024,
4233 $drive->{iops} || 0,
4234 $drive->{iops_rd} || 0,
4235 $drive->{iops_wr} || 0,
4236 ($drive->{mbps_max} || 0)*1024*1024,
4237 ($drive->{mbps_rd_max} || 0)*1024*1024,
4238 ($drive->{mbps_wr_max} || 0)*1024*1024,
4239 $drive->{iops_max} || 0,
4240 $drive->{iops_rd_max} || 0,
4241 $drive->{iops_wr_max} || 0);
4250 if ($drive->{file} eq 'none
') {
4251 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4253 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4254 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4255 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4263 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4265 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4266 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4270 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4271 $forcemachine, $spice_ticket) = @_;
4273 PVE::QemuConfig->lock_config($vmid, sub {
4274 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4276 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4278 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4280 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4282 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4283 vmconfig_apply_pending($vmid, $conf, $storecfg);
4284 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4287 my $defaults = load_defaults();
4289 # set environment variable useful inside network script
4290 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4292 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4294 my $migrate_port = 0;
4297 if ($statefile eq 'tcp
') {
4298 my $localip = "localhost";
4299 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4300 my $nodename = PVE::INotify::nodename();
4301 if ($datacenterconf->{migration_unsecure}) {
4302 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4303 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4305 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4306 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4307 $migrate_uri = "tcp:${localip}:${migrate_port}";
4308 push @$cmd, '-incoming
', $migrate_uri;
4311 } elsif ($statefile eq 'unix
') {
4312 # should be default for secure migrations as a ssh TCP forward
4313 # tunnel is not deterministic reliable ready and fails regurarly
4314 # to set up in time, so use UNIX socket forwards
4315 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4316 unlink $socket_addr;
4318 $migrate_uri = "unix:$socket_addr";
4320 push @$cmd, '-incoming
', $migrate_uri;
4324 push @$cmd, '-loadstate
', $statefile;
4331 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4332 my $d = parse_hostpci($conf->{"hostpci$i"});
4334 my $pcidevices = $d->{pciid};
4335 foreach my $pcidevice (@$pcidevices) {
4336 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4338 my $info = pci_device_info("0000:$pciid");
4339 die "IOMMU not present\n" if !check_iommu_support();
4340 die "no pci device info for device '$pciid'\n" if !$info;
4341 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4342 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4346 PVE::Storage::activate_volumes($storecfg, $vollist);
4348 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4350 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4351 eval { run_command($cmd); };
4354 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4355 : $defaults->{cpuunits};
4359 Slice => 'qemu
.slice
',
4361 CPUShares => $cpuunits
4363 if (my $cpulimit = $conf->{cpulimit}) {
4364 $properties{CPUQuota} = int($cpulimit * 100);
4366 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4367 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4368 run_command($cmd, timeout => $statefile ? undef : 30, umask => 0077);
4372 # deactivate volumes if start fails
4373 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4374 die "start failed: $err";
4377 print "migration listens on $migrate_uri\n" if $migrate_uri;
4379 if ($statefile && $statefile ne 'tcp
') {
4380 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4384 if ($migratedfrom) {
4387 set_migration_caps($vmid);
4392 print "spice listens on port $spice_port\n";
4393 if ($spice_ticket) {
4394 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4395 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4401 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4402 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4403 if $conf->{balloon};
4406 foreach my $opt (keys %$conf) {
4407 next if $opt !~ m/^net\d+$/;
4408 my $nicconf = parse_net($conf->{$opt});
4409 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4413 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4414 path => "machine/peripheral/balloon0",
4415 property => "guest-stats-polling-interval",
4416 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4422 my ($vmid, $execute, %params) = @_;
4424 my $cmd = { execute => $execute, arguments => \%params };
4425 vm_qmp_command($vmid, $cmd);
4428 sub vm_mon_cmd_nocheck {
4429 my ($vmid, $execute, %params) = @_;
4431 my $cmd = { execute => $execute, arguments => \%params };
4432 vm_qmp_command($vmid, $cmd, 1);
4435 sub vm_qmp_command {
4436 my ($vmid, $cmd, $nocheck) = @_;
4441 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4442 $timeout = $cmd->{arguments}->{timeout};
4443 delete $cmd->{arguments}->{timeout};
4447 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4448 my $sname = qmp_socket($vmid);
4449 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4450 my $qmpclient = PVE::QMPClient->new();
4452 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4453 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4454 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4455 if scalar(%{$cmd->{arguments}});
4456 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4458 die "unable to
open monitor
socket\n";
4462 syslog("err
", "VM
$vmid qmp command failed
- $err");
4469 sub vm_human_monitor_command {
4470 my ($vmid, $cmdline) = @_;
4475 execute => 'human-monitor-command',
4476 arguments => { 'command-line' => $cmdline},
4479 return vm_qmp_command($vmid, $cmd);
4482 sub vm_commandline {
4483 my ($storecfg, $vmid) = @_;
4485 my $conf = PVE::QemuConfig->load_config($vmid);
4487 my $defaults = load_defaults();
4489 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4491 return join(' ', @$cmd);
4495 my ($vmid, $skiplock) = @_;
4497 PVE::QemuConfig->lock_config($vmid, sub {
4499 my $conf = PVE::QemuConfig->load_config($vmid);
4501 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4503 vm_mon_cmd($vmid, "system_reset
");
4507 sub get_vm_volumes {
4511 foreach_volid($conf, sub {
4512 my ($volid, $is_cdrom) = @_;
4514 return if $volid =~ m|^/|;
4516 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4519 push @$vollist, $volid;
4525 sub vm_stop_cleanup {
4526 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4531 my $vollist = get_vm_volumes($conf);
4532 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4535 foreach my $ext (qw(mon qmp pid vnc qga)) {
4536 unlink "/var/run/qemu-server/${vmid}.$ext";
4539 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4541 warn $@ if $@; # avoid errors - just warn
4544 # Note: use $nockeck to skip tests if VM configuration file exists.
4545 # We need that when migration VMs to other nodes (files already moved)
4546 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4548 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4550 $force = 1 if !defined($force) && !$shutdown;
4553 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4554 kill 15, $pid if $pid;
4555 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4556 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4560 PVE
::QemuConfig-
>lock_config($vmid, sub {
4562 my $pid = check_running
($vmid, $nocheck);
4567 $conf = PVE
::QemuConfig-
>load_config($vmid);
4568 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4569 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4570 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4571 $timeout = $opts->{down
} if $opts->{down
};
4575 $timeout = 60 if !defined($timeout);
4579 if (defined($conf) && $conf->{agent
}) {
4580 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4582 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4585 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4592 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4597 if ($count >= $timeout) {
4599 warn "VM still running - terminating now with SIGTERM\n";
4602 die "VM quit/powerdown failed - got timeout\n";
4605 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4610 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4613 die "VM quit/powerdown failed\n";
4621 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4626 if ($count >= $timeout) {
4627 warn "VM still running - terminating now with SIGKILL\n";
4632 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4637 my ($vmid, $skiplock) = @_;
4639 PVE
::QemuConfig-
>lock_config($vmid, sub {
4641 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4643 PVE
::QemuConfig-
>check_lock($conf)
4644 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4646 vm_mon_cmd
($vmid, "stop");
4651 my ($vmid, $skiplock, $nocheck) = @_;
4653 PVE
::QemuConfig-
>lock_config($vmid, sub {
4657 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4659 PVE
::QemuConfig-
>check_lock($conf)
4660 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4662 vm_mon_cmd
($vmid, "cont");
4665 vm_mon_cmd_nocheck
($vmid, "cont");
4671 my ($vmid, $skiplock, $key) = @_;
4673 PVE
::QemuConfig-
>lock_config($vmid, sub {
4675 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4677 # there is no qmp command, so we use the human monitor command
4678 vm_human_monitor_command
($vmid, "sendkey $key");
4683 my ($storecfg, $vmid, $skiplock) = @_;
4685 PVE
::QemuConfig-
>lock_config($vmid, sub {
4687 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4689 if (!check_running
($vmid)) {
4690 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4692 die "VM $vmid is running - destroy failed\n";
4700 my ($filename, $buf) = @_;
4702 my $fh = IO
::File-
>new($filename, "w");
4703 return undef if !$fh;
4705 my $res = print $fh $buf;
4712 sub pci_device_info
{
4717 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4718 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4720 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4721 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4723 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4724 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4726 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4727 return undef if !defined($product) || $product !~ s/^0x//;
4732 product
=> $product,
4738 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4747 my $name = $dev->{name
};
4749 my $fn = "$pcisysfs/devices/$name/reset";
4751 return file_write
($fn, "1");
4754 sub pci_dev_bind_to_vfio
{
4757 my $name = $dev->{name
};
4759 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4761 if (!-d
$vfio_basedir) {
4762 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4764 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4766 my $testdir = "$vfio_basedir/$name";
4767 return 1 if -d
$testdir;
4769 my $data = "$dev->{vendor} $dev->{product}";
4770 return undef if !file_write
("$vfio_basedir/new_id", $data);
4772 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4773 if (!file_write
($fn, $name)) {
4774 return undef if -f
$fn;
4777 $fn = "$vfio_basedir/bind";
4778 if (! -d
$testdir) {
4779 return undef if !file_write
($fn, $name);
4785 sub pci_dev_group_bind_to_vfio
{
4788 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4790 if (!-d
$vfio_basedir) {
4791 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4793 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4795 # get IOMMU group devices
4796 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4797 my @devs = grep /^0000:/, readdir($D);
4800 foreach my $pciid (@devs) {
4801 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4803 # pci bridges, switches or root ports are not supported
4804 # they have a pci_bus subdirectory so skip them
4805 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4807 my $info = pci_device_info
($1);
4808 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4814 sub print_pci_addr
{
4815 my ($id, $bridges) = @_;
4819 piix3
=> { bus
=> 0, addr
=> 1 },
4820 #addr2 : first videocard
4821 balloon0
=> { bus
=> 0, addr
=> 3 },
4822 watchdog
=> { bus
=> 0, addr
=> 4 },
4823 scsihw0
=> { bus
=> 0, addr
=> 5 },
4824 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4825 scsihw1
=> { bus
=> 0, addr
=> 6 },
4826 ahci0
=> { bus
=> 0, addr
=> 7 },
4827 qga0
=> { bus
=> 0, addr
=> 8 },
4828 spice
=> { bus
=> 0, addr
=> 9 },
4829 virtio0
=> { bus
=> 0, addr
=> 10 },
4830 virtio1
=> { bus
=> 0, addr
=> 11 },
4831 virtio2
=> { bus
=> 0, addr
=> 12 },
4832 virtio3
=> { bus
=> 0, addr
=> 13 },
4833 virtio4
=> { bus
=> 0, addr
=> 14 },
4834 virtio5
=> { bus
=> 0, addr
=> 15 },
4835 hostpci0
=> { bus
=> 0, addr
=> 16 },
4836 hostpci1
=> { bus
=> 0, addr
=> 17 },
4837 net0
=> { bus
=> 0, addr
=> 18 },
4838 net1
=> { bus
=> 0, addr
=> 19 },
4839 net2
=> { bus
=> 0, addr
=> 20 },
4840 net3
=> { bus
=> 0, addr
=> 21 },
4841 net4
=> { bus
=> 0, addr
=> 22 },
4842 net5
=> { bus
=> 0, addr
=> 23 },
4843 vga1
=> { bus
=> 0, addr
=> 24 },
4844 vga2
=> { bus
=> 0, addr
=> 25 },
4845 vga3
=> { bus
=> 0, addr
=> 26 },
4846 hostpci2
=> { bus
=> 0, addr
=> 27 },
4847 hostpci3
=> { bus
=> 0, addr
=> 28 },
4848 #addr29 : usb-host (pve-usb.cfg)
4849 'pci.1' => { bus
=> 0, addr
=> 30 },
4850 'pci.2' => { bus
=> 0, addr
=> 31 },
4851 'net6' => { bus
=> 1, addr
=> 1 },
4852 'net7' => { bus
=> 1, addr
=> 2 },
4853 'net8' => { bus
=> 1, addr
=> 3 },
4854 'net9' => { bus
=> 1, addr
=> 4 },
4855 'net10' => { bus
=> 1, addr
=> 5 },
4856 'net11' => { bus
=> 1, addr
=> 6 },
4857 'net12' => { bus
=> 1, addr
=> 7 },
4858 'net13' => { bus
=> 1, addr
=> 8 },
4859 'net14' => { bus
=> 1, addr
=> 9 },
4860 'net15' => { bus
=> 1, addr
=> 10 },
4861 'net16' => { bus
=> 1, addr
=> 11 },
4862 'net17' => { bus
=> 1, addr
=> 12 },
4863 'net18' => { bus
=> 1, addr
=> 13 },
4864 'net19' => { bus
=> 1, addr
=> 14 },
4865 'net20' => { bus
=> 1, addr
=> 15 },
4866 'net21' => { bus
=> 1, addr
=> 16 },
4867 'net22' => { bus
=> 1, addr
=> 17 },
4868 'net23' => { bus
=> 1, addr
=> 18 },
4869 'net24' => { bus
=> 1, addr
=> 19 },
4870 'net25' => { bus
=> 1, addr
=> 20 },
4871 'net26' => { bus
=> 1, addr
=> 21 },
4872 'net27' => { bus
=> 1, addr
=> 22 },
4873 'net28' => { bus
=> 1, addr
=> 23 },
4874 'net29' => { bus
=> 1, addr
=> 24 },
4875 'net30' => { bus
=> 1, addr
=> 25 },
4876 'net31' => { bus
=> 1, addr
=> 26 },
4877 'xhci' => { bus
=> 1, addr
=> 27 },
4878 'virtio6' => { bus
=> 2, addr
=> 1 },
4879 'virtio7' => { bus
=> 2, addr
=> 2 },
4880 'virtio8' => { bus
=> 2, addr
=> 3 },
4881 'virtio9' => { bus
=> 2, addr
=> 4 },
4882 'virtio10' => { bus
=> 2, addr
=> 5 },
4883 'virtio11' => { bus
=> 2, addr
=> 6 },
4884 'virtio12' => { bus
=> 2, addr
=> 7 },
4885 'virtio13' => { bus
=> 2, addr
=> 8 },
4886 'virtio14' => { bus
=> 2, addr
=> 9 },
4887 'virtio15' => { bus
=> 2, addr
=> 10 },
4888 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4889 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4890 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4891 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4892 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4893 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4894 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4895 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4896 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4897 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4898 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4899 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4900 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4901 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4902 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4903 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4904 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4905 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4906 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4907 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4908 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4909 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4910 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4911 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4912 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4913 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4914 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4915 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4916 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4917 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4918 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4922 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4923 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4924 my $bus = $devices->{$id}->{bus
};
4925 $res = ",bus=pci.$bus,addr=$addr";
4926 $bridges->{$bus} = 1 if $bridges;
4932 sub print_pcie_addr
{
4937 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4938 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4939 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4940 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4943 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4944 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4945 my $bus = $devices->{$id}->{bus
};
4946 $res = ",bus=$bus,addr=$addr";
4952 # vzdump restore implementaion
4954 sub tar_archive_read_firstfile
{
4955 my $archive = shift;
4957 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4959 # try to detect archive type first
4960 my $pid = open (TMP
, "tar tf '$archive'|") ||
4961 die "unable to open file '$archive'\n";
4962 my $firstfile = <TMP
>;
4966 die "ERROR: archive contaions no data\n" if !$firstfile;
4972 sub tar_restore_cleanup
{
4973 my ($storecfg, $statfile) = @_;
4975 print STDERR
"starting cleanup\n";
4977 if (my $fd = IO
::File-
>new($statfile, "r")) {
4978 while (defined(my $line = <$fd>)) {
4979 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4982 if ($volid =~ m
|^/|) {
4983 unlink $volid || die 'unlink failed\n';
4985 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4987 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4989 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4991 print STDERR
"unable to parse line in statfile - $line";
4998 sub restore_archive
{
4999 my ($archive, $vmid, $user, $opts) = @_;
5001 my $format = $opts->{format
};
5004 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5005 $format = 'tar' if !$format;
5007 } elsif ($archive =~ m/\.tar$/) {
5008 $format = 'tar' if !$format;
5009 } elsif ($archive =~ m/.tar.lzo$/) {
5010 $format = 'tar' if !$format;
5012 } elsif ($archive =~ m/\.vma$/) {
5013 $format = 'vma' if !$format;
5014 } elsif ($archive =~ m/\.vma\.gz$/) {
5015 $format = 'vma' if !$format;
5017 } elsif ($archive =~ m/\.vma\.lzo$/) {
5018 $format = 'vma' if !$format;
5021 $format = 'vma' if !$format; # default
5024 # try to detect archive format
5025 if ($format eq 'tar') {
5026 return restore_tar_archive
($archive, $vmid, $user, $opts);
5028 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5032 sub restore_update_config_line
{
5033 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5035 return if $line =~ m/^\#qmdump\#/;
5036 return if $line =~ m/^\#vzdump\#/;
5037 return if $line =~ m/^lock:/;
5038 return if $line =~ m/^unused\d+:/;
5039 return if $line =~ m/^parent:/;
5040 return if $line =~ m/^template:/; # restored VM is never a template
5042 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5043 # try to convert old 1.X settings
5044 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5045 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5046 my ($model, $macaddr) = split(/\=/, $devconfig);
5047 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5050 bridge
=> "vmbr$ind",
5051 macaddr
=> $macaddr,
5053 my $netstr = print_net
($net);
5055 print $outfd "net$cookie->{netcount}: $netstr\n";
5056 $cookie->{netcount
}++;
5058 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5059 my ($id, $netstr) = ($1, $2);
5060 my $net = parse_net
($netstr);
5061 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5062 $netstr = print_net
($net);
5063 print $outfd "$id: $netstr\n";
5064 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5067 my $di = parse_drive
($virtdev, $value);
5068 if (defined($di->{backup
}) && !$di->{backup
}) {
5069 print $outfd "#$line";
5070 } elsif ($map->{$virtdev}) {
5071 delete $di->{format
}; # format can change on restore
5072 $di->{file
} = $map->{$virtdev};
5073 $value = print_drive
($vmid, $di);
5074 print $outfd "$virtdev: $value\n";
5084 my ($cfg, $vmid) = @_;
5086 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5088 my $volid_hash = {};
5089 foreach my $storeid (keys %$info) {
5090 foreach my $item (@{$info->{$storeid}}) {
5091 next if !($item->{volid
} && $item->{size
});
5092 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5093 $volid_hash->{$item->{volid
}} = $item;
5100 sub is_volume_in_use
{
5101 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5103 my $path = PVE
::Storage
::path
($storecfg, $volid);
5105 my $scan_config = sub {
5106 my ($cref, $snapname) = @_;
5108 foreach my $key (keys %$cref) {
5109 my $value = $cref->{$key};
5110 if (is_valid_drivename
($key)) {
5111 next if $skip_drive && $key eq $skip_drive;
5112 my $drive = parse_drive
($key, $value);
5113 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5114 return 1 if $volid eq $drive->{file
};
5115 if ($drive->{file
} =~ m!^/!) {
5116 return 1 if $drive->{file
} eq $path;
5118 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5120 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5122 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5130 return 1 if &$scan_config($conf);
5134 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5135 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5141 sub update_disksize
{
5142 my ($vmid, $conf, $volid_hash) = @_;
5148 # Note: it is allowed to define multiple storages with same path (alias), so
5149 # we need to check both 'volid' and real 'path' (two different volid can point
5150 # to the same path).
5155 foreach my $opt (keys %$conf) {
5156 if (is_valid_drivename
($opt)) {
5157 my $drive = parse_drive
($opt, $conf->{$opt});
5158 my $volid = $drive->{file
};
5161 $used->{$volid} = 1;
5162 if ($volid_hash->{$volid} &&
5163 (my $path = $volid_hash->{$volid}->{path
})) {
5164 $usedpath->{$path} = 1;
5167 next if drive_is_cdrom
($drive);
5168 next if !$volid_hash->{$volid};
5170 $drive->{size
} = $volid_hash->{$volid}->{size
};
5171 my $new = print_drive
($vmid, $drive);
5172 if ($new ne $conf->{$opt}) {
5174 $conf->{$opt} = $new;
5179 # remove 'unusedX' entry if volume is used
5180 foreach my $opt (keys %$conf) {
5181 next if $opt !~ m/^unused\d+$/;
5182 my $volid = $conf->{$opt};
5183 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5184 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5186 delete $conf->{$opt};
5190 foreach my $volid (sort keys %$volid_hash) {
5191 next if $volid =~ m/vm-$vmid-state-/;
5192 next if $used->{$volid};
5193 my $path = $volid_hash->{$volid}->{path
};
5194 next if !$path; # just to be sure
5195 next if $usedpath->{$path};
5197 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5198 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5205 my ($vmid, $nolock) = @_;
5207 my $cfg = PVE
::Storage
::config
();
5209 my $volid_hash = scan_volids
($cfg, $vmid);
5211 my $updatefn = sub {
5214 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5216 PVE
::QemuConfig-
>check_lock($conf);
5219 foreach my $volid (keys %$volid_hash) {
5220 my $info = $volid_hash->{$volid};
5221 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5224 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5226 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5229 if (defined($vmid)) {
5233 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5236 my $vmlist = config_list
();
5237 foreach my $vmid (keys %$vmlist) {
5241 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5247 sub restore_vma_archive
{
5248 my ($archive, $vmid, $user, $opts, $comp) = @_;
5250 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5251 my $readfrom = $archive;
5256 my $qarchive = PVE
::Tools
::shellquote
($archive);
5257 if ($comp eq 'gzip') {
5258 $uncomp = "zcat $qarchive|";
5259 } elsif ($comp eq 'lzop') {
5260 $uncomp = "lzop -d -c $qarchive|";
5262 die "unknown compression method '$comp'\n";
5267 my $tmpdir = "/var/tmp/vzdumptmp$$";
5270 # disable interrupts (always do cleanups)
5271 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5272 warn "got interrupt - ignored\n";
5275 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5276 POSIX
::mkfifo
($mapfifo, 0600);
5279 my $openfifo = sub {
5280 open($fifofh, '>', $mapfifo) || die $!;
5283 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5290 my $rpcenv = PVE
::RPCEnvironment
::get
();
5292 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5293 my $tmpfn = "$conffile.$$.tmp";
5295 # Note: $oldconf is undef if VM does not exists
5296 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5297 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5299 my $print_devmap = sub {
5300 my $virtdev_hash = {};
5302 my $cfgfn = "$tmpdir/qemu-server.conf";
5304 # we can read the config - that is already extracted
5305 my $fh = IO
::File-
>new($cfgfn, "r") ||
5306 "unable to read qemu-server.conf - $!\n";
5308 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5310 my $pve_firewall_dir = '/etc/pve/firewall';
5311 mkdir $pve_firewall_dir; # make sure the dir exists
5312 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5315 while (defined(my $line = <$fh>)) {
5316 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5317 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5318 die "archive does not contain data for drive '$virtdev'\n"
5319 if !$devinfo->{$devname};
5320 if (defined($opts->{storage
})) {
5321 $storeid = $opts->{storage
} || 'local';
5322 } elsif (!$storeid) {
5325 $format = 'raw' if !$format;
5326 $devinfo->{$devname}->{devname
} = $devname;
5327 $devinfo->{$devname}->{virtdev
} = $virtdev;
5328 $devinfo->{$devname}->{format
} = $format;
5329 $devinfo->{$devname}->{storeid
} = $storeid;
5331 # check permission on storage
5332 my $pool = $opts->{pool
}; # todo: do we need that?
5333 if ($user ne 'root@pam') {
5334 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5337 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5341 foreach my $devname (keys %$devinfo) {
5342 die "found no device mapping information for device '$devname'\n"
5343 if !$devinfo->{$devname}->{virtdev
};
5346 my $cfg = PVE
::Storage
::config
();
5348 # create empty/temp config
5350 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5351 foreach_drive
($oldconf, sub {
5352 my ($ds, $drive) = @_;
5354 return if drive_is_cdrom
($drive);
5356 my $volid = $drive->{file
};
5358 return if !$volid || $volid =~ m
|^/|;
5360 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5361 return if !$path || !$owner || ($owner != $vmid);
5363 # Note: only delete disk we want to restore
5364 # other volumes will become unused
5365 if ($virtdev_hash->{$ds}) {
5366 PVE
::Storage
::vdisk_free
($cfg, $volid);
5370 # delete vmstate files
5371 # since after the restore we have no snapshots anymore
5372 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5373 my $snap = $oldconf->{snapshots
}->{$snapname};
5374 if ($snap->{vmstate
}) {
5375 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5384 foreach my $virtdev (sort keys %$virtdev_hash) {
5385 my $d = $virtdev_hash->{$virtdev};
5386 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5387 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5389 # test if requested format is supported
5390 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5391 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5392 $d->{format
} = $defFormat if !$supported;
5394 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5395 $d->{format
}, undef, $alloc_size);
5396 print STDERR
"new volume ID is '$volid'\n";
5397 $d->{volid
} = $volid;
5398 my $path = PVE
::Storage
::path
($cfg, $volid);
5400 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5402 my $write_zeros = 1;
5403 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5407 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5409 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5410 $map->{$virtdev} = $volid;
5413 $fh->seek(0, 0) || die "seek failed - $!\n";
5415 my $outfd = new IO
::File
($tmpfn, "w") ||
5416 die "unable to write config for VM $vmid\n";
5418 my $cookie = { netcount
=> 0 };
5419 while (defined(my $line = <$fh>)) {
5420 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5429 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5430 die "interrupted by signal\n";
5432 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5434 $oldtimeout = alarm($timeout);
5441 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5442 my ($dev_id, $size, $devname) = ($1, $2, $3);
5443 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5444 } elsif ($line =~ m/^CTIME: /) {
5445 # we correctly received the vma config, so we can disable
5446 # the timeout now for disk allocation (set to 10 minutes, so
5447 # that we always timeout if something goes wrong)
5450 print $fifofh "done\n";
5451 my $tmp = $oldtimeout || 0;
5452 $oldtimeout = undef;
5458 print "restore vma archive: $cmd\n";
5459 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5463 alarm($oldtimeout) if $oldtimeout;
5466 foreach my $devname (keys %$devinfo) {
5467 my $volid = $devinfo->{$devname}->{volid
};
5468 push @$vollist, $volid if $volid;
5471 my $cfg = PVE
::Storage
::config
();
5472 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5480 foreach my $devname (keys %$devinfo) {
5481 my $volid = $devinfo->{$devname}->{volid
};
5484 if ($volid =~ m
|^/|) {
5485 unlink $volid || die 'unlink failed\n';
5487 PVE
::Storage
::vdisk_free
($cfg, $volid);
5489 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5491 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5498 rename($tmpfn, $conffile) ||
5499 die "unable to commit configuration file '$conffile'\n";
5501 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5503 eval { rescan
($vmid, 1); };
5507 sub restore_tar_archive
{
5508 my ($archive, $vmid, $user, $opts) = @_;
5510 if ($archive ne '-') {
5511 my $firstfile = tar_archive_read_firstfile
($archive);
5512 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5513 if $firstfile ne 'qemu-server.conf';
5516 my $storecfg = PVE
::Storage
::config
();
5518 # destroy existing data - keep empty config
5519 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5520 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5522 my $tocmd = "/usr/lib/qemu-server/qmextract";
5524 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5525 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5526 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5527 $tocmd .= ' --info' if $opts->{info
};
5529 # tar option "xf" does not autodetect compression when read from STDIN,
5530 # so we pipe to zcat
5531 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5532 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5534 my $tmpdir = "/var/tmp/vzdumptmp$$";
5537 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5538 local $ENV{VZDUMP_VMID
} = $vmid;
5539 local $ENV{VZDUMP_USER
} = $user;
5541 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5542 my $tmpfn = "$conffile.$$.tmp";
5544 # disable interrupts (always do cleanups)
5545 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5546 print STDERR
"got interrupt - ignored\n";
5551 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5552 die "interrupted by signal\n";
5555 if ($archive eq '-') {
5556 print "extracting archive from STDIN\n";
5557 run_command
($cmd, input
=> "<&STDIN");
5559 print "extracting archive '$archive'\n";
5563 return if $opts->{info
};
5567 my $statfile = "$tmpdir/qmrestore.stat";
5568 if (my $fd = IO
::File-
>new($statfile, "r")) {
5569 while (defined (my $line = <$fd>)) {
5570 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5571 $map->{$1} = $2 if $1;
5573 print STDERR
"unable to parse line in statfile - $line\n";
5579 my $confsrc = "$tmpdir/qemu-server.conf";
5581 my $srcfd = new IO
::File
($confsrc, "r") ||
5582 die "unable to open file '$confsrc'\n";
5584 my $outfd = new IO
::File
($tmpfn, "w") ||
5585 die "unable to write config for VM $vmid\n";
5587 my $cookie = { netcount
=> 0 };
5588 while (defined (my $line = <$srcfd>)) {
5589 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5601 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5608 rename $tmpfn, $conffile ||
5609 die "unable to commit configuration file '$conffile'\n";
5611 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5613 eval { rescan
($vmid, 1); };
5617 sub foreach_writable_storage
{
5618 my ($conf, $func) = @_;
5622 foreach my $ds (keys %$conf) {
5623 next if !is_valid_drivename
($ds);
5625 my $drive = parse_drive
($ds, $conf->{$ds});
5627 next if drive_is_cdrom
($drive);
5629 my $volid = $drive->{file
};
5631 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5632 $sidhash->{$sid} = $sid if $sid;
5635 foreach my $sid (sort keys %$sidhash) {
5640 sub do_snapshots_with_qemu
{
5641 my ($storecfg, $volid) = @_;
5643 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5645 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5646 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5650 if ($volid =~ m/\.(qcow2|qed)$/){
5657 sub qga_check_running
{
5660 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5662 warn "Qemu Guest Agent are not running - $@";
5668 sub template_create
{
5669 my ($vmid, $conf, $disk) = @_;
5671 my $storecfg = PVE
::Storage
::config
();
5673 foreach_drive
($conf, sub {
5674 my ($ds, $drive) = @_;
5676 return if drive_is_cdrom
($drive);
5677 return if $disk && $ds ne $disk;
5679 my $volid = $drive->{file
};
5680 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5682 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5683 $drive->{file
} = $voliddst;
5684 $conf->{$ds} = print_drive
($vmid, $drive);
5685 PVE
::QemuConfig-
>write_config($vmid, $conf);
5689 sub qemu_img_convert
{
5690 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5692 my $storecfg = PVE
::Storage
::config
();
5693 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5694 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5696 if ($src_storeid && $dst_storeid) {
5698 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5700 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5701 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5703 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5704 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5706 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5707 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5710 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5711 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5712 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5713 if ($is_zero_initialized) {
5714 push @$cmd, "zeroinit:$dst_path";
5716 push @$cmd, $dst_path;
5721 if($line =~ m/\((\S+)\/100\
%\)/){
5723 my $transferred = int($size * $percent / 100);
5724 my $remaining = $size - $transferred;
5726 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5731 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5733 die "copy failed: $err" if $err;
5737 sub qemu_img_format
{
5738 my ($scfg, $volname) = @_;
5740 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5747 sub qemu_drive_mirror
{
5748 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5750 my $storecfg = PVE
::Storage
::config
();
5751 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5753 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5755 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5757 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5759 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5761 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5762 $opts->{format
} = $format if $format;
5764 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5766 my $finish_job = sub {
5768 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5769 my $stat = @$stats[0];
5776 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5778 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5779 my $stat = @$stats[0];
5780 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5781 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5783 my $busy = $stat->{busy
};
5784 my $ready = $stat->{ready
};
5786 if (my $total = $stat->{len
}) {
5787 my $transferred = $stat->{offset
} || 0;
5788 my $remaining = $total - $transferred;
5789 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5791 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5795 if ($stat->{ready
} eq 'true') {
5797 last if $vmiddst != $vmid;
5799 # try to switch the disk if source and destination are on the same guest
5800 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5805 die $@ if $@ !~ m/cannot be completed/;
5814 my $cancel_job = sub {
5815 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5820 eval { &$cancel_job(); };
5821 die "mirroring error: $err";
5824 if ($vmiddst != $vmid) {
5825 # if we clone a disk for a new target vm, we don't switch the disk
5826 &$cancel_job(); # so we call block-job-cancel
5831 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5832 $newvmid, $storage, $format, $full, $newvollist) = @_;
5837 print "create linked clone of drive $drivename ($drive->{file})\n";
5838 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5839 push @$newvollist, $newvolid;
5841 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5842 $storeid = $storage if $storage;
5844 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5846 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5847 $format = qemu_img_format
($scfg, $volname);
5850 # test if requested format is supported - else use default
5851 my $supported = grep { $_ eq $format } @$validFormats;
5852 $format = $defFormat if !$supported;
5854 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5856 print "create full clone of drive $drivename ($drive->{file})\n";
5857 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5858 push @$newvollist, $newvolid;
5860 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5862 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5863 if (!$running || $snapname) {
5864 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5866 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5870 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5873 $disk->{format
} = undef;
5874 $disk->{file
} = $newvolid;
5875 $disk->{size
} = $size;
5880 # this only works if VM is running
5881 sub get_current_qemu_machine
{
5884 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5885 my $res = vm_qmp_command
($vmid, $cmd);
5887 my ($current, $default);
5888 foreach my $e (@$res) {
5889 $default = $e->{name
} if $e->{'is-default'};
5890 $current = $e->{name
} if $e->{'is-current'};
5893 # fallback to the default machine if current is not supported by qemu
5894 return $current || $default || 'pc';
5897 sub qemu_machine_feature_enabled
{
5898 my ($machine, $kvmver, $version_major, $version_minor) = @_;
5903 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
5905 $current_major = $3;
5906 $current_minor = $4;
5908 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
5910 $current_major = $1;
5911 $current_minor = $2;
5914 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
5919 sub qemu_machine_pxe
{
5920 my ($vmid, $conf, $machine) = @_;
5922 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
5924 foreach my $opt (keys %$conf) {
5925 next if $opt !~ m/^net(\d+)$/;
5926 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
5928 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
5929 return $machine.".pxe" if $romfile =~ m/pxe/;
5936 sub qemu_use_old_bios_files
{
5937 my ($machine_type) = @_;
5939 return if !$machine_type;
5941 my $use_old_bios_files = undef;
5943 if ($machine_type =~ m/^(\S+)\.pxe$/) {
5945 $use_old_bios_files = 1;
5947 my $kvmver = kvm_user_version
();
5948 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
5949 # load new efi bios files on migration. So this hack is required to allow
5950 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
5951 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
5952 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
5955 return ($use_old_bios_files, $machine_type);
5962 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
5963 my (undef, $id, $function) = @_;
5964 my $res = { id
=> $id, function
=> $function};
5965 push @{$devices->{$id}}, $res;
5971 sub vm_iothreads_list
{
5974 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
5977 foreach my $iothread (@$res) {
5978 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
5985 my ($conf, $drive) = @_;
5989 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
5991 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
5997 my $controller = int($drive->{index} / $maxdev);
5998 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6000 return ($maxdev, $controller, $controller_prefix);
6003 # bash completion helper
6005 sub complete_backup_archives
{
6006 my ($cmdname, $pname, $cvalue) = @_;
6008 my $cfg = PVE
::Storage
::config
();
6012 if ($cvalue =~ m/^([^:]+):/) {
6016 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6019 foreach my $id (keys %$data) {
6020 foreach my $item (@{$data->{$id}}) {
6021 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6022 push @$res, $item->{volid
} if defined($item->{volid
});
6029 my $complete_vmid_full = sub {
6032 my $idlist = vmstatus
();
6036 foreach my $id (keys %$idlist) {
6037 my $d = $idlist->{$id};
6038 if (defined($running)) {
6039 next if $d->{template
};
6040 next if $running && $d->{status
} ne 'running';
6041 next if !$running && $d->{status
} eq 'running';
6050 return &$complete_vmid_full();
6053 sub complete_vmid_stopped
{
6054 return &$complete_vmid_full(0);
6057 sub complete_vmid_running
{
6058 return &$complete_vmid_full(1);
6061 sub complete_storage
{
6063 my $cfg = PVE
::Storage
::config
();
6064 my $ids = $cfg->{ids
};
6067 foreach my $sid (keys %$ids) {
6068 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6069 next if !$ids->{$sid}->{content
}->{images
};