1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
32 use PVE
::RPCEnvironment
;
33 use PVE
::QemuServer
::PCI
qw(print_pci_addr print_pcie_addr);
34 use PVE
::QemuServer
::Memory
;
35 use PVE
::QemuServer
::USB
qw(parse_usb_device);
36 use Time
::HiRes
qw(gettimeofday);
37 use File
::Copy
qw(copy);
40 my $OVMF_CODE = '/usr/share/kvm/OVMF_CODE-pure-efi.fd';
41 my $OVMF_VARS = '/usr/share/kvm/OVMF_VARS-pure-efi.fd';
43 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
45 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
47 # Note about locking: we use flock on the config file protect
48 # against concurent actions.
49 # Aditionaly, we have a 'lock' setting in the config file. This
50 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
51 # allowed when such lock is set. But you can ignore this kind of
52 # lock with the --skiplock flag.
54 cfs_register_file
('/qemu-server/',
58 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
59 description
=> "Some command save/restore state from this location.",
65 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
66 description
=> "The name of the snapshot.",
67 type
=> 'string', format
=> 'pve-configid',
71 PVE
::JSONSchema
::register_standard_option
('pve-qm-image-format', {
73 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
74 description
=> "The drive's backing file's data format.",
78 #no warnings 'redefine';
81 my ($controller, $vmid, $option, $value) = @_;
83 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
84 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
88 my $nodename = PVE
::INotify
::nodename
();
90 mkdir "/etc/pve/nodes/$nodename";
91 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
94 my $var_run_tmpdir = "/var/run/qemu-server";
95 mkdir $var_run_tmpdir;
97 my $lock_dir = "/var/lock/qemu-server";
100 my $pcisysfs = "/sys/bus/pci";
102 my $cpu_vendor_list = {
104 486 => 'GenuineIntel',
105 pentium
=> 'GenuineIntel',
106 pentium2
=> 'GenuineIntel',
107 pentium3
=> 'GenuineIntel',
108 coreduo
=> 'GenuineIntel',
109 core2duo
=> 'GenuineIntel',
110 Conroe
=> 'GenuineIntel',
111 Penryn
=> 'GenuineIntel',
112 Nehalem
=> 'GenuineIntel',
113 Westmere
=> 'GenuineIntel',
114 SandyBridge
=> 'GenuineIntel',
115 IvyBridge
=> 'GenuineIntel',
116 Haswell
=> 'GenuineIntel',
117 'Haswell-noTSX' => 'GenuineIntel',
118 Broadwell
=> 'GenuineIntel',
119 'Broadwell-noTSX' => 'GenuineIntel',
120 'Skylake-Client' => 'GenuineIntel',
123 athlon
=> 'AuthenticAMD',
124 phenom
=> 'AuthenticAMD',
125 Opteron_G1
=> 'AuthenticAMD',
126 Opteron_G2
=> 'AuthenticAMD',
127 Opteron_G3
=> 'AuthenticAMD',
128 Opteron_G4
=> 'AuthenticAMD',
129 Opteron_G5
=> 'AuthenticAMD',
131 # generic types, use vendor from host node
141 description
=> "Emulated CPU type.",
143 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
148 description
=> "Do not identify as a KVM virtual machine.",
159 enum
=> [qw(i6300esb ib700)],
160 description
=> "Watchdog type to emulate.",
161 default => 'i6300esb',
166 enum
=> [qw(reset shutdown poweroff pause debug none)],
167 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
171 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
177 description
=> "Specifies whether a VM will be started during system bootup.",
183 description
=> "Automatic restart after crash (currently ignored).",
188 type
=> 'string', format
=> 'pve-hotplug-features',
189 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'.",
190 default => 'network,disk,usb',
195 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
201 description
=> "Lock/unlock the VM.",
202 enum
=> [qw(migrate backup snapshot rollback)],
207 description
=> "Limit of CPU usage.",
208 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.",
216 description
=> "CPU weight for a VM.",
217 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.",
225 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
232 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
238 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",
246 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.".
247 "It should not be necessary to set it.",
248 enum
=> PVE
::Tools
::kvmkeymaplist
(),
253 type
=> 'string', format
=> 'dns-name',
254 description
=> "Set a name for the VM. Only used on the configuration web interface.",
259 description
=> "SCSI controller model",
260 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
266 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
271 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 win10 l24 l26 solaris)],
272 description
=> "Specify guest operating system.",
273 verbose_description
=> <<EODESC,
274 Specify guest operating system. This is used to enable special
275 optimization/features for specific operating systems:
278 other;; unspecified OS
279 wxp;; Microsoft Windows XP
280 w2k;; Microsoft Windows 2000
281 w2k3;; Microsoft Windows 2003
282 w2k8;; Microsoft Windows 2008
283 wvista;; Microsoft Windows Vista
284 win7;; Microsoft Windows 7
285 win8;; Microsoft Windows 8/2012/2012r2
286 win10;; Microsoft Windows 10/2016
287 l24;; Linux 2.4 Kernel
288 l26;; Linux 2.6/3.X Kernel
289 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
295 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
296 pattern
=> '[acdn]{1,4}',
301 type
=> 'string', format
=> 'pve-qm-bootdisk',
302 description
=> "Enable booting from specified disk.",
303 pattern
=> '(ide|sata|scsi|virtio)\d+',
308 description
=> "The number of CPUs. Please use option -sockets instead.",
315 description
=> "The number of CPU sockets.",
322 description
=> "The number of cores per socket.",
329 description
=> "Enable/disable NUMA.",
335 description
=> "Enable/disable hugepages memory.",
336 enum
=> [qw(any 2 1024)],
341 description
=> "Number of hotplugged vcpus.",
348 description
=> "Enable/disable ACPI.",
354 description
=> "Enable/disable Qemu GuestAgent.",
360 description
=> "Enable/disable KVM hardware virtualization.",
366 description
=> "Enable/disable time drift fix.",
372 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
377 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
382 description
=> "Select the VGA type.",
383 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
384 " modes (>= 1280x1024x16) then you should use the options " .
385 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
386 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
387 "display sever. For win* OS you can select how many independent " .
388 "displays you want, Linux guests can add displays them self. " .
389 "You can also run without any graphic card, using a serial device" .
391 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
395 type
=> 'string', format
=> 'pve-qm-watchdog',
396 description
=> "Create a virtual hardware watchdog device.",
397 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
398 " (by a guest action), the watchdog must be periodically polled " .
399 "by an agent inside the guest or else the watchdog will reset " .
400 "the guest (or execute the respective action specified)",
405 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
406 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'.",
407 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
410 startup
=> get_standard_option
('pve-startup-order'),
414 description
=> "Enable/disable Template.",
420 description
=> "Arbitrary arguments passed to kvm.",
421 verbose_description
=> <<EODESCR,
422 Arbitrary arguments passed to kvm, for example:
424 args: -no-reboot -no-hpet
426 NOTE: this option is for experts only.
433 description
=> "Enable/disable the USB tablet device.",
434 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
435 "usually needed to allow absolute mouse positioning with VNC. " .
436 "Else the mouse runs out of sync with normal VNC clients. " .
437 "If you're running lots of console-only guests on one host, " .
438 "you may consider disabling this to save some context switches. " .
439 "This is turned off by default if you use spice (-vga=qxl).",
444 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
448 migrate_downtime
=> {
451 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
457 type
=> 'string', format
=> 'pve-qm-ide',
458 typetext
=> '<volume>',
459 description
=> "This is an alias for option -ide2",
463 description
=> "Emulated CPU type.",
467 parent
=> get_standard_option
('pve-snapshot-name', {
469 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
473 description
=> "Timestamp for snapshots.",
479 type
=> 'string', format
=> 'pve-volume-id',
480 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
482 vmstatestorage
=> get_standard_option
('pve-storage-id', {
483 description
=> "Default storage for VM state volumes/files.",
487 description
=> "Specific the Qemu machine type.",
489 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
494 description
=> "Specify SMBIOS type 1 fields.",
495 type
=> 'string', format
=> 'pve-qm-smbios1',
502 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
508 enum
=> [ qw(seabios ovmf) ],
509 description
=> "Select BIOS implementation.",
510 default => 'seabios',
514 # what about other qemu settings ?
516 #machine => 'string',
529 ##soundhw => 'string',
531 while (my ($k, $v) = each %$confdesc) {
532 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
535 my $MAX_IDE_DISKS = 4;
536 my $MAX_SCSI_DISKS = 14;
537 my $MAX_VIRTIO_DISKS = 16;
538 my $MAX_SATA_DISKS = 6;
539 my $MAX_USB_DEVICES = 5;
541 my $MAX_UNUSED_DISKS = 8;
542 my $MAX_HOSTPCI_DEVICES = 4;
543 my $MAX_SERIAL_PORTS = 4;
544 my $MAX_PARALLEL_PORTS = 3;
550 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
551 description
=> "CPUs accessing this NUMA node.",
552 format_description
=> "id[-id];...",
556 description
=> "Amount of memory this NUMA node provides.",
561 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
562 description
=> "Host NUMA nodes to use.",
563 format_description
=> "id[-id];...",
568 enum
=> [qw(preferred bind interleave)],
569 description
=> "NUMA allocation policy.",
573 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
576 type
=> 'string', format
=> $numa_fmt,
577 description
=> "NUMA topology.",
579 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
581 for (my $i = 0; $i < $MAX_NUMA; $i++) {
582 $confdesc->{"numa$i"} = $numadesc;
585 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
586 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
587 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
588 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
590 my $net_fmt_bridge_descr = <<__EOD__;
591 Bridge to attach the network device to. The Proxmox VE standard bridge
594 If you do not specify a bridge, we create a kvm user (NATed) network
595 device, which provides DHCP and DNS services. The following addresses
602 The DHCP server assign addresses to the guest starting from 10.0.2.15.
608 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
609 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
610 format_description
=> "XX:XX:XX:XX:XX:XX",
615 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'.",
616 enum
=> $nic_model_list,
619 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
622 description
=> $net_fmt_bridge_descr,
623 format_description
=> 'bridge',
628 minimum
=> 0, maximum
=> 16,
629 description
=> 'Number of packet queues to be used on the device.',
635 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
640 minimum
=> 1, maximum
=> 4094,
641 description
=> 'VLAN tag to apply to packets on this interface.',
646 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
647 description
=> 'VLAN trunks to pass through this interface.',
648 format_description
=> 'vlanid[;vlanid...]',
653 description
=> 'Whether this interface should be protected by the firewall.',
658 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
665 type
=> 'string', format
=> $net_fmt,
666 description
=> "Specify network devices.",
669 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
671 for (my $i = 0; $i < $MAX_NETS; $i++) {
672 $confdesc->{"net$i"} = $netdesc;
675 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
676 sub verify_volume_id_or_qm_path
{
677 my ($volid, $noerr) = @_;
679 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
683 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
684 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
686 return undef if $noerr;
694 my %drivedesc_base = (
695 volume
=> { alias
=> 'file' },
698 format
=> 'pve-volume-id-or-qm-path',
700 format_description
=> 'volume',
701 description
=> "The drive's backing volume.",
705 enum
=> [qw(cdrom disk)],
706 description
=> "The drive's media type.",
712 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
717 description
=> "Force the drive's physical geometry to have a specific head count.",
722 description
=> "Force the drive's physical geometry to have a specific sector count.",
727 enum
=> [qw(none lba auto)],
728 description
=> "Force disk geometry bios translation mode.",
733 description
=> "Whether the drive should be included when making snapshots.",
738 enum
=> [qw(none writethrough writeback unsafe directsync)],
739 description
=> "The drive's cache mode",
742 format
=> get_standard_option
('pve-qm-image-format'),
745 format
=> 'disk-size',
746 format_description
=> 'DiskSize',
747 description
=> "Disk size. This is purely informational and has no effect.",
752 description
=> "Whether the drive should be included when making backups.",
757 description
=> 'Whether the drive should considered for replication jobs.',
763 enum
=> [qw(ignore report stop)],
764 description
=> 'Read error action.',
769 enum
=> [qw(enospc ignore report stop)],
770 description
=> 'Write error action.',
775 enum
=> [qw(native threads)],
776 description
=> 'AIO type to use.',
781 enum
=> [qw(ignore on)],
782 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
787 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
792 format
=> 'urlencoded',
793 format_description
=> 'serial',
794 maxLength
=> 20*3, # *3 since it's %xx url enoded
795 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
800 my %iothread_fmt = ( iothread
=> {
802 description
=> "Whether to use iothreads for this drive",
809 format
=> 'urlencoded',
810 format_description
=> 'model',
811 maxLength
=> 40*3, # *3 since it's %xx url enoded
812 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
820 description
=> "Number of queues.",
826 my %scsiblock_fmt = (
829 description
=> "whether to use scsi-block for full passthrough of host block device\n\nWARNING: can lead to I/O errors in combination with low memory or high memory fragmentation on host",
835 my $add_throttle_desc = sub {
836 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
839 format_description
=> $unit,
840 description
=> "Maximum $what in $longunit.",
843 $d->{minimum
} = $minimum if defined($minimum);
844 $drivedesc_base{$key} = $d;
846 # throughput: (leaky bucket)
847 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
848 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
849 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
850 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
851 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
852 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
853 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
854 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
855 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
857 # pools: (pool of IO before throttling starts taking effect)
858 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
859 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
860 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
861 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
862 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
863 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
866 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
867 $add_throttle_desc->('bps_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
868 $add_throttle_desc->('bps_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
869 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
870 $add_throttle_desc->('iops_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
871 $add_throttle_desc->('iops_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
874 $drivedesc_base{'bps_rd_length'} = { alias
=> 'bps_rd_max_length' };
875 $drivedesc_base{'bps_wr_length'} = { alias
=> 'bps_wr_max_length' };
876 $drivedesc_base{'iops_rd_length'} = { alias
=> 'iops_rd_max_length' };
877 $drivedesc_base{'iops_wr_length'} = { alias
=> 'iops_wr_max_length' };
883 PVE
::JSONSchema
::register_format
("pve-qm-ide", $ide_fmt);
887 type
=> 'string', format
=> $ide_fmt,
888 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
890 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
900 type
=> 'string', format
=> $scsi_fmt,
901 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
903 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
910 type
=> 'string', format
=> $sata_fmt,
911 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
913 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
921 type
=> 'string', format
=> $virtio_fmt,
922 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
924 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
935 volume
=> { alias
=> 'file' },
938 format
=> 'pve-volume-id-or-qm-path',
940 format_description
=> 'volume',
941 description
=> "The drive's backing volume.",
943 format
=> get_standard_option
('pve-qm-image-format'),
946 format
=> 'disk-size',
947 format_description
=> 'DiskSize',
948 description
=> "Disk size. This is purely informational and has no effect.",
955 type
=> 'string', format
=> $efidisk_fmt,
956 description
=> "Configure a Disk for storing EFI vars",
959 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
964 type
=> 'string', format
=> 'pve-qm-usb-device',
965 format_description
=> 'HOSTUSBDEVICE|spice',
966 description
=> <<EODESCR,
967 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
969 'bus-port(.port)*' (decimal numbers) or
970 'vendor_id:product_id' (hexadeciaml numbers) or
973 You can use the 'lsusb -t' command to list existing usb devices.
975 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
977 The value 'spice' can be used to add a usb redirection devices for spice.
983 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).",
990 type
=> 'string', format
=> $usb_fmt,
991 description
=> "Configure an USB device (n is 0 to 4).",
993 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
995 # NOTE: the match-groups of this regex are used in parse_hostpci
996 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
1001 pattern
=> qr/$PCIRE(;$PCIRE)*/,
1002 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
1003 description
=> <<EODESCR,
1004 Host PCI device pass through. The PCI ID of a host's PCI device or a list
1005 of PCI virtual functions of the host. HOSTPCIID syntax is:
1007 'bus:dev.func' (hexadecimal numbers)
1009 You can us the 'lspci' command to list existing PCI devices.
1014 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1020 pattern
=> '[^,;]+',
1021 format_description
=> 'string',
1022 description
=> "Custom pci device rom filename (must be located in /usr/share/kvm/).",
1027 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1033 description
=> "Enable vfio-vga device support.",
1038 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1042 type
=> 'string', format
=> 'pve-qm-hostpci',
1043 description
=> "Map host PCI devices into guest.",
1044 verbose_description
=> <<EODESCR,
1045 Map host PCI devices into guest.
1047 NOTE: This option allows direct access to host hardware. So it is no longer
1048 possible to migrate such machines - use with special care.
1050 CAUTION: Experimental! User reported problems with this option.
1053 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1058 pattern
=> '(/dev/.+|socket)',
1059 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1060 verbose_description
=> <<EODESCR,
1061 Create a serial device inside the VM (n is 0 to 3), and pass through a
1062 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1063 host side (use 'qm terminal' to open a terminal connection).
1065 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1067 CAUTION: Experimental! User reported problems with this option.
1074 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1075 description
=> "Map host parallel devices (n is 0 to 2).",
1076 verbose_description
=> <<EODESCR,
1077 Map host parallel devices (n is 0 to 2).
1079 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1081 CAUTION: Experimental! User reported problems with this option.
1085 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1086 $confdesc->{"parallel$i"} = $paralleldesc;
1089 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1090 $confdesc->{"serial$i"} = $serialdesc;
1093 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1094 $confdesc->{"hostpci$i"} = $hostpcidesc;
1097 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1098 $drivename_hash->{"ide$i"} = 1;
1099 $confdesc->{"ide$i"} = $idedesc;
1102 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1103 $drivename_hash->{"sata$i"} = 1;
1104 $confdesc->{"sata$i"} = $satadesc;
1107 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1108 $drivename_hash->{"scsi$i"} = 1;
1109 $confdesc->{"scsi$i"} = $scsidesc ;
1112 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1113 $drivename_hash->{"virtio$i"} = 1;
1114 $confdesc->{"virtio$i"} = $virtiodesc;
1117 $drivename_hash->{efidisk0
} = 1;
1118 $confdesc->{efidisk0
} = $efidisk_desc;
1120 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1121 $confdesc->{"usb$i"} = $usbdesc;
1126 type
=> 'string', format
=> 'pve-volume-id',
1127 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1130 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1131 $confdesc->{"unused$i"} = $unuseddesc;
1134 my $kvm_api_version = 0;
1138 return $kvm_api_version if $kvm_api_version;
1140 my $fh = IO
::File-
>new("</dev/kvm") ||
1143 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1144 $kvm_api_version = $v;
1149 return $kvm_api_version;
1152 my $kvm_user_version;
1154 sub kvm_user_version
{
1156 return $kvm_user_version if $kvm_user_version;
1158 $kvm_user_version = 'unknown';
1162 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1163 $kvm_user_version = $2;
1167 eval { run_command
("kvm -version", outfunc
=> $code); };
1170 return $kvm_user_version;
1174 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1176 sub valid_drive_names
{
1177 # order is important - used to autoselect boot disk
1178 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1179 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1180 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1181 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1185 sub is_valid_drivename
{
1188 return defined($drivename_hash->{$dev});
1193 return defined($confdesc->{$key});
1197 return $nic_model_list;
1200 sub os_list_description
{
1204 wxp
=> 'Windows XP',
1205 w2k
=> 'Windows 2000',
1206 w2k3
=>, 'Windows 2003',
1207 w2k8
=> 'Windows 2008',
1208 wvista
=> 'Windows Vista',
1209 win7
=> 'Windows 7',
1210 win8
=> 'Windows 8/2012',
1211 win10
=> 'Windows 10/2016',
1219 sub get_cdrom_path
{
1221 return $cdrom_path if $cdrom_path;
1223 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1224 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1225 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1229 my ($storecfg, $vmid, $cdrom) = @_;
1231 if ($cdrom eq 'cdrom') {
1232 return get_cdrom_path
();
1233 } elsif ($cdrom eq 'none') {
1235 } elsif ($cdrom =~ m
|^/|) {
1238 return PVE
::Storage
::path
($storecfg, $cdrom);
1242 # try to convert old style file names to volume IDs
1243 sub filename_to_volume_id
{
1244 my ($vmid, $file, $media) = @_;
1246 if (!($file eq 'none' || $file eq 'cdrom' ||
1247 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1249 return undef if $file =~ m
|/|;
1251 if ($media && $media eq 'cdrom') {
1252 $file = "local:iso/$file";
1254 $file = "local:$vmid/$file";
1261 sub verify_media_type
{
1262 my ($opt, $vtype, $media) = @_;
1267 if ($media eq 'disk') {
1269 } elsif ($media eq 'cdrom') {
1272 die "internal error";
1275 return if ($vtype eq $etype);
1277 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1280 sub cleanup_drive_path
{
1281 my ($opt, $storecfg, $drive) = @_;
1283 # try to convert filesystem paths to volume IDs
1285 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1286 ($drive->{file
} !~ m
|^/dev/.+|) &&
1287 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1288 ($drive->{file
} !~ m/^\d+$/)) {
1289 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1290 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1291 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1292 verify_media_type
($opt, $vtype, $drive->{media
});
1293 $drive->{file
} = $volid;
1296 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1299 sub parse_hotplug_features
{
1304 return $res if $data eq '0';
1306 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1308 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1309 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1312 die "invalid hotplug feature '$feature'\n";
1318 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1319 sub pve_verify_hotplug_features
{
1320 my ($value, $noerr) = @_;
1322 return $value if parse_hotplug_features
($value);
1324 return undef if $noerr;
1326 die "unable to parse hotplug option\n";
1329 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1330 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1331 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1332 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1333 # [,iothread=on][,serial=serial][,model=model]
1336 my ($key, $data) = @_;
1338 my ($interface, $index);
1340 if ($key =~ m/^([^\d]+)(\d+)$/) {
1347 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1348 : $confdesc->{$key}->{format
};
1350 warn "invalid drive key: $key\n";
1353 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1354 return undef if !$res;
1355 $res->{interface
} = $interface;
1356 $res->{index} = $index;
1359 foreach my $opt (qw(bps bps_rd bps_wr)) {
1360 if (my $bps = defined(delete $res->{$opt})) {
1361 if (defined($res->{"m$opt"})) {
1362 warn "both $opt and m$opt specified\n";
1366 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1370 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1371 for my $requirement (
1372 [mbps_max
=> 'mbps'],
1373 [mbps_rd_max
=> 'mbps_rd'],
1374 [mbps_wr_max
=> 'mbps_wr'],
1375 [miops_max
=> 'miops'],
1376 [miops_rd_max
=> 'miops_rd'],
1377 [miops_wr_max
=> 'miops_wr'],
1378 [bps_max_length
=> 'mbps_max'],
1379 [bps_rd_max_length
=> 'mbps_rd_max'],
1380 [bps_wr_max_length
=> 'mbps_wr_max'],
1381 [iops_max_length
=> 'iops_max'],
1382 [iops_rd_max_length
=> 'iops_rd_max'],
1383 [iops_wr_max_length
=> 'iops_wr_max']) {
1384 my ($option, $requires) = @$requirement;
1385 if ($res->{$option} && !$res->{$requires}) {
1386 warn "$option requires $requires\n";
1391 return undef if $error;
1393 return undef if $res->{mbps_rd
} && $res->{mbps
};
1394 return undef if $res->{mbps_wr
} && $res->{mbps
};
1395 return undef if $res->{iops_rd
} && $res->{iops
};
1396 return undef if $res->{iops_wr
} && $res->{iops
};
1398 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1399 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1400 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1401 return undef if $res->{interface
} eq 'virtio';
1404 if (my $size = $res->{size
}) {
1405 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1412 my ($vmid, $drive) = @_;
1413 my $data = { %$drive };
1414 delete $data->{$_} for qw(index interface);
1415 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1419 my($fh, $noerr) = @_;
1422 my $SG_GET_VERSION_NUM = 0x2282;
1424 my $versionbuf = "\x00" x
8;
1425 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1427 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1430 my $version = unpack("I", $versionbuf);
1431 if ($version < 30000) {
1432 die "scsi generic interface too old\n" if !$noerr;
1436 my $buf = "\x00" x
36;
1437 my $sensebuf = "\x00" x
8;
1438 my $cmd = pack("C x3 C x1", 0x12, 36);
1440 # see /usr/include/scsi/sg.h
1441 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";
1443 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1444 length($sensebuf), 0, length($buf), $buf,
1445 $cmd, $sensebuf, 6000);
1447 $ret = ioctl($fh, $SG_IO, $packet);
1449 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1453 my @res = unpack($sg_io_hdr_t, $packet);
1454 if ($res[17] || $res[18]) {
1455 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1460 (my $byte0, my $byte1, $res->{vendor
},
1461 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1463 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1464 $res->{type
} = $byte0 & 31;
1472 my $fh = IO
::File-
>new("+<$path") || return undef;
1473 my $res = scsi_inquiry
($fh, 1);
1479 sub machine_type_is_q35
{
1482 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1485 sub print_tabletdevice_full
{
1488 my $q35 = machine_type_is_q35
($conf);
1490 # we use uhci for old VMs because tablet driver was buggy in older qemu
1491 my $usbbus = $q35 ?
"ehci" : "uhci";
1493 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1496 sub print_drivedevice_full
{
1497 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1502 if ($drive->{interface
} eq 'virtio') {
1503 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1504 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1505 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1506 } elsif ($drive->{interface
} eq 'scsi') {
1508 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1509 my $unit = $drive->{index} % $maxdev;
1510 my $devicetype = 'hd';
1512 if (drive_is_cdrom
($drive)) {
1515 if ($drive->{file
} =~ m
|^/|) {
1516 $path = $drive->{file
};
1517 if (my $info = path_is_scsi
($path)) {
1518 if ($info->{type
} == 0 && $drive->{scsiblock
}) {
1519 $devicetype = 'block';
1520 } elsif ($info->{type
} == 1) { # tape
1521 $devicetype = 'generic';
1525 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1528 if($path =~ m/^iscsi\:\/\
//){
1529 $devicetype = 'generic';
1533 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1534 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1536 $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}";
1539 } elsif ($drive->{interface
} eq 'ide'){
1541 my $controller = int($drive->{index} / $maxdev);
1542 my $unit = $drive->{index} % $maxdev;
1543 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1545 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1546 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1547 $model = URI
::Escape
::uri_unescape
($model);
1548 $device .= ",model=$model";
1550 } elsif ($drive->{interface
} eq 'sata'){
1551 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1552 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1553 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1554 } elsif ($drive->{interface
} eq 'usb') {
1556 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1558 die "unsupported interface type";
1561 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1566 sub get_initiator_name
{
1569 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1570 while (defined(my $line = <$fh>)) {
1571 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1580 sub print_drive_full
{
1581 my ($storecfg, $vmid, $drive) = @_;
1584 my $volid = $drive->{file
};
1587 if (drive_is_cdrom
($drive)) {
1588 $path = get_iso_path
($storecfg, $vmid, $volid);
1590 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1592 $path = PVE
::Storage
::path
($storecfg, $volid);
1593 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1594 $format = qemu_img_format
($scfg, $volname);
1602 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard);
1603 foreach my $o (@qemu_drive_options) {
1604 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1606 foreach my $type (['', '-total'], [_rd
=> '-read'], [_wr
=> '-write']) {
1607 my ($dir, $qmpname) = @$type;
1608 if (my $v = $drive->{"mbps$dir"}) {
1609 $opts .= ",throttling.bps$qmpname=".int($v*1024*1024);
1611 if (my $v = $drive->{"mbps${dir}_max"}) {
1612 $opts .= ",throttling.bps$qmpname-max=".int($v*1024*1024);
1614 if (my $v = $drive->{"bps${dir}_max_length"}) {
1615 $opts .= ",throttling.bps$qmpname-max-length=$v";
1617 if (my $v = $drive->{"iops${dir}"}) {
1618 $opts .= ",throttling.iops$qmpname=$v";
1620 if (my $v = $drive->{"iops${dir}_max"}) {
1621 $opts .= ",throttling.iops$qmpname-max=$v";
1623 if (my $v = $drive->{"iops${dir}_max_length"}) {
1624 $opts .= ",throttling.iops$qmpname-max-length=$v";
1628 if (my $serial = $drive->{serial
}) {
1629 $serial = URI
::Escape
::uri_unescape
($serial);
1630 $opts .= ",serial=$serial";
1633 $opts .= ",format=$format" if $format && !$drive->{format
};
1635 my $cache_direct = 0;
1637 if (my $cache = $drive->{cache
}) {
1638 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1639 } elsif (!drive_is_cdrom
($drive)) {
1640 $opts .= ",cache=none";
1644 # aio native works only with O_DIRECT
1645 if (!$drive->{aio
}) {
1647 $opts .= ",aio=native";
1649 $opts .= ",aio=threads";
1653 if (!drive_is_cdrom
($drive)) {
1655 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1656 $detectzeroes = 'off';
1657 } elsif ($drive->{discard
}) {
1658 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1660 # This used to be our default with discard not being specified:
1661 $detectzeroes = 'on';
1663 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1666 my $pathinfo = $path ?
"file=$path," : '';
1668 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1671 sub print_netdevice_full
{
1672 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1674 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1676 my $device = $net->{model
};
1677 if ($net->{model
} eq 'virtio') {
1678 $device = 'virtio-net-pci';
1681 my $pciaddr = print_pci_addr
("$netid", $bridges);
1682 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1683 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1684 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1685 my $vectors = $net->{queues
} * 2 + 2;
1686 $tmpstr .= ",vectors=$vectors,mq=on";
1688 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1690 if ($use_old_bios_files) {
1692 if ($device eq 'virtio-net-pci') {
1693 $romfile = 'pxe-virtio.rom';
1694 } elsif ($device eq 'e1000') {
1695 $romfile = 'pxe-e1000.rom';
1696 } elsif ($device eq 'ne2k') {
1697 $romfile = 'pxe-ne2k_pci.rom';
1698 } elsif ($device eq 'pcnet') {
1699 $romfile = 'pxe-pcnet.rom';
1700 } elsif ($device eq 'rtl8139') {
1701 $romfile = 'pxe-rtl8139.rom';
1703 $tmpstr .= ",romfile=$romfile" if $romfile;
1709 sub print_netdev_full
{
1710 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1713 if ($netid =~ m/^net(\d+)$/) {
1717 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1719 my $ifname = "tap${vmid}i$i";
1721 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1722 die "interface name '$ifname' is too long (max 15 character)\n"
1723 if length($ifname) >= 16;
1725 my $vhostparam = '';
1726 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1728 my $vmname = $conf->{name
} || "vm$vmid";
1731 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1733 if ($net->{bridge
}) {
1734 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1736 $netdev = "type=user,id=$netid,hostname=$vmname";
1739 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1745 sub print_cpu_device
{
1746 my ($conf, $id) = @_;
1748 my $kvm = $conf->{kvm
} // 1;
1749 my $cpu = $kvm ?
"kvm64" : "qemu64";
1750 if (my $cputype = $conf->{cpu
}) {
1751 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1752 or die "Cannot parse cpu description: $cputype\n";
1753 $cpu = $cpuconf->{cputype
};
1756 my $cores = $conf->{cores
} || 1;
1758 my $current_core = ($id - 1) % $cores;
1759 my $current_socket = int(($id - 1 - $current_core)/$cores);
1761 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1764 sub drive_is_cdrom
{
1767 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1771 sub parse_number_sets
{
1774 foreach my $part (split(/;/, $set)) {
1775 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1776 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1777 push @$res, [ $1, $2 ];
1779 die "invalid range: $part\n";
1788 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1789 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1790 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1797 return undef if !$value;
1799 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1801 my @idlist = split(/;/, $res->{host
});
1802 delete $res->{host
};
1803 foreach my $id (@idlist) {
1804 if ($id =~ /^$PCIRE$/) {
1806 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1808 my $pcidevices = lspci
($1);
1809 $res->{pciid
} = $pcidevices->{$1};
1812 # should have been caught by parse_property_string already
1813 die "failed to parse PCI id: $id\n";
1819 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1823 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1828 if (!defined($res->{macaddr
})) {
1829 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1830 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1838 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1841 sub add_random_macs
{
1842 my ($settings) = @_;
1844 foreach my $opt (keys %$settings) {
1845 next if $opt !~ m/^net(\d+)$/;
1846 my $net = parse_net
($settings->{$opt});
1848 $settings->{$opt} = print_net
($net);
1852 sub vm_is_volid_owner
{
1853 my ($storecfg, $vmid, $volid) = @_;
1855 if ($volid !~ m
|^/|) {
1857 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1858 if ($owner && ($owner == $vmid)) {
1866 sub split_flagged_list
{
1867 my $text = shift || '';
1868 $text =~ s/[,;]/ /g;
1870 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1873 sub join_flagged_list
{
1874 my ($how, $lst) = @_;
1875 join $how, map { $lst->{$_} . $_ } keys %$lst;
1878 sub vmconfig_delete_pending_option
{
1879 my ($conf, $key, $force) = @_;
1881 delete $conf->{pending
}->{$key};
1882 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1883 $pending_delete_hash->{$key} = $force ?
'!' : '';
1884 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1887 sub vmconfig_undelete_pending_option
{
1888 my ($conf, $key) = @_;
1890 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1891 delete $pending_delete_hash->{$key};
1893 if (%$pending_delete_hash) {
1894 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1896 delete $conf->{pending
}->{delete};
1900 sub vmconfig_register_unused_drive
{
1901 my ($storecfg, $vmid, $conf, $drive) = @_;
1903 if (!drive_is_cdrom
($drive)) {
1904 my $volid = $drive->{file
};
1905 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1906 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1911 sub vmconfig_cleanup_pending
{
1914 # remove pending changes when nothing changed
1916 foreach my $opt (keys %{$conf->{pending
}}) {
1917 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1919 delete $conf->{pending
}->{$opt};
1923 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1924 my $pending_delete_hash = {};
1925 while (my ($opt, $force) = each %$current_delete_hash) {
1926 if (defined($conf->{$opt})) {
1927 $pending_delete_hash->{$opt} = $force;
1933 if (%$pending_delete_hash) {
1934 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1936 delete $conf->{pending
}->{delete};
1942 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1946 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1947 format_description
=> 'UUID',
1948 description
=> "Set SMBIOS1 UUID.",
1954 format_description
=> 'string',
1955 description
=> "Set SMBIOS1 version.",
1961 format_description
=> 'string',
1962 description
=> "Set SMBIOS1 serial number.",
1968 format_description
=> 'string',
1969 description
=> "Set SMBIOS1 manufacturer.",
1975 format_description
=> 'string',
1976 description
=> "Set SMBIOS1 product ID.",
1982 format_description
=> 'string',
1983 description
=> "Set SMBIOS1 SKU string.",
1989 format_description
=> 'string',
1990 description
=> "Set SMBIOS1 family string.",
1998 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
2005 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
2008 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
2010 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
2011 sub verify_bootdisk
{
2012 my ($value, $noerr) = @_;
2014 return $value if is_valid_drivename
($value);
2016 return undef if $noerr;
2018 die "invalid boot disk '$value'\n";
2021 sub parse_watchdog
{
2024 return undef if !$value;
2026 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
2031 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
2032 sub verify_usb_device
{
2033 my ($value, $noerr) = @_;
2035 return $value if parse_usb_device
($value);
2037 return undef if $noerr;
2039 die "unable to parse usb device\n";
2042 # add JSON properties for create and set function
2043 sub json_config_properties
{
2046 foreach my $opt (keys %$confdesc) {
2047 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2048 $prop->{$opt} = $confdesc->{$opt};
2055 my ($key, $value) = @_;
2057 die "unknown setting '$key'\n" if !$confdesc->{$key};
2059 my $type = $confdesc->{$key}->{type
};
2061 if (!defined($value)) {
2062 die "got undefined value\n";
2065 if ($value =~ m/[\n\r]/) {
2066 die "property contains a line feed\n";
2069 if ($type eq 'boolean') {
2070 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2071 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2072 die "type check ('boolean') failed - got '$value'\n";
2073 } elsif ($type eq 'integer') {
2074 return int($1) if $value =~ m/^(\d+)$/;
2075 die "type check ('integer') failed - got '$value'\n";
2076 } elsif ($type eq 'number') {
2077 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2078 die "type check ('number') failed - got '$value'\n";
2079 } elsif ($type eq 'string') {
2080 if (my $fmt = $confdesc->{$key}->{format
}) {
2081 PVE
::JSONSchema
::check_format
($fmt, $value);
2084 $value =~ s/^\"(.*)\"$/$1/;
2087 die "internal error"
2091 sub check_iommu_support
{
2092 #fixme : need to check IOMMU support
2093 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2103 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2104 utime undef, undef, $conf;
2108 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2110 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2112 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2114 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2116 if ($conf->{template
}) {
2117 # check if any base image is still used by a linked clone
2118 foreach_drive
($conf, sub {
2119 my ($ds, $drive) = @_;
2121 return if drive_is_cdrom
($drive);
2123 my $volid = $drive->{file
};
2125 return if !$volid || $volid =~ m
|^/|;
2127 die "base volume '$volid' is still in use by linked cloned\n"
2128 if PVE
::Storage
::volume_is_base_and_used
($storecfg, $volid);
2133 # only remove disks owned by this VM
2134 foreach_drive
($conf, sub {
2135 my ($ds, $drive) = @_;
2137 return if drive_is_cdrom
($drive);
2139 my $volid = $drive->{file
};
2141 return if !$volid || $volid =~ m
|^/|;
2143 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2144 return if !$path || !$owner || ($owner != $vmid);
2147 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2149 warn "Could not remove disk '$volid', check manually: $@" if $@;
2153 if ($keep_empty_config) {
2154 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2159 # also remove unused disk
2161 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2164 PVE
::Storage
::foreach_volid
($dl, sub {
2165 my ($volid, $sid, $volname, $d) = @_;
2166 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2175 sub parse_vm_config
{
2176 my ($filename, $raw) = @_;
2178 return undef if !defined($raw);
2181 digest
=> Digest
::SHA
::sha1_hex
($raw),
2186 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2187 || die "got strange filename '$filename'";
2195 my @lines = split(/\n/, $raw);
2196 foreach my $line (@lines) {
2197 next if $line =~ m/^\s*$/;
2199 if ($line =~ m/^\[PENDING\]\s*$/i) {
2200 $section = 'pending';
2201 if (defined($descr)) {
2203 $conf->{description
} = $descr;
2206 $conf = $res->{$section} = {};
2209 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2211 if (defined($descr)) {
2213 $conf->{description
} = $descr;
2216 $conf = $res->{snapshots
}->{$section} = {};
2220 if ($line =~ m/^\#(.*)\s*$/) {
2221 $descr = '' if !defined($descr);
2222 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2226 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2227 $descr = '' if !defined($descr);
2228 $descr .= PVE
::Tools
::decode_text
($2);
2229 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2230 $conf->{snapstate
} = $1;
2231 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2234 $conf->{$key} = $value;
2235 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2237 if ($section eq 'pending') {
2238 $conf->{delete} = $value; # we parse this later
2240 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2242 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2245 eval { $value = check_type
($key, $value); };
2247 warn "vm $vmid - unable to parse value of '$key' - $@";
2249 $key = 'ide2' if $key eq 'cdrom';
2250 my $fmt = $confdesc->{$key}->{format
};
2251 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2252 my $v = parse_drive
($key, $value);
2253 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2254 $v->{file
} = $volid;
2255 $value = print_drive
($vmid, $v);
2257 warn "vm $vmid - unable to parse value of '$key'\n";
2262 $conf->{$key} = $value;
2267 if (defined($descr)) {
2269 $conf->{description
} = $descr;
2271 delete $res->{snapstate
}; # just to be sure
2276 sub write_vm_config
{
2277 my ($filename, $conf) = @_;
2279 delete $conf->{snapstate
}; # just to be sure
2281 if ($conf->{cdrom
}) {
2282 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2283 $conf->{ide2
} = $conf->{cdrom
};
2284 delete $conf->{cdrom
};
2287 # we do not use 'smp' any longer
2288 if ($conf->{sockets
}) {
2289 delete $conf->{smp
};
2290 } elsif ($conf->{smp
}) {
2291 $conf->{sockets
} = $conf->{smp
};
2292 delete $conf->{cores
};
2293 delete $conf->{smp
};
2296 my $used_volids = {};
2298 my $cleanup_config = sub {
2299 my ($cref, $pending, $snapname) = @_;
2301 foreach my $key (keys %$cref) {
2302 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2303 $key eq 'snapstate' || $key eq 'pending';
2304 my $value = $cref->{$key};
2305 if ($key eq 'delete') {
2306 die "propertry 'delete' is only allowed in [PENDING]\n"
2308 # fixme: check syntax?
2311 eval { $value = check_type
($key, $value); };
2312 die "unable to parse value of '$key' - $@" if $@;
2314 $cref->{$key} = $value;
2316 if (!$snapname && is_valid_drivename
($key)) {
2317 my $drive = parse_drive
($key, $value);
2318 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2323 &$cleanup_config($conf);
2325 &$cleanup_config($conf->{pending
}, 1);
2327 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2328 die "internal error" if $snapname eq 'pending';
2329 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2332 # remove 'unusedX' settings if we re-add a volume
2333 foreach my $key (keys %$conf) {
2334 my $value = $conf->{$key};
2335 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2336 delete $conf->{$key};
2340 my $generate_raw_config = sub {
2341 my ($conf, $pending) = @_;
2345 # add description as comment to top of file
2346 if (defined(my $descr = $conf->{description
})) {
2348 foreach my $cl (split(/\n/, $descr)) {
2349 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2352 $raw .= "#\n" if $pending;
2356 foreach my $key (sort keys %$conf) {
2357 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2358 $raw .= "$key: $conf->{$key}\n";
2363 my $raw = &$generate_raw_config($conf);
2365 if (scalar(keys %{$conf->{pending
}})){
2366 $raw .= "\n[PENDING]\n";
2367 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2370 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2371 $raw .= "\n[$snapname]\n";
2372 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2382 # we use static defaults from our JSON schema configuration
2383 foreach my $key (keys %$confdesc) {
2384 if (defined(my $default = $confdesc->{$key}->{default})) {
2385 $res->{$key} = $default;
2389 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2390 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2396 my $vmlist = PVE
::Cluster
::get_vmlist
();
2398 return $res if !$vmlist || !$vmlist->{ids
};
2399 my $ids = $vmlist->{ids
};
2401 foreach my $vmid (keys %$ids) {
2402 my $d = $ids->{$vmid};
2403 next if !$d->{node
} || $d->{node
} ne $nodename;
2404 next if !$d->{type
} || $d->{type
} ne 'qemu';
2405 $res->{$vmid}->{exists} = 1;
2410 # test if VM uses local resources (to prevent migration)
2411 sub check_local_resources
{
2412 my ($conf, $noerr) = @_;
2416 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2417 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2419 foreach my $k (keys %$conf) {
2420 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2421 # sockets are safe: they will recreated be on the target side post-migrate
2422 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2423 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2426 die "VM uses local resources\n" if $loc_res && !$noerr;
2431 # check if used storages are available on all nodes (use by migrate)
2432 sub check_storage_availability
{
2433 my ($storecfg, $conf, $node) = @_;
2435 foreach_drive
($conf, sub {
2436 my ($ds, $drive) = @_;
2438 my $volid = $drive->{file
};
2441 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2444 # check if storage is available on both nodes
2445 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2446 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2450 # list nodes where all VM images are available (used by has_feature API)
2452 my ($conf, $storecfg) = @_;
2454 my $nodelist = PVE
::Cluster
::get_nodelist
();
2455 my $nodehash = { map { $_ => 1 } @$nodelist };
2456 my $nodename = PVE
::INotify
::nodename
();
2458 foreach_drive
($conf, sub {
2459 my ($ds, $drive) = @_;
2461 my $volid = $drive->{file
};
2464 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2466 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2467 if ($scfg->{disable
}) {
2469 } elsif (my $avail = $scfg->{nodes
}) {
2470 foreach my $node (keys %$nodehash) {
2471 delete $nodehash->{$node} if !$avail->{$node};
2473 } elsif (!$scfg->{shared
}) {
2474 foreach my $node (keys %$nodehash) {
2475 delete $nodehash->{$node} if $node ne $nodename
2485 my ($pidfile, $pid) = @_;
2487 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2491 return undef if !$line;
2492 my @param = split(/\0/, $line);
2494 my $cmd = $param[0];
2495 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2497 for (my $i = 0; $i < scalar (@param); $i++) {
2500 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2501 my $p = $param[$i+1];
2502 return 1 if $p && ($p eq $pidfile);
2511 my ($vmid, $nocheck, $node) = @_;
2513 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2515 die "unable to find configuration file for VM $vmid - no such machine\n"
2516 if !$nocheck && ! -f
$filename;
2518 my $pidfile = pidfile_name
($vmid);
2520 if (my $fd = IO
::File-
>new("<$pidfile")) {
2525 my $mtime = $st->mtime;
2526 if ($mtime > time()) {
2527 warn "file '$filename' modified in future\n";
2530 if ($line =~ m/^(\d+)$/) {
2532 if (check_cmdline
($pidfile, $pid)) {
2533 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2545 my $vzlist = config_list
();
2547 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2549 while (defined(my $de = $fd->read)) {
2550 next if $de !~ m/^(\d+)\.pid$/;
2552 next if !defined($vzlist->{$vmid});
2553 if (my $pid = check_running
($vmid)) {
2554 $vzlist->{$vmid}->{pid
} = $pid;
2562 my ($storecfg, $conf) = @_;
2564 my $bootdisk = $conf->{bootdisk
};
2565 return undef if !$bootdisk;
2566 return undef if !is_valid_drivename
($bootdisk);
2568 return undef if !$conf->{$bootdisk};
2570 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2571 return undef if !defined($drive);
2573 return undef if drive_is_cdrom
($drive);
2575 my $volid = $drive->{file
};
2576 return undef if !$volid;
2578 return $drive->{size
};
2581 my $last_proc_pid_stat;
2583 # get VM status information
2584 # This must be fast and should not block ($full == false)
2585 # We only query KVM using QMP if $full == true (this can be slow)
2587 my ($opt_vmid, $full) = @_;
2591 my $storecfg = PVE
::Storage
::config
();
2593 my $list = vzlist
();
2594 my $defaults = load_defaults
();
2596 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2598 my $cpucount = $cpuinfo->{cpus
} || 1;
2600 foreach my $vmid (keys %$list) {
2601 next if $opt_vmid && ($vmid ne $opt_vmid);
2603 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2604 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2607 $d->{pid
} = $list->{$vmid}->{pid
};
2609 # fixme: better status?
2610 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2612 my $size = disksize
($storecfg, $conf);
2613 if (defined($size)) {
2614 $d->{disk
} = 0; # no info available
2615 $d->{maxdisk
} = $size;
2621 $d->{cpus
} = ($conf->{sockets
} || $defaults->{sockets
})
2622 * ($conf->{cores
} || $defaults->{cores
});
2623 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2624 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2626 $d->{name
} = $conf->{name
} || "VM $vmid";
2627 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024)
2628 : $defaults->{memory
}*(1024*1024);
2630 if ($conf->{balloon
}) {
2631 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2632 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
}
2633 : $defaults->{shares
};
2644 $d->{diskwrite
} = 0;
2646 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2651 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2652 foreach my $dev (keys %$netdev) {
2653 next if $dev !~ m/^tap([1-9]\d*)i/;
2655 my $d = $res->{$vmid};
2658 $d->{netout
} += $netdev->{$dev}->{receive
};
2659 $d->{netin
} += $netdev->{$dev}->{transmit
};
2662 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2663 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2668 my $ctime = gettimeofday
;
2670 foreach my $vmid (keys %$list) {
2672 my $d = $res->{$vmid};
2673 my $pid = $d->{pid
};
2676 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2677 next if !$pstat; # not running
2679 my $used = $pstat->{utime} + $pstat->{stime
};
2681 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2683 if ($pstat->{vsize
}) {
2684 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2687 my $old = $last_proc_pid_stat->{$pid};
2689 $last_proc_pid_stat->{$pid} = {
2697 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2699 if ($dtime > 1000) {
2700 my $dutime = $used - $old->{used
};
2702 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2703 $last_proc_pid_stat->{$pid} = {
2709 $d->{cpu
} = $old->{cpu
};
2713 return $res if !$full;
2715 my $qmpclient = PVE
::QMPClient-
>new();
2717 my $ballooncb = sub {
2718 my ($vmid, $resp) = @_;
2720 my $info = $resp->{'return'};
2721 return if !$info->{max_mem
};
2723 my $d = $res->{$vmid};
2725 # use memory assigned to VM
2726 $d->{maxmem
} = $info->{max_mem
};
2727 $d->{balloon
} = $info->{actual
};
2729 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2730 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2731 $d->{freemem
} = $info->{free_mem
};
2734 $d->{ballooninfo
} = $info;
2737 my $blockstatscb = sub {
2738 my ($vmid, $resp) = @_;
2739 my $data = $resp->{'return'} || [];
2740 my $totalrdbytes = 0;
2741 my $totalwrbytes = 0;
2743 for my $blockstat (@$data) {
2744 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2745 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2747 $blockstat->{device
} =~ s/drive-//;
2748 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2750 $res->{$vmid}->{diskread
} = $totalrdbytes;
2751 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2754 my $statuscb = sub {
2755 my ($vmid, $resp) = @_;
2757 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2758 # this fails if ballon driver is not loaded, so this must be
2759 # the last commnand (following command are aborted if this fails).
2760 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2762 my $status = 'unknown';
2763 if (!defined($status = $resp->{'return'}->{status
})) {
2764 warn "unable to get VM status\n";
2768 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2771 foreach my $vmid (keys %$list) {
2772 next if $opt_vmid && ($vmid ne $opt_vmid);
2773 next if !$res->{$vmid}->{pid
}; # not running
2774 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2777 $qmpclient->queue_execute(undef, 2);
2779 foreach my $vmid (keys %$list) {
2780 next if $opt_vmid && ($vmid ne $opt_vmid);
2781 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2788 my ($conf, $func, @param) = @_;
2790 foreach my $ds (valid_drive_names
()) {
2791 next if !defined($conf->{$ds});
2793 my $drive = parse_drive
($ds, $conf->{$ds});
2796 &$func($ds, $drive, @param);
2801 my ($conf, $func, @param) = @_;
2805 my $test_volid = sub {
2806 my ($volid, $is_cdrom, $replicate, $snapname) = @_;
2810 $volhash->{$volid}->{cdrom
} //= 1;
2811 $volhash->{$volid}->{cdrom
} = 0 if !$is_cdrom;
2813 $volhash->{$volid}->{replicate
} //= 0;
2814 $volhash->{$volid}->{replicate
} = 1 if $replicate;
2816 $volhash->{$volid}->{referenced_in_config
} //= 0;
2817 $volhash->{$volid}->{referenced_in_config
} = 1 if !defined($snapname);
2819 $volhash->{$volid}->{referenced_in_snapshot
}->{$snapname} = 1
2820 if defined($snapname);
2823 foreach_drive
($conf, sub {
2824 my ($ds, $drive) = @_;
2825 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, undef);
2828 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2829 my $snap = $conf->{snapshots
}->{$snapname};
2830 $test_volid->($snap->{vmstate
}, 0, 1, $snapname);
2831 foreach_drive
($snap, sub {
2832 my ($ds, $drive) = @_;
2833 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, $snapname);
2837 foreach my $volid (keys %$volhash) {
2838 &$func($volid, $volhash->{$volid}, @param);
2842 sub vga_conf_has_spice
{
2845 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2850 sub config_to_command
{
2851 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2854 my $globalFlags = [];
2855 my $machineFlags = [];
2861 my $kvmver = kvm_user_version
();
2862 my $vernum = 0; # unknown
2863 my $ostype = $conf->{ostype
};
2864 my $winversion = windows_version
($ostype);
2865 my $kvm = $conf->{kvm
} // 1;
2867 die "KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.\n" if (!$cpuinfo->{hvm
} && $kvm);
2869 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2870 $vernum = $1*1000000+$2*1000;
2871 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2872 $vernum = $1*1000000+$2*1000+$3;
2875 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2877 my $have_ovz = -f
'/proc/vz/vestat';
2879 my $q35 = machine_type_is_q35
($conf);
2880 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2881 my $machine_type = $forcemachine || $conf->{machine
};
2882 my $use_old_bios_files = undef;
2883 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2885 my $cpuunits = defined($conf->{cpuunits
}) ?
2886 $conf->{cpuunits
} : $defaults->{cpuunits
};
2888 push @$cmd, '/usr/bin/kvm';
2890 push @$cmd, '-id', $vmid;
2894 my $qmpsocket = qmp_socket
($vmid);
2895 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2896 push @$cmd, '-mon', "chardev=qmp,mode=control";
2899 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2901 push @$cmd, '-daemonize';
2903 if ($conf->{smbios1
}) {
2904 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2907 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2908 die "uefi base image not found\n" if ! -f
$OVMF_CODE;
2912 if (my $efidisk = $conf->{efidisk0
}) {
2913 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $efidisk);
2914 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
2916 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
2920 $format = $d->{format
} if $d->{format
};
2922 warn "no efidisk configured! Using temporary efivars disk.\n";
2923 $path = "/tmp/$vmid-ovmf.fd";
2924 PVE
::Tools
::file_copy
($OVMF_VARS, $path, -s
$OVMF_VARS);
2927 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$OVMF_CODE";
2928 push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0,file=$path";
2932 # add usb controllers
2933 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2934 push @$devices, @usbcontrollers if @usbcontrollers;
2935 my $vga = $conf->{vga
};
2937 my $qxlnum = vga_conf_has_spice
($vga);
2938 $vga = 'qxl' if $qxlnum;
2941 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 9)) {
2942 $vga = (!$winversion || $winversion >= 6) ?
'std' : 'cirrus';
2944 $vga = ($winversion >= 6) ?
'std' : 'cirrus';
2948 # enable absolute mouse coordinates (needed by vnc)
2950 if (defined($conf->{tablet
})) {
2951 $tablet = $conf->{tablet
};
2953 $tablet = $defaults->{tablet
};
2954 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2955 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2958 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2961 my $gpu_passthrough;
2964 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2965 my $d = parse_hostpci
($conf->{"hostpci$i"});
2968 my $pcie = $d->{pcie
};
2970 die "q35 machine model is not enabled" if !$q35;
2971 $pciaddr = print_pcie_addr
("hostpci$i");
2973 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2976 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2977 my $romfile = $d->{romfile
};
2980 if ($d->{'x-vga'}) {
2981 $xvga = ',x-vga=on';
2984 $gpu_passthrough = 1;
2986 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2990 my $pcidevices = $d->{pciid
};
2991 my $multifunction = 1 if @$pcidevices > 1;
2994 foreach my $pcidevice (@$pcidevices) {
2996 my $id = "hostpci$i";
2997 $id .= ".$j" if $multifunction;
2998 my $addr = $pciaddr;
2999 $addr .= ".$j" if $multifunction;
3000 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
3003 $devicestr .= "$rombar$xvga";
3004 $devicestr .= ",multifunction=on" if $multifunction;
3005 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
3008 push @$devices, '-device', $devicestr;
3014 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
3015 push @$devices, @usbdevices if @usbdevices;
3017 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
3018 if (my $path = $conf->{"serial$i"}) {
3019 if ($path eq 'socket') {
3020 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
3021 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
3022 push @$devices, '-device', "isa-serial,chardev=serial$i";
3024 die "no such serial device\n" if ! -c
$path;
3025 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
3026 push @$devices, '-device', "isa-serial,chardev=serial$i";
3032 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
3033 if (my $path = $conf->{"parallel$i"}) {
3034 die "no such parallel device\n" if ! -c
$path;
3035 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
3036 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
3037 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
3041 my $vmname = $conf->{name
} || "vm$vmid";
3043 push @$cmd, '-name', $vmname;
3046 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
3047 $sockets = $conf->{sockets
} if $conf->{sockets
};
3049 my $cores = $conf->{cores
} || 1;
3051 my $maxcpus = $sockets * $cores;
3053 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3055 my $allowed_vcpus = $cpuinfo->{cpus
};
3057 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3058 if ($allowed_vcpus < $maxcpus);
3060 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
3062 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3063 for (my $i = 2; $i <= $vcpus; $i++) {
3064 my $cpustr = print_cpu_device
($conf,$i);
3065 push @$cmd, '-device', $cpustr;
3070 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3072 push @$cmd, '-nodefaults';
3074 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3076 my $bootindex_hash = {};
3078 foreach my $o (split(//, $bootorder)) {
3079 $bootindex_hash->{$o} = $i*100;
3083 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3085 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3087 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3089 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3091 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3092 my $socket = vnc_socket
($vmid);
3093 push @$cmd, '-vnc', "unix:$socket,x509,password";
3095 push @$cmd, '-nographic';
3099 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3101 my $useLocaltime = $conf->{localtime};
3103 if ($winversion >= 5) { # windows
3104 $useLocaltime = 1 if !defined($conf->{localtime});
3106 # use time drift fix when acpi is enabled
3107 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3108 $tdf = 1 if !defined($conf->{tdf
});
3112 if ($winversion >= 6) {
3113 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3114 push @$cmd, '-no-hpet';
3117 push @$rtcFlags, 'driftfix=slew' if $tdf;
3120 push @$machineFlags, 'accel=tcg';
3123 if ($machine_type) {
3124 push @$machineFlags, "type=${machine_type}";
3127 if ($conf->{startdate
}) {
3128 push @$rtcFlags, "base=$conf->{startdate}";
3129 } elsif ($useLocaltime) {
3130 push @$rtcFlags, 'base=localtime';
3133 my $cpu = $kvm ?
"kvm64" : "qemu64";
3134 if (my $cputype = $conf->{cpu
}) {
3135 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3136 or die "Cannot parse cpu description: $cputype\n";
3137 $cpu = $cpuconf->{cputype
};
3138 $kvm_off = 1 if $cpuconf->{hidden
};
3141 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3143 push @$cpuFlags , '-x2apic'
3144 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3146 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3148 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3150 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3152 push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
3153 push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
3156 add_hyperv_enlightenments
($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios
}, $gpu_passthrough) if $kvm;
3158 push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm;
3160 push @$cpuFlags, 'kvm=off' if $kvm_off;
3162 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3163 die "internal error"; # should not happen
3165 push @$cpuFlags, "vendor=${cpu_vendor}"
3166 if $cpu_vendor ne 'default';
3168 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3170 push @$cmd, '-cpu', $cpu;
3172 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3174 push @$cmd, '-S' if $conf->{freeze
};
3176 # set keyboard layout
3177 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3178 push @$cmd, '-k', $kb if $kb;
3181 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3182 #push @$cmd, '-soundhw', 'es1370';
3183 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3185 if($conf->{agent
}) {
3186 my $qgasocket = qmp_socket
($vmid, 1);
3187 my $pciaddr = print_pci_addr
("qga0", $bridges);
3188 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3189 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3190 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3198 for(my $i = 1; $i < $qxlnum; $i++){
3199 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3200 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3203 # assume other OS works like Linux
3204 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3205 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3209 my $pciaddr = print_pci_addr
("spice", $bridges);
3211 my $nodename = PVE
::INotify
::nodename
();
3212 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3213 my @nodeaddrs = PVE
::Tools
::getaddrinfo_all
('localhost', family
=> $pfamily);
3214 die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
3215 my $localhost = PVE
::Network
::addr_to_ip
($nodeaddrs[0]->{addr
});
3216 $spice_port = PVE
::Tools
::next_spice_port
($pfamily, $localhost);
3218 push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
3220 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3221 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3222 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3225 # enable balloon by default, unless explicitly disabled
3226 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3227 $pciaddr = print_pci_addr
("balloon0", $bridges);
3228 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3231 if ($conf->{watchdog
}) {
3232 my $wdopts = parse_watchdog
($conf->{watchdog
});
3233 $pciaddr = print_pci_addr
("watchdog", $bridges);
3234 my $watchdog = $wdopts->{model
} || 'i6300esb';
3235 push @$devices, '-device', "$watchdog$pciaddr";
3236 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3240 my $scsicontroller = {};
3241 my $ahcicontroller = {};
3242 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3244 # Add iscsi initiator name if available
3245 if (my $initiator = get_initiator_name
()) {
3246 push @$devices, '-iscsi', "initiator-name=$initiator";
3249 foreach_drive
($conf, sub {
3250 my ($ds, $drive) = @_;
3252 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3253 push @$vollist, $drive->{file
};
3256 # ignore efidisk here, already added in bios/fw handling code above
3257 return if $drive->{interface
} eq 'efidisk';
3259 $use_virtio = 1 if $ds =~ m/^virtio/;
3261 if (drive_is_cdrom
($drive)) {
3262 if ($bootindex_hash->{d
}) {
3263 $drive->{bootindex
} = $bootindex_hash->{d
};
3264 $bootindex_hash->{d
} += 1;
3267 if ($bootindex_hash->{c
}) {
3268 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3269 $bootindex_hash->{c
} += 1;
3273 if($drive->{interface
} eq 'virtio'){
3274 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3277 if ($drive->{interface
} eq 'scsi') {
3279 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3281 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3282 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3285 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3286 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3287 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3288 } elsif ($drive->{iothread
}) {
3289 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3293 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3294 $queues = ",num_queues=$drive->{queues}";
3297 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3298 $scsicontroller->{$controller}=1;
3301 if ($drive->{interface
} eq 'sata') {
3302 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3303 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3304 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3305 $ahcicontroller->{$controller}=1;
3308 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3309 push @$devices, '-drive',$drive_cmd;
3310 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3313 for (my $i = 0; $i < $MAX_NETS; $i++) {
3314 next if !$conf->{"net$i"};
3315 my $d = parse_net
($conf->{"net$i"});
3318 $use_virtio = 1 if $d->{model
} eq 'virtio';
3320 if ($bootindex_hash->{n
}) {
3321 $d->{bootindex
} = $bootindex_hash->{n
};
3322 $bootindex_hash->{n
} += 1;
3325 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3326 push @$devices, '-netdev', $netdevfull;
3328 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3329 push @$devices, '-device', $netdevicefull;
3334 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3339 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3341 while (my ($k, $v) = each %$bridges) {
3342 $pciaddr = print_pci_addr
("pci.$k");
3343 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3348 if ($conf->{args
}) {
3349 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3353 push @$cmd, @$devices;
3354 push @$cmd, '-rtc', join(',', @$rtcFlags)
3355 if scalar(@$rtcFlags);
3356 push @$cmd, '-machine', join(',', @$machineFlags)
3357 if scalar(@$machineFlags);
3358 push @$cmd, '-global', join(',', @$globalFlags)
3359 if scalar(@$globalFlags);
3361 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3366 return "${var_run_tmpdir}/$vmid.vnc";
3372 my $res = vm_mon_cmd
($vmid, 'query-spice');
3374 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3378 my ($vmid, $qga) = @_;
3379 my $sockettype = $qga ?
'qga' : 'qmp';
3380 return "${var_run_tmpdir}/$vmid.$sockettype";
3385 return "${var_run_tmpdir}/$vmid.pid";
3388 sub vm_devices_list
{
3391 my $res = vm_mon_cmd
($vmid, 'query-pci');
3393 foreach my $pcibus (@$res) {
3394 foreach my $device (@{$pcibus->{devices
}}) {
3395 next if !$device->{'qdev_id'};
3396 if ($device->{'pci_bridge'}) {
3397 $devices->{$device->{'qdev_id'}} = 1;
3398 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3399 next if !$bridge_device->{'qdev_id'};
3400 $devices->{$bridge_device->{'qdev_id'}} = 1;
3401 $devices->{$device->{'qdev_id'}}++;
3404 $devices->{$device->{'qdev_id'}} = 1;
3409 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3410 foreach my $block (@$resblock) {
3411 if($block->{device
} =~ m/^drive-(\S+)/){
3416 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3417 foreach my $mice (@$resmice) {
3418 if ($mice->{name
} eq 'QEMU HID Tablet') {
3419 $devices->{tablet
} = 1;
3424 # for usb devices there is no query-usb
3425 # but we can iterate over the entries in
3426 # qom-list path=/machine/peripheral
3427 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3428 foreach my $per (@$resperipheral) {
3429 if ($per->{name
} =~ m/^usb\d+$/) {
3430 $devices->{$per->{name
}} = 1;
3438 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3440 my $q35 = machine_type_is_q35
($conf);
3442 my $devices_list = vm_devices_list
($vmid);
3443 return 1 if defined($devices_list->{$deviceid});
3445 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3447 if ($deviceid eq 'tablet') {
3449 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3451 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3453 die "usb hotplug currently not reliable\n";
3454 # since we can't reliably hot unplug all added usb devices
3455 # and usb passthrough disables live migration
3456 # we disable usb hotplugging for now
3457 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3459 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3461 qemu_iothread_add
($vmid, $deviceid, $device);
3463 qemu_driveadd
($storecfg, $vmid, $device);
3464 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3466 qemu_deviceadd
($vmid, $devicefull);
3467 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3469 eval { qemu_drivedel
($vmid, $deviceid); };
3474 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3477 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3478 my $pciaddr = print_pci_addr
($deviceid);
3479 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3481 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3483 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3484 qemu_iothread_add
($vmid, $deviceid, $device);
3485 $devicefull .= ",iothread=iothread-$deviceid";
3488 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3489 $devicefull .= ",num_queues=$device->{queues}";
3492 qemu_deviceadd
($vmid, $devicefull);
3493 qemu_deviceaddverify
($vmid, $deviceid);
3495 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3497 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3498 qemu_driveadd
($storecfg, $vmid, $device);
3500 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3501 eval { qemu_deviceadd
($vmid, $devicefull); };
3503 eval { qemu_drivedel
($vmid, $deviceid); };
3508 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3510 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3512 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3513 my $use_old_bios_files = undef;
3514 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3516 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3517 qemu_deviceadd
($vmid, $netdevicefull);
3518 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3520 eval { qemu_netdevdel
($vmid, $deviceid); };
3525 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3528 my $pciaddr = print_pci_addr
($deviceid);
3529 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3531 qemu_deviceadd
($vmid, $devicefull);
3532 qemu_deviceaddverify
($vmid, $deviceid);
3535 die "can't hotplug device '$deviceid'\n";
3541 # fixme: this should raise exceptions on error!
3542 sub vm_deviceunplug
{
3543 my ($vmid, $conf, $deviceid) = @_;
3545 my $devices_list = vm_devices_list
($vmid);
3546 return 1 if !defined($devices_list->{$deviceid});
3548 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3550 if ($deviceid eq 'tablet') {
3552 qemu_devicedel
($vmid, $deviceid);
3554 } elsif ($deviceid =~ m/^usb\d+$/) {
3556 die "usb hotplug currently not reliable\n";
3557 # when unplugging usb devices this way,
3558 # there may be remaining usb controllers/hubs
3559 # so we disable it for now
3560 qemu_devicedel
($vmid, $deviceid);
3561 qemu_devicedelverify
($vmid, $deviceid);
3563 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3565 qemu_devicedel
($vmid, $deviceid);
3566 qemu_devicedelverify
($vmid, $deviceid);
3567 qemu_drivedel
($vmid, $deviceid);
3568 qemu_iothread_del
($conf, $vmid, $deviceid);
3570 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3572 qemu_devicedel
($vmid, $deviceid);
3573 qemu_devicedelverify
($vmid, $deviceid);
3574 qemu_iothread_del
($conf, $vmid, $deviceid);
3576 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3578 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3579 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3580 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3582 qemu_devicedel
($vmid, $deviceid);
3583 qemu_drivedel
($vmid, $deviceid);
3584 qemu_deletescsihw
($conf, $vmid, $deviceid);
3586 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3588 qemu_devicedel
($vmid, $deviceid);
3589 qemu_devicedelverify
($vmid, $deviceid);
3590 qemu_netdevdel
($vmid, $deviceid);
3593 die "can't unplug device '$deviceid'\n";
3599 sub qemu_deviceadd
{
3600 my ($vmid, $devicefull) = @_;
3602 $devicefull = "driver=".$devicefull;
3603 my %options = split(/[=,]/, $devicefull);
3605 vm_mon_cmd
($vmid, "device_add" , %options);
3608 sub qemu_devicedel
{
3609 my ($vmid, $deviceid) = @_;
3611 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3614 sub qemu_iothread_add
{
3615 my($vmid, $deviceid, $device) = @_;
3617 if ($device->{iothread
}) {
3618 my $iothreads = vm_iothreads_list
($vmid);
3619 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3623 sub qemu_iothread_del
{
3624 my($conf, $vmid, $deviceid) = @_;
3626 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3627 if ($device->{iothread
}) {
3628 my $iothreads = vm_iothreads_list
($vmid);
3629 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3633 sub qemu_objectadd
{
3634 my($vmid, $objectid, $qomtype) = @_;
3636 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3641 sub qemu_objectdel
{
3642 my($vmid, $objectid) = @_;
3644 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3650 my ($storecfg, $vmid, $device) = @_;
3652 my $drive = print_drive_full
($storecfg, $vmid, $device);
3653 $drive =~ s/\\/\\\\/g;
3654 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3656 # If the command succeeds qemu prints: "OK
"
3657 return 1 if $ret =~ m/OK/s;
3659 die "adding drive failed
: $ret\n";
3663 my($vmid, $deviceid) = @_;
3665 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3668 return 1 if $ret eq "";
3670 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3671 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3673 die "deleting drive
$deviceid failed
: $ret\n";
3676 sub qemu_deviceaddverify {
3677 my ($vmid, $deviceid) = @_;
3679 for (my $i = 0; $i <= 5; $i++) {
3680 my $devices_list = vm_devices_list($vmid);
3681 return 1 if defined($devices_list->{$deviceid});
3685 die "error on hotplug device
'$deviceid'\n";
3689 sub qemu_devicedelverify {
3690 my ($vmid, $deviceid) = @_;
3692 # need to verify that the device is correctly removed as device_del
3693 # is async and empty return is not reliable
3695 for (my $i = 0; $i <= 5; $i++) {
3696 my $devices_list = vm_devices_list($vmid);
3697 return 1 if !defined($devices_list->{$deviceid});
3701 die "error on hot-unplugging device
'$deviceid'\n";
3704 sub qemu_findorcreatescsihw {
3705 my ($storecfg, $conf, $vmid, $device) = @_;
3707 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3709 my $scsihwid="$controller_prefix$controller";
3710 my $devices_list = vm_devices_list($vmid);
3712 if(!defined($devices_list->{$scsihwid})) {
3713 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3719 sub qemu_deletescsihw {
3720 my ($conf, $vmid, $opt) = @_;
3722 my $device = parse_drive($opt, $conf->{$opt});
3724 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3725 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3729 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3731 my $devices_list = vm_devices_list($vmid);
3732 foreach my $opt (keys %{$devices_list}) {
3733 if (PVE::QemuServer::is_valid_drivename($opt)) {
3734 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3735 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3741 my $scsihwid="scsihw
$controller";
3743 vm_deviceunplug($vmid, $conf, $scsihwid);
3748 sub qemu_add_pci_bridge {
3749 my ($storecfg, $conf, $vmid, $device) = @_;
3755 print_pci_addr($device, $bridges);
3757 while (my ($k, $v) = each %$bridges) {
3760 return 1 if !defined($bridgeid) || $bridgeid < 1;
3762 my $bridge = "pci
.$bridgeid";
3763 my $devices_list = vm_devices_list($vmid);
3765 if (!defined($devices_list->{$bridge})) {
3766 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3772 sub qemu_set_link_status {
3773 my ($vmid, $device, $up) = @_;
3775 vm_mon_cmd($vmid, "set_link
", name => $device,
3776 up => $up ? JSON::true : JSON::false);
3779 sub qemu_netdevadd {
3780 my ($vmid, $conf, $device, $deviceid) = @_;
3782 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3783 my %options = split(/[=,]/, $netdev);
3785 vm_mon_cmd($vmid, "netdev_add
", %options);
3789 sub qemu_netdevdel {
3790 my ($vmid, $deviceid) = @_;
3792 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3795 sub qemu_usb_hotplug {
3796 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3800 # remove the old one first
3801 vm_deviceunplug($vmid, $conf, $deviceid);
3803 # check if xhci controller is necessary and available
3804 if ($device->{usb3}) {
3806 my $devicelist = vm_devices_list($vmid);
3808 if (!$devicelist->{xhci}) {
3809 my $pciaddr = print_pci_addr("xhci
");
3810 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3813 my $d = parse_usb_device($device->{host});
3814 $d->{usb3} = $device->{usb3};
3817 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3820 sub qemu_cpu_hotplug {
3821 my ($vmid, $conf, $vcpus) = @_;
3823 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3826 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3827 $sockets = $conf->{sockets} if $conf->{sockets};
3828 my $cores = $conf->{cores} || 1;
3829 my $maxcpus = $sockets * $cores;
3831 $vcpus = $maxcpus if !$vcpus;
3833 die "you can
't add more vcpus than maxcpus\n"
3834 if $vcpus > $maxcpus;
3836 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3838 if ($vcpus < $currentvcpus) {
3840 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3842 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3843 qemu_devicedel($vmid, "cpu$i");
3845 my $currentrunningvcpus = undef;
3847 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3848 last if scalar(@{$currentrunningvcpus}) == $i-1;
3849 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3853 #update conf after each succesfull cpu unplug
3854 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3855 PVE::QemuConfig->write_config($vmid, $conf);
3858 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3864 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3865 die "vcpus in running vm does not match its configuration\n"
3866 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3868 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3870 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3871 my $cpustr = print_cpu_device($conf, $i);
3872 qemu_deviceadd($vmid, $cpustr);
3875 my $currentrunningvcpus = undef;
3877 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3878 last if scalar(@{$currentrunningvcpus}) == $i;
3879 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3883 #update conf after each succesfull cpu hotplug
3884 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3885 PVE::QemuConfig->write_config($vmid, $conf);
3889 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3890 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3895 sub qemu_block_set_io_throttle {
3896 my ($vmid, $deviceid,
3897 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3898 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3899 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3900 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3902 return if !check_running($vmid) ;
3904 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3906 bps_rd => int($bps_rd),
3907 bps_wr => int($bps_wr),
3909 iops_rd => int($iops_rd),
3910 iops_wr => int($iops_wr),
3911 bps_max => int($bps_max),
3912 bps_rd_max => int($bps_rd_max),
3913 bps_wr_max => int($bps_wr_max),
3914 iops_max => int($iops_max),
3915 iops_rd_max => int($iops_rd_max),
3916 iops_wr_max => int($iops_wr_max),
3917 bps_max_length => int($bps_max_length),
3918 bps_rd_max_length => int($bps_rd_max_length),
3919 bps_wr_max_length => int($bps_wr_max_length),
3920 iops_max_length => int($iops_max_length),
3921 iops_rd_max_length => int($iops_rd_max_length),
3922 iops_wr_max_length => int($iops_wr_max_length),
3927 # old code, only used to shutdown old VM after update
3929 my ($fh, $timeout) = @_;
3931 my $sel = new IO::Select;
3938 while (scalar (@ready = $sel->can_read($timeout))) {
3940 if ($count = $fh->sysread($buf, 8192)) {
3941 if ($buf =~ /^(.*)\(qemu\) $/s) {
3948 if (!defined($count)) {
3955 die "monitor read timeout\n" if !scalar(@ready);
3960 # old code, only used to shutdown old VM after update
3961 sub vm_monitor_command {
3962 my ($vmid, $cmdstr, $nocheck) = @_;
3967 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3969 my $sname = "${var_run_tmpdir}/$vmid.mon";
3971 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3972 die "unable to connect to VM $vmid socket - $!\n";
3976 # hack: migrate sometime blocks the monitor (when migrate_downtime
3978 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3979 $timeout = 60*60; # 1 hour
3983 my $data = __read_avail($sock, $timeout);
3985 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3986 die "got unexpected qemu monitor banner\n";
3989 my $sel = new IO::Select;
3992 if (!scalar(my @ready = $sel->can_write($timeout))) {
3993 die "monitor write error - timeout";
3996 my $fullcmd = "$cmdstr\r";
3998 # syslog('info
', "VM $vmid monitor command: $cmdstr");
4001 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4002 die "monitor write error - $!";
4005 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
4009 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4010 $timeout = 60*60; # 1 hour
4011 } elsif ($cmdstr =~ m/^(eject|change)/) {
4012 $timeout = 60; # note: cdrom mount command is slow
4014 if ($res = __read_avail($sock, $timeout)) {
4016 my @lines = split("\r?\n", $res);
4018 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4020 $res = join("\n", @lines);
4028 syslog("err", "VM $vmid monitor command failed - $err");
4035 sub qemu_block_resize {
4036 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4038 my $running = check_running($vmid);
4040 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4042 return if !$running;
4044 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4048 sub qemu_volume_snapshot {
4049 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4051 my $running = check_running($vmid);
4053 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4054 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4056 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4060 sub qemu_volume_snapshot_delete {
4061 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4063 my $running = check_running($vmid);
4065 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4066 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4068 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4072 sub set_migration_caps {
4078 "auto-converge" => 1,
4080 "x-rdma-pin-all" => 0,
4085 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4087 for my $supported_capability (@$supported_capabilities) {
4089 capability => $supported_capability->{capability},
4090 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4094 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4097 my $fast_plug_option = {
4105 'vmstatestorage
' => 1,
4108 # hotplug changes in [PENDING]
4109 # $selection hash can be used to only apply specified options, for
4110 # example: { cores => 1 } (only apply changed 'cores
')
4111 # $errors ref is used to return error messages
4112 sub vmconfig_hotplug_pending {
4113 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4115 my $defaults = load_defaults();
4117 # commit values which do not have any impact on running VM first
4118 # Note: those option cannot raise errors, we we do not care about
4119 # $selection and always apply them.
4121 my $add_error = sub {
4122 my ($opt, $msg) = @_;
4123 $errors->{$opt} = "hotplug problem - $msg";
4127 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4128 if ($fast_plug_option->{$opt}) {
4129 $conf->{$opt} = $conf->{pending}->{$opt};
4130 delete $conf->{pending}->{$opt};
4136 PVE::QemuConfig->write_config($vmid, $conf);
4137 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4140 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4142 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4143 while (my ($opt, $force) = each %$pending_delete_hash) {
4144 next if $selection && !$selection->{$opt};
4146 if ($opt eq 'hotplug
') {
4147 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4148 } elsif ($opt eq 'tablet
') {
4149 die "skip\n" if !$hotplug_features->{usb};
4150 if ($defaults->{tablet}) {
4151 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4153 vm_deviceunplug($vmid, $conf, $opt);
4155 } elsif ($opt =~ m/^usb\d+/) {
4157 # since we cannot reliably hot unplug usb devices
4158 # we are disabling it
4159 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4160 vm_deviceunplug($vmid, $conf, $opt);
4161 } elsif ($opt eq 'vcpus
') {
4162 die "skip\n" if !$hotplug_features->{cpu};
4163 qemu_cpu_hotplug($vmid, $conf, undef);
4164 } elsif ($opt eq 'balloon
') {
4165 # enable balloon device is not hotpluggable
4166 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4167 } elsif ($fast_plug_option->{$opt}) {
4169 } elsif ($opt =~ m/^net(\d+)$/) {
4170 die "skip\n" if !$hotplug_features->{network};
4171 vm_deviceunplug($vmid, $conf, $opt);
4172 } elsif (is_valid_drivename($opt)) {
4173 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4174 vm_deviceunplug($vmid, $conf, $opt);
4175 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4176 } elsif ($opt =~ m/^memory$/) {
4177 die "skip\n" if !$hotplug_features->{memory};
4178 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4179 } elsif ($opt eq 'cpuunits
') {
4180 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4181 } elsif ($opt eq 'cpulimit
') {
4182 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4188 &$add_error($opt, $err) if $err ne "skip\n";
4190 # save new config if hotplug was successful
4191 delete $conf->{$opt};
4192 vmconfig_undelete_pending_option($conf, $opt);
4193 PVE::QemuConfig->write_config($vmid, $conf);
4194 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4198 foreach my $opt (keys %{$conf->{pending}}) {
4199 next if $selection && !$selection->{$opt};
4200 my $value = $conf->{pending}->{$opt};
4202 if ($opt eq 'hotplug
') {
4203 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4204 } elsif ($opt eq 'tablet
') {
4205 die "skip\n" if !$hotplug_features->{usb};
4207 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4208 } elsif ($value == 0) {
4209 vm_deviceunplug($vmid, $conf, $opt);
4211 } elsif ($opt =~ m/^usb\d+$/) {
4213 # since we cannot reliably hot unplug usb devices
4214 # we are disabling it
4215 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4216 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4217 die "skip\n" if !$d;
4218 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4219 } elsif ($opt eq 'vcpus
') {
4220 die "skip\n" if !$hotplug_features->{cpu};
4221 qemu_cpu_hotplug($vmid, $conf, $value);
4222 } elsif ($opt eq 'balloon
') {
4223 # enable/disable balloning device is not hotpluggable
4224 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4225 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4226 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4228 # allow manual ballooning if shares is set to zero
4229 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4230 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4231 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4233 } elsif ($opt =~ m/^net(\d+)$/) {
4234 # some changes can be done without hotplug
4235 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4236 $vmid, $opt, $value);
4237 } elsif (is_valid_drivename($opt)) {
4238 # some changes can be done without hotplug
4239 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4240 $vmid, $opt, $value, 1);
4241 } elsif ($opt =~ m/^memory$/) { #dimms
4242 die "skip\n" if !$hotplug_features->{memory};
4243 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4244 } elsif ($opt eq 'cpuunits
') {
4245 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4246 } elsif ($opt eq 'cpulimit
') {
4247 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4248 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4250 die "skip\n"; # skip non-hot-pluggable options
4254 &$add_error($opt, $err) if $err ne "skip\n";
4256 # save new config if hotplug was successful
4257 $conf->{$opt} = $value;
4258 delete $conf->{pending}->{$opt};
4259 PVE::QemuConfig->write_config($vmid, $conf);
4260 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4265 sub try_deallocate_drive {
4266 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4268 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4269 my $volid = $drive->{file};
4270 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4271 my $sid = PVE::Storage::parse_volume_id($volid);
4272 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4274 # check if the disk is really unused
4275 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4276 if is_volume_in_use($storecfg, $conf, $key, $volid);
4277 PVE::Storage::vdisk_free($storecfg, $volid);
4280 # If vm is not owner of this disk remove from config
4288 sub vmconfig_delete_or_detach_drive {
4289 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4291 my $drive = parse_drive($opt, $conf->{$opt});
4293 my $rpcenv = PVE::RPCEnvironment::get();
4294 my $authuser = $rpcenv->get_user();
4297 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4298 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4300 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4304 sub vmconfig_apply_pending {
4305 my ($vmid, $conf, $storecfg) = @_;
4309 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4310 while (my ($opt, $force) = each %$pending_delete_hash) {
4311 die "internal error" if $opt =~ m/^unused/;
4312 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4313 if (!defined($conf->{$opt})) {
4314 vmconfig_undelete_pending_option($conf, $opt);
4315 PVE::QemuConfig->write_config($vmid, $conf);
4316 } elsif (is_valid_drivename($opt)) {
4317 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4318 vmconfig_undelete_pending_option($conf, $opt);
4319 delete $conf->{$opt};
4320 PVE::QemuConfig->write_config($vmid, $conf);
4322 vmconfig_undelete_pending_option($conf, $opt);
4323 delete $conf->{$opt};
4324 PVE::QemuConfig->write_config($vmid, $conf);
4328 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4330 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4331 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4333 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4334 # skip if nothing changed
4335 } elsif (is_valid_drivename($opt)) {
4336 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4337 if defined($conf->{$opt});
4338 $conf->{$opt} = $conf->{pending}->{$opt};
4340 $conf->{$opt} = $conf->{pending}->{$opt};
4343 delete $conf->{pending}->{$opt};
4344 PVE::QemuConfig->write_config($vmid, $conf);
4348 my $safe_num_ne = sub {
4351 return 0 if !defined($a) && !defined($b);
4352 return 1 if !defined($a);
4353 return 1 if !defined($b);
4358 my $safe_string_ne = sub {
4361 return 0 if !defined($a) && !defined($b);
4362 return 1 if !defined($a);
4363 return 1 if !defined($b);
4368 sub vmconfig_update_net {
4369 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4371 my $newnet = parse_net($value);
4373 if ($conf->{$opt}) {
4374 my $oldnet = parse_net($conf->{$opt});
4376 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4377 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4378 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4379 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4381 # for non online change, we try to hot-unplug
4382 die "skip\n" if !$hotplug;
4383 vm_deviceunplug($vmid, $conf, $opt);
4386 die "internal error" if $opt !~ m/net(\d+)/;
4387 my $iface = "tap${vmid}i$1";
4389 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4390 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4391 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4392 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4393 PVE::Network::tap_unplug($iface);
4394 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4395 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4396 # Rate can be applied on its own but any change above needs to
4397 # include the rate in tap_plug since OVS resets everything.
4398 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4401 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4402 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4410 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4416 sub vmconfig_update_disk {
4417 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4419 # fixme: do we need force?
4421 my $drive = parse_drive($opt, $value);
4423 if ($conf->{$opt}) {
4425 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4427 my $media = $drive->{media} || 'disk
';
4428 my $oldmedia = $old_drive->{media} || 'disk
';
4429 die "unable to change media type\n" if $media ne $oldmedia;
4431 if (!drive_is_cdrom($old_drive)) {
4433 if ($drive->{file} ne $old_drive->{file}) {
4435 die "skip\n" if !$hotplug;
4437 # unplug and register as unused
4438 vm_deviceunplug($vmid, $conf, $opt);
4439 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4442 # update existing disk
4444 # skip non hotpluggable value
4445 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4446 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4447 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4448 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4453 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4454 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4455 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4456 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4457 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4458 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4459 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4460 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4461 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4462 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4463 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4464 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4465 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4466 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4467 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4468 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4469 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4470 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4472 qemu_block_set_io_throttle($vmid,"drive-$opt",
4473 ($drive->{mbps} || 0)*1024*1024,
4474 ($drive->{mbps_rd} || 0)*1024*1024,
4475 ($drive->{mbps_wr} || 0)*1024*1024,
4476 $drive->{iops} || 0,
4477 $drive->{iops_rd} || 0,
4478 $drive->{iops_wr} || 0,
4479 ($drive->{mbps_max} || 0)*1024*1024,
4480 ($drive->{mbps_rd_max} || 0)*1024*1024,
4481 ($drive->{mbps_wr_max} || 0)*1024*1024,
4482 $drive->{iops_max} || 0,
4483 $drive->{iops_rd_max} || 0,
4484 $drive->{iops_wr_max} || 0,
4485 $drive->{bps_max_length} || 1,
4486 $drive->{bps_rd_max_length} || 1,
4487 $drive->{bps_wr_max_length} || 1,
4488 $drive->{iops_max_length} || 1,
4489 $drive->{iops_rd_max_length} || 1,
4490 $drive->{iops_wr_max_length} || 1);
4499 if ($drive->{file} eq 'none
') {
4500 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4502 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4503 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4504 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4512 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4514 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4515 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4519 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4520 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
4522 PVE::QemuConfig->lock_config($vmid, sub {
4523 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4525 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4527 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4529 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4531 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4532 vmconfig_apply_pending($vmid, $conf, $storecfg);
4533 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4536 my $defaults = load_defaults();
4538 # set environment variable useful inside network script
4539 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4541 my $local_volumes = {};
4543 if ($targetstorage) {
4544 foreach_drive($conf, sub {
4545 my ($ds, $drive) = @_;
4547 return if drive_is_cdrom($drive);
4549 my $volid = $drive->{file};
4553 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
4555 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4556 return if $scfg->{shared};
4557 $local_volumes->{$ds} = [$volid, $storeid, $volname];
4562 foreach my $opt (sort keys %$local_volumes) {
4564 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
4565 my $drive = parse_drive($opt, $conf->{$opt});
4567 #if remote storage is specified, use default format
4568 if ($targetstorage && $targetstorage ne "1") {
4569 $storeid = $targetstorage;
4570 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4571 $format = $defFormat;
4573 #else we use same format than original
4574 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4575 $format = qemu_img_format($scfg, $volid);
4578 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
4579 my $newdrive = $drive;
4580 $newdrive->{format} = $format;
4581 $newdrive->{file} = $newvolid;
4582 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
4583 $local_volumes->{$opt} = $drivestr;
4584 #pass drive to conf for command line
4585 $conf->{$opt} = $drivestr;
4589 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4591 my $migrate_port = 0;
4594 if ($statefile eq 'tcp
') {
4595 my $localip = "localhost";
4596 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4597 my $nodename = PVE::INotify::nodename();
4599 if (!defined($migration_type)) {
4600 if (defined($datacenterconf->{migration}->{type})) {
4601 $migration_type = $datacenterconf->{migration}->{type};
4603 $migration_type = 'secure
';
4607 if ($migration_type eq 'insecure
') {
4608 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4609 if ($migrate_network_addr) {
4610 $localip = $migrate_network_addr;
4612 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4615 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4618 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4619 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4620 $migrate_uri = "tcp:${localip}:${migrate_port}";
4621 push @$cmd, '-incoming
', $migrate_uri;
4624 } elsif ($statefile eq 'unix
') {
4625 # should be default for secure migrations as a ssh TCP forward
4626 # tunnel is not deterministic reliable ready and fails regurarly
4627 # to set up in time, so use UNIX socket forwards
4628 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4629 unlink $socket_addr;
4631 $migrate_uri = "unix:$socket_addr";
4633 push @$cmd, '-incoming
', $migrate_uri;
4637 push @$cmd, '-loadstate
', $statefile;
4644 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4645 my $d = parse_hostpci($conf->{"hostpci$i"});
4647 my $pcidevices = $d->{pciid};
4648 foreach my $pcidevice (@$pcidevices) {
4649 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4651 my $info = pci_device_info("0000:$pciid");
4652 die "IOMMU not present\n" if !check_iommu_support();
4653 die "no pci device info for device '$pciid'\n" if !$info;
4654 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4655 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4659 PVE::Storage::activate_volumes($storecfg, $vollist);
4661 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4663 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4664 eval { run_command($cmd); };
4667 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4668 : $defaults->{cpuunits};
4670 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4673 Slice => 'qemu
.slice
',
4675 CPUShares => $cpuunits
4678 if (my $cpulimit = $conf->{cpulimit}) {
4679 $properties{CPUQuota} = int($cpulimit * 100);
4681 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4683 if ($conf->{hugepages}) {
4686 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4687 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4689 PVE::QemuServer::Memory::hugepages_mount();
4690 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4693 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4694 run_command($cmd, %run_params);
4698 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4702 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4704 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4708 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4709 run_command($cmd, %run_params);
4714 # deactivate volumes if start fails
4715 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4716 die "start failed: $err";
4719 print "migration listens on $migrate_uri\n" if $migrate_uri;
4721 if ($statefile && $statefile ne 'tcp
' && $statefile ne 'unix
') {
4722 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4726 #start nbd server for storage migration
4727 if ($targetstorage) {
4728 my $nodename = PVE::INotify::nodename();
4729 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4730 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
4731 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4732 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4734 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet
', data => { host => "${localip}", port => "${migrate_port}" } } );
4736 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4738 foreach my $opt (sort keys %$local_volumes) {
4739 my $volid = $local_volumes->{$opt};
4740 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
4741 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
4742 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
4746 if ($migratedfrom) {
4748 set_migration_caps($vmid);
4753 print "spice listens on port $spice_port\n";
4754 if ($spice_ticket) {
4755 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4756 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4761 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4762 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4763 if $conf->{balloon};
4766 foreach my $opt (keys %$conf) {
4767 next if $opt !~ m/^net\d+$/;
4768 my $nicconf = parse_net($conf->{$opt});
4769 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4773 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4774 path => "machine/peripheral/balloon0",
4775 property => "guest-stats-polling-interval",
4776 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4782 my ($vmid, $execute, %params) = @_;
4784 my $cmd = { execute => $execute, arguments => \%params };
4785 vm_qmp_command($vmid, $cmd);
4788 sub vm_mon_cmd_nocheck {
4789 my ($vmid, $execute, %params) = @_;
4791 my $cmd = { execute => $execute, arguments => \%params };
4792 vm_qmp_command($vmid, $cmd, 1);
4795 sub vm_qmp_command {
4796 my ($vmid, $cmd, $nocheck) = @_;
4801 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4802 $timeout = $cmd->{arguments}->{timeout};
4803 delete $cmd->{arguments}->{timeout};
4807 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4808 my $sname = qmp_socket($vmid);
4809 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4810 my $qmpclient = PVE::QMPClient->new();
4812 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4813 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4814 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4815 if scalar(%{$cmd->{arguments}});
4816 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4818 die "unable to
open monitor
socket\n";
4822 syslog("err
", "VM
$vmid qmp command failed
- $err");
4829 sub vm_human_monitor_command {
4830 my ($vmid, $cmdline) = @_;
4835 execute => 'human-monitor-command',
4836 arguments => { 'command-line' => $cmdline},
4839 return vm_qmp_command($vmid, $cmd);
4842 sub vm_commandline {
4843 my ($storecfg, $vmid) = @_;
4845 my $conf = PVE::QemuConfig->load_config($vmid);
4847 my $defaults = load_defaults();
4849 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4851 return PVE::Tools::cmd2string($cmd);
4855 my ($vmid, $skiplock) = @_;
4857 PVE::QemuConfig->lock_config($vmid, sub {
4859 my $conf = PVE::QemuConfig->load_config($vmid);
4861 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4863 vm_mon_cmd($vmid, "system_reset
");
4867 sub get_vm_volumes {
4871 foreach_volid($conf, sub {
4872 my ($volid, $attr) = @_;
4874 return if $volid =~ m|^/|;
4876 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4879 push @$vollist, $volid;
4885 sub vm_stop_cleanup {
4886 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4891 my $vollist = get_vm_volumes($conf);
4892 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4895 foreach my $ext (qw(mon qmp pid vnc qga)) {
4896 unlink "/var/run/qemu-server/${vmid}.$ext";
4899 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4901 warn $@ if $@; # avoid errors - just warn
4904 # Note: use $nockeck to skip tests if VM configuration file exists.
4905 # We need that when migration VMs to other nodes (files already moved)
4906 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4908 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4910 $force = 1 if !defined($force) && !$shutdown;
4913 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4914 kill 15, $pid if $pid;
4915 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4916 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4920 PVE
::QemuConfig-
>lock_config($vmid, sub {
4922 my $pid = check_running
($vmid, $nocheck);
4927 $conf = PVE
::QemuConfig-
>load_config($vmid);
4928 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4929 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4930 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4931 $timeout = $opts->{down
} if $opts->{down
};
4935 $timeout = 60 if !defined($timeout);
4939 if (defined($conf) && $conf->{agent
}) {
4940 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4942 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4945 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4952 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4957 if ($count >= $timeout) {
4959 warn "VM still running - terminating now with SIGTERM\n";
4962 die "VM quit/powerdown failed - got timeout\n";
4965 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4970 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4973 die "VM quit/powerdown failed\n";
4981 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4986 if ($count >= $timeout) {
4987 warn "VM still running - terminating now with SIGKILL\n";
4992 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4997 my ($vmid, $skiplock) = @_;
4999 PVE
::QemuConfig-
>lock_config($vmid, sub {
5001 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5003 PVE
::QemuConfig-
>check_lock($conf)
5004 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5006 vm_mon_cmd
($vmid, "stop");
5011 my ($vmid, $skiplock, $nocheck) = @_;
5013 PVE
::QemuConfig-
>lock_config($vmid, sub {
5017 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5019 PVE
::QemuConfig-
>check_lock($conf)
5020 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5022 vm_mon_cmd
($vmid, "cont");
5025 vm_mon_cmd_nocheck
($vmid, "cont");
5031 my ($vmid, $skiplock, $key) = @_;
5033 PVE
::QemuConfig-
>lock_config($vmid, sub {
5035 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5037 # there is no qmp command, so we use the human monitor command
5038 vm_human_monitor_command
($vmid, "sendkey $key");
5043 my ($storecfg, $vmid, $skiplock) = @_;
5045 PVE
::QemuConfig-
>lock_config($vmid, sub {
5047 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5049 if (!check_running
($vmid)) {
5050 destroy_vm
($storecfg, $vmid, undef, $skiplock);
5052 die "VM $vmid is running - destroy failed\n";
5060 my ($filename, $buf) = @_;
5062 my $fh = IO
::File-
>new($filename, "w");
5063 return undef if !$fh;
5065 my $res = print $fh $buf;
5072 sub pci_device_info
{
5077 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
5078 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
5080 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
5081 return undef if !defined($irq) || $irq !~ m/^\d+$/;
5083 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
5084 return undef if !defined($vendor) || $vendor !~ s/^0x//;
5086 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
5087 return undef if !defined($product) || $product !~ s/^0x//;
5092 product
=> $product,
5098 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
5107 my $name = $dev->{name
};
5109 my $fn = "$pcisysfs/devices/$name/reset";
5111 return file_write
($fn, "1");
5114 sub pci_dev_bind_to_vfio
{
5117 my $name = $dev->{name
};
5119 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5121 if (!-d
$vfio_basedir) {
5122 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5124 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5126 my $testdir = "$vfio_basedir/$name";
5127 return 1 if -d
$testdir;
5129 my $data = "$dev->{vendor} $dev->{product}";
5130 return undef if !file_write
("$vfio_basedir/new_id", $data);
5132 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5133 if (!file_write
($fn, $name)) {
5134 return undef if -f
$fn;
5137 $fn = "$vfio_basedir/bind";
5138 if (! -d
$testdir) {
5139 return undef if !file_write
($fn, $name);
5145 sub pci_dev_group_bind_to_vfio
{
5148 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5150 if (!-d
$vfio_basedir) {
5151 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5153 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5155 # get IOMMU group devices
5156 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5157 my @devs = grep /^0000:/, readdir($D);
5160 foreach my $pciid (@devs) {
5161 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5163 # pci bridges, switches or root ports are not supported
5164 # they have a pci_bus subdirectory so skip them
5165 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5167 my $info = pci_device_info
($1);
5168 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5174 # vzdump restore implementaion
5176 sub tar_archive_read_firstfile
{
5177 my $archive = shift;
5179 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5181 # try to detect archive type first
5182 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5183 die "unable to open file '$archive'\n";
5184 my $firstfile = <$fh>;
5188 die "ERROR: archive contaions no data\n" if !$firstfile;
5194 sub tar_restore_cleanup
{
5195 my ($storecfg, $statfile) = @_;
5197 print STDERR
"starting cleanup\n";
5199 if (my $fd = IO
::File-
>new($statfile, "r")) {
5200 while (defined(my $line = <$fd>)) {
5201 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5204 if ($volid =~ m
|^/|) {
5205 unlink $volid || die 'unlink failed\n';
5207 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5209 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5211 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5213 print STDERR
"unable to parse line in statfile - $line";
5220 sub restore_archive
{
5221 my ($archive, $vmid, $user, $opts) = @_;
5223 my $format = $opts->{format
};
5226 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5227 $format = 'tar' if !$format;
5229 } elsif ($archive =~ m/\.tar$/) {
5230 $format = 'tar' if !$format;
5231 } elsif ($archive =~ m/.tar.lzo$/) {
5232 $format = 'tar' if !$format;
5234 } elsif ($archive =~ m/\.vma$/) {
5235 $format = 'vma' if !$format;
5236 } elsif ($archive =~ m/\.vma\.gz$/) {
5237 $format = 'vma' if !$format;
5239 } elsif ($archive =~ m/\.vma\.lzo$/) {
5240 $format = 'vma' if !$format;
5243 $format = 'vma' if !$format; # default
5246 # try to detect archive format
5247 if ($format eq 'tar') {
5248 return restore_tar_archive
($archive, $vmid, $user, $opts);
5250 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5254 sub restore_update_config_line
{
5255 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5257 return if $line =~ m/^\#qmdump\#/;
5258 return if $line =~ m/^\#vzdump\#/;
5259 return if $line =~ m/^lock:/;
5260 return if $line =~ m/^unused\d+:/;
5261 return if $line =~ m/^parent:/;
5262 return if $line =~ m/^template:/; # restored VM is never a template
5264 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5265 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5266 # try to convert old 1.X settings
5267 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5268 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5269 my ($model, $macaddr) = split(/\=/, $devconfig);
5270 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5273 bridge
=> "vmbr$ind",
5274 macaddr
=> $macaddr,
5276 my $netstr = print_net
($net);
5278 print $outfd "net$cookie->{netcount}: $netstr\n";
5279 $cookie->{netcount
}++;
5281 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5282 my ($id, $netstr) = ($1, $2);
5283 my $net = parse_net
($netstr);
5284 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5285 $netstr = print_net
($net);
5286 print $outfd "$id: $netstr\n";
5287 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5290 my $di = parse_drive
($virtdev, $value);
5291 if (defined($di->{backup
}) && !$di->{backup
}) {
5292 print $outfd "#$line";
5293 } elsif ($map->{$virtdev}) {
5294 delete $di->{format
}; # format can change on restore
5295 $di->{file
} = $map->{$virtdev};
5296 $value = print_drive
($vmid, $di);
5297 print $outfd "$virtdev: $value\n";
5307 my ($cfg, $vmid) = @_;
5309 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5311 my $volid_hash = {};
5312 foreach my $storeid (keys %$info) {
5313 foreach my $item (@{$info->{$storeid}}) {
5314 next if !($item->{volid
} && $item->{size
});
5315 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5316 $volid_hash->{$item->{volid
}} = $item;
5323 sub is_volume_in_use
{
5324 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5326 my $path = PVE
::Storage
::path
($storecfg, $volid);
5328 my $scan_config = sub {
5329 my ($cref, $snapname) = @_;
5331 foreach my $key (keys %$cref) {
5332 my $value = $cref->{$key};
5333 if (is_valid_drivename
($key)) {
5334 next if $skip_drive && $key eq $skip_drive;
5335 my $drive = parse_drive
($key, $value);
5336 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5337 return 1 if $volid eq $drive->{file
};
5338 if ($drive->{file
} =~ m!^/!) {
5339 return 1 if $drive->{file
} eq $path;
5341 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5343 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5345 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5353 return 1 if &$scan_config($conf);
5357 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5358 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5364 sub update_disksize
{
5365 my ($vmid, $conf, $volid_hash) = @_;
5369 # used and unused disks
5370 my $referenced = {};
5372 # Note: it is allowed to define multiple storages with same path (alias), so
5373 # we need to check both 'volid' and real 'path' (two different volid can point
5374 # to the same path).
5376 my $referencedpath = {};
5379 foreach my $opt (keys %$conf) {
5380 if (is_valid_drivename
($opt)) {
5381 my $drive = parse_drive
($opt, $conf->{$opt});
5382 my $volid = $drive->{file
};
5385 $referenced->{$volid} = 1;
5386 if ($volid_hash->{$volid} &&
5387 (my $path = $volid_hash->{$volid}->{path
})) {
5388 $referencedpath->{$path} = 1;
5391 next if drive_is_cdrom
($drive);
5392 next if !$volid_hash->{$volid};
5394 $drive->{size
} = $volid_hash->{$volid}->{size
};
5395 my $new = print_drive
($vmid, $drive);
5396 if ($new ne $conf->{$opt}) {
5398 $conf->{$opt} = $new;
5403 # remove 'unusedX' entry if volume is used
5404 foreach my $opt (keys %$conf) {
5405 next if $opt !~ m/^unused\d+$/;
5406 my $volid = $conf->{$opt};
5407 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5408 if ($referenced->{$volid} || ($path && $referencedpath->{$path})) {
5410 delete $conf->{$opt};
5413 $referenced->{$volid} = 1;
5414 $referencedpath->{$path} = 1 if $path;
5417 foreach my $volid (sort keys %$volid_hash) {
5418 next if $volid =~ m/vm-$vmid-state-/;
5419 next if $referenced->{$volid};
5420 my $path = $volid_hash->{$volid}->{path
};
5421 next if !$path; # just to be sure
5422 next if $referencedpath->{$path};
5424 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5425 $referencedpath->{$path} = 1; # avoid to add more than once (aliases)
5432 my ($vmid, $nolock) = @_;
5434 my $cfg = PVE
::Storage
::config
();
5436 my $volid_hash = scan_volids
($cfg, $vmid);
5438 my $updatefn = sub {
5441 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5443 PVE
::QemuConfig-
>check_lock($conf);
5446 foreach my $volid (keys %$volid_hash) {
5447 my $info = $volid_hash->{$volid};
5448 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5451 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5453 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5456 if (defined($vmid)) {
5460 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5463 my $vmlist = config_list
();
5464 foreach my $vmid (keys %$vmlist) {
5468 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5474 sub restore_vma_archive
{
5475 my ($archive, $vmid, $user, $opts, $comp) = @_;
5477 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5478 my $readfrom = $archive;
5483 my $qarchive = PVE
::Tools
::shellquote
($archive);
5484 if ($comp eq 'gzip') {
5485 $uncomp = "zcat $qarchive|";
5486 } elsif ($comp eq 'lzop') {
5487 $uncomp = "lzop -d -c $qarchive|";
5489 die "unknown compression method '$comp'\n";
5494 my $tmpdir = "/var/tmp/vzdumptmp$$";
5497 # disable interrupts (always do cleanups)
5501 local $SIG{HUP
} = sub { warn "got interrupt - ignored\n"; };
5503 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5504 POSIX
::mkfifo
($mapfifo, 0600);
5507 my $openfifo = sub {
5508 open($fifofh, '>', $mapfifo) || die $!;
5511 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5518 my $rpcenv = PVE
::RPCEnvironment
::get
();
5520 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5521 my $tmpfn = "$conffile.$$.tmp";
5523 # Note: $oldconf is undef if VM does not exists
5524 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5525 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5527 my $print_devmap = sub {
5528 my $virtdev_hash = {};
5530 my $cfgfn = "$tmpdir/qemu-server.conf";
5532 # we can read the config - that is already extracted
5533 my $fh = IO
::File-
>new($cfgfn, "r") ||
5534 "unable to read qemu-server.conf - $!\n";
5536 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5538 my $pve_firewall_dir = '/etc/pve/firewall';
5539 mkdir $pve_firewall_dir; # make sure the dir exists
5540 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5543 while (defined(my $line = <$fh>)) {
5544 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5545 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5546 die "archive does not contain data for drive '$virtdev'\n"
5547 if !$devinfo->{$devname};
5548 if (defined($opts->{storage
})) {
5549 $storeid = $opts->{storage
} || 'local';
5550 } elsif (!$storeid) {
5553 $format = 'raw' if !$format;
5554 $devinfo->{$devname}->{devname
} = $devname;
5555 $devinfo->{$devname}->{virtdev
} = $virtdev;
5556 $devinfo->{$devname}->{format
} = $format;
5557 $devinfo->{$devname}->{storeid
} = $storeid;
5559 # check permission on storage
5560 my $pool = $opts->{pool
}; # todo: do we need that?
5561 if ($user ne 'root@pam') {
5562 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5565 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5569 foreach my $devname (keys %$devinfo) {
5570 die "found no device mapping information for device '$devname'\n"
5571 if !$devinfo->{$devname}->{virtdev
};
5574 my $cfg = PVE
::Storage
::config
();
5576 # create empty/temp config
5578 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5579 foreach_drive
($oldconf, sub {
5580 my ($ds, $drive) = @_;
5582 return if drive_is_cdrom
($drive);
5584 my $volid = $drive->{file
};
5586 return if !$volid || $volid =~ m
|^/|;
5588 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5589 return if !$path || !$owner || ($owner != $vmid);
5591 # Note: only delete disk we want to restore
5592 # other volumes will become unused
5593 if ($virtdev_hash->{$ds}) {
5594 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5601 # delete vmstate files
5602 # since after the restore we have no snapshots anymore
5603 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5604 my $snap = $oldconf->{snapshots
}->{$snapname};
5605 if ($snap->{vmstate
}) {
5606 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5615 foreach my $virtdev (sort keys %$virtdev_hash) {
5616 my $d = $virtdev_hash->{$virtdev};
5617 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5618 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5620 # test if requested format is supported
5621 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5622 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5623 $d->{format
} = $defFormat if !$supported;
5625 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5626 $d->{format
}, undef, $alloc_size);
5627 print STDERR
"new volume ID is '$volid'\n";
5628 $d->{volid
} = $volid;
5629 my $path = PVE
::Storage
::path
($cfg, $volid);
5631 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5633 my $write_zeros = 1;
5634 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5638 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5640 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5641 $map->{$virtdev} = $volid;
5644 $fh->seek(0, 0) || die "seek failed - $!\n";
5646 my $outfd = new IO
::File
($tmpfn, "w") ||
5647 die "unable to write config for VM $vmid\n";
5649 my $cookie = { netcount
=> 0 };
5650 while (defined(my $line = <$fh>)) {
5651 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5664 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5665 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5667 $oldtimeout = alarm($timeout);
5674 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5675 my ($dev_id, $size, $devname) = ($1, $2, $3);
5676 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5677 } elsif ($line =~ m/^CTIME: /) {
5678 # we correctly received the vma config, so we can disable
5679 # the timeout now for disk allocation (set to 10 minutes, so
5680 # that we always timeout if something goes wrong)
5683 print $fifofh "done\n";
5684 my $tmp = $oldtimeout || 0;
5685 $oldtimeout = undef;
5691 print "restore vma archive: $cmd\n";
5692 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5696 alarm($oldtimeout) if $oldtimeout;
5699 foreach my $devname (keys %$devinfo) {
5700 my $volid = $devinfo->{$devname}->{volid
};
5701 push @$vollist, $volid if $volid;
5704 my $cfg = PVE
::Storage
::config
();
5705 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5713 foreach my $devname (keys %$devinfo) {
5714 my $volid = $devinfo->{$devname}->{volid
};
5717 if ($volid =~ m
|^/|) {
5718 unlink $volid || die 'unlink failed\n';
5720 PVE
::Storage
::vdisk_free
($cfg, $volid);
5722 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5724 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5731 rename($tmpfn, $conffile) ||
5732 die "unable to commit configuration file '$conffile'\n";
5734 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5736 eval { rescan
($vmid, 1); };
5740 sub restore_tar_archive
{
5741 my ($archive, $vmid, $user, $opts) = @_;
5743 if ($archive ne '-') {
5744 my $firstfile = tar_archive_read_firstfile
($archive);
5745 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5746 if $firstfile ne 'qemu-server.conf';
5749 my $storecfg = PVE
::Storage
::config
();
5751 # destroy existing data - keep empty config
5752 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5753 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5755 my $tocmd = "/usr/lib/qemu-server/qmextract";
5757 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5758 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5759 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5760 $tocmd .= ' --info' if $opts->{info
};
5762 # tar option "xf" does not autodetect compression when read from STDIN,
5763 # so we pipe to zcat
5764 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5765 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5767 my $tmpdir = "/var/tmp/vzdumptmp$$";
5770 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5771 local $ENV{VZDUMP_VMID
} = $vmid;
5772 local $ENV{VZDUMP_USER
} = $user;
5774 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5775 my $tmpfn = "$conffile.$$.tmp";
5777 # disable interrupts (always do cleanups)
5781 local $SIG{HUP
} = sub { print STDERR
"got interrupt - ignored\n"; };
5789 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5791 if ($archive eq '-') {
5792 print "extracting archive from STDIN\n";
5793 run_command
($cmd, input
=> "<&STDIN");
5795 print "extracting archive '$archive'\n";
5799 return if $opts->{info
};
5803 my $statfile = "$tmpdir/qmrestore.stat";
5804 if (my $fd = IO
::File-
>new($statfile, "r")) {
5805 while (defined (my $line = <$fd>)) {
5806 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5807 $map->{$1} = $2 if $1;
5809 print STDERR
"unable to parse line in statfile - $line\n";
5815 my $confsrc = "$tmpdir/qemu-server.conf";
5817 my $srcfd = new IO
::File
($confsrc, "r") ||
5818 die "unable to open file '$confsrc'\n";
5820 my $outfd = new IO
::File
($tmpfn, "w") ||
5821 die "unable to write config for VM $vmid\n";
5823 my $cookie = { netcount
=> 0 };
5824 while (defined (my $line = <$srcfd>)) {
5825 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5837 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5844 rename $tmpfn, $conffile ||
5845 die "unable to commit configuration file '$conffile'\n";
5847 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5849 eval { rescan
($vmid, 1); };
5853 sub foreach_storage_used_by_vm
{
5854 my ($conf, $func) = @_;
5858 foreach_drive
($conf, sub {
5859 my ($ds, $drive) = @_;
5860 return if drive_is_cdrom
($drive);
5862 my $volid = $drive->{file
};
5864 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5865 $sidhash->{$sid} = $sid if $sid;
5868 foreach my $sid (sort keys %$sidhash) {
5873 sub do_snapshots_with_qemu
{
5874 my ($storecfg, $volid) = @_;
5876 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5878 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5879 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5883 if ($volid =~ m/\.(qcow2|qed)$/){
5890 sub qga_check_running
{
5893 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5895 warn "Qemu Guest Agent is not running - $@";
5901 sub template_create
{
5902 my ($vmid, $conf, $disk) = @_;
5904 my $storecfg = PVE
::Storage
::config
();
5906 foreach_drive
($conf, sub {
5907 my ($ds, $drive) = @_;
5909 return if drive_is_cdrom
($drive);
5910 return if $disk && $ds ne $disk;
5912 my $volid = $drive->{file
};
5913 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5915 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5916 $drive->{file
} = $voliddst;
5917 $conf->{$ds} = print_drive
($vmid, $drive);
5918 PVE
::QemuConfig-
>write_config($vmid, $conf);
5922 sub qemu_img_convert
{
5923 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5925 my $storecfg = PVE
::Storage
::config
();
5926 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5927 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5929 if ($src_storeid && $dst_storeid) {
5931 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5933 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5934 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5936 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5937 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5939 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5940 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5943 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5944 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5945 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5946 if ($is_zero_initialized) {
5947 push @$cmd, "zeroinit:$dst_path";
5949 push @$cmd, $dst_path;
5954 if($line =~ m/\((\S+)\/100\
%\)/){
5956 my $transferred = int($size * $percent / 100);
5957 my $remaining = $size - $transferred;
5959 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5964 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5966 die "copy failed: $err" if $err;
5970 sub qemu_img_format
{
5971 my ($scfg, $volname) = @_;
5973 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5980 sub qemu_drive_mirror
{
5981 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
5983 $jobs = {} if !$jobs;
5987 $jobs->{"drive-$drive"} = {};
5989 if ($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+):exportname=(\S+)/) {
5992 my $exportname = $3;
5995 my $unixsocket = "/run/qemu-server/$vmid.mirror-drive-$drive";
5996 $qemu_target = "nbd+unix:///$exportname?socket=$unixsocket";
5997 my $cmd = ['socat', '-T30', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=5"];
6000 if (!defined($pid)) {
6001 die "forking socat tunnel failed\n";
6002 } elsif ($pid == 0) {
6004 warn "exec failed: $!\n";
6007 $jobs->{"drive-$drive"}->{pid
} = $pid;
6010 while (!-S
$unixsocket) {
6011 die "nbd connection helper timed out\n"
6016 my $storecfg = PVE
::Storage
::config
();
6017 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6019 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6021 $format = qemu_img_format
($dst_scfg, $dst_volname);
6023 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6025 $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
6028 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
6029 $opts->{format
} = $format if $format;
6031 print "drive mirror is starting for drive-$drive\n";
6033 eval { vm_mon_cmd
($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
6036 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6037 die "mirroring error: $err";
6040 qemu_drive_mirror_monitor
($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
6043 sub qemu_drive_mirror_monitor
{
6044 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
6047 my $err_complete = 0;
6050 die "storage migration timed out\n" if $err_complete > 300;
6052 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6054 my $running_mirror_jobs = {};
6055 foreach my $stat (@$stats) {
6056 next if $stat->{type
} ne 'mirror';
6057 $running_mirror_jobs->{$stat->{device
}} = $stat;
6060 my $readycounter = 0;
6062 foreach my $job (keys %$jobs) {
6064 if(defined($jobs->{$job}->{complete
}) && !defined($running_mirror_jobs->{$job})) {
6065 print "$job : finished\n";
6066 delete $jobs->{$job};
6070 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
6072 my $busy = $running_mirror_jobs->{$job}->{busy
};
6073 my $ready = $running_mirror_jobs->{$job}->{ready
};
6074 if (my $total = $running_mirror_jobs->{$job}->{len
}) {
6075 my $transferred = $running_mirror_jobs->{$job}->{offset
} || 0;
6076 my $remaining = $total - $transferred;
6077 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6079 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6082 $readycounter++ if $running_mirror_jobs->{$job}->{ready
};
6085 last if scalar(keys %$jobs) == 0;
6087 if ($readycounter == scalar(keys %$jobs)) {
6088 print "all mirroring jobs are ready \n";
6089 last if $skipcomplete; #do the complete later
6091 if ($vmiddst && $vmiddst != $vmid) {
6092 my $agent_running = $qga && qga_check_running
($vmid);
6093 if ($agent_running) {
6094 print "freeze filesystem\n";
6095 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6097 print "suspend vm\n";
6098 eval { PVE
::QemuServer
::vm_suspend
($vmid, 1); };
6101 # if we clone a disk for a new target vm, we don't switch the disk
6102 PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs);
6104 if ($agent_running) {
6105 print "unfreeze filesystem\n";
6106 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6108 print "resume vm\n";
6109 eval { PVE
::QemuServer
::vm_resume
($vmid, 1, 1); };
6115 foreach my $job (keys %$jobs) {
6116 # try to switch the disk if source and destination are on the same guest
6117 print "$job: Completing block job...\n";
6119 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> $job) };
6120 if ($@ =~ m/cannot be completed/) {
6121 print "$job: Block job cannot be completed, try again.\n";
6124 print "$job: Completed successfully.\n";
6125 $jobs->{$job}->{complete
} = 1;
6126 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6137 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6138 die "mirroring error: $err";
6143 sub qemu_blockjobs_cancel
{
6144 my ($vmid, $jobs) = @_;
6146 foreach my $job (keys %$jobs) {
6147 print "$job: Cancelling block job\n";
6148 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> $job); };
6149 $jobs->{$job}->{cancel
} = 1;
6153 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6155 my $running_jobs = {};
6156 foreach my $stat (@$stats) {
6157 $running_jobs->{$stat->{device
}} = $stat;
6160 foreach my $job (keys %$jobs) {
6162 if (defined($jobs->{$job}->{cancel
}) && !defined($running_jobs->{$job})) {
6163 print "$job: Done.\n";
6164 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6165 delete $jobs->{$job};
6169 last if scalar(keys %$jobs) == 0;
6175 sub qemu_blockjobs_finish_tunnel
{
6176 my ($vmid, $job, $cpid) = @_;
6180 for (my $i = 1; $i < 20; $i++) {
6181 my $waitpid = waitpid($cpid, WNOHANG
);
6182 last if (defined($waitpid) && ($waitpid == $cpid));
6186 } elsif ($i >= 15) {
6191 unlink "/run/qemu-server/$vmid.mirror-$job";
6195 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6196 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
6201 print "create linked clone of drive $drivename ($drive->{file})\n";
6202 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6203 push @$newvollist, $newvolid;
6206 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6207 $storeid = $storage if $storage;
6209 my $dst_format = resolve_dst_disk_format
($storecfg, $storeid, $volname, $format);
6210 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6212 print "create full clone of drive $drivename ($drive->{file})\n";
6213 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $dst_format, undef, ($size/1024));
6214 push @$newvollist, $newvolid;
6216 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
6218 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6219 if (!$running || $snapname) {
6220 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6223 my $kvmver = get_running_qemu_version
($vmid);
6224 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
6225 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6226 if $drive->{iothread
};
6229 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
6233 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6236 $disk->{format
} = undef;
6237 $disk->{file
} = $newvolid;
6238 $disk->{size
} = $size;
6243 # this only works if VM is running
6244 sub get_current_qemu_machine
{
6247 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6248 my $res = vm_qmp_command
($vmid, $cmd);
6250 my ($current, $default);
6251 foreach my $e (@$res) {
6252 $default = $e->{name
} if $e->{'is-default'};
6253 $current = $e->{name
} if $e->{'is-current'};
6256 # fallback to the default machine if current is not supported by qemu
6257 return $current || $default || 'pc';
6260 sub get_running_qemu_version
{
6262 my $cmd = { execute
=> 'query-version', arguments
=> {} };
6263 my $res = vm_qmp_command
($vmid, $cmd);
6264 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6267 sub qemu_machine_feature_enabled
{
6268 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6273 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6275 $current_major = $3;
6276 $current_minor = $4;
6278 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6280 $current_major = $1;
6281 $current_minor = $2;
6284 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6289 sub qemu_machine_pxe
{
6290 my ($vmid, $conf, $machine) = @_;
6292 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6294 foreach my $opt (keys %$conf) {
6295 next if $opt !~ m/^net(\d+)$/;
6296 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6298 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6299 return $machine.".pxe" if $romfile =~ m/pxe/;
6306 sub qemu_use_old_bios_files
{
6307 my ($machine_type) = @_;
6309 return if !$machine_type;
6311 my $use_old_bios_files = undef;
6313 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6315 $use_old_bios_files = 1;
6317 my $kvmver = kvm_user_version
();
6318 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6319 # load new efi bios files on migration. So this hack is required to allow
6320 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6321 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6322 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6325 return ($use_old_bios_files, $machine_type);
6328 sub create_efidisk
{
6329 my ($storecfg, $storeid, $vmid, $fmt) = @_;
6331 die "EFI vars default image not found\n" if ! -f
$OVMF_VARS;
6333 my $vars_size = PVE
::Tools
::convert_size
(-s
$OVMF_VARS, 'b' => 'kb');
6334 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
6335 PVE
::Storage
::activate_volumes
($storecfg, [$volid]);
6337 my $path = PVE
::Storage
::path
($storecfg, $volid);
6339 run_command
(['/usr/bin/qemu-img', 'convert', '-n', '-f', 'raw', '-O', $fmt, $OVMF_VARS, $path]);
6341 die "Copying EFI vars image failed: $@" if $@;
6343 return ($volid, $vars_size);
6350 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6351 my (undef, $id, $function) = @_;
6352 my $res = { id
=> $id, function
=> $function};
6353 push @{$devices->{$id}}, $res;
6356 # Entries should be sorted by functions.
6357 foreach my $id (keys %$devices) {
6358 my $dev = $devices->{$id};
6359 $devices->{$id} = [ sort { $a->{function
} <=> $b->{function
} } @$dev ];
6365 sub vm_iothreads_list
{
6368 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6371 foreach my $iothread (@$res) {
6372 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6379 my ($conf, $drive) = @_;
6383 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)) {
6385 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6391 my $controller = int($drive->{index} / $maxdev);
6392 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6394 return ($maxdev, $controller, $controller_prefix);
6397 sub add_hyperv_enlightenments
{
6398 my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough) = @_;
6400 return if $winversion < 6;
6401 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6403 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6405 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
6406 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6407 push @$cpuFlags , 'hv_vapic';
6408 push @$cpuFlags , 'hv_time';
6410 push @$cpuFlags , 'hv_spinlocks=0xffff';
6413 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
6414 push @$cpuFlags , 'hv_reset';
6415 push @$cpuFlags , 'hv_vpindex';
6416 push @$cpuFlags , 'hv_runtime';
6419 if ($winversion >= 7) {
6420 push @$cpuFlags , 'hv_relaxed';
6424 sub windows_version
{
6427 return 0 if !$ostype;
6431 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6433 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6435 } elsif ($ostype =~ m/^win(\d+)$/) {
6442 sub resolve_dst_disk_format
{
6443 my ($storecfg, $storeid, $src_volname, $format) = @_;
6444 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6447 # if no target format is specified, use the source disk format as hint
6449 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6450 $format = qemu_img_format
($scfg, $src_volname);
6456 # test if requested format is supported - else use default
6457 my $supported = grep { $_ eq $format } @$validFormats;
6458 $format = $defFormat if !$supported;
6462 sub resolve_first_disk
{
6464 my @disks = PVE
::QemuServer
::valid_drive_names
();
6466 foreach my $ds (reverse @disks) {
6467 next if !$conf->{$ds};
6468 my $disk = PVE
::QemuServer
::parse_drive
($ds, $conf->{$ds});
6469 next if PVE
::QemuServer
::drive_is_cdrom
($disk);
6475 sub generate_smbios1_uuid
{
6476 my ($uuid, $uuid_str);
6477 UUID
::generate
($uuid);
6478 UUID
::unparse
($uuid, $uuid_str);
6479 return "uuid=$uuid_str";
6482 # bash completion helper
6484 sub complete_backup_archives
{
6485 my ($cmdname, $pname, $cvalue) = @_;
6487 my $cfg = PVE
::Storage
::config
();
6491 if ($cvalue =~ m/^([^:]+):/) {
6495 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6498 foreach my $id (keys %$data) {
6499 foreach my $item (@{$data->{$id}}) {
6500 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6501 push @$res, $item->{volid
} if defined($item->{volid
});
6508 my $complete_vmid_full = sub {
6511 my $idlist = vmstatus
();
6515 foreach my $id (keys %$idlist) {
6516 my $d = $idlist->{$id};
6517 if (defined($running)) {
6518 next if $d->{template
};
6519 next if $running && $d->{status
} ne 'running';
6520 next if !$running && $d->{status
} eq 'running';
6529 return &$complete_vmid_full();
6532 sub complete_vmid_stopped
{
6533 return &$complete_vmid_full(0);
6536 sub complete_vmid_running
{
6537 return &$complete_vmid_full(1);
6540 sub complete_storage
{
6542 my $cfg = PVE
::Storage
::config
();
6543 my $ids = $cfg->{ids
};
6546 foreach my $sid (keys %$ids) {
6547 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6548 next if !$ids->{$sid}->{content
}->{images
};
6558 vm_mon_cmd
($vmid, 'nbd-server-stop');