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';
42 my $OVMF_IMG = '/usr/share/kvm/OVMF-pure-efi.fd';
44 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
46 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
48 # Note about locking: we use flock on the config file protect
49 # against concurent actions.
50 # Aditionaly, we have a 'lock' setting in the config file. This
51 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
52 # allowed when such lock is set. But you can ignore this kind of
53 # lock with the --skiplock flag.
55 cfs_register_file
('/qemu-server/',
59 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
60 description
=> "Some command save/restore state from this location.",
66 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
67 description
=> "The name of the snapshot.",
68 type
=> 'string', format
=> 'pve-configid',
72 PVE
::JSONSchema
::register_standard_option
('pve-qm-image-format', {
74 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
75 description
=> "The drive's backing file's data format.",
79 #no warnings 'redefine';
82 my ($controller, $vmid, $option, $value) = @_;
84 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
85 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
89 my $nodename = PVE
::INotify
::nodename
();
91 mkdir "/etc/pve/nodes/$nodename";
92 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
95 my $var_run_tmpdir = "/var/run/qemu-server";
96 mkdir $var_run_tmpdir;
98 my $lock_dir = "/var/lock/qemu-server";
101 my $pcisysfs = "/sys/bus/pci";
103 my $cpu_vendor_list = {
105 486 => 'GenuineIntel',
106 pentium
=> 'GenuineIntel',
107 pentium2
=> 'GenuineIntel',
108 pentium3
=> 'GenuineIntel',
109 coreduo
=> 'GenuineIntel',
110 core2duo
=> 'GenuineIntel',
111 Conroe
=> 'GenuineIntel',
112 Penryn
=> 'GenuineIntel',
113 Nehalem
=> 'GenuineIntel',
114 Westmere
=> 'GenuineIntel',
115 SandyBridge
=> 'GenuineIntel',
116 IvyBridge
=> 'GenuineIntel',
117 Haswell
=> 'GenuineIntel',
118 'Haswell-noTSX' => 'GenuineIntel',
119 Broadwell
=> 'GenuineIntel',
120 'Broadwell-noTSX' => 'GenuineIntel',
121 'Skylake-Client' => 'GenuineIntel',
124 athlon
=> 'AuthenticAMD',
125 phenom
=> 'AuthenticAMD',
126 Opteron_G1
=> 'AuthenticAMD',
127 Opteron_G2
=> 'AuthenticAMD',
128 Opteron_G3
=> 'AuthenticAMD',
129 Opteron_G4
=> 'AuthenticAMD',
130 Opteron_G5
=> 'AuthenticAMD',
132 # generic types, use vendor from host node
142 description
=> "Emulated CPU type.",
144 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
149 description
=> "Do not identify as a KVM virtual machine.",
160 enum
=> [qw(i6300esb ib700)],
161 description
=> "Watchdog type to emulate.",
162 default => 'i6300esb',
167 enum
=> [qw(reset shutdown poweroff pause debug none)],
168 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
172 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
178 description
=> "Specifies whether a VM will be started during system bootup.",
184 description
=> "Automatic restart after crash (currently ignored).",
189 type
=> 'string', format
=> 'pve-hotplug-features',
190 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'.",
191 default => 'network,disk,usb',
196 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
202 description
=> "Lock/unlock the VM.",
203 enum
=> [qw(migrate backup snapshot rollback)],
208 description
=> "Limit of CPU usage.",
209 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.",
217 description
=> "CPU weight for a VM.",
218 verbose_description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
226 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
233 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
239 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",
247 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.",
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
286 l24;; Linux 2.4 Kernel
287 l26;; Linux 2.6/3.X Kernel
288 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
294 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
295 pattern
=> '[acdn]{1,4}',
300 type
=> 'string', format
=> 'pve-qm-bootdisk',
301 description
=> "Enable booting from specified disk.",
302 pattern
=> '(ide|sata|scsi|virtio)\d+',
307 description
=> "The number of CPUs. Please use option -sockets instead.",
314 description
=> "The number of CPU sockets.",
321 description
=> "The number of cores per socket.",
328 description
=> "Enable/disable NUMA.",
334 description
=> "Enable/disable hugepages memory.",
335 enum
=> [qw(any 2 1024)],
340 description
=> "Number of hotplugged vcpus.",
347 description
=> "Enable/disable ACPI.",
353 description
=> "Enable/disable Qemu GuestAgent.",
359 description
=> "Enable/disable KVM hardware virtualization.",
365 description
=> "Enable/disable time drift fix.",
371 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
376 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
381 description
=> "Select the VGA type.",
382 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
383 " modes (>= 1280x1024x16) then you should use the options " .
384 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
385 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
386 "display sever. For win* OS you can select how many independent " .
387 "displays you want, Linux guests can add displays them self. " .
388 "You can also run without any graphic card, using a serial device" .
390 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
394 type
=> 'string', format
=> 'pve-qm-watchdog',
395 description
=> "Create a virtual hardware watchdog device.",
396 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
397 " (by a guest action), the watchdog must be periodically polled " .
398 "by an agent inside the guest or else the watchdog will reset " .
399 "the guest (or execute the respective action specified)",
404 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
405 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'.",
406 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
409 startup
=> get_standard_option
('pve-startup-order'),
413 description
=> "Enable/disable Template.",
419 description
=> "Arbitrary arguments passed to kvm.",
420 verbose_description
=> <<EODESCR,
421 Arbitrary arguments passed to kvm, for example:
423 args: -no-reboot -no-hpet
425 NOTE: this option is for experts only.
432 description
=> "Enable/disable the USB tablet device.",
433 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
434 "usually needed to allow absolute mouse positioning with VNC. " .
435 "Else the mouse runs out of sync with normal VNC clients. " .
436 "If you're running lots of console-only guests on one host, " .
437 "you may consider disabling this to save some context switches. " .
438 "This is turned off by default if you use spice (-vga=qxl).",
443 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
447 migrate_downtime
=> {
450 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
456 type
=> 'string', format
=> 'pve-qm-ide',
457 typetext
=> '<volume>',
458 description
=> "This is an alias for option -ide2",
462 description
=> "Emulated CPU type.",
466 parent
=> get_standard_option
('pve-snapshot-name', {
468 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
472 description
=> "Timestamp for snapshots.",
478 type
=> 'string', format
=> 'pve-volume-id',
479 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
482 description
=> "Specific the Qemu machine type.",
484 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
489 description
=> "Specify SMBIOS type 1 fields.",
490 type
=> 'string', format
=> 'pve-qm-smbios1',
494 replicate
=> get_standard_option
('pve-replicate'),
498 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
504 enum
=> [ qw(seabios ovmf) ],
505 description
=> "Select BIOS implementation.",
506 default => 'seabios',
510 # what about other qemu settings ?
512 #machine => 'string',
525 ##soundhw => 'string',
527 while (my ($k, $v) = each %$confdesc) {
528 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
531 my $MAX_IDE_DISKS = 4;
532 my $MAX_SCSI_DISKS = 14;
533 my $MAX_VIRTIO_DISKS = 16;
534 my $MAX_SATA_DISKS = 6;
535 my $MAX_USB_DEVICES = 5;
537 my $MAX_UNUSED_DISKS = 8;
538 my $MAX_HOSTPCI_DEVICES = 4;
539 my $MAX_SERIAL_PORTS = 4;
540 my $MAX_PARALLEL_PORTS = 3;
546 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
547 description
=> "CPUs accessing this NUMA node.",
548 format_description
=> "id[-id];...",
552 description
=> "Amount of memory this NUMA node provides.",
557 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
558 description
=> "Host NUMA nodes to use.",
559 format_description
=> "id[-id];...",
564 enum
=> [qw(preferred bind interleave)],
565 description
=> "NUMA allocation policy.",
569 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
572 type
=> 'string', format
=> $numa_fmt,
573 description
=> "NUMA topology.",
575 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
577 for (my $i = 0; $i < $MAX_NUMA; $i++) {
578 $confdesc->{"numa$i"} = $numadesc;
581 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
582 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
583 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
584 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
586 my $net_fmt_bridge_descr = <<__EOD__;
587 Bridge to attach the network device to. The Proxmox VE standard bridge
590 If you do not specify a bridge, we create a kvm user (NATed) network
591 device, which provides DHCP and DNS services. The following addresses
598 The DHCP server assign addresses to the guest starting from 10.0.2.15.
604 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
605 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
606 format_description
=> "XX:XX:XX:XX:XX:XX",
611 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'.",
612 enum
=> $nic_model_list,
615 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
618 description
=> $net_fmt_bridge_descr,
619 format_description
=> 'bridge',
624 minimum
=> 0, maximum
=> 16,
625 description
=> 'Number of packet queues to be used on the device.',
631 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
636 minimum
=> 1, maximum
=> 4094,
637 description
=> 'VLAN tag to apply to packets on this interface.',
642 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
643 description
=> 'VLAN trunks to pass through this interface.',
644 format_description
=> 'vlanid[;vlanid...]',
649 description
=> 'Whether this interface should be protected by the firewall.',
654 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
661 type
=> 'string', format
=> $net_fmt,
662 description
=> "Specify network devices.",
665 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
667 for (my $i = 0; $i < $MAX_NETS; $i++) {
668 $confdesc->{"net$i"} = $netdesc;
671 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
672 sub verify_volume_id_or_qm_path
{
673 my ($volid, $noerr) = @_;
675 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
679 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
680 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
682 return undef if $noerr;
690 my %drivedesc_base = (
691 volume
=> { alias
=> 'file' },
694 format
=> 'pve-volume-id-or-qm-path',
696 format_description
=> 'volume',
697 description
=> "The drive's backing volume.",
701 enum
=> [qw(cdrom disk)],
702 description
=> "The drive's media type.",
708 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
713 description
=> "Force the drive's physical geometry to have a specific head count.",
718 description
=> "Force the drive's physical geometry to have a specific sector count.",
723 enum
=> [qw(none lba auto)],
724 description
=> "Force disk geometry bios translation mode.",
729 description
=> "Whether the drive should be included when making snapshots.",
734 enum
=> [qw(none writethrough writeback unsafe directsync)],
735 description
=> "The drive's cache mode",
738 format
=> get_standard_option
('pve-qm-image-format'),
741 format
=> 'disk-size',
742 format_description
=> 'DiskSize',
743 description
=> "Disk size. This is purely informational and has no effect.",
748 description
=> "Whether the drive should be included when making backups.",
753 description
=> 'Will include this drive to an storage replical job.',
759 enum
=> [qw(ignore report stop)],
760 description
=> 'Read error action.',
765 enum
=> [qw(enospc ignore report stop)],
766 description
=> 'Write error action.',
771 enum
=> [qw(native threads)],
772 description
=> 'AIO type to use.',
777 enum
=> [qw(ignore on)],
778 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
783 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
788 format
=> 'urlencoded',
789 format_description
=> 'serial',
790 maxLength
=> 20*3, # *3 since it's %xx url enoded
791 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
796 my %iothread_fmt = ( iothread
=> {
798 description
=> "Whether to use iothreads for this drive",
805 format
=> 'urlencoded',
806 format_description
=> 'model',
807 maxLength
=> 40*3, # *3 since it's %xx url enoded
808 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
816 description
=> "Number of queues.",
822 my %scsiblock_fmt = (
825 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",
831 my $add_throttle_desc = sub {
832 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
835 format_description
=> $unit,
836 description
=> "Maximum $what in $longunit.",
839 $d->{minimum
} = $minimum if defined($minimum);
840 $drivedesc_base{$key} = $d;
842 # throughput: (leaky bucket)
843 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
844 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
845 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
846 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
847 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
848 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
849 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
850 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
851 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
853 # pools: (pool of IO before throttling starts taking effect)
854 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
855 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
856 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
857 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
858 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
859 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
862 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
863 $add_throttle_desc->('bps_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
864 $add_throttle_desc->('bps_wr_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
865 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
866 $add_throttle_desc->('iops_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
867 $add_throttle_desc->('iops_wr_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
873 PVE
::JSONSchema
::register_format
("pve-qm-ide", $ide_fmt);
877 type
=> 'string', format
=> $ide_fmt,
878 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
880 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
890 type
=> 'string', format
=> $scsi_fmt,
891 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
893 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
900 type
=> 'string', format
=> $sata_fmt,
901 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
903 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
911 type
=> 'string', format
=> $virtio_fmt,
912 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
914 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
925 volume
=> { alias
=> 'file' },
928 format
=> 'pve-volume-id-or-qm-path',
930 format_description
=> 'volume',
931 description
=> "The drive's backing volume.",
933 format
=> get_standard_option
('pve-qm-image-format'),
936 format
=> 'disk-size',
937 format_description
=> 'DiskSize',
938 description
=> "Disk size. This is purely informational and has no effect.",
945 type
=> 'string', format
=> $efidisk_fmt,
946 description
=> "Configure a Disk for storing EFI vars",
949 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
954 type
=> 'string', format
=> 'pve-qm-usb-device',
955 format_description
=> 'HOSTUSBDEVICE|spice',
956 description
=> <<EODESCR,
957 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
959 'bus-port(.port)*' (decimal numbers) or
960 'vendor_id:product_id' (hexadeciaml numbers) or
963 You can use the 'lsusb -t' command to list existing usb devices.
965 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
967 The value 'spice' can be used to add a usb redirection devices for spice.
973 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).",
980 type
=> 'string', format
=> $usb_fmt,
981 description
=> "Configure an USB device (n is 0 to 4).",
983 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
985 # NOTE: the match-groups of this regex are used in parse_hostpci
986 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
991 pattern
=> qr/$PCIRE(;$PCIRE)*/,
992 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
993 description
=> <<EODESCR,
994 Host PCI device pass through. The PCI ID of a host's PCI device or a list
995 of PCI virtual functions of the host. HOSTPCIID syntax is:
997 'bus:dev.func' (hexadecimal numbers)
999 You can us the 'lspci' command to list existing PCI devices.
1004 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1010 pattern
=> '[^,;]+',
1011 format_description
=> 'string',
1012 description
=> "Custom pci device rom filename (must be located in /usr/share/kvm/).",
1017 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1023 description
=> "Enable vfio-vga device support.",
1028 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1032 type
=> 'string', format
=> 'pve-qm-hostpci',
1033 description
=> "Map host PCI devices into guest.",
1034 verbose_description
=> <<EODESCR,
1035 Map host PCI devices into guest.
1037 NOTE: This option allows direct access to host hardware. So it is no longer
1038 possible to migrate such machines - use with special care.
1040 CAUTION: Experimental! User reported problems with this option.
1043 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1048 pattern
=> '(/dev/.+|socket)',
1049 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1050 verbose_description
=> <<EODESCR,
1051 Create a serial device inside the VM (n is 0 to 3), and pass through a
1052 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1053 host side (use 'qm terminal' to open a terminal connection).
1055 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1057 CAUTION: Experimental! User reported problems with this option.
1064 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1065 description
=> "Map host parallel devices (n is 0 to 2).",
1066 verbose_description
=> <<EODESCR,
1067 Map host parallel devices (n is 0 to 2).
1069 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1071 CAUTION: Experimental! User reported problems with this option.
1075 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1076 $confdesc->{"parallel$i"} = $paralleldesc;
1079 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1080 $confdesc->{"serial$i"} = $serialdesc;
1083 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1084 $confdesc->{"hostpci$i"} = $hostpcidesc;
1087 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1088 $drivename_hash->{"ide$i"} = 1;
1089 $confdesc->{"ide$i"} = $idedesc;
1092 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1093 $drivename_hash->{"sata$i"} = 1;
1094 $confdesc->{"sata$i"} = $satadesc;
1097 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1098 $drivename_hash->{"scsi$i"} = 1;
1099 $confdesc->{"scsi$i"} = $scsidesc ;
1102 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1103 $drivename_hash->{"virtio$i"} = 1;
1104 $confdesc->{"virtio$i"} = $virtiodesc;
1107 $drivename_hash->{efidisk0
} = 1;
1108 $confdesc->{efidisk0
} = $efidisk_desc;
1110 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1111 $confdesc->{"usb$i"} = $usbdesc;
1116 type
=> 'string', format
=> 'pve-volume-id',
1117 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1120 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1121 $confdesc->{"unused$i"} = $unuseddesc;
1124 my $kvm_api_version = 0;
1128 return $kvm_api_version if $kvm_api_version;
1130 my $fh = IO
::File-
>new("</dev/kvm") ||
1133 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1134 $kvm_api_version = $v;
1139 return $kvm_api_version;
1142 my $kvm_user_version;
1144 sub kvm_user_version
{
1146 return $kvm_user_version if $kvm_user_version;
1148 $kvm_user_version = 'unknown';
1152 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1153 $kvm_user_version = $2;
1157 eval { run_command
("kvm -version", outfunc
=> $code); };
1160 return $kvm_user_version;
1164 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1166 sub valid_drive_names
{
1167 # order is important - used to autoselect boot disk
1168 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1169 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1170 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1171 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1175 sub is_valid_drivename
{
1178 return defined($drivename_hash->{$dev});
1183 return defined($confdesc->{$key});
1187 return $nic_model_list;
1190 sub os_list_description
{
1194 wxp
=> 'Windows XP',
1195 w2k
=> 'Windows 2000',
1196 w2k3
=>, 'Windows 2003',
1197 w2k8
=> 'Windows 2008',
1198 wvista
=> 'Windows Vista',
1199 win7
=> 'Windows 7',
1200 win8
=> 'Windows 8/2012',
1201 win10
=> 'Windows 10/2016',
1209 sub get_cdrom_path
{
1211 return $cdrom_path if $cdrom_path;
1213 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1214 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1215 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1219 my ($storecfg, $vmid, $cdrom) = @_;
1221 if ($cdrom eq 'cdrom') {
1222 return get_cdrom_path
();
1223 } elsif ($cdrom eq 'none') {
1225 } elsif ($cdrom =~ m
|^/|) {
1228 return PVE
::Storage
::path
($storecfg, $cdrom);
1232 # try to convert old style file names to volume IDs
1233 sub filename_to_volume_id
{
1234 my ($vmid, $file, $media) = @_;
1236 if (!($file eq 'none' || $file eq 'cdrom' ||
1237 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1239 return undef if $file =~ m
|/|;
1241 if ($media && $media eq 'cdrom') {
1242 $file = "local:iso/$file";
1244 $file = "local:$vmid/$file";
1251 sub verify_media_type
{
1252 my ($opt, $vtype, $media) = @_;
1257 if ($media eq 'disk') {
1259 } elsif ($media eq 'cdrom') {
1262 die "internal error";
1265 return if ($vtype eq $etype);
1267 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1270 sub cleanup_drive_path
{
1271 my ($opt, $storecfg, $drive) = @_;
1273 # try to convert filesystem paths to volume IDs
1275 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1276 ($drive->{file
} !~ m
|^/dev/.+|) &&
1277 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1278 ($drive->{file
} !~ m/^\d+$/)) {
1279 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1280 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1281 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1282 verify_media_type
($opt, $vtype, $drive->{media
});
1283 $drive->{file
} = $volid;
1286 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1289 sub parse_hotplug_features
{
1294 return $res if $data eq '0';
1296 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1298 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1299 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1302 die "invalid hotplug feature '$feature'\n";
1308 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1309 sub pve_verify_hotplug_features
{
1310 my ($value, $noerr) = @_;
1312 return $value if parse_hotplug_features
($value);
1314 return undef if $noerr;
1316 die "unable to parse hotplug option\n";
1319 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1320 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1321 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1322 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1323 # [,iothread=on][,serial=serial][,model=model]
1326 my ($key, $data) = @_;
1328 my ($interface, $index);
1330 if ($key =~ m/^([^\d]+)(\d+)$/) {
1337 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1338 : $confdesc->{$key}->{format
};
1340 warn "invalid drive key: $key\n";
1343 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1344 return undef if !$res;
1345 $res->{interface
} = $interface;
1346 $res->{index} = $index;
1349 foreach my $opt (qw(bps bps_rd bps_wr)) {
1350 if (my $bps = defined(delete $res->{$opt})) {
1351 if (defined($res->{"m$opt"})) {
1352 warn "both $opt and m$opt specified\n";
1356 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1360 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1361 for my $requirement (
1362 [bps_max_length
=> 'mbps_max'],
1363 [bps_rd_max_length
=> 'mbps_rd_max'],
1364 [bps_wr_max_length
=> 'mbps_wr_max'],
1365 [iops_max_length
=> 'iops_max'],
1366 [iops_rd_max_length
=> 'iops_rd_max'],
1367 [iops_wr_max_length
=> 'iops_wr_max']) {
1368 my ($option, $requires) = @$requirement;
1369 if ($res->{$option} && !$res->{$requires}) {
1370 warn "$option requires $requires\n";
1375 return undef if $error;
1377 return undef if $res->{mbps_rd
} && $res->{mbps
};
1378 return undef if $res->{mbps_wr
} && $res->{mbps
};
1379 return undef if $res->{iops_rd
} && $res->{iops
};
1380 return undef if $res->{iops_wr
} && $res->{iops
};
1382 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1383 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1384 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1385 return undef if $res->{interface
} eq 'virtio';
1388 if (my $size = $res->{size
}) {
1389 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1396 my ($vmid, $drive) = @_;
1397 my $data = { %$drive };
1398 delete $data->{$_} for qw(index interface);
1399 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1403 my($fh, $noerr) = @_;
1406 my $SG_GET_VERSION_NUM = 0x2282;
1408 my $versionbuf = "\x00" x
8;
1409 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1411 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1414 my $version = unpack("I", $versionbuf);
1415 if ($version < 30000) {
1416 die "scsi generic interface too old\n" if !$noerr;
1420 my $buf = "\x00" x
36;
1421 my $sensebuf = "\x00" x
8;
1422 my $cmd = pack("C x3 C x1", 0x12, 36);
1424 # see /usr/include/scsi/sg.h
1425 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";
1427 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1428 length($sensebuf), 0, length($buf), $buf,
1429 $cmd, $sensebuf, 6000);
1431 $ret = ioctl($fh, $SG_IO, $packet);
1433 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1437 my @res = unpack($sg_io_hdr_t, $packet);
1438 if ($res[17] || $res[18]) {
1439 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1444 (my $byte0, my $byte1, $res->{vendor
},
1445 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1447 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1448 $res->{type
} = $byte0 & 31;
1456 my $fh = IO
::File-
>new("+<$path") || return undef;
1457 my $res = scsi_inquiry
($fh, 1);
1463 sub machine_type_is_q35
{
1466 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1469 sub print_tabletdevice_full
{
1472 my $q35 = machine_type_is_q35
($conf);
1474 # we use uhci for old VMs because tablet driver was buggy in older qemu
1475 my $usbbus = $q35 ?
"ehci" : "uhci";
1477 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1480 sub print_drivedevice_full
{
1481 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1486 if ($drive->{interface
} eq 'virtio') {
1487 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1488 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1489 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1490 } elsif ($drive->{interface
} eq 'scsi') {
1492 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1493 my $unit = $drive->{index} % $maxdev;
1494 my $devicetype = 'hd';
1496 if (drive_is_cdrom
($drive)) {
1499 if ($drive->{file
} =~ m
|^/|) {
1500 $path = $drive->{file
};
1501 if (my $info = path_is_scsi
($path)) {
1502 if ($info->{type
} == 0 && $drive->{scsiblock
}) {
1503 $devicetype = 'block';
1504 } elsif ($info->{type
} == 1) { # tape
1505 $devicetype = 'generic';
1509 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1512 if($path =~ m/^iscsi\:\/\
//){
1513 $devicetype = 'generic';
1517 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1518 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1520 $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}";
1523 } elsif ($drive->{interface
} eq 'ide'){
1525 my $controller = int($drive->{index} / $maxdev);
1526 my $unit = $drive->{index} % $maxdev;
1527 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1529 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1530 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1531 $model = URI
::Escape
::uri_unescape
($model);
1532 $device .= ",model=$model";
1534 } elsif ($drive->{interface
} eq 'sata'){
1535 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1536 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1537 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1538 } elsif ($drive->{interface
} eq 'usb') {
1540 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1542 die "unsupported interface type";
1545 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1550 sub get_initiator_name
{
1553 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1554 while (defined(my $line = <$fh>)) {
1555 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1564 sub print_drive_full
{
1565 my ($storecfg, $vmid, $drive) = @_;
1568 my $volid = $drive->{file
};
1571 if (drive_is_cdrom
($drive)) {
1572 $path = get_iso_path
($storecfg, $vmid, $volid);
1574 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1576 $path = PVE
::Storage
::path
($storecfg, $volid);
1577 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1578 $format = qemu_img_format
($scfg, $volname);
1586 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
1587 foreach my $o (@qemu_drive_options) {
1588 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1590 if (my $serial = $drive->{serial
}) {
1591 $serial = URI
::Escape
::uri_unescape
($serial);
1592 $opts .= ",serial=$serial";
1595 $opts .= ",format=$format" if $format && !$drive->{format
};
1597 foreach my $o (qw(bps bps_rd bps_wr)) {
1598 my $v = $drive->{"m$o"};
1599 $opts .= ",$o=" . int($v*1024*1024) if $v;
1602 my $cache_direct = 0;
1604 if (my $cache = $drive->{cache
}) {
1605 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1606 } elsif (!drive_is_cdrom
($drive)) {
1607 $opts .= ",cache=none";
1611 # aio native works only with O_DIRECT
1612 if (!$drive->{aio
}) {
1614 $opts .= ",aio=native";
1616 $opts .= ",aio=threads";
1620 if (!drive_is_cdrom
($drive)) {
1622 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1623 $detectzeroes = 'off';
1624 } elsif ($drive->{discard
}) {
1625 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1627 # This used to be our default with discard not being specified:
1628 $detectzeroes = 'on';
1630 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1633 my $pathinfo = $path ?
"file=$path," : '';
1635 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1638 sub print_netdevice_full
{
1639 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1641 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1643 my $device = $net->{model
};
1644 if ($net->{model
} eq 'virtio') {
1645 $device = 'virtio-net-pci';
1648 my $pciaddr = print_pci_addr
("$netid", $bridges);
1649 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1650 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1651 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1652 my $vectors = $net->{queues
} * 2 + 2;
1653 $tmpstr .= ",vectors=$vectors,mq=on";
1655 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1657 if ($use_old_bios_files) {
1659 if ($device eq 'virtio-net-pci') {
1660 $romfile = 'pxe-virtio.rom';
1661 } elsif ($device eq 'e1000') {
1662 $romfile = 'pxe-e1000.rom';
1663 } elsif ($device eq 'ne2k') {
1664 $romfile = 'pxe-ne2k_pci.rom';
1665 } elsif ($device eq 'pcnet') {
1666 $romfile = 'pxe-pcnet.rom';
1667 } elsif ($device eq 'rtl8139') {
1668 $romfile = 'pxe-rtl8139.rom';
1670 $tmpstr .= ",romfile=$romfile" if $romfile;
1676 sub print_netdev_full
{
1677 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1680 if ($netid =~ m/^net(\d+)$/) {
1684 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1686 my $ifname = "tap${vmid}i$i";
1688 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1689 die "interface name '$ifname' is too long (max 15 character)\n"
1690 if length($ifname) >= 16;
1692 my $vhostparam = '';
1693 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1695 my $vmname = $conf->{name
} || "vm$vmid";
1698 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1700 if ($net->{bridge
}) {
1701 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1703 $netdev = "type=user,id=$netid,hostname=$vmname";
1706 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1712 sub print_cpu_device
{
1713 my ($conf, $id) = @_;
1715 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
1716 my $cpu = $nokvm ?
"qemu64" : "kvm64";
1717 if (my $cputype = $conf->{cpu
}) {
1718 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1719 or die "Cannot parse cpu description: $cputype\n";
1720 $cpu = $cpuconf->{cputype
};
1724 $sockets = $conf->{sockets
} if $conf->{sockets
};
1725 my $cores = $conf->{cores
} || 1;
1727 my $current_core = ($id - 1) % $cores;
1728 my $current_socket = int(($id - $current_core)/$cores);
1730 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1733 sub drive_is_cdrom
{
1736 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1740 sub parse_number_sets
{
1743 foreach my $part (split(/;/, $set)) {
1744 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1745 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1746 push @$res, [ $1, $2 ];
1748 die "invalid range: $part\n";
1757 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1758 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1759 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1766 return undef if !$value;
1768 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1770 my @idlist = split(/;/, $res->{host
});
1771 delete $res->{host
};
1772 foreach my $id (@idlist) {
1773 if ($id =~ /^$PCIRE$/) {
1775 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1777 my $pcidevices = lspci
($1);
1778 $res->{pciid
} = $pcidevices->{$1};
1781 # should have been caught by parse_property_string already
1782 die "failed to parse PCI id: $id\n";
1788 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1792 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1797 if (!defined($res->{macaddr
})) {
1798 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1799 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1807 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1810 sub add_random_macs
{
1811 my ($settings) = @_;
1813 foreach my $opt (keys %$settings) {
1814 next if $opt !~ m/^net(\d+)$/;
1815 my $net = parse_net
($settings->{$opt});
1817 $settings->{$opt} = print_net
($net);
1821 sub vm_is_volid_owner
{
1822 my ($storecfg, $vmid, $volid) = @_;
1824 if ($volid !~ m
|^/|) {
1826 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1827 if ($owner && ($owner == $vmid)) {
1835 sub split_flagged_list
{
1836 my $text = shift || '';
1837 $text =~ s/[,;]/ /g;
1839 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1842 sub join_flagged_list
{
1843 my ($how, $lst) = @_;
1844 join $how, map { $lst->{$_} . $_ } keys %$lst;
1847 sub vmconfig_delete_pending_option
{
1848 my ($conf, $key, $force) = @_;
1850 delete $conf->{pending
}->{$key};
1851 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1852 $pending_delete_hash->{$key} = $force ?
'!' : '';
1853 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1856 sub vmconfig_undelete_pending_option
{
1857 my ($conf, $key) = @_;
1859 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1860 delete $pending_delete_hash->{$key};
1862 if (%$pending_delete_hash) {
1863 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1865 delete $conf->{pending
}->{delete};
1869 sub vmconfig_register_unused_drive
{
1870 my ($storecfg, $vmid, $conf, $drive) = @_;
1872 if (!drive_is_cdrom
($drive)) {
1873 my $volid = $drive->{file
};
1874 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1875 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1880 sub vmconfig_cleanup_pending
{
1883 # remove pending changes when nothing changed
1885 foreach my $opt (keys %{$conf->{pending
}}) {
1886 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1888 delete $conf->{pending
}->{$opt};
1892 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1893 my $pending_delete_hash = {};
1894 while (my ($opt, $force) = each %$current_delete_hash) {
1895 if (defined($conf->{$opt})) {
1896 $pending_delete_hash->{$opt} = $force;
1902 if (%$pending_delete_hash) {
1903 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1905 delete $conf->{pending
}->{delete};
1911 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1915 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1916 format_description
=> 'UUID',
1917 description
=> "Set SMBIOS1 UUID.",
1923 format_description
=> 'string',
1924 description
=> "Set SMBIOS1 version.",
1930 format_description
=> 'string',
1931 description
=> "Set SMBIOS1 serial number.",
1937 format_description
=> 'string',
1938 description
=> "Set SMBIOS1 manufacturer.",
1944 format_description
=> 'string',
1945 description
=> "Set SMBIOS1 product ID.",
1951 format_description
=> 'string',
1952 description
=> "Set SMBIOS1 SKU string.",
1958 format_description
=> 'string',
1959 description
=> "Set SMBIOS1 family string.",
1967 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1974 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1977 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1979 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1980 sub verify_bootdisk
{
1981 my ($value, $noerr) = @_;
1983 return $value if is_valid_drivename
($value);
1985 return undef if $noerr;
1987 die "invalid boot disk '$value'\n";
1990 sub parse_watchdog
{
1993 return undef if !$value;
1995 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
2000 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
2001 sub verify_usb_device
{
2002 my ($value, $noerr) = @_;
2004 return $value if parse_usb_device
($value);
2006 return undef if $noerr;
2008 die "unable to parse usb device\n";
2011 # add JSON properties for create and set function
2012 sub json_config_properties
{
2015 foreach my $opt (keys %$confdesc) {
2016 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2017 $prop->{$opt} = $confdesc->{$opt};
2024 my ($key, $value) = @_;
2026 die "unknown setting '$key'\n" if !$confdesc->{$key};
2028 my $type = $confdesc->{$key}->{type
};
2030 if (!defined($value)) {
2031 die "got undefined value\n";
2034 if ($value =~ m/[\n\r]/) {
2035 die "property contains a line feed\n";
2038 if ($type eq 'boolean') {
2039 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2040 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2041 die "type check ('boolean') failed - got '$value'\n";
2042 } elsif ($type eq 'integer') {
2043 return int($1) if $value =~ m/^(\d+)$/;
2044 die "type check ('integer') failed - got '$value'\n";
2045 } elsif ($type eq 'number') {
2046 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2047 die "type check ('number') failed - got '$value'\n";
2048 } elsif ($type eq 'string') {
2049 if (my $fmt = $confdesc->{$key}->{format
}) {
2050 PVE
::JSONSchema
::check_format
($fmt, $value);
2053 $value =~ s/^\"(.*)\"$/$1/;
2056 die "internal error"
2060 sub check_iommu_support
{
2061 #fixme : need to check IOMMU support
2062 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2072 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2073 utime undef, undef, $conf;
2077 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2079 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2081 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2083 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2085 # only remove disks owned by this VM
2086 foreach_drive
($conf, sub {
2087 my ($ds, $drive) = @_;
2089 return if drive_is_cdrom
($drive);
2091 my $volid = $drive->{file
};
2093 return if !$volid || $volid =~ m
|^/|;
2095 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2096 return if !$path || !$owner || ($owner != $vmid);
2099 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2101 warn "Could not remove disk '$volid', check manually: $@" if $@;
2105 if ($keep_empty_config) {
2106 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2111 # also remove unused disk
2113 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2116 PVE
::Storage
::foreach_volid
($dl, sub {
2117 my ($volid, $sid, $volname, $d) = @_;
2118 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2127 sub parse_vm_config
{
2128 my ($filename, $raw) = @_;
2130 return undef if !defined($raw);
2133 digest
=> Digest
::SHA
::sha1_hex
($raw),
2138 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2139 || die "got strange filename '$filename'";
2147 my @lines = split(/\n/, $raw);
2148 foreach my $line (@lines) {
2149 next if $line =~ m/^\s*$/;
2151 if ($line =~ m/^\[PENDING\]\s*$/i) {
2152 $section = 'pending';
2153 if (defined($descr)) {
2155 $conf->{description
} = $descr;
2158 $conf = $res->{$section} = {};
2161 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2163 if (defined($descr)) {
2165 $conf->{description
} = $descr;
2168 $conf = $res->{snapshots
}->{$section} = {};
2172 if ($line =~ m/^\#(.*)\s*$/) {
2173 $descr = '' if !defined($descr);
2174 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2178 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2179 $descr = '' if !defined($descr);
2180 $descr .= PVE
::Tools
::decode_text
($2);
2181 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2182 $conf->{snapstate
} = $1;
2183 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2186 $conf->{$key} = $value;
2187 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2189 if ($section eq 'pending') {
2190 $conf->{delete} = $value; # we parse this later
2192 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2194 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2197 eval { $value = check_type
($key, $value); };
2199 warn "vm $vmid - unable to parse value of '$key' - $@";
2201 $key = 'ide2' if $key eq 'cdrom';
2202 my $fmt = $confdesc->{$key}->{format
};
2203 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2204 my $v = parse_drive
($key, $value);
2205 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2206 $v->{file
} = $volid;
2207 $value = print_drive
($vmid, $v);
2209 warn "vm $vmid - unable to parse value of '$key'\n";
2214 $conf->{$key} = $value;
2219 if (defined($descr)) {
2221 $conf->{description
} = $descr;
2223 delete $res->{snapstate
}; # just to be sure
2228 sub write_vm_config
{
2229 my ($filename, $conf) = @_;
2231 delete $conf->{snapstate
}; # just to be sure
2233 if ($conf->{cdrom
}) {
2234 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2235 $conf->{ide2
} = $conf->{cdrom
};
2236 delete $conf->{cdrom
};
2239 # we do not use 'smp' any longer
2240 if ($conf->{sockets
}) {
2241 delete $conf->{smp
};
2242 } elsif ($conf->{smp
}) {
2243 $conf->{sockets
} = $conf->{smp
};
2244 delete $conf->{cores
};
2245 delete $conf->{smp
};
2248 my $used_volids = {};
2250 my $cleanup_config = sub {
2251 my ($cref, $pending, $snapname) = @_;
2253 foreach my $key (keys %$cref) {
2254 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2255 $key eq 'snapstate' || $key eq 'pending';
2256 my $value = $cref->{$key};
2257 if ($key eq 'delete') {
2258 die "propertry 'delete' is only allowed in [PENDING]\n"
2260 # fixme: check syntax?
2263 eval { $value = check_type
($key, $value); };
2264 die "unable to parse value of '$key' - $@" if $@;
2266 $cref->{$key} = $value;
2268 if (!$snapname && is_valid_drivename
($key)) {
2269 my $drive = parse_drive
($key, $value);
2270 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2275 &$cleanup_config($conf);
2277 &$cleanup_config($conf->{pending
}, 1);
2279 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2280 die "internal error" if $snapname eq 'pending';
2281 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2284 # remove 'unusedX' settings if we re-add a volume
2285 foreach my $key (keys %$conf) {
2286 my $value = $conf->{$key};
2287 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2288 delete $conf->{$key};
2292 my $generate_raw_config = sub {
2293 my ($conf, $pending) = @_;
2297 # add description as comment to top of file
2298 if (defined(my $descr = $conf->{description
})) {
2300 foreach my $cl (split(/\n/, $descr)) {
2301 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2304 $raw .= "#\n" if $pending;
2308 foreach my $key (sort keys %$conf) {
2309 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2310 $raw .= "$key: $conf->{$key}\n";
2315 my $raw = &$generate_raw_config($conf);
2317 if (scalar(keys %{$conf->{pending
}})){
2318 $raw .= "\n[PENDING]\n";
2319 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2322 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2323 $raw .= "\n[$snapname]\n";
2324 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2334 # we use static defaults from our JSON schema configuration
2335 foreach my $key (keys %$confdesc) {
2336 if (defined(my $default = $confdesc->{$key}->{default})) {
2337 $res->{$key} = $default;
2341 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2342 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2348 my $vmlist = PVE
::Cluster
::get_vmlist
();
2350 return $res if !$vmlist || !$vmlist->{ids
};
2351 my $ids = $vmlist->{ids
};
2353 foreach my $vmid (keys %$ids) {
2354 my $d = $ids->{$vmid};
2355 next if !$d->{node
} || $d->{node
} ne $nodename;
2356 next if !$d->{type
} || $d->{type
} ne 'qemu';
2357 $res->{$vmid}->{exists} = 1;
2362 # test if VM uses local resources (to prevent migration)
2363 sub check_local_resources
{
2364 my ($conf, $noerr) = @_;
2368 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2369 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2371 foreach my $k (keys %$conf) {
2372 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2373 # sockets are safe: they will recreated be on the target side post-migrate
2374 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2375 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2378 die "VM uses local resources\n" if $loc_res && !$noerr;
2383 # check if used storages are available on all nodes (use by migrate)
2384 sub check_storage_availability
{
2385 my ($storecfg, $conf, $node) = @_;
2387 foreach_drive
($conf, sub {
2388 my ($ds, $drive) = @_;
2390 my $volid = $drive->{file
};
2393 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2396 # check if storage is available on both nodes
2397 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2398 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2402 # list nodes where all VM images are available (used by has_feature API)
2404 my ($conf, $storecfg) = @_;
2406 my $nodelist = PVE
::Cluster
::get_nodelist
();
2407 my $nodehash = { map { $_ => 1 } @$nodelist };
2408 my $nodename = PVE
::INotify
::nodename
();
2410 foreach_drive
($conf, sub {
2411 my ($ds, $drive) = @_;
2413 my $volid = $drive->{file
};
2416 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2418 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2419 if ($scfg->{disable
}) {
2421 } elsif (my $avail = $scfg->{nodes
}) {
2422 foreach my $node (keys %$nodehash) {
2423 delete $nodehash->{$node} if !$avail->{$node};
2425 } elsif (!$scfg->{shared
}) {
2426 foreach my $node (keys %$nodehash) {
2427 delete $nodehash->{$node} if $node ne $nodename
2437 my ($pidfile, $pid) = @_;
2439 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2443 return undef if !$line;
2444 my @param = split(/\0/, $line);
2446 my $cmd = $param[0];
2447 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2449 for (my $i = 0; $i < scalar (@param); $i++) {
2452 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2453 my $p = $param[$i+1];
2454 return 1 if $p && ($p eq $pidfile);
2463 my ($vmid, $nocheck, $node) = @_;
2465 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2467 die "unable to find configuration file for VM $vmid - no such machine\n"
2468 if !$nocheck && ! -f
$filename;
2470 my $pidfile = pidfile_name
($vmid);
2472 if (my $fd = IO
::File-
>new("<$pidfile")) {
2477 my $mtime = $st->mtime;
2478 if ($mtime > time()) {
2479 warn "file '$filename' modified in future\n";
2482 if ($line =~ m/^(\d+)$/) {
2484 if (check_cmdline
($pidfile, $pid)) {
2485 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2497 my $vzlist = config_list
();
2499 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2501 while (defined(my $de = $fd->read)) {
2502 next if $de !~ m/^(\d+)\.pid$/;
2504 next if !defined($vzlist->{$vmid});
2505 if (my $pid = check_running
($vmid)) {
2506 $vzlist->{$vmid}->{pid
} = $pid;
2514 my ($storecfg, $conf) = @_;
2516 my $bootdisk = $conf->{bootdisk
};
2517 return undef if !$bootdisk;
2518 return undef if !is_valid_drivename
($bootdisk);
2520 return undef if !$conf->{$bootdisk};
2522 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2523 return undef if !defined($drive);
2525 return undef if drive_is_cdrom
($drive);
2527 my $volid = $drive->{file
};
2528 return undef if !$volid;
2530 return $drive->{size
};
2533 my $last_proc_pid_stat;
2535 # get VM status information
2536 # This must be fast and should not block ($full == false)
2537 # We only query KVM using QMP if $full == true (this can be slow)
2539 my ($opt_vmid, $full) = @_;
2543 my $storecfg = PVE
::Storage
::config
();
2545 my $list = vzlist
();
2546 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2548 my $cpucount = $cpuinfo->{cpus
} || 1;
2550 foreach my $vmid (keys %$list) {
2551 next if $opt_vmid && ($vmid ne $opt_vmid);
2553 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2554 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2557 $d->{pid
} = $list->{$vmid}->{pid
};
2559 # fixme: better status?
2560 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2562 my $size = disksize
($storecfg, $conf);
2563 if (defined($size)) {
2564 $d->{disk
} = 0; # no info available
2565 $d->{maxdisk
} = $size;
2571 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2572 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2573 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2575 $d->{name
} = $conf->{name
} || "VM $vmid";
2576 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2578 if ($conf->{balloon
}) {
2579 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2580 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2591 $d->{diskwrite
} = 0;
2593 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2598 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2599 foreach my $dev (keys %$netdev) {
2600 next if $dev !~ m/^tap([1-9]\d*)i/;
2602 my $d = $res->{$vmid};
2605 $d->{netout
} += $netdev->{$dev}->{receive
};
2606 $d->{netin
} += $netdev->{$dev}->{transmit
};
2609 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2610 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2615 my $ctime = gettimeofday
;
2617 foreach my $vmid (keys %$list) {
2619 my $d = $res->{$vmid};
2620 my $pid = $d->{pid
};
2623 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2624 next if !$pstat; # not running
2626 my $used = $pstat->{utime} + $pstat->{stime
};
2628 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2630 if ($pstat->{vsize
}) {
2631 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2634 my $old = $last_proc_pid_stat->{$pid};
2636 $last_proc_pid_stat->{$pid} = {
2644 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2646 if ($dtime > 1000) {
2647 my $dutime = $used - $old->{used
};
2649 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2650 $last_proc_pid_stat->{$pid} = {
2656 $d->{cpu
} = $old->{cpu
};
2660 return $res if !$full;
2662 my $qmpclient = PVE
::QMPClient-
>new();
2664 my $ballooncb = sub {
2665 my ($vmid, $resp) = @_;
2667 my $info = $resp->{'return'};
2668 return if !$info->{max_mem
};
2670 my $d = $res->{$vmid};
2672 # use memory assigned to VM
2673 $d->{maxmem
} = $info->{max_mem
};
2674 $d->{balloon
} = $info->{actual
};
2676 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2677 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2678 $d->{freemem
} = $info->{free_mem
};
2681 $d->{ballooninfo
} = $info;
2684 my $blockstatscb = sub {
2685 my ($vmid, $resp) = @_;
2686 my $data = $resp->{'return'} || [];
2687 my $totalrdbytes = 0;
2688 my $totalwrbytes = 0;
2690 for my $blockstat (@$data) {
2691 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2692 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2694 $blockstat->{device
} =~ s/drive-//;
2695 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2697 $res->{$vmid}->{diskread
} = $totalrdbytes;
2698 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2701 my $statuscb = sub {
2702 my ($vmid, $resp) = @_;
2704 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2705 # this fails if ballon driver is not loaded, so this must be
2706 # the last commnand (following command are aborted if this fails).
2707 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2709 my $status = 'unknown';
2710 if (!defined($status = $resp->{'return'}->{status
})) {
2711 warn "unable to get VM status\n";
2715 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2718 foreach my $vmid (keys %$list) {
2719 next if $opt_vmid && ($vmid ne $opt_vmid);
2720 next if !$res->{$vmid}->{pid
}; # not running
2721 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2724 $qmpclient->queue_execute(undef, 2);
2726 foreach my $vmid (keys %$list) {
2727 next if $opt_vmid && ($vmid ne $opt_vmid);
2728 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2735 my ($conf, $func, @param) = @_;
2737 foreach my $ds (valid_drive_names
()) {
2738 next if !defined($conf->{$ds});
2740 my $drive = parse_drive
($ds, $conf->{$ds});
2743 &$func($ds, $drive, @param);
2748 my ($conf, $func, @param) = @_;
2752 my $test_volid = sub {
2753 my ($volid, $is_cdrom) = @_;
2757 $volhash->{$volid} = $is_cdrom || 0;
2760 foreach_drive
($conf, sub {
2761 my ($ds, $drive) = @_;
2762 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2765 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2766 my $snap = $conf->{snapshots
}->{$snapname};
2767 &$test_volid($snap->{vmstate
}, 0);
2768 foreach_drive
($snap, sub {
2769 my ($ds, $drive) = @_;
2770 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2774 foreach my $volid (keys %$volhash) {
2775 &$func($volid, $volhash->{$volid}, @param);
2779 sub vga_conf_has_spice
{
2782 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2787 sub config_to_command
{
2788 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2791 my $globalFlags = [];
2792 my $machineFlags = [];
2798 my $kvmver = kvm_user_version
();
2799 my $vernum = 0; # unknown
2800 my $ostype = $conf->{ostype
};
2801 my $winversion = windows_version
($ostype);
2803 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2804 $vernum = $1*1000000+$2*1000;
2805 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2806 $vernum = $1*1000000+$2*1000+$3;
2809 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2811 my $have_ovz = -f
'/proc/vz/vestat';
2813 my $q35 = machine_type_is_q35
($conf);
2814 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2815 my $machine_type = $forcemachine || $conf->{machine
};
2816 my $use_old_bios_files = undef;
2817 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2819 my $cpuunits = defined($conf->{cpuunits
}) ?
2820 $conf->{cpuunits
} : $defaults->{cpuunits
};
2822 push @$cmd, '/usr/bin/kvm';
2824 push @$cmd, '-id', $vmid;
2828 my $qmpsocket = qmp_socket
($vmid);
2829 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2830 push @$cmd, '-mon', "chardev=qmp,mode=control";
2833 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2835 push @$cmd, '-daemonize';
2837 if ($conf->{smbios1
}) {
2838 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2841 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2844 # prefer the OVMF_CODE variant
2845 if (-f
$OVMF_CODE) {
2846 $ovmfbase = $OVMF_CODE;
2847 } elsif (-f
$OVMF_IMG) {
2848 $ovmfbase = $OVMF_IMG;
2851 die "no uefi base img found\n" if !$ovmfbase;
2852 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$ovmfbase";
2854 if (defined($conf->{efidisk0
}) && ($ovmfbase eq $OVMF_CODE)) {
2855 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $conf->{efidisk0
});
2856 my $format = $d->{format
} // 'raw';
2858 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
2860 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
2861 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2862 $format = qemu_img_format
($scfg, $volname);
2867 push @$cmd, '-drive', "if=pflash,unit=1,id=drive-efidisk0,format=$format,file=$path";
2868 } elsif ($ovmfbase eq $OVMF_CODE) {
2869 warn "using uefi without permanent efivars disk\n";
2870 my $ovmfvar_dst = "/tmp/$vmid-ovmf.fd";
2871 PVE
::Tools
::file_copy
($OVMF_VARS, $ovmfvar_dst, 256*1024);
2872 push @$cmd, '-drive', "if=pflash,unit=1,format=raw,file=$ovmfvar_dst";
2874 # if the base img is not OVMF_CODE, we do not have to bother
2875 # to create/use a vars image, since it will not be used anyway
2876 # this can only happen if someone manually deletes the OVMF_CODE image
2877 # or has an old pve-qemu-kvm version installed.
2878 # both should not happen, but we ignore it here
2883 # add usb controllers
2884 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2885 push @$devices, @usbcontrollers if @usbcontrollers;
2886 my $vga = $conf->{vga
};
2888 my $qxlnum = vga_conf_has_spice
($vga);
2889 $vga = 'qxl' if $qxlnum;
2892 $vga = $winversion >= 6 ?
'std' : 'cirrus';
2895 # enable absolute mouse coordinates (needed by vnc)
2897 if (defined($conf->{tablet
})) {
2898 $tablet = $conf->{tablet
};
2900 $tablet = $defaults->{tablet
};
2901 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2902 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2905 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2908 my $gpu_passthrough;
2911 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2912 my $d = parse_hostpci
($conf->{"hostpci$i"});
2915 my $pcie = $d->{pcie
};
2917 die "q35 machine model is not enabled" if !$q35;
2918 $pciaddr = print_pcie_addr
("hostpci$i");
2920 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2923 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2924 my $romfile = $d->{romfile
};
2927 if ($d->{'x-vga'}) {
2928 $xvga = ',x-vga=on';
2931 $gpu_passthrough = 1;
2933 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2937 my $pcidevices = $d->{pciid
};
2938 my $multifunction = 1 if @$pcidevices > 1;
2941 foreach my $pcidevice (@$pcidevices) {
2943 my $id = "hostpci$i";
2944 $id .= ".$j" if $multifunction;
2945 my $addr = $pciaddr;
2946 $addr .= ".$j" if $multifunction;
2947 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2950 $devicestr .= "$rombar$xvga";
2951 $devicestr .= ",multifunction=on" if $multifunction;
2952 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
2955 push @$devices, '-device', $devicestr;
2961 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
2962 push @$devices, @usbdevices if @usbdevices;
2964 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2965 if (my $path = $conf->{"serial$i"}) {
2966 if ($path eq 'socket') {
2967 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2968 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2969 push @$devices, '-device', "isa-serial,chardev=serial$i";
2971 die "no such serial device\n" if ! -c
$path;
2972 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2973 push @$devices, '-device', "isa-serial,chardev=serial$i";
2979 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2980 if (my $path = $conf->{"parallel$i"}) {
2981 die "no such parallel device\n" if ! -c
$path;
2982 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2983 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2984 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2988 my $vmname = $conf->{name
} || "vm$vmid";
2990 push @$cmd, '-name', $vmname;
2993 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2994 $sockets = $conf->{sockets
} if $conf->{sockets
};
2996 my $cores = $conf->{cores
} || 1;
2998 my $maxcpus = $sockets * $cores;
3000 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3002 my $allowed_vcpus = $cpuinfo->{cpus
};
3004 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3005 if ($allowed_vcpus < $maxcpus);
3007 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
3009 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3010 for (my $i = 2; $i <= $vcpus; $i++) {
3011 my $cpustr = print_cpu_device
($conf,$i);
3012 push @$cmd, '-device', $cpustr;
3017 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3019 push @$cmd, '-nodefaults';
3021 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3023 my $bootindex_hash = {};
3025 foreach my $o (split(//, $bootorder)) {
3026 $bootindex_hash->{$o} = $i*100;
3030 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3032 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3034 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3036 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3038 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3039 my $socket = vnc_socket
($vmid);
3040 push @$cmd, '-vnc', "unix:$socket,x509,password";
3042 push @$cmd, '-nographic';
3046 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3048 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3049 my $useLocaltime = $conf->{localtime};
3051 if ($winversion >= 5) { # windows
3052 $useLocaltime = 1 if !defined($conf->{localtime});
3054 # use time drift fix when acpi is enabled
3055 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3056 $tdf = 1 if !defined($conf->{tdf
});
3060 if ($winversion >= 6) {
3061 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3062 push @$cmd, '-no-hpet';
3065 push @$rtcFlags, 'driftfix=slew' if $tdf;
3068 push @$machineFlags, 'accel=tcg';
3070 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3073 if ($machine_type) {
3074 push @$machineFlags, "type=${machine_type}";
3077 if ($conf->{startdate
}) {
3078 push @$rtcFlags, "base=$conf->{startdate}";
3079 } elsif ($useLocaltime) {
3080 push @$rtcFlags, 'base=localtime';
3083 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3084 if (my $cputype = $conf->{cpu
}) {
3085 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3086 or die "Cannot parse cpu description: $cputype\n";
3087 $cpu = $cpuconf->{cputype
};
3088 $kvm_off = 1 if $cpuconf->{hidden
};
3091 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3093 push @$cpuFlags , '-x2apic'
3094 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3096 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3098 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3100 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3102 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3103 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3106 add_hyperv_enlighments
($cpuFlags, $winversion, $machine_type, $kvmver, $nokvm, $conf->{bios
}, $gpu_passthrough);
3108 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3110 push @$cpuFlags, 'kvm=off' if $kvm_off;
3112 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3113 die "internal error"; # should not happen
3115 push @$cpuFlags, "vendor=${cpu_vendor}"
3116 if $cpu_vendor ne 'default';
3118 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3120 push @$cmd, '-cpu', $cpu;
3122 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3124 push @$cmd, '-S' if $conf->{freeze
};
3126 # set keyboard layout
3127 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3128 push @$cmd, '-k', $kb if $kb;
3131 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3132 #push @$cmd, '-soundhw', 'es1370';
3133 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3135 if($conf->{agent
}) {
3136 my $qgasocket = qmp_socket
($vmid, 1);
3137 my $pciaddr = print_pci_addr
("qga0", $bridges);
3138 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3139 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3140 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3148 for(my $i = 1; $i < $qxlnum; $i++){
3149 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3150 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3153 # assume other OS works like Linux
3154 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3155 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3159 my $pciaddr = print_pci_addr
("spice", $bridges);
3161 my $nodename = PVE
::INotify
::nodename
();
3162 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3163 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3165 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=HIGH,seamless-migration=on";
3167 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3168 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3169 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3172 # enable balloon by default, unless explicitly disabled
3173 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3174 $pciaddr = print_pci_addr
("balloon0", $bridges);
3175 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3178 if ($conf->{watchdog
}) {
3179 my $wdopts = parse_watchdog
($conf->{watchdog
});
3180 $pciaddr = print_pci_addr
("watchdog", $bridges);
3181 my $watchdog = $wdopts->{model
} || 'i6300esb';
3182 push @$devices, '-device', "$watchdog$pciaddr";
3183 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3187 my $scsicontroller = {};
3188 my $ahcicontroller = {};
3189 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3191 # Add iscsi initiator name if available
3192 if (my $initiator = get_initiator_name
()) {
3193 push @$devices, '-iscsi', "initiator-name=$initiator";
3196 foreach_drive
($conf, sub {
3197 my ($ds, $drive) = @_;
3199 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3200 push @$vollist, $drive->{file
};
3203 $use_virtio = 1 if $ds =~ m/^virtio/;
3205 if (drive_is_cdrom
($drive)) {
3206 if ($bootindex_hash->{d
}) {
3207 $drive->{bootindex
} = $bootindex_hash->{d
};
3208 $bootindex_hash->{d
} += 1;
3211 if ($bootindex_hash->{c
}) {
3212 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3213 $bootindex_hash->{c
} += 1;
3217 if($drive->{interface
} eq 'virtio'){
3218 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3221 if ($drive->{interface
} eq 'scsi') {
3223 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3225 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3226 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3229 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3230 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3231 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3232 } elsif ($drive->{iothread
}) {
3233 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3237 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3238 $queues = ",num_queues=$drive->{queues}";
3241 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3242 $scsicontroller->{$controller}=1;
3245 if ($drive->{interface
} eq 'sata') {
3246 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3247 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3248 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3249 $ahcicontroller->{$controller}=1;
3252 if ($drive->{interface
} eq 'efidisk') {
3253 # this will be added somewhere else
3257 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3258 push @$devices, '-drive',$drive_cmd;
3259 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3262 for (my $i = 0; $i < $MAX_NETS; $i++) {
3263 next if !$conf->{"net$i"};
3264 my $d = parse_net
($conf->{"net$i"});
3267 $use_virtio = 1 if $d->{model
} eq 'virtio';
3269 if ($bootindex_hash->{n
}) {
3270 $d->{bootindex
} = $bootindex_hash->{n
};
3271 $bootindex_hash->{n
} += 1;
3274 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3275 push @$devices, '-netdev', $netdevfull;
3277 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3278 push @$devices, '-device', $netdevicefull;
3283 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3288 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3290 while (my ($k, $v) = each %$bridges) {
3291 $pciaddr = print_pci_addr
("pci.$k");
3292 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3297 if ($conf->{args
}) {
3298 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3302 push @$cmd, @$devices;
3303 push @$cmd, '-rtc', join(',', @$rtcFlags)
3304 if scalar(@$rtcFlags);
3305 push @$cmd, '-machine', join(',', @$machineFlags)
3306 if scalar(@$machineFlags);
3307 push @$cmd, '-global', join(',', @$globalFlags)
3308 if scalar(@$globalFlags);
3310 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3315 return "${var_run_tmpdir}/$vmid.vnc";
3321 my $res = vm_mon_cmd
($vmid, 'query-spice');
3323 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3327 my ($vmid, $qga) = @_;
3328 my $sockettype = $qga ?
'qga' : 'qmp';
3329 return "${var_run_tmpdir}/$vmid.$sockettype";
3334 return "${var_run_tmpdir}/$vmid.pid";
3337 sub vm_devices_list
{
3340 my $res = vm_mon_cmd
($vmid, 'query-pci');
3342 foreach my $pcibus (@$res) {
3343 foreach my $device (@{$pcibus->{devices
}}) {
3344 next if !$device->{'qdev_id'};
3345 if ($device->{'pci_bridge'}) {
3346 $devices->{$device->{'qdev_id'}} = 1;
3347 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3348 next if !$bridge_device->{'qdev_id'};
3349 $devices->{$bridge_device->{'qdev_id'}} = 1;
3350 $devices->{$device->{'qdev_id'}}++;
3353 $devices->{$device->{'qdev_id'}} = 1;
3358 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3359 foreach my $block (@$resblock) {
3360 if($block->{device
} =~ m/^drive-(\S+)/){
3365 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3366 foreach my $mice (@$resmice) {
3367 if ($mice->{name
} eq 'QEMU HID Tablet') {
3368 $devices->{tablet
} = 1;
3373 # for usb devices there is no query-usb
3374 # but we can iterate over the entries in
3375 # qom-list path=/machine/peripheral
3376 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3377 foreach my $per (@$resperipheral) {
3378 if ($per->{name
} =~ m/^usb\d+$/) {
3379 $devices->{$per->{name
}} = 1;
3387 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3389 my $q35 = machine_type_is_q35
($conf);
3391 my $devices_list = vm_devices_list
($vmid);
3392 return 1 if defined($devices_list->{$deviceid});
3394 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3396 if ($deviceid eq 'tablet') {
3398 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3400 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3402 die "usb hotplug currently not reliable\n";
3403 # since we can't reliably hot unplug all added usb devices
3404 # and usb passthrough disables live migration
3405 # we disable usb hotplugging for now
3406 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3408 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3410 qemu_iothread_add
($vmid, $deviceid, $device);
3412 qemu_driveadd
($storecfg, $vmid, $device);
3413 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3415 qemu_deviceadd
($vmid, $devicefull);
3416 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3418 eval { qemu_drivedel
($vmid, $deviceid); };
3423 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3426 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3427 my $pciaddr = print_pci_addr
($deviceid);
3428 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3430 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3432 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3433 qemu_iothread_add
($vmid, $deviceid, $device);
3434 $devicefull .= ",iothread=iothread-$deviceid";
3437 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3438 $devicefull .= ",num_queues=$device->{queues}";
3441 qemu_deviceadd
($vmid, $devicefull);
3442 qemu_deviceaddverify
($vmid, $deviceid);
3444 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3446 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3447 qemu_driveadd
($storecfg, $vmid, $device);
3449 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3450 eval { qemu_deviceadd
($vmid, $devicefull); };
3452 eval { qemu_drivedel
($vmid, $deviceid); };
3457 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3459 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3461 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3462 my $use_old_bios_files = undef;
3463 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3465 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3466 qemu_deviceadd
($vmid, $netdevicefull);
3467 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3469 eval { qemu_netdevdel
($vmid, $deviceid); };
3474 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3477 my $pciaddr = print_pci_addr
($deviceid);
3478 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3480 qemu_deviceadd
($vmid, $devicefull);
3481 qemu_deviceaddverify
($vmid, $deviceid);
3484 die "can't hotplug device '$deviceid'\n";
3490 # fixme: this should raise exceptions on error!
3491 sub vm_deviceunplug
{
3492 my ($vmid, $conf, $deviceid) = @_;
3494 my $devices_list = vm_devices_list
($vmid);
3495 return 1 if !defined($devices_list->{$deviceid});
3497 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3499 if ($deviceid eq 'tablet') {
3501 qemu_devicedel
($vmid, $deviceid);
3503 } elsif ($deviceid =~ m/^usb\d+$/) {
3505 die "usb hotplug currently not reliable\n";
3506 # when unplugging usb devices this way,
3507 # there may be remaining usb controllers/hubs
3508 # so we disable it for now
3509 qemu_devicedel
($vmid, $deviceid);
3510 qemu_devicedelverify
($vmid, $deviceid);
3512 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3514 qemu_devicedel
($vmid, $deviceid);
3515 qemu_devicedelverify
($vmid, $deviceid);
3516 qemu_drivedel
($vmid, $deviceid);
3517 qemu_iothread_del
($conf, $vmid, $deviceid);
3519 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3521 qemu_devicedel
($vmid, $deviceid);
3522 qemu_devicedelverify
($vmid, $deviceid);
3523 qemu_iothread_del
($conf, $vmid, $deviceid);
3525 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3527 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3528 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3529 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3531 qemu_devicedel
($vmid, $deviceid);
3532 qemu_drivedel
($vmid, $deviceid);
3533 qemu_deletescsihw
($conf, $vmid, $deviceid);
3535 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3537 qemu_devicedel
($vmid, $deviceid);
3538 qemu_devicedelverify
($vmid, $deviceid);
3539 qemu_netdevdel
($vmid, $deviceid);
3542 die "can't unplug device '$deviceid'\n";
3548 sub qemu_deviceadd
{
3549 my ($vmid, $devicefull) = @_;
3551 $devicefull = "driver=".$devicefull;
3552 my %options = split(/[=,]/, $devicefull);
3554 vm_mon_cmd
($vmid, "device_add" , %options);
3557 sub qemu_devicedel
{
3558 my ($vmid, $deviceid) = @_;
3560 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3563 sub qemu_iothread_add
{
3564 my($vmid, $deviceid, $device) = @_;
3566 if ($device->{iothread
}) {
3567 my $iothreads = vm_iothreads_list
($vmid);
3568 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3572 sub qemu_iothread_del
{
3573 my($conf, $vmid, $deviceid) = @_;
3575 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3576 if ($device->{iothread
}) {
3577 my $iothreads = vm_iothreads_list
($vmid);
3578 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3582 sub qemu_objectadd
{
3583 my($vmid, $objectid, $qomtype) = @_;
3585 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3590 sub qemu_objectdel
{
3591 my($vmid, $objectid) = @_;
3593 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3599 my ($storecfg, $vmid, $device) = @_;
3601 my $drive = print_drive_full
($storecfg, $vmid, $device);
3602 $drive =~ s/\\/\\\\/g;
3603 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3605 # If the command succeeds qemu prints: "OK
"
3606 return 1 if $ret =~ m/OK/s;
3608 die "adding drive failed
: $ret\n";
3612 my($vmid, $deviceid) = @_;
3614 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3617 return 1 if $ret eq "";
3619 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3620 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3622 die "deleting drive
$deviceid failed
: $ret\n";
3625 sub qemu_deviceaddverify {
3626 my ($vmid, $deviceid) = @_;
3628 for (my $i = 0; $i <= 5; $i++) {
3629 my $devices_list = vm_devices_list($vmid);
3630 return 1 if defined($devices_list->{$deviceid});
3634 die "error on hotplug device
'$deviceid'\n";
3638 sub qemu_devicedelverify {
3639 my ($vmid, $deviceid) = @_;
3641 # need to verify that the device is correctly removed as device_del
3642 # is async and empty return is not reliable
3644 for (my $i = 0; $i <= 5; $i++) {
3645 my $devices_list = vm_devices_list($vmid);
3646 return 1 if !defined($devices_list->{$deviceid});
3650 die "error on hot-unplugging device
'$deviceid'\n";
3653 sub qemu_findorcreatescsihw {
3654 my ($storecfg, $conf, $vmid, $device) = @_;
3656 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3658 my $scsihwid="$controller_prefix$controller";
3659 my $devices_list = vm_devices_list($vmid);
3661 if(!defined($devices_list->{$scsihwid})) {
3662 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3668 sub qemu_deletescsihw {
3669 my ($conf, $vmid, $opt) = @_;
3671 my $device = parse_drive($opt, $conf->{$opt});
3673 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3674 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3678 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3680 my $devices_list = vm_devices_list($vmid);
3681 foreach my $opt (keys %{$devices_list}) {
3682 if (PVE::QemuServer::is_valid_drivename($opt)) {
3683 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3684 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3690 my $scsihwid="scsihw
$controller";
3692 vm_deviceunplug($vmid, $conf, $scsihwid);
3697 sub qemu_add_pci_bridge {
3698 my ($storecfg, $conf, $vmid, $device) = @_;
3704 print_pci_addr($device, $bridges);
3706 while (my ($k, $v) = each %$bridges) {
3709 return 1 if !defined($bridgeid) || $bridgeid < 1;
3711 my $bridge = "pci
.$bridgeid";
3712 my $devices_list = vm_devices_list($vmid);
3714 if (!defined($devices_list->{$bridge})) {
3715 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3721 sub qemu_set_link_status {
3722 my ($vmid, $device, $up) = @_;
3724 vm_mon_cmd($vmid, "set_link
", name => $device,
3725 up => $up ? JSON::true : JSON::false);
3728 sub qemu_netdevadd {
3729 my ($vmid, $conf, $device, $deviceid) = @_;
3731 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3732 my %options = split(/[=,]/, $netdev);
3734 vm_mon_cmd($vmid, "netdev_add
", %options);
3738 sub qemu_netdevdel {
3739 my ($vmid, $deviceid) = @_;
3741 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3744 sub qemu_usb_hotplug {
3745 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3749 # remove the old one first
3750 vm_deviceunplug($vmid, $conf, $deviceid);
3752 # check if xhci controller is necessary and available
3753 if ($device->{usb3}) {
3755 my $devicelist = vm_devices_list($vmid);
3757 if (!$devicelist->{xhci}) {
3758 my $pciaddr = print_pci_addr("xhci
");
3759 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3762 my $d = parse_usb_device($device->{host});
3763 $d->{usb3} = $device->{usb3};
3766 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3769 sub qemu_cpu_hotplug {
3770 my ($vmid, $conf, $vcpus) = @_;
3772 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3775 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3776 $sockets = $conf->{sockets} if $conf->{sockets};
3777 my $cores = $conf->{cores} || 1;
3778 my $maxcpus = $sockets * $cores;
3780 $vcpus = $maxcpus if !$vcpus;
3782 die "you can
't add more vcpus than maxcpus\n"
3783 if $vcpus > $maxcpus;
3785 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3787 if ($vcpus < $currentvcpus) {
3789 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3791 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3792 qemu_devicedel($vmid, "cpu$i");
3794 my $currentrunningvcpus = undef;
3796 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3797 last if scalar(@{$currentrunningvcpus}) == $i-1;
3798 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3802 #update conf after each succesfull cpu unplug
3803 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3804 PVE::QemuConfig->write_config($vmid, $conf);
3807 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3813 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3814 die "vcpus in running vm does not match its configuration\n"
3815 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3817 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3819 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3820 my $cpustr = print_cpu_device($conf, $i);
3821 qemu_deviceadd($vmid, $cpustr);
3824 my $currentrunningvcpus = undef;
3826 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3827 last if scalar(@{$currentrunningvcpus}) == $i;
3828 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3832 #update conf after each succesfull cpu hotplug
3833 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3834 PVE::QemuConfig->write_config($vmid, $conf);
3838 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3839 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3844 sub qemu_block_set_io_throttle {
3845 my ($vmid, $deviceid,
3846 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3847 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3848 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3849 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3851 return if !check_running($vmid) ;
3853 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3855 bps_rd => int($bps_rd),
3856 bps_wr => int($bps_wr),
3858 iops_rd => int($iops_rd),
3859 iops_wr => int($iops_wr),
3860 bps_max => int($bps_max),
3861 bps_rd_max => int($bps_rd_max),
3862 bps_wr_max => int($bps_wr_max),
3863 iops_max => int($iops_max),
3864 iops_rd_max => int($iops_rd_max),
3865 iops_wr_max => int($iops_wr_max),
3866 bps_max_length => int($bps_max_length),
3867 bps_rd_max_length => int($bps_rd_max_length),
3868 bps_wr_max_length => int($bps_wr_max_length),
3869 iops_max_length => int($iops_max_length),
3870 iops_rd_max_length => int($iops_rd_max_length),
3871 iops_wr_max_length => int($iops_wr_max_length),
3876 # old code, only used to shutdown old VM after update
3878 my ($fh, $timeout) = @_;
3880 my $sel = new IO::Select;
3887 while (scalar (@ready = $sel->can_read($timeout))) {
3889 if ($count = $fh->sysread($buf, 8192)) {
3890 if ($buf =~ /^(.*)\(qemu\) $/s) {
3897 if (!defined($count)) {
3904 die "monitor read timeout\n" if !scalar(@ready);
3909 # old code, only used to shutdown old VM after update
3910 sub vm_monitor_command {
3911 my ($vmid, $cmdstr, $nocheck) = @_;
3916 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3918 my $sname = "${var_run_tmpdir}/$vmid.mon";
3920 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3921 die "unable to connect to VM $vmid socket - $!\n";
3925 # hack: migrate sometime blocks the monitor (when migrate_downtime
3927 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3928 $timeout = 60*60; # 1 hour
3932 my $data = __read_avail($sock, $timeout);
3934 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3935 die "got unexpected qemu monitor banner\n";
3938 my $sel = new IO::Select;
3941 if (!scalar(my @ready = $sel->can_write($timeout))) {
3942 die "monitor write error - timeout";
3945 my $fullcmd = "$cmdstr\r";
3947 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3950 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3951 die "monitor write error - $!";
3954 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3958 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3959 $timeout = 60*60; # 1 hour
3960 } elsif ($cmdstr =~ m/^(eject|change)/) {
3961 $timeout = 60; # note: cdrom mount command is slow
3963 if ($res = __read_avail($sock, $timeout)) {
3965 my @lines = split("\r?\n", $res);
3967 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3969 $res = join("\n", @lines);
3977 syslog("err", "VM $vmid monitor command failed - $err");
3984 sub qemu_block_resize {
3985 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3987 my $running = check_running($vmid);
3989 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3991 return if !$running;
3993 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3997 sub qemu_volume_snapshot {
3998 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4000 my $running = check_running($vmid);
4002 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4003 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4005 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4009 sub qemu_volume_snapshot_delete {
4010 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4012 my $running = check_running($vmid);
4014 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4015 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4017 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4021 sub set_migration_caps {
4027 "auto-converge" => 1,
4029 "x-rdma-pin-all" => 0,
4034 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4036 for my $supported_capability (@$supported_capabilities) {
4038 capability => $supported_capability->{capability},
4039 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4043 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4046 my $fast_plug_option = {
4056 # hotplug changes in [PENDING]
4057 # $selection hash can be used to only apply specified options, for
4058 # example: { cores => 1 } (only apply changed 'cores
')
4059 # $errors ref is used to return error messages
4060 sub vmconfig_hotplug_pending {
4061 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4063 my $defaults = load_defaults();
4065 # commit values which do not have any impact on running VM first
4066 # Note: those option cannot raise errors, we we do not care about
4067 # $selection and always apply them.
4069 my $add_error = sub {
4070 my ($opt, $msg) = @_;
4071 $errors->{$opt} = "hotplug problem - $msg";
4075 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4076 if ($fast_plug_option->{$opt}) {
4077 $conf->{$opt} = $conf->{pending}->{$opt};
4078 delete $conf->{pending}->{$opt};
4084 PVE::QemuConfig->write_config($vmid, $conf);
4085 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4088 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4090 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4091 while (my ($opt, $force) = each %$pending_delete_hash) {
4092 next if $selection && !$selection->{$opt};
4094 if ($opt eq 'hotplug
') {
4095 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4096 } elsif ($opt eq 'tablet
') {
4097 die "skip\n" if !$hotplug_features->{usb};
4098 if ($defaults->{tablet}) {
4099 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4101 vm_deviceunplug($vmid, $conf, $opt);
4103 } elsif ($opt =~ m/^usb\d+/) {
4105 # since we cannot reliably hot unplug usb devices
4106 # we are disabling it
4107 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4108 vm_deviceunplug($vmid, $conf, $opt);
4109 } elsif ($opt eq 'vcpus
') {
4110 die "skip\n" if !$hotplug_features->{cpu};
4111 qemu_cpu_hotplug($vmid, $conf, undef);
4112 } elsif ($opt eq 'balloon
') {
4113 # enable balloon device is not hotpluggable
4114 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4115 } elsif ($fast_plug_option->{$opt}) {
4117 } elsif ($opt =~ m/^net(\d+)$/) {
4118 die "skip\n" if !$hotplug_features->{network};
4119 vm_deviceunplug($vmid, $conf, $opt);
4120 } elsif (is_valid_drivename($opt)) {
4121 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4122 vm_deviceunplug($vmid, $conf, $opt);
4123 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4124 } elsif ($opt =~ m/^memory$/) {
4125 die "skip\n" if !$hotplug_features->{memory};
4126 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4127 } elsif ($opt eq 'cpuunits
') {
4128 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4129 } elsif ($opt eq 'cpulimit
') {
4130 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4136 &$add_error($opt, $err) if $err ne "skip\n";
4138 # save new config if hotplug was successful
4139 delete $conf->{$opt};
4140 vmconfig_undelete_pending_option($conf, $opt);
4141 PVE::QemuConfig->write_config($vmid, $conf);
4142 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4146 foreach my $opt (keys %{$conf->{pending}}) {
4147 next if $selection && !$selection->{$opt};
4148 my $value = $conf->{pending}->{$opt};
4150 if ($opt eq 'hotplug
') {
4151 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4152 } elsif ($opt eq 'tablet
') {
4153 die "skip\n" if !$hotplug_features->{usb};
4155 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4156 } elsif ($value == 0) {
4157 vm_deviceunplug($vmid, $conf, $opt);
4159 } elsif ($opt =~ m/^usb\d+$/) {
4161 # since we cannot reliably hot unplug usb devices
4162 # we are disabling it
4163 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4164 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4165 die "skip\n" if !$d;
4166 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4167 } elsif ($opt eq 'vcpus
') {
4168 die "skip\n" if !$hotplug_features->{cpu};
4169 qemu_cpu_hotplug($vmid, $conf, $value);
4170 } elsif ($opt eq 'balloon
') {
4171 # enable/disable balloning device is not hotpluggable
4172 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4173 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4174 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4176 # allow manual ballooning if shares is set to zero
4177 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4178 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4179 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4181 } elsif ($opt =~ m/^net(\d+)$/) {
4182 # some changes can be done without hotplug
4183 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4184 $vmid, $opt, $value);
4185 } elsif (is_valid_drivename($opt)) {
4186 # some changes can be done without hotplug
4187 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4188 $vmid, $opt, $value, 1);
4189 } elsif ($opt =~ m/^memory$/) { #dimms
4190 die "skip\n" if !$hotplug_features->{memory};
4191 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4192 } elsif ($opt eq 'cpuunits
') {
4193 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4194 } elsif ($opt eq 'cpulimit
') {
4195 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4196 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4198 die "skip\n"; # skip non-hot-pluggable options
4202 &$add_error($opt, $err) if $err ne "skip\n";
4204 # save new config if hotplug was successful
4205 $conf->{$opt} = $value;
4206 delete $conf->{pending}->{$opt};
4207 PVE::QemuConfig->write_config($vmid, $conf);
4208 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4213 sub try_deallocate_drive {
4214 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4216 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4217 my $volid = $drive->{file};
4218 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4219 my $sid = PVE::Storage::parse_volume_id($volid);
4220 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4222 # check if the disk is really unused
4223 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4224 if is_volume_in_use($storecfg, $conf, $key, $volid);
4225 PVE::Storage::vdisk_free($storecfg, $volid);
4228 # If vm is not owner of this disk remove from config
4236 sub vmconfig_delete_or_detach_drive {
4237 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4239 my $drive = parse_drive($opt, $conf->{$opt});
4241 my $rpcenv = PVE::RPCEnvironment::get();
4242 my $authuser = $rpcenv->get_user();
4245 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4246 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4248 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4252 sub vmconfig_apply_pending {
4253 my ($vmid, $conf, $storecfg) = @_;
4257 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4258 while (my ($opt, $force) = each %$pending_delete_hash) {
4259 die "internal error" if $opt =~ m/^unused/;
4260 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4261 if (!defined($conf->{$opt})) {
4262 vmconfig_undelete_pending_option($conf, $opt);
4263 PVE::QemuConfig->write_config($vmid, $conf);
4264 } elsif (is_valid_drivename($opt)) {
4265 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4266 vmconfig_undelete_pending_option($conf, $opt);
4267 delete $conf->{$opt};
4268 PVE::QemuConfig->write_config($vmid, $conf);
4270 vmconfig_undelete_pending_option($conf, $opt);
4271 delete $conf->{$opt};
4272 PVE::QemuConfig->write_config($vmid, $conf);
4276 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4278 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4279 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4281 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4282 # skip if nothing changed
4283 } elsif (is_valid_drivename($opt)) {
4284 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4285 if defined($conf->{$opt});
4286 $conf->{$opt} = $conf->{pending}->{$opt};
4288 $conf->{$opt} = $conf->{pending}->{$opt};
4291 delete $conf->{pending}->{$opt};
4292 PVE::QemuConfig->write_config($vmid, $conf);
4296 my $safe_num_ne = sub {
4299 return 0 if !defined($a) && !defined($b);
4300 return 1 if !defined($a);
4301 return 1 if !defined($b);
4306 my $safe_string_ne = sub {
4309 return 0 if !defined($a) && !defined($b);
4310 return 1 if !defined($a);
4311 return 1 if !defined($b);
4316 sub vmconfig_update_net {
4317 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4319 my $newnet = parse_net($value);
4321 if ($conf->{$opt}) {
4322 my $oldnet = parse_net($conf->{$opt});
4324 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4325 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4326 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4327 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4329 # for non online change, we try to hot-unplug
4330 die "skip\n" if !$hotplug;
4331 vm_deviceunplug($vmid, $conf, $opt);
4334 die "internal error" if $opt !~ m/net(\d+)/;
4335 my $iface = "tap${vmid}i$1";
4337 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4338 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4339 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4340 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4341 PVE::Network::tap_unplug($iface);
4342 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4343 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4344 # Rate can be applied on its own but any change above needs to
4345 # include the rate in tap_plug since OVS resets everything.
4346 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4349 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4350 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4358 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4364 sub vmconfig_update_disk {
4365 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4367 # fixme: do we need force?
4369 my $drive = parse_drive($opt, $value);
4371 if ($conf->{$opt}) {
4373 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4375 my $media = $drive->{media} || 'disk
';
4376 my $oldmedia = $old_drive->{media} || 'disk
';
4377 die "unable to change media type\n" if $media ne $oldmedia;
4379 if (!drive_is_cdrom($old_drive)) {
4381 if ($drive->{file} ne $old_drive->{file}) {
4383 die "skip\n" if !$hotplug;
4385 # unplug and register as unused
4386 vm_deviceunplug($vmid, $conf, $opt);
4387 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4390 # update existing disk
4392 # skip non hotpluggable value
4393 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4394 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4395 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4396 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4401 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4402 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4403 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4404 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4405 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4406 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4407 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4408 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4409 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4410 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4411 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4412 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4413 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4414 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4415 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4416 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4417 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4418 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4420 qemu_block_set_io_throttle($vmid,"drive-$opt",
4421 ($drive->{mbps} || 0)*1024*1024,
4422 ($drive->{mbps_rd} || 0)*1024*1024,
4423 ($drive->{mbps_wr} || 0)*1024*1024,
4424 $drive->{iops} || 0,
4425 $drive->{iops_rd} || 0,
4426 $drive->{iops_wr} || 0,
4427 ($drive->{mbps_max} || 0)*1024*1024,
4428 ($drive->{mbps_rd_max} || 0)*1024*1024,
4429 ($drive->{mbps_wr_max} || 0)*1024*1024,
4430 $drive->{iops_max} || 0,
4431 $drive->{iops_rd_max} || 0,
4432 $drive->{iops_wr_max} || 0,
4433 $drive->{bps_max_length} || 1,
4434 $drive->{bps_rd_max_length} || 1,
4435 $drive->{bps_wr_max_length} || 1,
4436 $drive->{iops_max_length} || 1,
4437 $drive->{iops_rd_max_length} || 1,
4438 $drive->{iops_wr_max_length} || 1);
4447 if ($drive->{file} eq 'none
') {
4448 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4450 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4451 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4452 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4460 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4462 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4463 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4467 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4468 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
4470 PVE::QemuConfig->lock_config($vmid, sub {
4471 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4473 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4475 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4477 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4479 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4480 vmconfig_apply_pending($vmid, $conf, $storecfg);
4481 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4484 my $defaults = load_defaults();
4486 # set environment variable useful inside network script
4487 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4489 my $local_volumes = {};
4491 if ($targetstorage) {
4492 foreach_drive($conf, sub {
4493 my ($ds, $drive) = @_;
4495 return if drive_is_cdrom($drive);
4497 my $volid = $drive->{file};
4501 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
4503 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4504 return if $scfg->{shared};
4505 $local_volumes->{$ds} = [$volid, $storeid, $volname];
4510 foreach my $opt (sort keys %$local_volumes) {
4512 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
4513 my $drive = parse_drive($opt, $conf->{$opt});
4515 #if remote storage is specified, use default format
4516 if ($targetstorage && $targetstorage ne "1") {
4517 $storeid = $targetstorage;
4518 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4519 $format = $defFormat;
4521 #else we use same format than original
4522 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4523 $format = qemu_img_format($scfg, $volid);
4526 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
4527 my $newdrive = $drive;
4528 $newdrive->{format} = $format;
4529 $newdrive->{file} = $newvolid;
4530 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
4531 $local_volumes->{$opt} = $drivestr;
4532 #pass drive to conf for command line
4533 $conf->{$opt} = $drivestr;
4537 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4539 my $migrate_port = 0;
4542 if ($statefile eq 'tcp
') {
4543 my $localip = "localhost";
4544 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4545 my $nodename = PVE::INotify::nodename();
4547 if (!defined($migration_type)) {
4548 if (defined($datacenterconf->{migration}->{type})) {
4549 $migration_type = $datacenterconf->{migration}->{type};
4551 $migration_type = 'secure
';
4555 if ($migration_type eq 'insecure
') {
4556 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4557 if ($migrate_network_addr) {
4558 $localip = $migrate_network_addr;
4560 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4563 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4566 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4567 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4568 $migrate_uri = "tcp:${localip}:${migrate_port}";
4569 push @$cmd, '-incoming
', $migrate_uri;
4572 } elsif ($statefile eq 'unix
') {
4573 # should be default for secure migrations as a ssh TCP forward
4574 # tunnel is not deterministic reliable ready and fails regurarly
4575 # to set up in time, so use UNIX socket forwards
4576 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4577 unlink $socket_addr;
4579 $migrate_uri = "unix:$socket_addr";
4581 push @$cmd, '-incoming
', $migrate_uri;
4585 push @$cmd, '-loadstate
', $statefile;
4592 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4593 my $d = parse_hostpci($conf->{"hostpci$i"});
4595 my $pcidevices = $d->{pciid};
4596 foreach my $pcidevice (@$pcidevices) {
4597 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4599 my $info = pci_device_info("0000:$pciid");
4600 die "IOMMU not present\n" if !check_iommu_support();
4601 die "no pci device info for device '$pciid'\n" if !$info;
4602 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4603 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4607 PVE::Storage::activate_volumes($storecfg, $vollist);
4609 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4611 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4612 eval { run_command($cmd); };
4615 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4616 : $defaults->{cpuunits};
4618 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4621 Slice => 'qemu
.slice
',
4623 CPUShares => $cpuunits
4626 if (my $cpulimit = $conf->{cpulimit}) {
4627 $properties{CPUQuota} = int($cpulimit * 100);
4629 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4631 if ($conf->{hugepages}) {
4634 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4635 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4637 PVE::QemuServer::Memory::hugepages_mount();
4638 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4641 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4642 run_command($cmd, %run_params);
4646 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4650 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4652 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4656 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4657 run_command($cmd, %run_params);
4662 # deactivate volumes if start fails
4663 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4664 die "start failed: $err";
4667 print "migration listens on $migrate_uri\n" if $migrate_uri;
4669 if ($statefile && $statefile ne 'tcp
' && $statefile ne 'unix
') {
4670 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4674 #start nbd server for storage migration
4675 if ($targetstorage) {
4676 my $nodename = PVE::INotify::nodename();
4677 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4678 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
4679 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4680 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4682 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet
', data => { host => "${localip}", port => "${migrate_port}" } } );
4684 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4686 foreach my $opt (sort keys %$local_volumes) {
4687 my $volid = $local_volumes->{$opt};
4688 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
4689 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
4690 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
4694 if ($migratedfrom) {
4696 set_migration_caps($vmid);
4701 print "spice listens on port $spice_port\n";
4702 if ($spice_ticket) {
4703 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4704 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4709 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4710 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4711 if $conf->{balloon};
4714 foreach my $opt (keys %$conf) {
4715 next if $opt !~ m/^net\d+$/;
4716 my $nicconf = parse_net($conf->{$opt});
4717 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4721 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4722 path => "machine/peripheral/balloon0",
4723 property => "guest-stats-polling-interval",
4724 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4730 my ($vmid, $execute, %params) = @_;
4732 my $cmd = { execute => $execute, arguments => \%params };
4733 vm_qmp_command($vmid, $cmd);
4736 sub vm_mon_cmd_nocheck {
4737 my ($vmid, $execute, %params) = @_;
4739 my $cmd = { execute => $execute, arguments => \%params };
4740 vm_qmp_command($vmid, $cmd, 1);
4743 sub vm_qmp_command {
4744 my ($vmid, $cmd, $nocheck) = @_;
4749 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4750 $timeout = $cmd->{arguments}->{timeout};
4751 delete $cmd->{arguments}->{timeout};
4755 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4756 my $sname = qmp_socket($vmid);
4757 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4758 my $qmpclient = PVE::QMPClient->new();
4760 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4761 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4762 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4763 if scalar(%{$cmd->{arguments}});
4764 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4766 die "unable to
open monitor
socket\n";
4770 syslog("err
", "VM
$vmid qmp command failed
- $err");
4777 sub vm_human_monitor_command {
4778 my ($vmid, $cmdline) = @_;
4783 execute => 'human-monitor-command',
4784 arguments => { 'command-line' => $cmdline},
4787 return vm_qmp_command($vmid, $cmd);
4790 sub vm_commandline {
4791 my ($storecfg, $vmid) = @_;
4793 my $conf = PVE::QemuConfig->load_config($vmid);
4795 my $defaults = load_defaults();
4797 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4799 return PVE::Tools::cmd2string($cmd);
4803 my ($vmid, $skiplock) = @_;
4805 PVE::QemuConfig->lock_config($vmid, sub {
4807 my $conf = PVE::QemuConfig->load_config($vmid);
4809 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4811 vm_mon_cmd($vmid, "system_reset
");
4815 sub get_vm_volumes {
4819 foreach_volid($conf, sub {
4820 my ($volid, $is_cdrom) = @_;
4822 return if $volid =~ m|^/|;
4824 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4827 push @$vollist, $volid;
4833 sub vm_stop_cleanup {
4834 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4839 my $vollist = get_vm_volumes($conf);
4840 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4843 foreach my $ext (qw(mon qmp pid vnc qga)) {
4844 unlink "/var/run/qemu-server/${vmid}.$ext";
4847 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4849 warn $@ if $@; # avoid errors - just warn
4852 # Note: use $nockeck to skip tests if VM configuration file exists.
4853 # We need that when migration VMs to other nodes (files already moved)
4854 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4856 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4858 $force = 1 if !defined($force) && !$shutdown;
4861 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4862 kill 15, $pid if $pid;
4863 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4864 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4868 PVE
::QemuConfig-
>lock_config($vmid, sub {
4870 my $pid = check_running
($vmid, $nocheck);
4875 $conf = PVE
::QemuConfig-
>load_config($vmid);
4876 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4877 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4878 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4879 $timeout = $opts->{down
} if $opts->{down
};
4883 $timeout = 60 if !defined($timeout);
4887 if (defined($conf) && $conf->{agent
}) {
4888 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4890 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4893 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4900 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4905 if ($count >= $timeout) {
4907 warn "VM still running - terminating now with SIGTERM\n";
4910 die "VM quit/powerdown failed - got timeout\n";
4913 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4918 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4921 die "VM quit/powerdown failed\n";
4929 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4934 if ($count >= $timeout) {
4935 warn "VM still running - terminating now with SIGKILL\n";
4940 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4945 my ($vmid, $skiplock) = @_;
4947 PVE
::QemuConfig-
>lock_config($vmid, sub {
4949 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4951 PVE
::QemuConfig-
>check_lock($conf)
4952 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4954 vm_mon_cmd
($vmid, "stop");
4959 my ($vmid, $skiplock, $nocheck) = @_;
4961 PVE
::QemuConfig-
>lock_config($vmid, sub {
4965 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4967 PVE
::QemuConfig-
>check_lock($conf)
4968 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4970 vm_mon_cmd
($vmid, "cont");
4973 vm_mon_cmd_nocheck
($vmid, "cont");
4979 my ($vmid, $skiplock, $key) = @_;
4981 PVE
::QemuConfig-
>lock_config($vmid, sub {
4983 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4985 # there is no qmp command, so we use the human monitor command
4986 vm_human_monitor_command
($vmid, "sendkey $key");
4991 my ($storecfg, $vmid, $skiplock) = @_;
4993 PVE
::QemuConfig-
>lock_config($vmid, sub {
4995 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4997 if (!check_running
($vmid)) {
4998 destroy_vm
($storecfg, $vmid, undef, $skiplock);
5000 die "VM $vmid is running - destroy failed\n";
5008 my ($filename, $buf) = @_;
5010 my $fh = IO
::File-
>new($filename, "w");
5011 return undef if !$fh;
5013 my $res = print $fh $buf;
5020 sub pci_device_info
{
5025 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
5026 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
5028 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
5029 return undef if !defined($irq) || $irq !~ m/^\d+$/;
5031 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
5032 return undef if !defined($vendor) || $vendor !~ s/^0x//;
5034 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
5035 return undef if !defined($product) || $product !~ s/^0x//;
5040 product
=> $product,
5046 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
5055 my $name = $dev->{name
};
5057 my $fn = "$pcisysfs/devices/$name/reset";
5059 return file_write
($fn, "1");
5062 sub pci_dev_bind_to_vfio
{
5065 my $name = $dev->{name
};
5067 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5069 if (!-d
$vfio_basedir) {
5070 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5072 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5074 my $testdir = "$vfio_basedir/$name";
5075 return 1 if -d
$testdir;
5077 my $data = "$dev->{vendor} $dev->{product}";
5078 return undef if !file_write
("$vfio_basedir/new_id", $data);
5080 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5081 if (!file_write
($fn, $name)) {
5082 return undef if -f
$fn;
5085 $fn = "$vfio_basedir/bind";
5086 if (! -d
$testdir) {
5087 return undef if !file_write
($fn, $name);
5093 sub pci_dev_group_bind_to_vfio
{
5096 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5098 if (!-d
$vfio_basedir) {
5099 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5101 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5103 # get IOMMU group devices
5104 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5105 my @devs = grep /^0000:/, readdir($D);
5108 foreach my $pciid (@devs) {
5109 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5111 # pci bridges, switches or root ports are not supported
5112 # they have a pci_bus subdirectory so skip them
5113 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5115 my $info = pci_device_info
($1);
5116 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5122 # vzdump restore implementaion
5124 sub tar_archive_read_firstfile
{
5125 my $archive = shift;
5127 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5129 # try to detect archive type first
5130 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5131 die "unable to open file '$archive'\n";
5132 my $firstfile = <$fh>;
5136 die "ERROR: archive contaions no data\n" if !$firstfile;
5142 sub tar_restore_cleanup
{
5143 my ($storecfg, $statfile) = @_;
5145 print STDERR
"starting cleanup\n";
5147 if (my $fd = IO
::File-
>new($statfile, "r")) {
5148 while (defined(my $line = <$fd>)) {
5149 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5152 if ($volid =~ m
|^/|) {
5153 unlink $volid || die 'unlink failed\n';
5155 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5157 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5159 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5161 print STDERR
"unable to parse line in statfile - $line";
5168 sub restore_archive
{
5169 my ($archive, $vmid, $user, $opts) = @_;
5171 my $format = $opts->{format
};
5174 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5175 $format = 'tar' if !$format;
5177 } elsif ($archive =~ m/\.tar$/) {
5178 $format = 'tar' if !$format;
5179 } elsif ($archive =~ m/.tar.lzo$/) {
5180 $format = 'tar' if !$format;
5182 } elsif ($archive =~ m/\.vma$/) {
5183 $format = 'vma' if !$format;
5184 } elsif ($archive =~ m/\.vma\.gz$/) {
5185 $format = 'vma' if !$format;
5187 } elsif ($archive =~ m/\.vma\.lzo$/) {
5188 $format = 'vma' if !$format;
5191 $format = 'vma' if !$format; # default
5194 # try to detect archive format
5195 if ($format eq 'tar') {
5196 return restore_tar_archive
($archive, $vmid, $user, $opts);
5198 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5202 sub restore_update_config_line
{
5203 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5205 return if $line =~ m/^\#qmdump\#/;
5206 return if $line =~ m/^\#vzdump\#/;
5207 return if $line =~ m/^lock:/;
5208 return if $line =~ m/^unused\d+:/;
5209 return if $line =~ m/^parent:/;
5210 return if $line =~ m/^template:/; # restored VM is never a template
5212 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5213 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5214 # try to convert old 1.X settings
5215 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5216 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5217 my ($model, $macaddr) = split(/\=/, $devconfig);
5218 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5221 bridge
=> "vmbr$ind",
5222 macaddr
=> $macaddr,
5224 my $netstr = print_net
($net);
5226 print $outfd "net$cookie->{netcount}: $netstr\n";
5227 $cookie->{netcount
}++;
5229 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5230 my ($id, $netstr) = ($1, $2);
5231 my $net = parse_net
($netstr);
5232 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5233 $netstr = print_net
($net);
5234 print $outfd "$id: $netstr\n";
5235 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5238 my $di = parse_drive
($virtdev, $value);
5239 if (defined($di->{backup
}) && !$di->{backup
}) {
5240 print $outfd "#$line";
5241 } elsif ($map->{$virtdev}) {
5242 delete $di->{format
}; # format can change on restore
5243 $di->{file
} = $map->{$virtdev};
5244 $value = print_drive
($vmid, $di);
5245 print $outfd "$virtdev: $value\n";
5255 my ($cfg, $vmid) = @_;
5257 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5259 my $volid_hash = {};
5260 foreach my $storeid (keys %$info) {
5261 foreach my $item (@{$info->{$storeid}}) {
5262 next if !($item->{volid
} && $item->{size
});
5263 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5264 $volid_hash->{$item->{volid
}} = $item;
5271 sub is_volume_in_use
{
5272 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5274 my $path = PVE
::Storage
::path
($storecfg, $volid);
5276 my $scan_config = sub {
5277 my ($cref, $snapname) = @_;
5279 foreach my $key (keys %$cref) {
5280 my $value = $cref->{$key};
5281 if (is_valid_drivename
($key)) {
5282 next if $skip_drive && $key eq $skip_drive;
5283 my $drive = parse_drive
($key, $value);
5284 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5285 return 1 if $volid eq $drive->{file
};
5286 if ($drive->{file
} =~ m!^/!) {
5287 return 1 if $drive->{file
} eq $path;
5289 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5291 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5293 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5301 return 1 if &$scan_config($conf);
5305 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5306 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5312 sub update_disksize
{
5313 my ($vmid, $conf, $volid_hash) = @_;
5319 # Note: it is allowed to define multiple storages with same path (alias), so
5320 # we need to check both 'volid' and real 'path' (two different volid can point
5321 # to the same path).
5326 foreach my $opt (keys %$conf) {
5327 if (is_valid_drivename
($opt)) {
5328 my $drive = parse_drive
($opt, $conf->{$opt});
5329 my $volid = $drive->{file
};
5332 $used->{$volid} = 1;
5333 if ($volid_hash->{$volid} &&
5334 (my $path = $volid_hash->{$volid}->{path
})) {
5335 $usedpath->{$path} = 1;
5338 next if drive_is_cdrom
($drive);
5339 next if !$volid_hash->{$volid};
5341 $drive->{size
} = $volid_hash->{$volid}->{size
};
5342 my $new = print_drive
($vmid, $drive);
5343 if ($new ne $conf->{$opt}) {
5345 $conf->{$opt} = $new;
5350 # remove 'unusedX' entry if volume is used
5351 foreach my $opt (keys %$conf) {
5352 next if $opt !~ m/^unused\d+$/;
5353 my $volid = $conf->{$opt};
5354 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5355 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5357 delete $conf->{$opt};
5361 foreach my $volid (sort keys %$volid_hash) {
5362 next if $volid =~ m/vm-$vmid-state-/;
5363 next if $used->{$volid};
5364 my $path = $volid_hash->{$volid}->{path
};
5365 next if !$path; # just to be sure
5366 next if $usedpath->{$path};
5368 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5369 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5376 my ($vmid, $nolock) = @_;
5378 my $cfg = PVE
::Storage
::config
();
5380 my $volid_hash = scan_volids
($cfg, $vmid);
5382 my $updatefn = sub {
5385 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5387 PVE
::QemuConfig-
>check_lock($conf);
5390 foreach my $volid (keys %$volid_hash) {
5391 my $info = $volid_hash->{$volid};
5392 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5395 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5397 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5400 if (defined($vmid)) {
5404 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5407 my $vmlist = config_list
();
5408 foreach my $vmid (keys %$vmlist) {
5412 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5418 sub restore_vma_archive
{
5419 my ($archive, $vmid, $user, $opts, $comp) = @_;
5421 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5422 my $readfrom = $archive;
5427 my $qarchive = PVE
::Tools
::shellquote
($archive);
5428 if ($comp eq 'gzip') {
5429 $uncomp = "zcat $qarchive|";
5430 } elsif ($comp eq 'lzop') {
5431 $uncomp = "lzop -d -c $qarchive|";
5433 die "unknown compression method '$comp'\n";
5438 my $tmpdir = "/var/tmp/vzdumptmp$$";
5441 # disable interrupts (always do cleanups)
5442 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5443 warn "got interrupt - ignored\n";
5446 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5447 POSIX
::mkfifo
($mapfifo, 0600);
5450 my $openfifo = sub {
5451 open($fifofh, '>', $mapfifo) || die $!;
5454 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5461 my $rpcenv = PVE
::RPCEnvironment
::get
();
5463 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5464 my $tmpfn = "$conffile.$$.tmp";
5466 # Note: $oldconf is undef if VM does not exists
5467 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5468 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5470 my $print_devmap = sub {
5471 my $virtdev_hash = {};
5473 my $cfgfn = "$tmpdir/qemu-server.conf";
5475 # we can read the config - that is already extracted
5476 my $fh = IO
::File-
>new($cfgfn, "r") ||
5477 "unable to read qemu-server.conf - $!\n";
5479 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5481 my $pve_firewall_dir = '/etc/pve/firewall';
5482 mkdir $pve_firewall_dir; # make sure the dir exists
5483 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5486 while (defined(my $line = <$fh>)) {
5487 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5488 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5489 die "archive does not contain data for drive '$virtdev'\n"
5490 if !$devinfo->{$devname};
5491 if (defined($opts->{storage
})) {
5492 $storeid = $opts->{storage
} || 'local';
5493 } elsif (!$storeid) {
5496 $format = 'raw' if !$format;
5497 $devinfo->{$devname}->{devname
} = $devname;
5498 $devinfo->{$devname}->{virtdev
} = $virtdev;
5499 $devinfo->{$devname}->{format
} = $format;
5500 $devinfo->{$devname}->{storeid
} = $storeid;
5502 # check permission on storage
5503 my $pool = $opts->{pool
}; # todo: do we need that?
5504 if ($user ne 'root@pam') {
5505 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5508 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5512 foreach my $devname (keys %$devinfo) {
5513 die "found no device mapping information for device '$devname'\n"
5514 if !$devinfo->{$devname}->{virtdev
};
5517 my $cfg = PVE
::Storage
::config
();
5519 # create empty/temp config
5521 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5522 foreach_drive
($oldconf, sub {
5523 my ($ds, $drive) = @_;
5525 return if drive_is_cdrom
($drive);
5527 my $volid = $drive->{file
};
5529 return if !$volid || $volid =~ m
|^/|;
5531 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5532 return if !$path || !$owner || ($owner != $vmid);
5534 # Note: only delete disk we want to restore
5535 # other volumes will become unused
5536 if ($virtdev_hash->{$ds}) {
5537 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5544 # delete vmstate files
5545 # since after the restore we have no snapshots anymore
5546 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5547 my $snap = $oldconf->{snapshots
}->{$snapname};
5548 if ($snap->{vmstate
}) {
5549 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5558 foreach my $virtdev (sort keys %$virtdev_hash) {
5559 my $d = $virtdev_hash->{$virtdev};
5560 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5561 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5563 # test if requested format is supported
5564 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5565 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5566 $d->{format
} = $defFormat if !$supported;
5568 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5569 $d->{format
}, undef, $alloc_size);
5570 print STDERR
"new volume ID is '$volid'\n";
5571 $d->{volid
} = $volid;
5572 my $path = PVE
::Storage
::path
($cfg, $volid);
5574 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5576 my $write_zeros = 1;
5577 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5581 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5583 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5584 $map->{$virtdev} = $volid;
5587 $fh->seek(0, 0) || die "seek failed - $!\n";
5589 my $outfd = new IO
::File
($tmpfn, "w") ||
5590 die "unable to write config for VM $vmid\n";
5592 my $cookie = { netcount
=> 0 };
5593 while (defined(my $line = <$fh>)) {
5594 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5603 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5604 die "interrupted by signal\n";
5606 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5608 $oldtimeout = alarm($timeout);
5615 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5616 my ($dev_id, $size, $devname) = ($1, $2, $3);
5617 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5618 } elsif ($line =~ m/^CTIME: /) {
5619 # we correctly received the vma config, so we can disable
5620 # the timeout now for disk allocation (set to 10 minutes, so
5621 # that we always timeout if something goes wrong)
5624 print $fifofh "done\n";
5625 my $tmp = $oldtimeout || 0;
5626 $oldtimeout = undef;
5632 print "restore vma archive: $cmd\n";
5633 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5637 alarm($oldtimeout) if $oldtimeout;
5640 foreach my $devname (keys %$devinfo) {
5641 my $volid = $devinfo->{$devname}->{volid
};
5642 push @$vollist, $volid if $volid;
5645 my $cfg = PVE
::Storage
::config
();
5646 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5654 foreach my $devname (keys %$devinfo) {
5655 my $volid = $devinfo->{$devname}->{volid
};
5658 if ($volid =~ m
|^/|) {
5659 unlink $volid || die 'unlink failed\n';
5661 PVE
::Storage
::vdisk_free
($cfg, $volid);
5663 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5665 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5672 rename($tmpfn, $conffile) ||
5673 die "unable to commit configuration file '$conffile'\n";
5675 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5677 eval { rescan
($vmid, 1); };
5681 sub restore_tar_archive
{
5682 my ($archive, $vmid, $user, $opts) = @_;
5684 if ($archive ne '-') {
5685 my $firstfile = tar_archive_read_firstfile
($archive);
5686 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5687 if $firstfile ne 'qemu-server.conf';
5690 my $storecfg = PVE
::Storage
::config
();
5692 # destroy existing data - keep empty config
5693 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5694 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5696 my $tocmd = "/usr/lib/qemu-server/qmextract";
5698 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5699 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5700 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5701 $tocmd .= ' --info' if $opts->{info
};
5703 # tar option "xf" does not autodetect compression when read from STDIN,
5704 # so we pipe to zcat
5705 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5706 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5708 my $tmpdir = "/var/tmp/vzdumptmp$$";
5711 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5712 local $ENV{VZDUMP_VMID
} = $vmid;
5713 local $ENV{VZDUMP_USER
} = $user;
5715 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5716 my $tmpfn = "$conffile.$$.tmp";
5718 # disable interrupts (always do cleanups)
5719 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5720 print STDERR
"got interrupt - ignored\n";
5725 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5726 die "interrupted by signal\n";
5729 if ($archive eq '-') {
5730 print "extracting archive from STDIN\n";
5731 run_command
($cmd, input
=> "<&STDIN");
5733 print "extracting archive '$archive'\n";
5737 return if $opts->{info
};
5741 my $statfile = "$tmpdir/qmrestore.stat";
5742 if (my $fd = IO
::File-
>new($statfile, "r")) {
5743 while (defined (my $line = <$fd>)) {
5744 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5745 $map->{$1} = $2 if $1;
5747 print STDERR
"unable to parse line in statfile - $line\n";
5753 my $confsrc = "$tmpdir/qemu-server.conf";
5755 my $srcfd = new IO
::File
($confsrc, "r") ||
5756 die "unable to open file '$confsrc'\n";
5758 my $outfd = new IO
::File
($tmpfn, "w") ||
5759 die "unable to write config for VM $vmid\n";
5761 my $cookie = { netcount
=> 0 };
5762 while (defined (my $line = <$srcfd>)) {
5763 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5775 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5782 rename $tmpfn, $conffile ||
5783 die "unable to commit configuration file '$conffile'\n";
5785 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5787 eval { rescan
($vmid, 1); };
5791 sub foreach_writable_storage
{
5792 my ($conf, $func) = @_;
5796 foreach my $ds (keys %$conf) {
5797 next if !is_valid_drivename
($ds);
5799 my $drive = parse_drive
($ds, $conf->{$ds});
5801 next if drive_is_cdrom
($drive);
5803 my $volid = $drive->{file
};
5805 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5806 $sidhash->{$sid} = $sid if $sid;
5809 foreach my $sid (sort keys %$sidhash) {
5814 sub do_snapshots_with_qemu
{
5815 my ($storecfg, $volid) = @_;
5817 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5819 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5820 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5824 if ($volid =~ m/\.(qcow2|qed)$/){
5831 sub qga_check_running
{
5834 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5836 warn "Qemu Guest Agent are not running - $@";
5842 sub template_create
{
5843 my ($vmid, $conf, $disk) = @_;
5845 my $storecfg = PVE
::Storage
::config
();
5847 foreach_drive
($conf, sub {
5848 my ($ds, $drive) = @_;
5850 return if drive_is_cdrom
($drive);
5851 return if $disk && $ds ne $disk;
5853 my $volid = $drive->{file
};
5854 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5856 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5857 $drive->{file
} = $voliddst;
5858 $conf->{$ds} = print_drive
($vmid, $drive);
5859 PVE
::QemuConfig-
>write_config($vmid, $conf);
5863 sub qemu_img_convert
{
5864 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5866 my $storecfg = PVE
::Storage
::config
();
5867 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5868 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5870 if ($src_storeid && $dst_storeid) {
5872 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5874 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5875 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5877 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5878 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5880 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5881 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5884 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5885 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5886 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5887 if ($is_zero_initialized) {
5888 push @$cmd, "zeroinit:$dst_path";
5890 push @$cmd, $dst_path;
5895 if($line =~ m/\((\S+)\/100\
%\)/){
5897 my $transferred = int($size * $percent / 100);
5898 my $remaining = $size - $transferred;
5900 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5905 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5907 die "copy failed: $err" if $err;
5911 sub qemu_img_format
{
5912 my ($scfg, $volname) = @_;
5914 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5921 sub qemu_drive_mirror
{
5922 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
5924 $jobs = {} if !$jobs;
5928 $jobs->{"drive-$drive"} = {};
5930 if ($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+):exportname=(\S+)/) {
5933 my $exportname = $3;
5936 my $unixsocket = "/run/qemu-server/$vmid.mirror-drive-$drive";
5937 $qemu_target = "nbd+unix:///$exportname?socket=$unixsocket";
5938 my $cmd = ['socat', '-T30', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=5"];
5941 if (!defined($pid)) {
5942 die "forking socat tunnel failed\n";
5943 } elsif ($pid == 0) {
5945 warn "exec failed: $!\n";
5948 $jobs->{"drive-$drive"}->{pid
} = $pid;
5951 while (!-S
$unixsocket) {
5952 die "nbd connection helper timed out\n"
5957 my $storecfg = PVE
::Storage
::config
();
5958 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5960 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5962 $format = qemu_img_format
($dst_scfg, $dst_volname);
5964 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5966 $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5969 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5970 $opts->{format
} = $format if $format;
5972 print "drive mirror is starting for drive-$drive\n";
5974 eval { vm_mon_cmd
($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
5977 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
5978 die "mirroring error: $err";
5981 qemu_drive_mirror_monitor
($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
5984 sub qemu_drive_mirror_monitor
{
5985 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
5988 my $err_complete = 0;
5991 die "storage migration timed out\n" if $err_complete > 300;
5993 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5995 my $running_mirror_jobs = {};
5996 foreach my $stat (@$stats) {
5997 next if $stat->{type
} ne 'mirror';
5998 $running_mirror_jobs->{$stat->{device
}} = $stat;
6001 my $readycounter = 0;
6003 foreach my $job (keys %$jobs) {
6005 if(defined($jobs->{$job}->{complete
}) && !defined($running_mirror_jobs->{$job})) {
6006 print "$job : finished\n";
6007 delete $jobs->{$job};
6011 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
6013 my $busy = $running_mirror_jobs->{$job}->{busy
};
6014 my $ready = $running_mirror_jobs->{$job}->{ready
};
6015 if (my $total = $running_mirror_jobs->{$job}->{len
}) {
6016 my $transferred = $running_mirror_jobs->{$job}->{offset
} || 0;
6017 my $remaining = $total - $transferred;
6018 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6020 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6023 $readycounter++ if $running_mirror_jobs->{$job}->{ready
};
6026 last if scalar(keys %$jobs) == 0;
6028 if ($readycounter == scalar(keys %$jobs)) {
6029 print "all mirroring jobs are ready \n";
6030 last if $skipcomplete; #do the complete later
6032 if ($vmiddst && $vmiddst != $vmid) {
6034 print "freeze filesystem\n";
6035 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6037 print "suspend vm\n";
6038 eval { PVE
::QemuServer
::vm_suspend
($vmid, 1); };
6041 # if we clone a disk for a new target vm, we don't switch the disk
6042 PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs);
6045 print "unfreeze filesystem\n";
6046 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6048 print "resume vm\n";
6049 eval { PVE
::QemuServer
::vm_resume
($vmid, 1, 1); };
6055 foreach my $job (keys %$jobs) {
6056 # try to switch the disk if source and destination are on the same guest
6057 print "$job: Completing block job...\n";
6059 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> $job) };
6060 if ($@ =~ m/cannot be completed/) {
6061 print "$job: Block job cannot be completed, try again.\n";
6064 print "$job: Completed successfully.\n";
6065 $jobs->{$job}->{complete
} = 1;
6066 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6077 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6078 die "mirroring error: $err";
6083 sub qemu_blockjobs_cancel
{
6084 my ($vmid, $jobs) = @_;
6086 foreach my $job (keys %$jobs) {
6087 print "$job: Cancelling block job\n";
6088 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> $job); };
6089 $jobs->{$job}->{cancel
} = 1;
6093 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6095 my $running_jobs = {};
6096 foreach my $stat (@$stats) {
6097 $running_jobs->{$stat->{device
}} = $stat;
6100 foreach my $job (keys %$jobs) {
6102 if (defined($jobs->{$job}->{cancel
}) && !defined($running_jobs->{$job})) {
6103 print "$job: Done.\n";
6104 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6105 delete $jobs->{$job};
6109 last if scalar(keys %$jobs) == 0;
6115 sub qemu_blockjobs_finish_tunnel
{
6116 my ($vmid, $job, $cpid) = @_;
6120 for (my $i = 1; $i < 20; $i++) {
6121 my $waitpid = waitpid($cpid, WNOHANG
);
6122 last if (defined($waitpid) && ($waitpid == $cpid));
6126 } elsif ($i >= 15) {
6131 unlink "/run/qemu-server/$vmid.mirror-$job";
6135 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6136 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
6141 print "create linked clone of drive $drivename ($drive->{file})\n";
6142 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6143 push @$newvollist, $newvolid;
6146 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6147 $storeid = $storage if $storage;
6149 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6151 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6152 $format = qemu_img_format
($scfg, $volname);
6155 # test if requested format is supported - else use default
6156 my $supported = grep { $_ eq $format } @$validFormats;
6157 $format = $defFormat if !$supported;
6159 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6161 print "create full clone of drive $drivename ($drive->{file})\n";
6162 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6163 push @$newvollist, $newvolid;
6165 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
6167 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6168 if (!$running || $snapname) {
6169 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6172 my $kvmver = get_running_qemu_version
($vmid);
6173 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
6174 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6175 if $drive->{iothread
};
6178 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
6182 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6185 $disk->{format
} = undef;
6186 $disk->{file
} = $newvolid;
6187 $disk->{size
} = $size;
6192 # this only works if VM is running
6193 sub get_current_qemu_machine
{
6196 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6197 my $res = vm_qmp_command
($vmid, $cmd);
6199 my ($current, $default);
6200 foreach my $e (@$res) {
6201 $default = $e->{name
} if $e->{'is-default'};
6202 $current = $e->{name
} if $e->{'is-current'};
6205 # fallback to the default machine if current is not supported by qemu
6206 return $current || $default || 'pc';
6209 sub get_running_qemu_version
{
6211 my $cmd = { execute
=> 'query-version', arguments
=> {} };
6212 my $res = vm_qmp_command
($vmid, $cmd);
6213 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6216 sub qemu_machine_feature_enabled
{
6217 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6222 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6224 $current_major = $3;
6225 $current_minor = $4;
6227 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6229 $current_major = $1;
6230 $current_minor = $2;
6233 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6238 sub qemu_machine_pxe
{
6239 my ($vmid, $conf, $machine) = @_;
6241 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6243 foreach my $opt (keys %$conf) {
6244 next if $opt !~ m/^net(\d+)$/;
6245 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6247 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6248 return $machine.".pxe" if $romfile =~ m/pxe/;
6255 sub qemu_use_old_bios_files
{
6256 my ($machine_type) = @_;
6258 return if !$machine_type;
6260 my $use_old_bios_files = undef;
6262 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6264 $use_old_bios_files = 1;
6266 my $kvmver = kvm_user_version
();
6267 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6268 # load new efi bios files on migration. So this hack is required to allow
6269 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6270 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6271 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6274 return ($use_old_bios_files, $machine_type);
6281 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6282 my (undef, $id, $function) = @_;
6283 my $res = { id
=> $id, function
=> $function};
6284 push @{$devices->{$id}}, $res;
6290 sub vm_iothreads_list
{
6293 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6296 foreach my $iothread (@$res) {
6297 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6304 my ($conf, $drive) = @_;
6308 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)) {
6310 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6316 my $controller = int($drive->{index} / $maxdev);
6317 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6319 return ($maxdev, $controller, $controller_prefix);
6322 sub add_hyperv_enlighments
{
6323 my ($cpuFlags, $winversion, $machine_type, $kvmver, $nokvm, $bios, $gpu_passthrough) = @_;
6326 return if $winversion < 6;
6327 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6329 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6331 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
6332 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6333 push @$cpuFlags , 'hv_vapic';
6334 push @$cpuFlags , 'hv_time';
6336 push @$cpuFlags , 'hv_spinlocks=0xffff';
6339 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
6340 push @$cpuFlags , 'hv_reset';
6341 push @$cpuFlags , 'hv_vpindex';
6342 push @$cpuFlags , 'hv_runtime';
6345 if ($winversion >= 7) {
6346 push @$cpuFlags , 'hv_relaxed';
6350 sub windows_version
{
6353 return 0 if !$ostype;
6357 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6359 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6361 } elsif ($ostype =~ m/^win(\d+)$/) {
6368 # bash completion helper
6370 sub complete_backup_archives
{
6371 my ($cmdname, $pname, $cvalue) = @_;
6373 my $cfg = PVE
::Storage
::config
();
6377 if ($cvalue =~ m/^([^:]+):/) {
6381 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6384 foreach my $id (keys %$data) {
6385 foreach my $item (@{$data->{$id}}) {
6386 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6387 push @$res, $item->{volid
} if defined($item->{volid
});
6394 my $complete_vmid_full = sub {
6397 my $idlist = vmstatus
();
6401 foreach my $id (keys %$idlist) {
6402 my $d = $idlist->{$id};
6403 if (defined($running)) {
6404 next if $d->{template
};
6405 next if $running && $d->{status
} ne 'running';
6406 next if !$running && $d->{status
} eq 'running';
6415 return &$complete_vmid_full();
6418 sub complete_vmid_stopped
{
6419 return &$complete_vmid_full(0);
6422 sub complete_vmid_running
{
6423 return &$complete_vmid_full(1);
6426 sub complete_storage
{
6428 my $cfg = PVE
::Storage
::config
();
6429 my $ids = $cfg->{ids
};
6432 foreach my $sid (keys %$ids) {
6433 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6434 next if !$ids->{$sid}->{content
}->{images
};
6444 vm_mon_cmd
($vmid, 'nbd-server-stop');