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',
497 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
503 enum
=> [ qw(seabios ovmf) ],
504 description
=> "Select BIOS implementation.",
505 default => 'seabios',
509 # what about other qemu settings ?
511 #machine => 'string',
524 ##soundhw => 'string',
526 while (my ($k, $v) = each %$confdesc) {
527 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
530 my $MAX_IDE_DISKS = 4;
531 my $MAX_SCSI_DISKS = 14;
532 my $MAX_VIRTIO_DISKS = 16;
533 my $MAX_SATA_DISKS = 6;
534 my $MAX_USB_DEVICES = 5;
536 my $MAX_UNUSED_DISKS = 8;
537 my $MAX_HOSTPCI_DEVICES = 4;
538 my $MAX_SERIAL_PORTS = 4;
539 my $MAX_PARALLEL_PORTS = 3;
545 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
546 description
=> "CPUs accessing this NUMA node.",
547 format_description
=> "id[-id];...",
551 description
=> "Amount of memory this NUMA node provides.",
556 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
557 description
=> "Host NUMA nodes to use.",
558 format_description
=> "id[-id];...",
563 enum
=> [qw(preferred bind interleave)],
564 description
=> "NUMA allocation policy.",
568 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
571 type
=> 'string', format
=> $numa_fmt,
572 description
=> "NUMA topology.",
574 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
576 for (my $i = 0; $i < $MAX_NUMA; $i++) {
577 $confdesc->{"numa$i"} = $numadesc;
580 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
581 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
582 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
583 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
585 my $net_fmt_bridge_descr = <<__EOD__;
586 Bridge to attach the network device to. The Proxmox VE standard bridge
589 If you do not specify a bridge, we create a kvm user (NATed) network
590 device, which provides DHCP and DNS services. The following addresses
597 The DHCP server assign addresses to the guest starting from 10.0.2.15.
603 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
604 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
605 format_description
=> "XX:XX:XX:XX:XX:XX",
610 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'.",
611 enum
=> $nic_model_list,
614 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
617 description
=> $net_fmt_bridge_descr,
618 format_description
=> 'bridge',
623 minimum
=> 0, maximum
=> 16,
624 description
=> 'Number of packet queues to be used on the device.',
630 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
635 minimum
=> 1, maximum
=> 4094,
636 description
=> 'VLAN tag to apply to packets on this interface.',
641 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
642 description
=> 'VLAN trunks to pass through this interface.',
643 format_description
=> 'vlanid[;vlanid...]',
648 description
=> 'Whether this interface should be protected by the firewall.',
653 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
660 type
=> 'string', format
=> $net_fmt,
661 description
=> "Specify network devices.",
664 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
666 for (my $i = 0; $i < $MAX_NETS; $i++) {
667 $confdesc->{"net$i"} = $netdesc;
670 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
671 sub verify_volume_id_or_qm_path
{
672 my ($volid, $noerr) = @_;
674 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
678 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
679 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
681 return undef if $noerr;
689 my %drivedesc_base = (
690 volume
=> { alias
=> 'file' },
693 format
=> 'pve-volume-id-or-qm-path',
695 format_description
=> 'volume',
696 description
=> "The drive's backing volume.",
700 enum
=> [qw(cdrom disk)],
701 description
=> "The drive's media type.",
707 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
712 description
=> "Force the drive's physical geometry to have a specific head count.",
717 description
=> "Force the drive's physical geometry to have a specific sector count.",
722 enum
=> [qw(none lba auto)],
723 description
=> "Force disk geometry bios translation mode.",
728 description
=> "Whether the drive should be included when making snapshots.",
733 enum
=> [qw(none writethrough writeback unsafe directsync)],
734 description
=> "The drive's cache mode",
737 format
=> get_standard_option
('pve-qm-image-format'),
740 format
=> 'disk-size',
741 format_description
=> 'DiskSize',
742 description
=> "Disk size. This is purely informational and has no effect.",
747 description
=> "Whether the drive should be included when making backups.",
752 enum
=> [qw(ignore report stop)],
753 description
=> 'Read error action.',
758 enum
=> [qw(enospc ignore report stop)],
759 description
=> 'Write error action.',
764 enum
=> [qw(native threads)],
765 description
=> 'AIO type to use.',
770 enum
=> [qw(ignore on)],
771 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
776 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
781 format
=> 'urlencoded',
782 format_description
=> 'serial',
783 maxLength
=> 20*3, # *3 since it's %xx url enoded
784 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
789 my %iothread_fmt = ( iothread
=> {
791 description
=> "Whether to use iothreads for this drive",
798 format
=> 'urlencoded',
799 format_description
=> 'model',
800 maxLength
=> 40*3, # *3 since it's %xx url enoded
801 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
809 description
=> "Number of queues.",
815 my %scsiblock_fmt = (
818 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",
824 my $add_throttle_desc = sub {
825 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
828 format_description
=> $unit,
829 description
=> "Maximum $what in $longunit.",
832 $d->{minimum
} = $minimum if defined($minimum);
833 $drivedesc_base{$key} = $d;
835 # throughput: (leaky bucket)
836 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
837 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
838 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
839 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
840 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
841 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
842 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
843 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
844 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
846 # pools: (pool of IO before throttling starts taking effect)
847 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
848 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
849 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
850 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
851 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
852 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
855 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
856 $add_throttle_desc->('bps_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
857 $add_throttle_desc->('bps_wr_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
858 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
859 $add_throttle_desc->('iops_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
860 $add_throttle_desc->('iops_wr_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
866 PVE
::JSONSchema
::register_format
("pve-qm-ide", $ide_fmt);
870 type
=> 'string', format
=> $ide_fmt,
871 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
873 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
883 type
=> 'string', format
=> $scsi_fmt,
884 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
886 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
893 type
=> 'string', format
=> $sata_fmt,
894 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
896 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
904 type
=> 'string', format
=> $virtio_fmt,
905 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
907 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
918 volume
=> { alias
=> 'file' },
921 format
=> 'pve-volume-id-or-qm-path',
923 format_description
=> 'volume',
924 description
=> "The drive's backing volume.",
926 format
=> get_standard_option
('pve-qm-image-format'),
929 format
=> 'disk-size',
930 format_description
=> 'DiskSize',
931 description
=> "Disk size. This is purely informational and has no effect.",
938 type
=> 'string', format
=> $efidisk_fmt,
939 description
=> "Configure a Disk for storing EFI vars",
942 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
947 type
=> 'string', format
=> 'pve-qm-usb-device',
948 format_description
=> 'HOSTUSBDEVICE|spice',
949 description
=> <<EODESCR,
950 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
952 'bus-port(.port)*' (decimal numbers) or
953 'vendor_id:product_id' (hexadeciaml numbers) or
956 You can use the 'lsusb -t' command to list existing usb devices.
958 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
960 The value 'spice' can be used to add a usb redirection devices for spice.
966 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).",
973 type
=> 'string', format
=> $usb_fmt,
974 description
=> "Configure an USB device (n is 0 to 4).",
976 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
978 # NOTE: the match-groups of this regex are used in parse_hostpci
979 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
984 pattern
=> qr/$PCIRE(;$PCIRE)*/,
985 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
986 description
=> <<EODESCR,
987 Host PCI device pass through. The PCI ID of a host's PCI device or a list
988 of PCI virtual functions of the host. HOSTPCIID syntax is:
990 'bus:dev.func' (hexadecimal numbers)
992 You can us the 'lspci' command to list existing PCI devices.
997 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1003 pattern
=> '[^,;]+',
1004 format_description
=> 'string',
1005 description
=> "Custom pci device rom filename (must be located in /usr/share/kvm/).",
1010 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1016 description
=> "Enable vfio-vga device support.",
1021 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1025 type
=> 'string', format
=> 'pve-qm-hostpci',
1026 description
=> "Map host PCI devices into guest.",
1027 verbose_description
=> <<EODESCR,
1028 Map host PCI devices into guest.
1030 NOTE: This option allows direct access to host hardware. So it is no longer
1031 possible to migrate such machines - use with special care.
1033 CAUTION: Experimental! User reported problems with this option.
1036 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1041 pattern
=> '(/dev/.+|socket)',
1042 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1043 verbose_description
=> <<EODESCR,
1044 Create a serial device inside the VM (n is 0 to 3), and pass through a
1045 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1046 host side (use 'qm terminal' to open a terminal connection).
1048 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1050 CAUTION: Experimental! User reported problems with this option.
1057 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1058 description
=> "Map host parallel devices (n is 0 to 2).",
1059 verbose_description
=> <<EODESCR,
1060 Map host parallel devices (n is 0 to 2).
1062 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1064 CAUTION: Experimental! User reported problems with this option.
1068 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1069 $confdesc->{"parallel$i"} = $paralleldesc;
1072 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1073 $confdesc->{"serial$i"} = $serialdesc;
1076 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1077 $confdesc->{"hostpci$i"} = $hostpcidesc;
1080 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1081 $drivename_hash->{"ide$i"} = 1;
1082 $confdesc->{"ide$i"} = $idedesc;
1085 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1086 $drivename_hash->{"sata$i"} = 1;
1087 $confdesc->{"sata$i"} = $satadesc;
1090 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1091 $drivename_hash->{"scsi$i"} = 1;
1092 $confdesc->{"scsi$i"} = $scsidesc ;
1095 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1096 $drivename_hash->{"virtio$i"} = 1;
1097 $confdesc->{"virtio$i"} = $virtiodesc;
1100 $drivename_hash->{efidisk0
} = 1;
1101 $confdesc->{efidisk0
} = $efidisk_desc;
1103 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1104 $confdesc->{"usb$i"} = $usbdesc;
1109 type
=> 'string', format
=> 'pve-volume-id',
1110 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1113 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1114 $confdesc->{"unused$i"} = $unuseddesc;
1117 my $kvm_api_version = 0;
1121 return $kvm_api_version if $kvm_api_version;
1123 my $fh = IO
::File-
>new("</dev/kvm") ||
1126 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1127 $kvm_api_version = $v;
1132 return $kvm_api_version;
1135 my $kvm_user_version;
1137 sub kvm_user_version
{
1139 return $kvm_user_version if $kvm_user_version;
1141 $kvm_user_version = 'unknown';
1145 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1146 $kvm_user_version = $2;
1150 eval { run_command
("kvm -version", outfunc
=> $code); };
1153 return $kvm_user_version;
1157 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1159 sub valid_drive_names
{
1160 # order is important - used to autoselect boot disk
1161 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1162 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1163 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1164 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1168 sub is_valid_drivename
{
1171 return defined($drivename_hash->{$dev});
1176 return defined($confdesc->{$key});
1180 return $nic_model_list;
1183 sub os_list_description
{
1187 wxp
=> 'Windows XP',
1188 w2k
=> 'Windows 2000',
1189 w2k3
=>, 'Windows 2003',
1190 w2k8
=> 'Windows 2008',
1191 wvista
=> 'Windows Vista',
1192 win7
=> 'Windows 7',
1193 win8
=> 'Windows 8/2012',
1194 win10
=> 'Windows 10/2016',
1202 sub get_cdrom_path
{
1204 return $cdrom_path if $cdrom_path;
1206 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1207 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1208 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1212 my ($storecfg, $vmid, $cdrom) = @_;
1214 if ($cdrom eq 'cdrom') {
1215 return get_cdrom_path
();
1216 } elsif ($cdrom eq 'none') {
1218 } elsif ($cdrom =~ m
|^/|) {
1221 return PVE
::Storage
::path
($storecfg, $cdrom);
1225 # try to convert old style file names to volume IDs
1226 sub filename_to_volume_id
{
1227 my ($vmid, $file, $media) = @_;
1229 if (!($file eq 'none' || $file eq 'cdrom' ||
1230 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1232 return undef if $file =~ m
|/|;
1234 if ($media && $media eq 'cdrom') {
1235 $file = "local:iso/$file";
1237 $file = "local:$vmid/$file";
1244 sub verify_media_type
{
1245 my ($opt, $vtype, $media) = @_;
1250 if ($media eq 'disk') {
1252 } elsif ($media eq 'cdrom') {
1255 die "internal error";
1258 return if ($vtype eq $etype);
1260 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1263 sub cleanup_drive_path
{
1264 my ($opt, $storecfg, $drive) = @_;
1266 # try to convert filesystem paths to volume IDs
1268 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1269 ($drive->{file
} !~ m
|^/dev/.+|) &&
1270 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1271 ($drive->{file
} !~ m/^\d+$/)) {
1272 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1273 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1274 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1275 verify_media_type
($opt, $vtype, $drive->{media
});
1276 $drive->{file
} = $volid;
1279 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1282 sub parse_hotplug_features
{
1287 return $res if $data eq '0';
1289 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1291 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1292 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1295 die "invalid hotplug feature '$feature'\n";
1301 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1302 sub pve_verify_hotplug_features
{
1303 my ($value, $noerr) = @_;
1305 return $value if parse_hotplug_features
($value);
1307 return undef if $noerr;
1309 die "unable to parse hotplug option\n";
1312 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1313 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1314 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1315 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1316 # [,iothread=on][,serial=serial][,model=model]
1319 my ($key, $data) = @_;
1321 my ($interface, $index);
1323 if ($key =~ m/^([^\d]+)(\d+)$/) {
1330 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1331 : $confdesc->{$key}->{format
};
1333 warn "invalid drive key: $key\n";
1336 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1337 return undef if !$res;
1338 $res->{interface
} = $interface;
1339 $res->{index} = $index;
1342 foreach my $opt (qw(bps bps_rd bps_wr)) {
1343 if (my $bps = defined(delete $res->{$opt})) {
1344 if (defined($res->{"m$opt"})) {
1345 warn "both $opt and m$opt specified\n";
1349 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1353 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1354 for my $requirement (
1355 [bps_max_length
=> 'mbps_max'],
1356 [bps_rd_max_length
=> 'mbps_rd_max'],
1357 [bps_wr_max_length
=> 'mbps_wr_max'],
1358 [iops_max_length
=> 'iops_max'],
1359 [iops_rd_max_length
=> 'iops_rd_max'],
1360 [iops_wr_max_length
=> 'iops_wr_max']) {
1361 my ($option, $requires) = @$requirement;
1362 if ($res->{$option} && !$res->{$requires}) {
1363 warn "$option requires $requires\n";
1368 return undef if $error;
1370 return undef if $res->{mbps_rd
} && $res->{mbps
};
1371 return undef if $res->{mbps_wr
} && $res->{mbps
};
1372 return undef if $res->{iops_rd
} && $res->{iops
};
1373 return undef if $res->{iops_wr
} && $res->{iops
};
1375 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1376 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1377 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1378 return undef if $res->{interface
} eq 'virtio';
1381 if (my $size = $res->{size
}) {
1382 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1389 my ($vmid, $drive) = @_;
1390 my $data = { %$drive };
1391 delete $data->{$_} for qw(index interface);
1392 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1396 my($fh, $noerr) = @_;
1399 my $SG_GET_VERSION_NUM = 0x2282;
1401 my $versionbuf = "\x00" x
8;
1402 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1404 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1407 my $version = unpack("I", $versionbuf);
1408 if ($version < 30000) {
1409 die "scsi generic interface too old\n" if !$noerr;
1413 my $buf = "\x00" x
36;
1414 my $sensebuf = "\x00" x
8;
1415 my $cmd = pack("C x3 C x1", 0x12, 36);
1417 # see /usr/include/scsi/sg.h
1418 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";
1420 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1421 length($sensebuf), 0, length($buf), $buf,
1422 $cmd, $sensebuf, 6000);
1424 $ret = ioctl($fh, $SG_IO, $packet);
1426 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1430 my @res = unpack($sg_io_hdr_t, $packet);
1431 if ($res[17] || $res[18]) {
1432 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1437 (my $byte0, my $byte1, $res->{vendor
},
1438 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1440 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1441 $res->{type
} = $byte0 & 31;
1449 my $fh = IO
::File-
>new("+<$path") || return undef;
1450 my $res = scsi_inquiry
($fh, 1);
1456 sub machine_type_is_q35
{
1459 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1462 sub print_tabletdevice_full
{
1465 my $q35 = machine_type_is_q35
($conf);
1467 # we use uhci for old VMs because tablet driver was buggy in older qemu
1468 my $usbbus = $q35 ?
"ehci" : "uhci";
1470 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1473 sub print_drivedevice_full
{
1474 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1479 if ($drive->{interface
} eq 'virtio') {
1480 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1481 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1482 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1483 } elsif ($drive->{interface
} eq 'scsi') {
1485 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1486 my $unit = $drive->{index} % $maxdev;
1487 my $devicetype = 'hd';
1489 if (drive_is_cdrom
($drive)) {
1492 if ($drive->{file
} =~ m
|^/|) {
1493 $path = $drive->{file
};
1494 if (my $info = path_is_scsi
($path)) {
1495 if ($info->{type
} == 0 && $drive->{scsiblock
}) {
1496 $devicetype = 'block';
1497 } elsif ($info->{type
} == 1) { # tape
1498 $devicetype = 'generic';
1502 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1505 if($path =~ m/^iscsi\:\/\
//){
1506 $devicetype = 'generic';
1510 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1511 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1513 $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}";
1516 } elsif ($drive->{interface
} eq 'ide'){
1518 my $controller = int($drive->{index} / $maxdev);
1519 my $unit = $drive->{index} % $maxdev;
1520 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1522 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1523 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1524 $model = URI
::Escape
::uri_unescape
($model);
1525 $device .= ",model=$model";
1527 } elsif ($drive->{interface
} eq 'sata'){
1528 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1529 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1530 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1531 } elsif ($drive->{interface
} eq 'usb') {
1533 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1535 die "unsupported interface type";
1538 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1543 sub get_initiator_name
{
1546 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1547 while (defined(my $line = <$fh>)) {
1548 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1557 sub print_drive_full
{
1558 my ($storecfg, $vmid, $drive) = @_;
1561 my $volid = $drive->{file
};
1564 if (drive_is_cdrom
($drive)) {
1565 $path = get_iso_path
($storecfg, $vmid, $volid);
1567 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1569 $path = PVE
::Storage
::path
($storecfg, $volid);
1570 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1571 $format = qemu_img_format
($scfg, $volname);
1579 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);
1580 foreach my $o (@qemu_drive_options) {
1581 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1583 if (my $serial = $drive->{serial
}) {
1584 $serial = URI
::Escape
::uri_unescape
($serial);
1585 $opts .= ",serial=$serial";
1588 $opts .= ",format=$format" if $format && !$drive->{format
};
1590 foreach my $o (qw(bps bps_rd bps_wr)) {
1591 my $v = $drive->{"m$o"};
1592 $opts .= ",$o=" . int($v*1024*1024) if $v;
1595 my $cache_direct = 0;
1597 if (my $cache = $drive->{cache
}) {
1598 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1599 } elsif (!drive_is_cdrom
($drive)) {
1600 $opts .= ",cache=none";
1604 # aio native works only with O_DIRECT
1605 if (!$drive->{aio
}) {
1607 $opts .= ",aio=native";
1609 $opts .= ",aio=threads";
1613 if (!drive_is_cdrom
($drive)) {
1615 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1616 $detectzeroes = 'off';
1617 } elsif ($drive->{discard
}) {
1618 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1620 # This used to be our default with discard not being specified:
1621 $detectzeroes = 'on';
1623 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1626 my $pathinfo = $path ?
"file=$path," : '';
1628 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1631 sub print_netdevice_full
{
1632 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1634 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1636 my $device = $net->{model
};
1637 if ($net->{model
} eq 'virtio') {
1638 $device = 'virtio-net-pci';
1641 my $pciaddr = print_pci_addr
("$netid", $bridges);
1642 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1643 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1644 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1645 my $vectors = $net->{queues
} * 2 + 2;
1646 $tmpstr .= ",vectors=$vectors,mq=on";
1648 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1650 if ($use_old_bios_files) {
1652 if ($device eq 'virtio-net-pci') {
1653 $romfile = 'pxe-virtio.rom';
1654 } elsif ($device eq 'e1000') {
1655 $romfile = 'pxe-e1000.rom';
1656 } elsif ($device eq 'ne2k') {
1657 $romfile = 'pxe-ne2k_pci.rom';
1658 } elsif ($device eq 'pcnet') {
1659 $romfile = 'pxe-pcnet.rom';
1660 } elsif ($device eq 'rtl8139') {
1661 $romfile = 'pxe-rtl8139.rom';
1663 $tmpstr .= ",romfile=$romfile" if $romfile;
1669 sub print_netdev_full
{
1670 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1673 if ($netid =~ m/^net(\d+)$/) {
1677 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1679 my $ifname = "tap${vmid}i$i";
1681 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1682 die "interface name '$ifname' is too long (max 15 character)\n"
1683 if length($ifname) >= 16;
1685 my $vhostparam = '';
1686 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1688 my $vmname = $conf->{name
} || "vm$vmid";
1691 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1693 if ($net->{bridge
}) {
1694 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1696 $netdev = "type=user,id=$netid,hostname=$vmname";
1699 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1705 sub print_cpu_device
{
1706 my ($conf, $id) = @_;
1708 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
1709 my $cpu = $nokvm ?
"qemu64" : "kvm64";
1710 if (my $cputype = $conf->{cpu
}) {
1711 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1712 or die "Cannot parse cpu description: $cputype\n";
1713 $cpu = $cpuconf->{cputype
};
1716 my $cores = $conf->{cores
} || 1;
1718 my $current_core = ($id - 1) % $cores;
1719 my $current_socket = int(($id - 1 - $current_core)/$cores);
1721 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1724 sub drive_is_cdrom
{
1727 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1731 sub parse_number_sets
{
1734 foreach my $part (split(/;/, $set)) {
1735 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1736 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1737 push @$res, [ $1, $2 ];
1739 die "invalid range: $part\n";
1748 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1749 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1750 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1757 return undef if !$value;
1759 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1761 my @idlist = split(/;/, $res->{host
});
1762 delete $res->{host
};
1763 foreach my $id (@idlist) {
1764 if ($id =~ /^$PCIRE$/) {
1766 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1768 my $pcidevices = lspci
($1);
1769 $res->{pciid
} = $pcidevices->{$1};
1772 # should have been caught by parse_property_string already
1773 die "failed to parse PCI id: $id\n";
1779 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1783 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1788 if (!defined($res->{macaddr
})) {
1789 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1790 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1798 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1801 sub add_random_macs
{
1802 my ($settings) = @_;
1804 foreach my $opt (keys %$settings) {
1805 next if $opt !~ m/^net(\d+)$/;
1806 my $net = parse_net
($settings->{$opt});
1808 $settings->{$opt} = print_net
($net);
1812 sub vm_is_volid_owner
{
1813 my ($storecfg, $vmid, $volid) = @_;
1815 if ($volid !~ m
|^/|) {
1817 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1818 if ($owner && ($owner == $vmid)) {
1826 sub split_flagged_list
{
1827 my $text = shift || '';
1828 $text =~ s/[,;]/ /g;
1830 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1833 sub join_flagged_list
{
1834 my ($how, $lst) = @_;
1835 join $how, map { $lst->{$_} . $_ } keys %$lst;
1838 sub vmconfig_delete_pending_option
{
1839 my ($conf, $key, $force) = @_;
1841 delete $conf->{pending
}->{$key};
1842 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1843 $pending_delete_hash->{$key} = $force ?
'!' : '';
1844 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1847 sub vmconfig_undelete_pending_option
{
1848 my ($conf, $key) = @_;
1850 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1851 delete $pending_delete_hash->{$key};
1853 if (%$pending_delete_hash) {
1854 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1856 delete $conf->{pending
}->{delete};
1860 sub vmconfig_register_unused_drive
{
1861 my ($storecfg, $vmid, $conf, $drive) = @_;
1863 if (!drive_is_cdrom
($drive)) {
1864 my $volid = $drive->{file
};
1865 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1866 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1871 sub vmconfig_cleanup_pending
{
1874 # remove pending changes when nothing changed
1876 foreach my $opt (keys %{$conf->{pending
}}) {
1877 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1879 delete $conf->{pending
}->{$opt};
1883 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1884 my $pending_delete_hash = {};
1885 while (my ($opt, $force) = each %$current_delete_hash) {
1886 if (defined($conf->{$opt})) {
1887 $pending_delete_hash->{$opt} = $force;
1893 if (%$pending_delete_hash) {
1894 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1896 delete $conf->{pending
}->{delete};
1902 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1906 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1907 format_description
=> 'UUID',
1908 description
=> "Set SMBIOS1 UUID.",
1914 format_description
=> 'string',
1915 description
=> "Set SMBIOS1 version.",
1921 format_description
=> 'string',
1922 description
=> "Set SMBIOS1 serial number.",
1928 format_description
=> 'string',
1929 description
=> "Set SMBIOS1 manufacturer.",
1935 format_description
=> 'string',
1936 description
=> "Set SMBIOS1 product ID.",
1942 format_description
=> 'string',
1943 description
=> "Set SMBIOS1 SKU string.",
1949 format_description
=> 'string',
1950 description
=> "Set SMBIOS1 family string.",
1958 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1965 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1968 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1970 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1971 sub verify_bootdisk
{
1972 my ($value, $noerr) = @_;
1974 return $value if is_valid_drivename
($value);
1976 return undef if $noerr;
1978 die "invalid boot disk '$value'\n";
1981 sub parse_watchdog
{
1984 return undef if !$value;
1986 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1991 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1992 sub verify_usb_device
{
1993 my ($value, $noerr) = @_;
1995 return $value if parse_usb_device
($value);
1997 return undef if $noerr;
1999 die "unable to parse usb device\n";
2002 # add JSON properties for create and set function
2003 sub json_config_properties
{
2006 foreach my $opt (keys %$confdesc) {
2007 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2008 $prop->{$opt} = $confdesc->{$opt};
2015 my ($key, $value) = @_;
2017 die "unknown setting '$key'\n" if !$confdesc->{$key};
2019 my $type = $confdesc->{$key}->{type
};
2021 if (!defined($value)) {
2022 die "got undefined value\n";
2025 if ($value =~ m/[\n\r]/) {
2026 die "property contains a line feed\n";
2029 if ($type eq 'boolean') {
2030 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2031 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2032 die "type check ('boolean') failed - got '$value'\n";
2033 } elsif ($type eq 'integer') {
2034 return int($1) if $value =~ m/^(\d+)$/;
2035 die "type check ('integer') failed - got '$value'\n";
2036 } elsif ($type eq 'number') {
2037 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2038 die "type check ('number') failed - got '$value'\n";
2039 } elsif ($type eq 'string') {
2040 if (my $fmt = $confdesc->{$key}->{format
}) {
2041 PVE
::JSONSchema
::check_format
($fmt, $value);
2044 $value =~ s/^\"(.*)\"$/$1/;
2047 die "internal error"
2051 sub check_iommu_support
{
2052 #fixme : need to check IOMMU support
2053 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2063 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2064 utime undef, undef, $conf;
2068 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2070 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2072 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2074 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2076 # only remove disks owned by this VM
2077 foreach_drive
($conf, sub {
2078 my ($ds, $drive) = @_;
2080 return if drive_is_cdrom
($drive);
2082 my $volid = $drive->{file
};
2084 return if !$volid || $volid =~ m
|^/|;
2086 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2087 return if !$path || !$owner || ($owner != $vmid);
2090 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2092 warn "Could not remove disk '$volid', check manually: $@" if $@;
2096 if ($keep_empty_config) {
2097 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2102 # also remove unused disk
2104 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2107 PVE
::Storage
::foreach_volid
($dl, sub {
2108 my ($volid, $sid, $volname, $d) = @_;
2109 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2118 sub parse_vm_config
{
2119 my ($filename, $raw) = @_;
2121 return undef if !defined($raw);
2124 digest
=> Digest
::SHA
::sha1_hex
($raw),
2129 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2130 || die "got strange filename '$filename'";
2138 my @lines = split(/\n/, $raw);
2139 foreach my $line (@lines) {
2140 next if $line =~ m/^\s*$/;
2142 if ($line =~ m/^\[PENDING\]\s*$/i) {
2143 $section = 'pending';
2144 if (defined($descr)) {
2146 $conf->{description
} = $descr;
2149 $conf = $res->{$section} = {};
2152 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2154 if (defined($descr)) {
2156 $conf->{description
} = $descr;
2159 $conf = $res->{snapshots
}->{$section} = {};
2163 if ($line =~ m/^\#(.*)\s*$/) {
2164 $descr = '' if !defined($descr);
2165 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2169 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2170 $descr = '' if !defined($descr);
2171 $descr .= PVE
::Tools
::decode_text
($2);
2172 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2173 $conf->{snapstate
} = $1;
2174 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2177 $conf->{$key} = $value;
2178 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2180 if ($section eq 'pending') {
2181 $conf->{delete} = $value; # we parse this later
2183 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2185 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2188 eval { $value = check_type
($key, $value); };
2190 warn "vm $vmid - unable to parse value of '$key' - $@";
2192 $key = 'ide2' if $key eq 'cdrom';
2193 my $fmt = $confdesc->{$key}->{format
};
2194 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2195 my $v = parse_drive
($key, $value);
2196 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2197 $v->{file
} = $volid;
2198 $value = print_drive
($vmid, $v);
2200 warn "vm $vmid - unable to parse value of '$key'\n";
2205 $conf->{$key} = $value;
2210 if (defined($descr)) {
2212 $conf->{description
} = $descr;
2214 delete $res->{snapstate
}; # just to be sure
2219 sub write_vm_config
{
2220 my ($filename, $conf) = @_;
2222 delete $conf->{snapstate
}; # just to be sure
2224 if ($conf->{cdrom
}) {
2225 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2226 $conf->{ide2
} = $conf->{cdrom
};
2227 delete $conf->{cdrom
};
2230 # we do not use 'smp' any longer
2231 if ($conf->{sockets
}) {
2232 delete $conf->{smp
};
2233 } elsif ($conf->{smp
}) {
2234 $conf->{sockets
} = $conf->{smp
};
2235 delete $conf->{cores
};
2236 delete $conf->{smp
};
2239 my $used_volids = {};
2241 my $cleanup_config = sub {
2242 my ($cref, $pending, $snapname) = @_;
2244 foreach my $key (keys %$cref) {
2245 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2246 $key eq 'snapstate' || $key eq 'pending';
2247 my $value = $cref->{$key};
2248 if ($key eq 'delete') {
2249 die "propertry 'delete' is only allowed in [PENDING]\n"
2251 # fixme: check syntax?
2254 eval { $value = check_type
($key, $value); };
2255 die "unable to parse value of '$key' - $@" if $@;
2257 $cref->{$key} = $value;
2259 if (!$snapname && is_valid_drivename
($key)) {
2260 my $drive = parse_drive
($key, $value);
2261 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2266 &$cleanup_config($conf);
2268 &$cleanup_config($conf->{pending
}, 1);
2270 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2271 die "internal error" if $snapname eq 'pending';
2272 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2275 # remove 'unusedX' settings if we re-add a volume
2276 foreach my $key (keys %$conf) {
2277 my $value = $conf->{$key};
2278 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2279 delete $conf->{$key};
2283 my $generate_raw_config = sub {
2284 my ($conf, $pending) = @_;
2288 # add description as comment to top of file
2289 if (defined(my $descr = $conf->{description
})) {
2291 foreach my $cl (split(/\n/, $descr)) {
2292 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2295 $raw .= "#\n" if $pending;
2299 foreach my $key (sort keys %$conf) {
2300 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2301 $raw .= "$key: $conf->{$key}\n";
2306 my $raw = &$generate_raw_config($conf);
2308 if (scalar(keys %{$conf->{pending
}})){
2309 $raw .= "\n[PENDING]\n";
2310 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2313 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2314 $raw .= "\n[$snapname]\n";
2315 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2325 # we use static defaults from our JSON schema configuration
2326 foreach my $key (keys %$confdesc) {
2327 if (defined(my $default = $confdesc->{$key}->{default})) {
2328 $res->{$key} = $default;
2332 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2333 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2339 my $vmlist = PVE
::Cluster
::get_vmlist
();
2341 return $res if !$vmlist || !$vmlist->{ids
};
2342 my $ids = $vmlist->{ids
};
2344 foreach my $vmid (keys %$ids) {
2345 my $d = $ids->{$vmid};
2346 next if !$d->{node
} || $d->{node
} ne $nodename;
2347 next if !$d->{type
} || $d->{type
} ne 'qemu';
2348 $res->{$vmid}->{exists} = 1;
2353 # test if VM uses local resources (to prevent migration)
2354 sub check_local_resources
{
2355 my ($conf, $noerr) = @_;
2359 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2360 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2362 foreach my $k (keys %$conf) {
2363 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2364 # sockets are safe: they will recreated be on the target side post-migrate
2365 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2366 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2369 die "VM uses local resources\n" if $loc_res && !$noerr;
2374 # check if used storages are available on all nodes (use by migrate)
2375 sub check_storage_availability
{
2376 my ($storecfg, $conf, $node) = @_;
2378 foreach_drive
($conf, sub {
2379 my ($ds, $drive) = @_;
2381 my $volid = $drive->{file
};
2384 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2387 # check if storage is available on both nodes
2388 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2389 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2393 # list nodes where all VM images are available (used by has_feature API)
2395 my ($conf, $storecfg) = @_;
2397 my $nodelist = PVE
::Cluster
::get_nodelist
();
2398 my $nodehash = { map { $_ => 1 } @$nodelist };
2399 my $nodename = PVE
::INotify
::nodename
();
2401 foreach_drive
($conf, sub {
2402 my ($ds, $drive) = @_;
2404 my $volid = $drive->{file
};
2407 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2409 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2410 if ($scfg->{disable
}) {
2412 } elsif (my $avail = $scfg->{nodes
}) {
2413 foreach my $node (keys %$nodehash) {
2414 delete $nodehash->{$node} if !$avail->{$node};
2416 } elsif (!$scfg->{shared
}) {
2417 foreach my $node (keys %$nodehash) {
2418 delete $nodehash->{$node} if $node ne $nodename
2428 my ($pidfile, $pid) = @_;
2430 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2434 return undef if !$line;
2435 my @param = split(/\0/, $line);
2437 my $cmd = $param[0];
2438 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2440 for (my $i = 0; $i < scalar (@param); $i++) {
2443 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2444 my $p = $param[$i+1];
2445 return 1 if $p && ($p eq $pidfile);
2454 my ($vmid, $nocheck, $node) = @_;
2456 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2458 die "unable to find configuration file for VM $vmid - no such machine\n"
2459 if !$nocheck && ! -f
$filename;
2461 my $pidfile = pidfile_name
($vmid);
2463 if (my $fd = IO
::File-
>new("<$pidfile")) {
2468 my $mtime = $st->mtime;
2469 if ($mtime > time()) {
2470 warn "file '$filename' modified in future\n";
2473 if ($line =~ m/^(\d+)$/) {
2475 if (check_cmdline
($pidfile, $pid)) {
2476 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2488 my $vzlist = config_list
();
2490 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2492 while (defined(my $de = $fd->read)) {
2493 next if $de !~ m/^(\d+)\.pid$/;
2495 next if !defined($vzlist->{$vmid});
2496 if (my $pid = check_running
($vmid)) {
2497 $vzlist->{$vmid}->{pid
} = $pid;
2505 my ($storecfg, $conf) = @_;
2507 my $bootdisk = $conf->{bootdisk
};
2508 return undef if !$bootdisk;
2509 return undef if !is_valid_drivename
($bootdisk);
2511 return undef if !$conf->{$bootdisk};
2513 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2514 return undef if !defined($drive);
2516 return undef if drive_is_cdrom
($drive);
2518 my $volid = $drive->{file
};
2519 return undef if !$volid;
2521 return $drive->{size
};
2524 my $last_proc_pid_stat;
2526 # get VM status information
2527 # This must be fast and should not block ($full == false)
2528 # We only query KVM using QMP if $full == true (this can be slow)
2530 my ($opt_vmid, $full) = @_;
2534 my $storecfg = PVE
::Storage
::config
();
2536 my $list = vzlist
();
2537 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2539 my $cpucount = $cpuinfo->{cpus
} || 1;
2541 foreach my $vmid (keys %$list) {
2542 next if $opt_vmid && ($vmid ne $opt_vmid);
2544 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2545 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2548 $d->{pid
} = $list->{$vmid}->{pid
};
2550 # fixme: better status?
2551 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2553 my $size = disksize
($storecfg, $conf);
2554 if (defined($size)) {
2555 $d->{disk
} = 0; # no info available
2556 $d->{maxdisk
} = $size;
2562 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2563 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2564 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2566 $d->{name
} = $conf->{name
} || "VM $vmid";
2567 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2569 if ($conf->{balloon
}) {
2570 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2571 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2582 $d->{diskwrite
} = 0;
2584 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2589 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2590 foreach my $dev (keys %$netdev) {
2591 next if $dev !~ m/^tap([1-9]\d*)i/;
2593 my $d = $res->{$vmid};
2596 $d->{netout
} += $netdev->{$dev}->{receive
};
2597 $d->{netin
} += $netdev->{$dev}->{transmit
};
2600 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2601 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2606 my $ctime = gettimeofday
;
2608 foreach my $vmid (keys %$list) {
2610 my $d = $res->{$vmid};
2611 my $pid = $d->{pid
};
2614 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2615 next if !$pstat; # not running
2617 my $used = $pstat->{utime} + $pstat->{stime
};
2619 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2621 if ($pstat->{vsize
}) {
2622 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2625 my $old = $last_proc_pid_stat->{$pid};
2627 $last_proc_pid_stat->{$pid} = {
2635 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2637 if ($dtime > 1000) {
2638 my $dutime = $used - $old->{used
};
2640 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2641 $last_proc_pid_stat->{$pid} = {
2647 $d->{cpu
} = $old->{cpu
};
2651 return $res if !$full;
2653 my $qmpclient = PVE
::QMPClient-
>new();
2655 my $ballooncb = sub {
2656 my ($vmid, $resp) = @_;
2658 my $info = $resp->{'return'};
2659 return if !$info->{max_mem
};
2661 my $d = $res->{$vmid};
2663 # use memory assigned to VM
2664 $d->{maxmem
} = $info->{max_mem
};
2665 $d->{balloon
} = $info->{actual
};
2667 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2668 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2669 $d->{freemem
} = $info->{free_mem
};
2672 $d->{ballooninfo
} = $info;
2675 my $blockstatscb = sub {
2676 my ($vmid, $resp) = @_;
2677 my $data = $resp->{'return'} || [];
2678 my $totalrdbytes = 0;
2679 my $totalwrbytes = 0;
2681 for my $blockstat (@$data) {
2682 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2683 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2685 $blockstat->{device
} =~ s/drive-//;
2686 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2688 $res->{$vmid}->{diskread
} = $totalrdbytes;
2689 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2692 my $statuscb = sub {
2693 my ($vmid, $resp) = @_;
2695 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2696 # this fails if ballon driver is not loaded, so this must be
2697 # the last commnand (following command are aborted if this fails).
2698 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2700 my $status = 'unknown';
2701 if (!defined($status = $resp->{'return'}->{status
})) {
2702 warn "unable to get VM status\n";
2706 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2709 foreach my $vmid (keys %$list) {
2710 next if $opt_vmid && ($vmid ne $opt_vmid);
2711 next if !$res->{$vmid}->{pid
}; # not running
2712 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2715 $qmpclient->queue_execute(undef, 2);
2717 foreach my $vmid (keys %$list) {
2718 next if $opt_vmid && ($vmid ne $opt_vmid);
2719 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2726 my ($conf, $func, @param) = @_;
2728 foreach my $ds (valid_drive_names
()) {
2729 next if !defined($conf->{$ds});
2731 my $drive = parse_drive
($ds, $conf->{$ds});
2734 &$func($ds, $drive, @param);
2739 my ($conf, $func, @param) = @_;
2743 my $test_volid = sub {
2744 my ($volid, $is_cdrom) = @_;
2748 $volhash->{$volid} = $is_cdrom || 0;
2751 foreach_drive
($conf, sub {
2752 my ($ds, $drive) = @_;
2753 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2756 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2757 my $snap = $conf->{snapshots
}->{$snapname};
2758 &$test_volid($snap->{vmstate
}, 0);
2759 foreach_drive
($snap, sub {
2760 my ($ds, $drive) = @_;
2761 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2765 foreach my $volid (keys %$volhash) {
2766 &$func($volid, $volhash->{$volid}, @param);
2770 sub vga_conf_has_spice
{
2773 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2778 sub config_to_command
{
2779 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2782 my $globalFlags = [];
2783 my $machineFlags = [];
2789 my $kvmver = kvm_user_version
();
2790 my $vernum = 0; # unknown
2791 my $ostype = $conf->{ostype
};
2792 my $winversion = windows_version
($ostype);
2794 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2795 $vernum = $1*1000000+$2*1000;
2796 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2797 $vernum = $1*1000000+$2*1000+$3;
2800 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2802 my $have_ovz = -f
'/proc/vz/vestat';
2804 my $q35 = machine_type_is_q35
($conf);
2805 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2806 my $machine_type = $forcemachine || $conf->{machine
};
2807 my $use_old_bios_files = undef;
2808 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2810 my $cpuunits = defined($conf->{cpuunits
}) ?
2811 $conf->{cpuunits
} : $defaults->{cpuunits
};
2813 push @$cmd, '/usr/bin/kvm';
2815 push @$cmd, '-id', $vmid;
2819 my $qmpsocket = qmp_socket
($vmid);
2820 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2821 push @$cmd, '-mon', "chardev=qmp,mode=control";
2824 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2826 push @$cmd, '-daemonize';
2828 if ($conf->{smbios1
}) {
2829 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2832 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2835 # prefer the OVMF_CODE variant
2836 if (-f
$OVMF_CODE) {
2837 $ovmfbase = $OVMF_CODE;
2838 } elsif (-f
$OVMF_IMG) {
2839 $ovmfbase = $OVMF_IMG;
2842 die "no uefi base img found\n" if !$ovmfbase;
2843 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$ovmfbase";
2845 if (defined($conf->{efidisk0
}) && ($ovmfbase eq $OVMF_CODE)) {
2846 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $conf->{efidisk0
});
2847 my $format = $d->{format
} // 'raw';
2849 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
2851 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
2852 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2853 $format = qemu_img_format
($scfg, $volname);
2858 push @$cmd, '-drive', "if=pflash,unit=1,id=drive-efidisk0,format=$format,file=$path";
2859 } elsif ($ovmfbase eq $OVMF_CODE) {
2860 warn "using uefi without permanent efivars disk\n";
2861 my $ovmfvar_dst = "/tmp/$vmid-ovmf.fd";
2862 PVE
::Tools
::file_copy
($OVMF_VARS, $ovmfvar_dst, 256*1024);
2863 push @$cmd, '-drive', "if=pflash,unit=1,format=raw,file=$ovmfvar_dst";
2865 # if the base img is not OVMF_CODE, we do not have to bother
2866 # to create/use a vars image, since it will not be used anyway
2867 # this can only happen if someone manually deletes the OVMF_CODE image
2868 # or has an old pve-qemu-kvm version installed.
2869 # both should not happen, but we ignore it here
2874 # add usb controllers
2875 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2876 push @$devices, @usbcontrollers if @usbcontrollers;
2877 my $vga = $conf->{vga
};
2879 my $qxlnum = vga_conf_has_spice
($vga);
2880 $vga = 'qxl' if $qxlnum;
2883 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 9)) {
2884 $vga = (!$winversion || $winversion >= 6) ?
'std' : 'cirrus';
2886 $vga = ($winversion >= 6) ?
'std' : 'cirrus';
2890 # enable absolute mouse coordinates (needed by vnc)
2892 if (defined($conf->{tablet
})) {
2893 $tablet = $conf->{tablet
};
2895 $tablet = $defaults->{tablet
};
2896 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2897 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2900 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2903 my $gpu_passthrough;
2906 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2907 my $d = parse_hostpci
($conf->{"hostpci$i"});
2910 my $pcie = $d->{pcie
};
2912 die "q35 machine model is not enabled" if !$q35;
2913 $pciaddr = print_pcie_addr
("hostpci$i");
2915 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2918 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2919 my $romfile = $d->{romfile
};
2922 if ($d->{'x-vga'}) {
2923 $xvga = ',x-vga=on';
2926 $gpu_passthrough = 1;
2928 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2932 my $pcidevices = $d->{pciid
};
2933 my $multifunction = 1 if @$pcidevices > 1;
2936 foreach my $pcidevice (@$pcidevices) {
2938 my $id = "hostpci$i";
2939 $id .= ".$j" if $multifunction;
2940 my $addr = $pciaddr;
2941 $addr .= ".$j" if $multifunction;
2942 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2945 $devicestr .= "$rombar$xvga";
2946 $devicestr .= ",multifunction=on" if $multifunction;
2947 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
2950 push @$devices, '-device', $devicestr;
2956 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
2957 push @$devices, @usbdevices if @usbdevices;
2959 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2960 if (my $path = $conf->{"serial$i"}) {
2961 if ($path eq 'socket') {
2962 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2963 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2964 push @$devices, '-device', "isa-serial,chardev=serial$i";
2966 die "no such serial device\n" if ! -c
$path;
2967 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2968 push @$devices, '-device', "isa-serial,chardev=serial$i";
2974 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2975 if (my $path = $conf->{"parallel$i"}) {
2976 die "no such parallel device\n" if ! -c
$path;
2977 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2978 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2979 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2983 my $vmname = $conf->{name
} || "vm$vmid";
2985 push @$cmd, '-name', $vmname;
2988 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2989 $sockets = $conf->{sockets
} if $conf->{sockets
};
2991 my $cores = $conf->{cores
} || 1;
2993 my $maxcpus = $sockets * $cores;
2995 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2997 my $allowed_vcpus = $cpuinfo->{cpus
};
2999 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3000 if ($allowed_vcpus < $maxcpus);
3002 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
3004 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3005 for (my $i = 2; $i <= $vcpus; $i++) {
3006 my $cpustr = print_cpu_device
($conf,$i);
3007 push @$cmd, '-device', $cpustr;
3012 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3014 push @$cmd, '-nodefaults';
3016 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3018 my $bootindex_hash = {};
3020 foreach my $o (split(//, $bootorder)) {
3021 $bootindex_hash->{$o} = $i*100;
3025 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3027 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3029 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3031 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3033 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3034 my $socket = vnc_socket
($vmid);
3035 push @$cmd, '-vnc', "unix:$socket,x509,password";
3037 push @$cmd, '-nographic';
3041 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3043 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3044 my $useLocaltime = $conf->{localtime};
3046 if ($winversion >= 5) { # windows
3047 $useLocaltime = 1 if !defined($conf->{localtime});
3049 # use time drift fix when acpi is enabled
3050 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3051 $tdf = 1 if !defined($conf->{tdf
});
3055 if ($winversion >= 6) {
3056 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3057 push @$cmd, '-no-hpet';
3060 push @$rtcFlags, 'driftfix=slew' if $tdf;
3063 push @$machineFlags, 'accel=tcg';
3065 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3068 if ($machine_type) {
3069 push @$machineFlags, "type=${machine_type}";
3072 if ($conf->{startdate
}) {
3073 push @$rtcFlags, "base=$conf->{startdate}";
3074 } elsif ($useLocaltime) {
3075 push @$rtcFlags, 'base=localtime';
3078 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3079 if (my $cputype = $conf->{cpu
}) {
3080 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3081 or die "Cannot parse cpu description: $cputype\n";
3082 $cpu = $cpuconf->{cputype
};
3083 $kvm_off = 1 if $cpuconf->{hidden
};
3086 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3088 push @$cpuFlags , '-x2apic'
3089 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3091 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3093 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3095 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3097 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3098 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3101 add_hyperv_enlighments
($cpuFlags, $winversion, $machine_type, $kvmver, $nokvm, $conf->{bios
}, $gpu_passthrough);
3103 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3105 push @$cpuFlags, 'kvm=off' if $kvm_off;
3107 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3108 die "internal error"; # should not happen
3110 push @$cpuFlags, "vendor=${cpu_vendor}"
3111 if $cpu_vendor ne 'default';
3113 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3115 push @$cmd, '-cpu', $cpu;
3117 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3119 push @$cmd, '-S' if $conf->{freeze
};
3121 # set keyboard layout
3122 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3123 push @$cmd, '-k', $kb if $kb;
3126 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3127 #push @$cmd, '-soundhw', 'es1370';
3128 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3130 if($conf->{agent
}) {
3131 my $qgasocket = qmp_socket
($vmid, 1);
3132 my $pciaddr = print_pci_addr
("qga0", $bridges);
3133 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3134 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3135 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3143 for(my $i = 1; $i < $qxlnum; $i++){
3144 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3145 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3148 # assume other OS works like Linux
3149 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3150 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3154 my $pciaddr = print_pci_addr
("spice", $bridges);
3156 my $nodename = PVE
::INotify
::nodename
();
3157 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3158 my @nodeaddrs = PVE
::Tools
::getaddrinfo_all
('localhost', family
=> $pfamily);
3159 die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
3160 my $localhost = PVE
::Network
::addr_to_ip
($nodeaddrs[0]->{addr
});
3161 $spice_port = PVE
::Tools
::next_spice_port
($pfamily, $localhost);
3163 push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
3165 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3166 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3167 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3170 # enable balloon by default, unless explicitly disabled
3171 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3172 $pciaddr = print_pci_addr
("balloon0", $bridges);
3173 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3176 if ($conf->{watchdog
}) {
3177 my $wdopts = parse_watchdog
($conf->{watchdog
});
3178 $pciaddr = print_pci_addr
("watchdog", $bridges);
3179 my $watchdog = $wdopts->{model
} || 'i6300esb';
3180 push @$devices, '-device', "$watchdog$pciaddr";
3181 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3185 my $scsicontroller = {};
3186 my $ahcicontroller = {};
3187 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3189 # Add iscsi initiator name if available
3190 if (my $initiator = get_initiator_name
()) {
3191 push @$devices, '-iscsi', "initiator-name=$initiator";
3194 foreach_drive
($conf, sub {
3195 my ($ds, $drive) = @_;
3197 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3198 push @$vollist, $drive->{file
};
3201 $use_virtio = 1 if $ds =~ m/^virtio/;
3203 if (drive_is_cdrom
($drive)) {
3204 if ($bootindex_hash->{d
}) {
3205 $drive->{bootindex
} = $bootindex_hash->{d
};
3206 $bootindex_hash->{d
} += 1;
3209 if ($bootindex_hash->{c
}) {
3210 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3211 $bootindex_hash->{c
} += 1;
3215 if($drive->{interface
} eq 'virtio'){
3216 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3219 if ($drive->{interface
} eq 'scsi') {
3221 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3223 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3224 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3227 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3228 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3229 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3230 } elsif ($drive->{iothread
}) {
3231 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3235 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3236 $queues = ",num_queues=$drive->{queues}";
3239 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3240 $scsicontroller->{$controller}=1;
3243 if ($drive->{interface
} eq 'sata') {
3244 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3245 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3246 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3247 $ahcicontroller->{$controller}=1;
3250 if ($drive->{interface
} eq 'efidisk') {
3251 # this will be added somewhere else
3255 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3256 push @$devices, '-drive',$drive_cmd;
3257 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3260 for (my $i = 0; $i < $MAX_NETS; $i++) {
3261 next if !$conf->{"net$i"};
3262 my $d = parse_net
($conf->{"net$i"});
3265 $use_virtio = 1 if $d->{model
} eq 'virtio';
3267 if ($bootindex_hash->{n
}) {
3268 $d->{bootindex
} = $bootindex_hash->{n
};
3269 $bootindex_hash->{n
} += 1;
3272 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3273 push @$devices, '-netdev', $netdevfull;
3275 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3276 push @$devices, '-device', $netdevicefull;
3281 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3286 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3288 while (my ($k, $v) = each %$bridges) {
3289 $pciaddr = print_pci_addr
("pci.$k");
3290 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3295 if ($conf->{args
}) {
3296 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3300 push @$cmd, @$devices;
3301 push @$cmd, '-rtc', join(',', @$rtcFlags)
3302 if scalar(@$rtcFlags);
3303 push @$cmd, '-machine', join(',', @$machineFlags)
3304 if scalar(@$machineFlags);
3305 push @$cmd, '-global', join(',', @$globalFlags)
3306 if scalar(@$globalFlags);
3308 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3313 return "${var_run_tmpdir}/$vmid.vnc";
3319 my $res = vm_mon_cmd
($vmid, 'query-spice');
3321 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3325 my ($vmid, $qga) = @_;
3326 my $sockettype = $qga ?
'qga' : 'qmp';
3327 return "${var_run_tmpdir}/$vmid.$sockettype";
3332 return "${var_run_tmpdir}/$vmid.pid";
3335 sub vm_devices_list
{
3338 my $res = vm_mon_cmd
($vmid, 'query-pci');
3340 foreach my $pcibus (@$res) {
3341 foreach my $device (@{$pcibus->{devices
}}) {
3342 next if !$device->{'qdev_id'};
3343 if ($device->{'pci_bridge'}) {
3344 $devices->{$device->{'qdev_id'}} = 1;
3345 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3346 next if !$bridge_device->{'qdev_id'};
3347 $devices->{$bridge_device->{'qdev_id'}} = 1;
3348 $devices->{$device->{'qdev_id'}}++;
3351 $devices->{$device->{'qdev_id'}} = 1;
3356 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3357 foreach my $block (@$resblock) {
3358 if($block->{device
} =~ m/^drive-(\S+)/){
3363 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3364 foreach my $mice (@$resmice) {
3365 if ($mice->{name
} eq 'QEMU HID Tablet') {
3366 $devices->{tablet
} = 1;
3371 # for usb devices there is no query-usb
3372 # but we can iterate over the entries in
3373 # qom-list path=/machine/peripheral
3374 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3375 foreach my $per (@$resperipheral) {
3376 if ($per->{name
} =~ m/^usb\d+$/) {
3377 $devices->{$per->{name
}} = 1;
3385 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3387 my $q35 = machine_type_is_q35
($conf);
3389 my $devices_list = vm_devices_list
($vmid);
3390 return 1 if defined($devices_list->{$deviceid});
3392 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3394 if ($deviceid eq 'tablet') {
3396 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3398 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3400 die "usb hotplug currently not reliable\n";
3401 # since we can't reliably hot unplug all added usb devices
3402 # and usb passthrough disables live migration
3403 # we disable usb hotplugging for now
3404 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3406 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3408 qemu_iothread_add
($vmid, $deviceid, $device);
3410 qemu_driveadd
($storecfg, $vmid, $device);
3411 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3413 qemu_deviceadd
($vmid, $devicefull);
3414 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3416 eval { qemu_drivedel
($vmid, $deviceid); };
3421 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3424 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3425 my $pciaddr = print_pci_addr
($deviceid);
3426 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3428 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3430 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3431 qemu_iothread_add
($vmid, $deviceid, $device);
3432 $devicefull .= ",iothread=iothread-$deviceid";
3435 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3436 $devicefull .= ",num_queues=$device->{queues}";
3439 qemu_deviceadd
($vmid, $devicefull);
3440 qemu_deviceaddverify
($vmid, $deviceid);
3442 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3444 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3445 qemu_driveadd
($storecfg, $vmid, $device);
3447 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3448 eval { qemu_deviceadd
($vmid, $devicefull); };
3450 eval { qemu_drivedel
($vmid, $deviceid); };
3455 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3457 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3459 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3460 my $use_old_bios_files = undef;
3461 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3463 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3464 qemu_deviceadd
($vmid, $netdevicefull);
3465 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3467 eval { qemu_netdevdel
($vmid, $deviceid); };
3472 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3475 my $pciaddr = print_pci_addr
($deviceid);
3476 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3478 qemu_deviceadd
($vmid, $devicefull);
3479 qemu_deviceaddverify
($vmid, $deviceid);
3482 die "can't hotplug device '$deviceid'\n";
3488 # fixme: this should raise exceptions on error!
3489 sub vm_deviceunplug
{
3490 my ($vmid, $conf, $deviceid) = @_;
3492 my $devices_list = vm_devices_list
($vmid);
3493 return 1 if !defined($devices_list->{$deviceid});
3495 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3497 if ($deviceid eq 'tablet') {
3499 qemu_devicedel
($vmid, $deviceid);
3501 } elsif ($deviceid =~ m/^usb\d+$/) {
3503 die "usb hotplug currently not reliable\n";
3504 # when unplugging usb devices this way,
3505 # there may be remaining usb controllers/hubs
3506 # so we disable it for now
3507 qemu_devicedel
($vmid, $deviceid);
3508 qemu_devicedelverify
($vmid, $deviceid);
3510 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3512 qemu_devicedel
($vmid, $deviceid);
3513 qemu_devicedelverify
($vmid, $deviceid);
3514 qemu_drivedel
($vmid, $deviceid);
3515 qemu_iothread_del
($conf, $vmid, $deviceid);
3517 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3519 qemu_devicedel
($vmid, $deviceid);
3520 qemu_devicedelverify
($vmid, $deviceid);
3521 qemu_iothread_del
($conf, $vmid, $deviceid);
3523 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3525 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3526 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3527 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3529 qemu_devicedel
($vmid, $deviceid);
3530 qemu_drivedel
($vmid, $deviceid);
3531 qemu_deletescsihw
($conf, $vmid, $deviceid);
3533 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3535 qemu_devicedel
($vmid, $deviceid);
3536 qemu_devicedelverify
($vmid, $deviceid);
3537 qemu_netdevdel
($vmid, $deviceid);
3540 die "can't unplug device '$deviceid'\n";
3546 sub qemu_deviceadd
{
3547 my ($vmid, $devicefull) = @_;
3549 $devicefull = "driver=".$devicefull;
3550 my %options = split(/[=,]/, $devicefull);
3552 vm_mon_cmd
($vmid, "device_add" , %options);
3555 sub qemu_devicedel
{
3556 my ($vmid, $deviceid) = @_;
3558 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3561 sub qemu_iothread_add
{
3562 my($vmid, $deviceid, $device) = @_;
3564 if ($device->{iothread
}) {
3565 my $iothreads = vm_iothreads_list
($vmid);
3566 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3570 sub qemu_iothread_del
{
3571 my($conf, $vmid, $deviceid) = @_;
3573 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3574 if ($device->{iothread
}) {
3575 my $iothreads = vm_iothreads_list
($vmid);
3576 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3580 sub qemu_objectadd
{
3581 my($vmid, $objectid, $qomtype) = @_;
3583 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3588 sub qemu_objectdel
{
3589 my($vmid, $objectid) = @_;
3591 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3597 my ($storecfg, $vmid, $device) = @_;
3599 my $drive = print_drive_full
($storecfg, $vmid, $device);
3600 $drive =~ s/\\/\\\\/g;
3601 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3603 # If the command succeeds qemu prints: "OK
"
3604 return 1 if $ret =~ m/OK/s;
3606 die "adding drive failed
: $ret\n";
3610 my($vmid, $deviceid) = @_;
3612 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3615 return 1 if $ret eq "";
3617 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3618 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3620 die "deleting drive
$deviceid failed
: $ret\n";
3623 sub qemu_deviceaddverify {
3624 my ($vmid, $deviceid) = @_;
3626 for (my $i = 0; $i <= 5; $i++) {
3627 my $devices_list = vm_devices_list($vmid);
3628 return 1 if defined($devices_list->{$deviceid});
3632 die "error on hotplug device
'$deviceid'\n";
3636 sub qemu_devicedelverify {
3637 my ($vmid, $deviceid) = @_;
3639 # need to verify that the device is correctly removed as device_del
3640 # is async and empty return is not reliable
3642 for (my $i = 0; $i <= 5; $i++) {
3643 my $devices_list = vm_devices_list($vmid);
3644 return 1 if !defined($devices_list->{$deviceid});
3648 die "error on hot-unplugging device
'$deviceid'\n";
3651 sub qemu_findorcreatescsihw {
3652 my ($storecfg, $conf, $vmid, $device) = @_;
3654 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3656 my $scsihwid="$controller_prefix$controller";
3657 my $devices_list = vm_devices_list($vmid);
3659 if(!defined($devices_list->{$scsihwid})) {
3660 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3666 sub qemu_deletescsihw {
3667 my ($conf, $vmid, $opt) = @_;
3669 my $device = parse_drive($opt, $conf->{$opt});
3671 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3672 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3676 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3678 my $devices_list = vm_devices_list($vmid);
3679 foreach my $opt (keys %{$devices_list}) {
3680 if (PVE::QemuServer::is_valid_drivename($opt)) {
3681 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3682 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3688 my $scsihwid="scsihw
$controller";
3690 vm_deviceunplug($vmid, $conf, $scsihwid);
3695 sub qemu_add_pci_bridge {
3696 my ($storecfg, $conf, $vmid, $device) = @_;
3702 print_pci_addr($device, $bridges);
3704 while (my ($k, $v) = each %$bridges) {
3707 return 1 if !defined($bridgeid) || $bridgeid < 1;
3709 my $bridge = "pci
.$bridgeid";
3710 my $devices_list = vm_devices_list($vmid);
3712 if (!defined($devices_list->{$bridge})) {
3713 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3719 sub qemu_set_link_status {
3720 my ($vmid, $device, $up) = @_;
3722 vm_mon_cmd($vmid, "set_link
", name => $device,
3723 up => $up ? JSON::true : JSON::false);
3726 sub qemu_netdevadd {
3727 my ($vmid, $conf, $device, $deviceid) = @_;
3729 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3730 my %options = split(/[=,]/, $netdev);
3732 vm_mon_cmd($vmid, "netdev_add
", %options);
3736 sub qemu_netdevdel {
3737 my ($vmid, $deviceid) = @_;
3739 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3742 sub qemu_usb_hotplug {
3743 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3747 # remove the old one first
3748 vm_deviceunplug($vmid, $conf, $deviceid);
3750 # check if xhci controller is necessary and available
3751 if ($device->{usb3}) {
3753 my $devicelist = vm_devices_list($vmid);
3755 if (!$devicelist->{xhci}) {
3756 my $pciaddr = print_pci_addr("xhci
");
3757 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3760 my $d = parse_usb_device($device->{host});
3761 $d->{usb3} = $device->{usb3};
3764 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3767 sub qemu_cpu_hotplug {
3768 my ($vmid, $conf, $vcpus) = @_;
3770 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3773 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3774 $sockets = $conf->{sockets} if $conf->{sockets};
3775 my $cores = $conf->{cores} || 1;
3776 my $maxcpus = $sockets * $cores;
3778 $vcpus = $maxcpus if !$vcpus;
3780 die "you can
't add more vcpus than maxcpus\n"
3781 if $vcpus > $maxcpus;
3783 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3785 if ($vcpus < $currentvcpus) {
3787 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3789 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3790 qemu_devicedel($vmid, "cpu$i");
3792 my $currentrunningvcpus = undef;
3794 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3795 last if scalar(@{$currentrunningvcpus}) == $i-1;
3796 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3800 #update conf after each succesfull cpu unplug
3801 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3802 PVE::QemuConfig->write_config($vmid, $conf);
3805 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3811 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3812 die "vcpus in running vm does not match its configuration\n"
3813 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3815 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3817 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3818 my $cpustr = print_cpu_device($conf, $i);
3819 qemu_deviceadd($vmid, $cpustr);
3822 my $currentrunningvcpus = undef;
3824 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3825 last if scalar(@{$currentrunningvcpus}) == $i;
3826 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3830 #update conf after each succesfull cpu hotplug
3831 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3832 PVE::QemuConfig->write_config($vmid, $conf);
3836 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3837 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3842 sub qemu_block_set_io_throttle {
3843 my ($vmid, $deviceid,
3844 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3845 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3846 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3847 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3849 return if !check_running($vmid) ;
3851 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3853 bps_rd => int($bps_rd),
3854 bps_wr => int($bps_wr),
3856 iops_rd => int($iops_rd),
3857 iops_wr => int($iops_wr),
3858 bps_max => int($bps_max),
3859 bps_rd_max => int($bps_rd_max),
3860 bps_wr_max => int($bps_wr_max),
3861 iops_max => int($iops_max),
3862 iops_rd_max => int($iops_rd_max),
3863 iops_wr_max => int($iops_wr_max),
3864 bps_max_length => int($bps_max_length),
3865 bps_rd_max_length => int($bps_rd_max_length),
3866 bps_wr_max_length => int($bps_wr_max_length),
3867 iops_max_length => int($iops_max_length),
3868 iops_rd_max_length => int($iops_rd_max_length),
3869 iops_wr_max_length => int($iops_wr_max_length),
3874 # old code, only used to shutdown old VM after update
3876 my ($fh, $timeout) = @_;
3878 my $sel = new IO::Select;
3885 while (scalar (@ready = $sel->can_read($timeout))) {
3887 if ($count = $fh->sysread($buf, 8192)) {
3888 if ($buf =~ /^(.*)\(qemu\) $/s) {
3895 if (!defined($count)) {
3902 die "monitor read timeout\n" if !scalar(@ready);
3907 # old code, only used to shutdown old VM after update
3908 sub vm_monitor_command {
3909 my ($vmid, $cmdstr, $nocheck) = @_;
3914 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3916 my $sname = "${var_run_tmpdir}/$vmid.mon";
3918 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3919 die "unable to connect to VM $vmid socket - $!\n";
3923 # hack: migrate sometime blocks the monitor (when migrate_downtime
3925 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3926 $timeout = 60*60; # 1 hour
3930 my $data = __read_avail($sock, $timeout);
3932 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3933 die "got unexpected qemu monitor banner\n";
3936 my $sel = new IO::Select;
3939 if (!scalar(my @ready = $sel->can_write($timeout))) {
3940 die "monitor write error - timeout";
3943 my $fullcmd = "$cmdstr\r";
3945 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3948 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3949 die "monitor write error - $!";
3952 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3956 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3957 $timeout = 60*60; # 1 hour
3958 } elsif ($cmdstr =~ m/^(eject|change)/) {
3959 $timeout = 60; # note: cdrom mount command is slow
3961 if ($res = __read_avail($sock, $timeout)) {
3963 my @lines = split("\r?\n", $res);
3965 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3967 $res = join("\n", @lines);
3975 syslog("err", "VM $vmid monitor command failed - $err");
3982 sub qemu_block_resize {
3983 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3985 my $running = check_running($vmid);
3987 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3989 return if !$running;
3991 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3995 sub qemu_volume_snapshot {
3996 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3998 my $running = check_running($vmid);
4000 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4001 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4003 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4007 sub qemu_volume_snapshot_delete {
4008 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4010 my $running = check_running($vmid);
4012 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4013 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4015 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4019 sub set_migration_caps {
4025 "auto-converge" => 1,
4027 "x-rdma-pin-all" => 0,
4032 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4034 for my $supported_capability (@$supported_capabilities) {
4036 capability => $supported_capability->{capability},
4037 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4041 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4044 my $fast_plug_option = {
4054 # hotplug changes in [PENDING]
4055 # $selection hash can be used to only apply specified options, for
4056 # example: { cores => 1 } (only apply changed 'cores
')
4057 # $errors ref is used to return error messages
4058 sub vmconfig_hotplug_pending {
4059 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4061 my $defaults = load_defaults();
4063 # commit values which do not have any impact on running VM first
4064 # Note: those option cannot raise errors, we we do not care about
4065 # $selection and always apply them.
4067 my $add_error = sub {
4068 my ($opt, $msg) = @_;
4069 $errors->{$opt} = "hotplug problem - $msg";
4073 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4074 if ($fast_plug_option->{$opt}) {
4075 $conf->{$opt} = $conf->{pending}->{$opt};
4076 delete $conf->{pending}->{$opt};
4082 PVE::QemuConfig->write_config($vmid, $conf);
4083 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4086 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4088 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4089 while (my ($opt, $force) = each %$pending_delete_hash) {
4090 next if $selection && !$selection->{$opt};
4092 if ($opt eq 'hotplug
') {
4093 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4094 } elsif ($opt eq 'tablet
') {
4095 die "skip\n" if !$hotplug_features->{usb};
4096 if ($defaults->{tablet}) {
4097 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4099 vm_deviceunplug($vmid, $conf, $opt);
4101 } elsif ($opt =~ m/^usb\d+/) {
4103 # since we cannot reliably hot unplug usb devices
4104 # we are disabling it
4105 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4106 vm_deviceunplug($vmid, $conf, $opt);
4107 } elsif ($opt eq 'vcpus
') {
4108 die "skip\n" if !$hotplug_features->{cpu};
4109 qemu_cpu_hotplug($vmid, $conf, undef);
4110 } elsif ($opt eq 'balloon
') {
4111 # enable balloon device is not hotpluggable
4112 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4113 } elsif ($fast_plug_option->{$opt}) {
4115 } elsif ($opt =~ m/^net(\d+)$/) {
4116 die "skip\n" if !$hotplug_features->{network};
4117 vm_deviceunplug($vmid, $conf, $opt);
4118 } elsif (is_valid_drivename($opt)) {
4119 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4120 vm_deviceunplug($vmid, $conf, $opt);
4121 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4122 } elsif ($opt =~ m/^memory$/) {
4123 die "skip\n" if !$hotplug_features->{memory};
4124 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4125 } elsif ($opt eq 'cpuunits
') {
4126 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4127 } elsif ($opt eq 'cpulimit
') {
4128 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4134 &$add_error($opt, $err) if $err ne "skip\n";
4136 # save new config if hotplug was successful
4137 delete $conf->{$opt};
4138 vmconfig_undelete_pending_option($conf, $opt);
4139 PVE::QemuConfig->write_config($vmid, $conf);
4140 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4144 foreach my $opt (keys %{$conf->{pending}}) {
4145 next if $selection && !$selection->{$opt};
4146 my $value = $conf->{pending}->{$opt};
4148 if ($opt eq 'hotplug
') {
4149 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4150 } elsif ($opt eq 'tablet
') {
4151 die "skip\n" if !$hotplug_features->{usb};
4153 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4154 } elsif ($value == 0) {
4155 vm_deviceunplug($vmid, $conf, $opt);
4157 } elsif ($opt =~ m/^usb\d+$/) {
4159 # since we cannot reliably hot unplug usb devices
4160 # we are disabling it
4161 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4162 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4163 die "skip\n" if !$d;
4164 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4165 } elsif ($opt eq 'vcpus
') {
4166 die "skip\n" if !$hotplug_features->{cpu};
4167 qemu_cpu_hotplug($vmid, $conf, $value);
4168 } elsif ($opt eq 'balloon
') {
4169 # enable/disable balloning device is not hotpluggable
4170 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4171 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4172 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4174 # allow manual ballooning if shares is set to zero
4175 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4176 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4177 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4179 } elsif ($opt =~ m/^net(\d+)$/) {
4180 # some changes can be done without hotplug
4181 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4182 $vmid, $opt, $value);
4183 } elsif (is_valid_drivename($opt)) {
4184 # some changes can be done without hotplug
4185 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4186 $vmid, $opt, $value, 1);
4187 } elsif ($opt =~ m/^memory$/) { #dimms
4188 die "skip\n" if !$hotplug_features->{memory};
4189 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4190 } elsif ($opt eq 'cpuunits
') {
4191 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4192 } elsif ($opt eq 'cpulimit
') {
4193 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4194 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4196 die "skip\n"; # skip non-hot-pluggable options
4200 &$add_error($opt, $err) if $err ne "skip\n";
4202 # save new config if hotplug was successful
4203 $conf->{$opt} = $value;
4204 delete $conf->{pending}->{$opt};
4205 PVE::QemuConfig->write_config($vmid, $conf);
4206 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4211 sub try_deallocate_drive {
4212 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4214 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4215 my $volid = $drive->{file};
4216 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4217 my $sid = PVE::Storage::parse_volume_id($volid);
4218 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4220 # check if the disk is really unused
4221 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4222 if is_volume_in_use($storecfg, $conf, $key, $volid);
4223 PVE::Storage::vdisk_free($storecfg, $volid);
4226 # If vm is not owner of this disk remove from config
4234 sub vmconfig_delete_or_detach_drive {
4235 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4237 my $drive = parse_drive($opt, $conf->{$opt});
4239 my $rpcenv = PVE::RPCEnvironment::get();
4240 my $authuser = $rpcenv->get_user();
4243 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4244 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4246 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4250 sub vmconfig_apply_pending {
4251 my ($vmid, $conf, $storecfg) = @_;
4255 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4256 while (my ($opt, $force) = each %$pending_delete_hash) {
4257 die "internal error" if $opt =~ m/^unused/;
4258 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4259 if (!defined($conf->{$opt})) {
4260 vmconfig_undelete_pending_option($conf, $opt);
4261 PVE::QemuConfig->write_config($vmid, $conf);
4262 } elsif (is_valid_drivename($opt)) {
4263 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4264 vmconfig_undelete_pending_option($conf, $opt);
4265 delete $conf->{$opt};
4266 PVE::QemuConfig->write_config($vmid, $conf);
4268 vmconfig_undelete_pending_option($conf, $opt);
4269 delete $conf->{$opt};
4270 PVE::QemuConfig->write_config($vmid, $conf);
4274 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4276 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4277 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4279 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4280 # skip if nothing changed
4281 } elsif (is_valid_drivename($opt)) {
4282 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4283 if defined($conf->{$opt});
4284 $conf->{$opt} = $conf->{pending}->{$opt};
4286 $conf->{$opt} = $conf->{pending}->{$opt};
4289 delete $conf->{pending}->{$opt};
4290 PVE::QemuConfig->write_config($vmid, $conf);
4294 my $safe_num_ne = sub {
4297 return 0 if !defined($a) && !defined($b);
4298 return 1 if !defined($a);
4299 return 1 if !defined($b);
4304 my $safe_string_ne = sub {
4307 return 0 if !defined($a) && !defined($b);
4308 return 1 if !defined($a);
4309 return 1 if !defined($b);
4314 sub vmconfig_update_net {
4315 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4317 my $newnet = parse_net($value);
4319 if ($conf->{$opt}) {
4320 my $oldnet = parse_net($conf->{$opt});
4322 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4323 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4324 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4325 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4327 # for non online change, we try to hot-unplug
4328 die "skip\n" if !$hotplug;
4329 vm_deviceunplug($vmid, $conf, $opt);
4332 die "internal error" if $opt !~ m/net(\d+)/;
4333 my $iface = "tap${vmid}i$1";
4335 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4336 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4337 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4338 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4339 PVE::Network::tap_unplug($iface);
4340 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4341 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4342 # Rate can be applied on its own but any change above needs to
4343 # include the rate in tap_plug since OVS resets everything.
4344 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4347 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4348 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4356 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4362 sub vmconfig_update_disk {
4363 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4365 # fixme: do we need force?
4367 my $drive = parse_drive($opt, $value);
4369 if ($conf->{$opt}) {
4371 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4373 my $media = $drive->{media} || 'disk
';
4374 my $oldmedia = $old_drive->{media} || 'disk
';
4375 die "unable to change media type\n" if $media ne $oldmedia;
4377 if (!drive_is_cdrom($old_drive)) {
4379 if ($drive->{file} ne $old_drive->{file}) {
4381 die "skip\n" if !$hotplug;
4383 # unplug and register as unused
4384 vm_deviceunplug($vmid, $conf, $opt);
4385 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4388 # update existing disk
4390 # skip non hotpluggable value
4391 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4392 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4393 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4394 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4399 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4400 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4401 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4402 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4403 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4404 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4405 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4406 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4407 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4408 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4409 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4410 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4411 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4412 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4413 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4414 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4415 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4416 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4418 qemu_block_set_io_throttle($vmid,"drive-$opt",
4419 ($drive->{mbps} || 0)*1024*1024,
4420 ($drive->{mbps_rd} || 0)*1024*1024,
4421 ($drive->{mbps_wr} || 0)*1024*1024,
4422 $drive->{iops} || 0,
4423 $drive->{iops_rd} || 0,
4424 $drive->{iops_wr} || 0,
4425 ($drive->{mbps_max} || 0)*1024*1024,
4426 ($drive->{mbps_rd_max} || 0)*1024*1024,
4427 ($drive->{mbps_wr_max} || 0)*1024*1024,
4428 $drive->{iops_max} || 0,
4429 $drive->{iops_rd_max} || 0,
4430 $drive->{iops_wr_max} || 0,
4431 $drive->{bps_max_length} || 1,
4432 $drive->{bps_rd_max_length} || 1,
4433 $drive->{bps_wr_max_length} || 1,
4434 $drive->{iops_max_length} || 1,
4435 $drive->{iops_rd_max_length} || 1,
4436 $drive->{iops_wr_max_length} || 1);
4445 if ($drive->{file} eq 'none
') {
4446 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4448 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4449 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4450 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4458 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4460 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4461 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4465 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4466 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
4468 PVE::QemuConfig->lock_config($vmid, sub {
4469 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4471 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4473 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4475 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4477 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4478 vmconfig_apply_pending($vmid, $conf, $storecfg);
4479 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4482 my $defaults = load_defaults();
4484 # set environment variable useful inside network script
4485 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4487 my $local_volumes = {};
4489 if ($targetstorage) {
4490 foreach_drive($conf, sub {
4491 my ($ds, $drive) = @_;
4493 return if drive_is_cdrom($drive);
4495 my $volid = $drive->{file};
4499 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
4501 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4502 return if $scfg->{shared};
4503 $local_volumes->{$ds} = [$volid, $storeid, $volname];
4508 foreach my $opt (sort keys %$local_volumes) {
4510 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
4511 my $drive = parse_drive($opt, $conf->{$opt});
4513 #if remote storage is specified, use default format
4514 if ($targetstorage && $targetstorage ne "1") {
4515 $storeid = $targetstorage;
4516 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4517 $format = $defFormat;
4519 #else we use same format than original
4520 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4521 $format = qemu_img_format($scfg, $volid);
4524 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
4525 my $newdrive = $drive;
4526 $newdrive->{format} = $format;
4527 $newdrive->{file} = $newvolid;
4528 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
4529 $local_volumes->{$opt} = $drivestr;
4530 #pass drive to conf for command line
4531 $conf->{$opt} = $drivestr;
4535 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4537 my $migrate_port = 0;
4540 if ($statefile eq 'tcp
') {
4541 my $localip = "localhost";
4542 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4543 my $nodename = PVE::INotify::nodename();
4545 if (!defined($migration_type)) {
4546 if (defined($datacenterconf->{migration}->{type})) {
4547 $migration_type = $datacenterconf->{migration}->{type};
4549 $migration_type = 'secure
';
4553 if ($migration_type eq 'insecure
') {
4554 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4555 if ($migrate_network_addr) {
4556 $localip = $migrate_network_addr;
4558 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4561 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4564 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4565 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4566 $migrate_uri = "tcp:${localip}:${migrate_port}";
4567 push @$cmd, '-incoming
', $migrate_uri;
4570 } elsif ($statefile eq 'unix
') {
4571 # should be default for secure migrations as a ssh TCP forward
4572 # tunnel is not deterministic reliable ready and fails regurarly
4573 # to set up in time, so use UNIX socket forwards
4574 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4575 unlink $socket_addr;
4577 $migrate_uri = "unix:$socket_addr";
4579 push @$cmd, '-incoming
', $migrate_uri;
4583 push @$cmd, '-loadstate
', $statefile;
4590 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4591 my $d = parse_hostpci($conf->{"hostpci$i"});
4593 my $pcidevices = $d->{pciid};
4594 foreach my $pcidevice (@$pcidevices) {
4595 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4597 my $info = pci_device_info("0000:$pciid");
4598 die "IOMMU not present\n" if !check_iommu_support();
4599 die "no pci device info for device '$pciid'\n" if !$info;
4600 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4601 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4605 PVE::Storage::activate_volumes($storecfg, $vollist);
4607 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4609 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4610 eval { run_command($cmd); };
4613 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4614 : $defaults->{cpuunits};
4616 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4619 Slice => 'qemu
.slice
',
4621 CPUShares => $cpuunits
4624 if (my $cpulimit = $conf->{cpulimit}) {
4625 $properties{CPUQuota} = int($cpulimit * 100);
4627 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4629 if ($conf->{hugepages}) {
4632 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4633 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4635 PVE::QemuServer::Memory::hugepages_mount();
4636 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4639 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4640 run_command($cmd, %run_params);
4644 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4648 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4650 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4654 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4655 run_command($cmd, %run_params);
4660 # deactivate volumes if start fails
4661 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4662 die "start failed: $err";
4665 print "migration listens on $migrate_uri\n" if $migrate_uri;
4667 if ($statefile && $statefile ne 'tcp
') {
4668 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4672 #start nbd server for storage migration
4673 if ($targetstorage) {
4674 my $nodename = PVE::INotify::nodename();
4675 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4676 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
4677 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4678 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4680 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet
', data => { host => "${localip}", port => "${migrate_port}" } } );
4682 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4684 foreach my $opt (sort keys %$local_volumes) {
4685 my $volid = $local_volumes->{$opt};
4686 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
4687 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
4688 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
4692 if ($migratedfrom) {
4694 set_migration_caps($vmid);
4699 print "spice listens on port $spice_port\n";
4700 if ($spice_ticket) {
4701 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4702 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4707 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4708 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4709 if $conf->{balloon};
4712 foreach my $opt (keys %$conf) {
4713 next if $opt !~ m/^net\d+$/;
4714 my $nicconf = parse_net($conf->{$opt});
4715 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4719 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4720 path => "machine/peripheral/balloon0",
4721 property => "guest-stats-polling-interval",
4722 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4728 my ($vmid, $execute, %params) = @_;
4730 my $cmd = { execute => $execute, arguments => \%params };
4731 vm_qmp_command($vmid, $cmd);
4734 sub vm_mon_cmd_nocheck {
4735 my ($vmid, $execute, %params) = @_;
4737 my $cmd = { execute => $execute, arguments => \%params };
4738 vm_qmp_command($vmid, $cmd, 1);
4741 sub vm_qmp_command {
4742 my ($vmid, $cmd, $nocheck) = @_;
4747 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4748 $timeout = $cmd->{arguments}->{timeout};
4749 delete $cmd->{arguments}->{timeout};
4753 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4754 my $sname = qmp_socket($vmid);
4755 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4756 my $qmpclient = PVE::QMPClient->new();
4758 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4759 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4760 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4761 if scalar(%{$cmd->{arguments}});
4762 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4764 die "unable to
open monitor
socket\n";
4768 syslog("err
", "VM
$vmid qmp command failed
- $err");
4775 sub vm_human_monitor_command {
4776 my ($vmid, $cmdline) = @_;
4781 execute => 'human-monitor-command',
4782 arguments => { 'command-line' => $cmdline},
4785 return vm_qmp_command($vmid, $cmd);
4788 sub vm_commandline {
4789 my ($storecfg, $vmid) = @_;
4791 my $conf = PVE::QemuConfig->load_config($vmid);
4793 my $defaults = load_defaults();
4795 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4797 return PVE::Tools::cmd2string($cmd);
4801 my ($vmid, $skiplock) = @_;
4803 PVE::QemuConfig->lock_config($vmid, sub {
4805 my $conf = PVE::QemuConfig->load_config($vmid);
4807 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4809 vm_mon_cmd($vmid, "system_reset
");
4813 sub get_vm_volumes {
4817 foreach_volid($conf, sub {
4818 my ($volid, $is_cdrom) = @_;
4820 return if $volid =~ m|^/|;
4822 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4825 push @$vollist, $volid;
4831 sub vm_stop_cleanup {
4832 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4837 my $vollist = get_vm_volumes($conf);
4838 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4841 foreach my $ext (qw(mon qmp pid vnc qga)) {
4842 unlink "/var/run/qemu-server/${vmid}.$ext";
4845 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4847 warn $@ if $@; # avoid errors - just warn
4850 # Note: use $nockeck to skip tests if VM configuration file exists.
4851 # We need that when migration VMs to other nodes (files already moved)
4852 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4854 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4856 $force = 1 if !defined($force) && !$shutdown;
4859 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4860 kill 15, $pid if $pid;
4861 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4862 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4866 PVE
::QemuConfig-
>lock_config($vmid, sub {
4868 my $pid = check_running
($vmid, $nocheck);
4873 $conf = PVE
::QemuConfig-
>load_config($vmid);
4874 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4875 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4876 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4877 $timeout = $opts->{down
} if $opts->{down
};
4881 $timeout = 60 if !defined($timeout);
4885 if (defined($conf) && $conf->{agent
}) {
4886 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4888 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4891 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4898 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4903 if ($count >= $timeout) {
4905 warn "VM still running - terminating now with SIGTERM\n";
4908 die "VM quit/powerdown failed - got timeout\n";
4911 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4916 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4919 die "VM quit/powerdown failed\n";
4927 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4932 if ($count >= $timeout) {
4933 warn "VM still running - terminating now with SIGKILL\n";
4938 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4943 my ($vmid, $skiplock) = @_;
4945 PVE
::QemuConfig-
>lock_config($vmid, sub {
4947 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4949 PVE
::QemuConfig-
>check_lock($conf)
4950 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4952 vm_mon_cmd
($vmid, "stop");
4957 my ($vmid, $skiplock, $nocheck) = @_;
4959 PVE
::QemuConfig-
>lock_config($vmid, sub {
4963 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4965 PVE
::QemuConfig-
>check_lock($conf)
4966 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4968 vm_mon_cmd
($vmid, "cont");
4971 vm_mon_cmd_nocheck
($vmid, "cont");
4977 my ($vmid, $skiplock, $key) = @_;
4979 PVE
::QemuConfig-
>lock_config($vmid, sub {
4981 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4983 # there is no qmp command, so we use the human monitor command
4984 vm_human_monitor_command
($vmid, "sendkey $key");
4989 my ($storecfg, $vmid, $skiplock) = @_;
4991 PVE
::QemuConfig-
>lock_config($vmid, sub {
4993 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4995 if (!check_running
($vmid)) {
4996 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4998 die "VM $vmid is running - destroy failed\n";
5006 my ($filename, $buf) = @_;
5008 my $fh = IO
::File-
>new($filename, "w");
5009 return undef if !$fh;
5011 my $res = print $fh $buf;
5018 sub pci_device_info
{
5023 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
5024 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
5026 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
5027 return undef if !defined($irq) || $irq !~ m/^\d+$/;
5029 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
5030 return undef if !defined($vendor) || $vendor !~ s/^0x//;
5032 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
5033 return undef if !defined($product) || $product !~ s/^0x//;
5038 product
=> $product,
5044 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
5053 my $name = $dev->{name
};
5055 my $fn = "$pcisysfs/devices/$name/reset";
5057 return file_write
($fn, "1");
5060 sub pci_dev_bind_to_vfio
{
5063 my $name = $dev->{name
};
5065 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5067 if (!-d
$vfio_basedir) {
5068 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5070 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5072 my $testdir = "$vfio_basedir/$name";
5073 return 1 if -d
$testdir;
5075 my $data = "$dev->{vendor} $dev->{product}";
5076 return undef if !file_write
("$vfio_basedir/new_id", $data);
5078 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5079 if (!file_write
($fn, $name)) {
5080 return undef if -f
$fn;
5083 $fn = "$vfio_basedir/bind";
5084 if (! -d
$testdir) {
5085 return undef if !file_write
($fn, $name);
5091 sub pci_dev_group_bind_to_vfio
{
5094 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5096 if (!-d
$vfio_basedir) {
5097 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5099 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5101 # get IOMMU group devices
5102 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5103 my @devs = grep /^0000:/, readdir($D);
5106 foreach my $pciid (@devs) {
5107 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5109 # pci bridges, switches or root ports are not supported
5110 # they have a pci_bus subdirectory so skip them
5111 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5113 my $info = pci_device_info
($1);
5114 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5120 # vzdump restore implementaion
5122 sub tar_archive_read_firstfile
{
5123 my $archive = shift;
5125 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5127 # try to detect archive type first
5128 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5129 die "unable to open file '$archive'\n";
5130 my $firstfile = <$fh>;
5134 die "ERROR: archive contaions no data\n" if !$firstfile;
5140 sub tar_restore_cleanup
{
5141 my ($storecfg, $statfile) = @_;
5143 print STDERR
"starting cleanup\n";
5145 if (my $fd = IO
::File-
>new($statfile, "r")) {
5146 while (defined(my $line = <$fd>)) {
5147 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5150 if ($volid =~ m
|^/|) {
5151 unlink $volid || die 'unlink failed\n';
5153 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5155 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5157 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5159 print STDERR
"unable to parse line in statfile - $line";
5166 sub restore_archive
{
5167 my ($archive, $vmid, $user, $opts) = @_;
5169 my $format = $opts->{format
};
5172 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5173 $format = 'tar' if !$format;
5175 } elsif ($archive =~ m/\.tar$/) {
5176 $format = 'tar' if !$format;
5177 } elsif ($archive =~ m/.tar.lzo$/) {
5178 $format = 'tar' if !$format;
5180 } elsif ($archive =~ m/\.vma$/) {
5181 $format = 'vma' if !$format;
5182 } elsif ($archive =~ m/\.vma\.gz$/) {
5183 $format = 'vma' if !$format;
5185 } elsif ($archive =~ m/\.vma\.lzo$/) {
5186 $format = 'vma' if !$format;
5189 $format = 'vma' if !$format; # default
5192 # try to detect archive format
5193 if ($format eq 'tar') {
5194 return restore_tar_archive
($archive, $vmid, $user, $opts);
5196 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5200 sub restore_update_config_line
{
5201 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5203 return if $line =~ m/^\#qmdump\#/;
5204 return if $line =~ m/^\#vzdump\#/;
5205 return if $line =~ m/^lock:/;
5206 return if $line =~ m/^unused\d+:/;
5207 return if $line =~ m/^parent:/;
5208 return if $line =~ m/^template:/; # restored VM is never a template
5210 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5211 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5212 # try to convert old 1.X settings
5213 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5214 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5215 my ($model, $macaddr) = split(/\=/, $devconfig);
5216 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5219 bridge
=> "vmbr$ind",
5220 macaddr
=> $macaddr,
5222 my $netstr = print_net
($net);
5224 print $outfd "net$cookie->{netcount}: $netstr\n";
5225 $cookie->{netcount
}++;
5227 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5228 my ($id, $netstr) = ($1, $2);
5229 my $net = parse_net
($netstr);
5230 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5231 $netstr = print_net
($net);
5232 print $outfd "$id: $netstr\n";
5233 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5236 my $di = parse_drive
($virtdev, $value);
5237 if (defined($di->{backup
}) && !$di->{backup
}) {
5238 print $outfd "#$line";
5239 } elsif ($map->{$virtdev}) {
5240 delete $di->{format
}; # format can change on restore
5241 $di->{file
} = $map->{$virtdev};
5242 $value = print_drive
($vmid, $di);
5243 print $outfd "$virtdev: $value\n";
5253 my ($cfg, $vmid) = @_;
5255 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5257 my $volid_hash = {};
5258 foreach my $storeid (keys %$info) {
5259 foreach my $item (@{$info->{$storeid}}) {
5260 next if !($item->{volid
} && $item->{size
});
5261 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5262 $volid_hash->{$item->{volid
}} = $item;
5269 sub is_volume_in_use
{
5270 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5272 my $path = PVE
::Storage
::path
($storecfg, $volid);
5274 my $scan_config = sub {
5275 my ($cref, $snapname) = @_;
5277 foreach my $key (keys %$cref) {
5278 my $value = $cref->{$key};
5279 if (is_valid_drivename
($key)) {
5280 next if $skip_drive && $key eq $skip_drive;
5281 my $drive = parse_drive
($key, $value);
5282 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5283 return 1 if $volid eq $drive->{file
};
5284 if ($drive->{file
} =~ m!^/!) {
5285 return 1 if $drive->{file
} eq $path;
5287 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5289 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5291 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5299 return 1 if &$scan_config($conf);
5303 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5304 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5310 sub update_disksize
{
5311 my ($vmid, $conf, $volid_hash) = @_;
5317 # Note: it is allowed to define multiple storages with same path (alias), so
5318 # we need to check both 'volid' and real 'path' (two different volid can point
5319 # to the same path).
5324 foreach my $opt (keys %$conf) {
5325 if (is_valid_drivename
($opt)) {
5326 my $drive = parse_drive
($opt, $conf->{$opt});
5327 my $volid = $drive->{file
};
5330 $used->{$volid} = 1;
5331 if ($volid_hash->{$volid} &&
5332 (my $path = $volid_hash->{$volid}->{path
})) {
5333 $usedpath->{$path} = 1;
5336 next if drive_is_cdrom
($drive);
5337 next if !$volid_hash->{$volid};
5339 $drive->{size
} = $volid_hash->{$volid}->{size
};
5340 my $new = print_drive
($vmid, $drive);
5341 if ($new ne $conf->{$opt}) {
5343 $conf->{$opt} = $new;
5348 # remove 'unusedX' entry if volume is used
5349 foreach my $opt (keys %$conf) {
5350 next if $opt !~ m/^unused\d+$/;
5351 my $volid = $conf->{$opt};
5352 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5353 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5355 delete $conf->{$opt};
5359 foreach my $volid (sort keys %$volid_hash) {
5360 next if $volid =~ m/vm-$vmid-state-/;
5361 next if $used->{$volid};
5362 my $path = $volid_hash->{$volid}->{path
};
5363 next if !$path; # just to be sure
5364 next if $usedpath->{$path};
5366 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5367 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5374 my ($vmid, $nolock) = @_;
5376 my $cfg = PVE
::Storage
::config
();
5378 my $volid_hash = scan_volids
($cfg, $vmid);
5380 my $updatefn = sub {
5383 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5385 PVE
::QemuConfig-
>check_lock($conf);
5388 foreach my $volid (keys %$volid_hash) {
5389 my $info = $volid_hash->{$volid};
5390 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5393 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5395 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5398 if (defined($vmid)) {
5402 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5405 my $vmlist = config_list
();
5406 foreach my $vmid (keys %$vmlist) {
5410 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5416 sub restore_vma_archive
{
5417 my ($archive, $vmid, $user, $opts, $comp) = @_;
5419 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5420 my $readfrom = $archive;
5425 my $qarchive = PVE
::Tools
::shellquote
($archive);
5426 if ($comp eq 'gzip') {
5427 $uncomp = "zcat $qarchive|";
5428 } elsif ($comp eq 'lzop') {
5429 $uncomp = "lzop -d -c $qarchive|";
5431 die "unknown compression method '$comp'\n";
5436 my $tmpdir = "/var/tmp/vzdumptmp$$";
5439 # disable interrupts (always do cleanups)
5440 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5441 warn "got interrupt - ignored\n";
5444 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5445 POSIX
::mkfifo
($mapfifo, 0600);
5448 my $openfifo = sub {
5449 open($fifofh, '>', $mapfifo) || die $!;
5452 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5459 my $rpcenv = PVE
::RPCEnvironment
::get
();
5461 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5462 my $tmpfn = "$conffile.$$.tmp";
5464 # Note: $oldconf is undef if VM does not exists
5465 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5466 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5468 my $print_devmap = sub {
5469 my $virtdev_hash = {};
5471 my $cfgfn = "$tmpdir/qemu-server.conf";
5473 # we can read the config - that is already extracted
5474 my $fh = IO
::File-
>new($cfgfn, "r") ||
5475 "unable to read qemu-server.conf - $!\n";
5477 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5479 my $pve_firewall_dir = '/etc/pve/firewall';
5480 mkdir $pve_firewall_dir; # make sure the dir exists
5481 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5484 while (defined(my $line = <$fh>)) {
5485 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5486 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5487 die "archive does not contain data for drive '$virtdev'\n"
5488 if !$devinfo->{$devname};
5489 if (defined($opts->{storage
})) {
5490 $storeid = $opts->{storage
} || 'local';
5491 } elsif (!$storeid) {
5494 $format = 'raw' if !$format;
5495 $devinfo->{$devname}->{devname
} = $devname;
5496 $devinfo->{$devname}->{virtdev
} = $virtdev;
5497 $devinfo->{$devname}->{format
} = $format;
5498 $devinfo->{$devname}->{storeid
} = $storeid;
5500 # check permission on storage
5501 my $pool = $opts->{pool
}; # todo: do we need that?
5502 if ($user ne 'root@pam') {
5503 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5506 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5510 foreach my $devname (keys %$devinfo) {
5511 die "found no device mapping information for device '$devname'\n"
5512 if !$devinfo->{$devname}->{virtdev
};
5515 my $cfg = PVE
::Storage
::config
();
5517 # create empty/temp config
5519 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5520 foreach_drive
($oldconf, sub {
5521 my ($ds, $drive) = @_;
5523 return if drive_is_cdrom
($drive);
5525 my $volid = $drive->{file
};
5527 return if !$volid || $volid =~ m
|^/|;
5529 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5530 return if !$path || !$owner || ($owner != $vmid);
5532 # Note: only delete disk we want to restore
5533 # other volumes will become unused
5534 if ($virtdev_hash->{$ds}) {
5535 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5542 # delete vmstate files
5543 # since after the restore we have no snapshots anymore
5544 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5545 my $snap = $oldconf->{snapshots
}->{$snapname};
5546 if ($snap->{vmstate
}) {
5547 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5556 foreach my $virtdev (sort keys %$virtdev_hash) {
5557 my $d = $virtdev_hash->{$virtdev};
5558 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5559 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5561 # test if requested format is supported
5562 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5563 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5564 $d->{format
} = $defFormat if !$supported;
5566 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5567 $d->{format
}, undef, $alloc_size);
5568 print STDERR
"new volume ID is '$volid'\n";
5569 $d->{volid
} = $volid;
5570 my $path = PVE
::Storage
::path
($cfg, $volid);
5572 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5574 my $write_zeros = 1;
5575 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5579 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5581 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5582 $map->{$virtdev} = $volid;
5585 $fh->seek(0, 0) || die "seek failed - $!\n";
5587 my $outfd = new IO
::File
($tmpfn, "w") ||
5588 die "unable to write config for VM $vmid\n";
5590 my $cookie = { netcount
=> 0 };
5591 while (defined(my $line = <$fh>)) {
5592 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5601 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5602 die "interrupted by signal\n";
5604 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5606 $oldtimeout = alarm($timeout);
5613 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5614 my ($dev_id, $size, $devname) = ($1, $2, $3);
5615 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5616 } elsif ($line =~ m/^CTIME: /) {
5617 # we correctly received the vma config, so we can disable
5618 # the timeout now for disk allocation (set to 10 minutes, so
5619 # that we always timeout if something goes wrong)
5622 print $fifofh "done\n";
5623 my $tmp = $oldtimeout || 0;
5624 $oldtimeout = undef;
5630 print "restore vma archive: $cmd\n";
5631 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5635 alarm($oldtimeout) if $oldtimeout;
5638 foreach my $devname (keys %$devinfo) {
5639 my $volid = $devinfo->{$devname}->{volid
};
5640 push @$vollist, $volid if $volid;
5643 my $cfg = PVE
::Storage
::config
();
5644 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5652 foreach my $devname (keys %$devinfo) {
5653 my $volid = $devinfo->{$devname}->{volid
};
5656 if ($volid =~ m
|^/|) {
5657 unlink $volid || die 'unlink failed\n';
5659 PVE
::Storage
::vdisk_free
($cfg, $volid);
5661 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5663 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5670 rename($tmpfn, $conffile) ||
5671 die "unable to commit configuration file '$conffile'\n";
5673 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5675 eval { rescan
($vmid, 1); };
5679 sub restore_tar_archive
{
5680 my ($archive, $vmid, $user, $opts) = @_;
5682 if ($archive ne '-') {
5683 my $firstfile = tar_archive_read_firstfile
($archive);
5684 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5685 if $firstfile ne 'qemu-server.conf';
5688 my $storecfg = PVE
::Storage
::config
();
5690 # destroy existing data - keep empty config
5691 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5692 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5694 my $tocmd = "/usr/lib/qemu-server/qmextract";
5696 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5697 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5698 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5699 $tocmd .= ' --info' if $opts->{info
};
5701 # tar option "xf" does not autodetect compression when read from STDIN,
5702 # so we pipe to zcat
5703 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5704 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5706 my $tmpdir = "/var/tmp/vzdumptmp$$";
5709 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5710 local $ENV{VZDUMP_VMID
} = $vmid;
5711 local $ENV{VZDUMP_USER
} = $user;
5713 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5714 my $tmpfn = "$conffile.$$.tmp";
5716 # disable interrupts (always do cleanups)
5717 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5718 print STDERR
"got interrupt - ignored\n";
5723 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5724 die "interrupted by signal\n";
5727 if ($archive eq '-') {
5728 print "extracting archive from STDIN\n";
5729 run_command
($cmd, input
=> "<&STDIN");
5731 print "extracting archive '$archive'\n";
5735 return if $opts->{info
};
5739 my $statfile = "$tmpdir/qmrestore.stat";
5740 if (my $fd = IO
::File-
>new($statfile, "r")) {
5741 while (defined (my $line = <$fd>)) {
5742 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5743 $map->{$1} = $2 if $1;
5745 print STDERR
"unable to parse line in statfile - $line\n";
5751 my $confsrc = "$tmpdir/qemu-server.conf";
5753 my $srcfd = new IO
::File
($confsrc, "r") ||
5754 die "unable to open file '$confsrc'\n";
5756 my $outfd = new IO
::File
($tmpfn, "w") ||
5757 die "unable to write config for VM $vmid\n";
5759 my $cookie = { netcount
=> 0 };
5760 while (defined (my $line = <$srcfd>)) {
5761 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5773 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5780 rename $tmpfn, $conffile ||
5781 die "unable to commit configuration file '$conffile'\n";
5783 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5785 eval { rescan
($vmid, 1); };
5789 sub foreach_writable_storage
{
5790 my ($conf, $func) = @_;
5794 foreach my $ds (keys %$conf) {
5795 next if !is_valid_drivename
($ds);
5797 my $drive = parse_drive
($ds, $conf->{$ds});
5799 next if drive_is_cdrom
($drive);
5801 my $volid = $drive->{file
};
5803 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5804 $sidhash->{$sid} = $sid if $sid;
5807 foreach my $sid (sort keys %$sidhash) {
5812 sub do_snapshots_with_qemu
{
5813 my ($storecfg, $volid) = @_;
5815 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5817 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5818 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5822 if ($volid =~ m/\.(qcow2|qed)$/){
5829 sub qga_check_running
{
5832 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5834 warn "Qemu Guest Agent are not running - $@";
5840 sub template_create
{
5841 my ($vmid, $conf, $disk) = @_;
5843 my $storecfg = PVE
::Storage
::config
();
5845 foreach_drive
($conf, sub {
5846 my ($ds, $drive) = @_;
5848 return if drive_is_cdrom
($drive);
5849 return if $disk && $ds ne $disk;
5851 my $volid = $drive->{file
};
5852 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5854 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5855 $drive->{file
} = $voliddst;
5856 $conf->{$ds} = print_drive
($vmid, $drive);
5857 PVE
::QemuConfig-
>write_config($vmid, $conf);
5861 sub qemu_img_convert
{
5862 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5864 my $storecfg = PVE
::Storage
::config
();
5865 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5866 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5868 if ($src_storeid && $dst_storeid) {
5870 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5872 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5873 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5875 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5876 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5878 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5879 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5882 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5883 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5884 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5885 if ($is_zero_initialized) {
5886 push @$cmd, "zeroinit:$dst_path";
5888 push @$cmd, $dst_path;
5893 if($line =~ m/\((\S+)\/100\
%\)/){
5895 my $transferred = int($size * $percent / 100);
5896 my $remaining = $size - $transferred;
5898 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5903 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5905 die "copy failed: $err" if $err;
5909 sub qemu_img_format
{
5910 my ($scfg, $volname) = @_;
5912 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5919 sub qemu_drive_mirror
{
5920 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
5922 $jobs = {} if !$jobs;
5926 $jobs->{"drive-$drive"} = {};
5928 if ($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+):exportname=(\S+)/) {
5931 my $exportname = $3;
5934 my $unixsocket = "/run/qemu-server/$vmid.mirror-drive-$drive";
5935 $qemu_target = "nbd+unix:///$exportname?socket=$unixsocket";
5936 my $cmd = ['socat', '-T30', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=5"];
5939 if (!defined($pid)) {
5940 die "forking socat tunnel failed\n";
5941 } elsif ($pid == 0) {
5943 warn "exec failed: $!\n";
5946 $jobs->{"drive-$drive"}->{pid
} = $pid;
5949 while (!-S
$unixsocket) {
5950 die "nbd connection helper timed out\n"
5955 my $storecfg = PVE
::Storage
::config
();
5956 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5958 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5960 $format = qemu_img_format
($dst_scfg, $dst_volname);
5962 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5964 $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5967 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5968 $opts->{format
} = $format if $format;
5970 print "drive mirror is starting for drive-$drive\n";
5972 eval { vm_mon_cmd
($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
5975 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
5976 die "mirroring error: $err";
5979 qemu_drive_mirror_monitor
($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
5982 sub qemu_drive_mirror_monitor
{
5983 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
5986 my $err_complete = 0;
5989 die "storage migration timed out\n" if $err_complete > 300;
5991 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5993 my $running_mirror_jobs = {};
5994 foreach my $stat (@$stats) {
5995 next if $stat->{type
} ne 'mirror';
5996 $running_mirror_jobs->{$stat->{device
}} = $stat;
5999 my $readycounter = 0;
6001 foreach my $job (keys %$jobs) {
6003 if(defined($jobs->{$job}->{complete
}) && !defined($running_mirror_jobs->{$job})) {
6004 print "$job : finished\n";
6005 delete $jobs->{$job};
6009 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
6011 my $busy = $running_mirror_jobs->{$job}->{busy
};
6012 my $ready = $running_mirror_jobs->{$job}->{ready
};
6013 if (my $total = $running_mirror_jobs->{$job}->{len
}) {
6014 my $transferred = $running_mirror_jobs->{$job}->{offset
} || 0;
6015 my $remaining = $total - $transferred;
6016 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6018 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6021 $readycounter++ if $running_mirror_jobs->{$job}->{ready
} eq 'true';
6024 last if scalar(keys %$jobs) == 0;
6026 if ($readycounter == scalar(keys %$jobs)) {
6027 print "all mirroring jobs are ready \n";
6028 last if $skipcomplete; #do the complete later
6030 if ($vmiddst && $vmiddst != $vmid) {
6032 print "freeze filesystem\n";
6033 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6035 print "suspend vm\n";
6036 eval { PVE
::QemuServer
::vm_suspend
($vmid, 1); };
6039 # if we clone a disk for a new target vm, we don't switch the disk
6040 PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs);
6043 print "unfreeze filesystem\n";
6044 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6046 print "resume vm\n";
6047 eval { PVE
::QemuServer
::vm_resume
($vmid, 1, 1); };
6053 foreach my $job (keys %$jobs) {
6054 # try to switch the disk if source and destination are on the same guest
6055 print "$job: Completing block job...\n";
6057 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> $job) };
6058 if ($@ =~ m/cannot be completed/) {
6059 print "$job: Block job cannot be completed, try again.\n";
6062 print "$job: Completed successfully.\n";
6063 $jobs->{$job}->{complete
} = 1;
6064 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6075 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6076 die "mirroring error: $err";
6081 sub qemu_blockjobs_cancel
{
6082 my ($vmid, $jobs) = @_;
6084 foreach my $job (keys %$jobs) {
6085 print "$job: Cancelling block job\n";
6086 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> $job); };
6087 $jobs->{$job}->{cancel
} = 1;
6091 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6093 my $running_jobs = {};
6094 foreach my $stat (@$stats) {
6095 $running_jobs->{$stat->{device
}} = $stat;
6098 foreach my $job (keys %$jobs) {
6100 if (defined($jobs->{$job}->{cancel
}) && !defined($running_jobs->{$job})) {
6101 print "$job: Done.\n";
6102 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6103 delete $jobs->{$job};
6107 last if scalar(keys %$jobs) == 0;
6113 sub qemu_blockjobs_finish_tunnel
{
6114 my ($vmid, $job, $cpid) = @_;
6118 for (my $i = 1; $i < 20; $i++) {
6119 my $waitpid = waitpid($cpid, WNOHANG
);
6120 last if (defined($waitpid) && ($waitpid == $cpid));
6124 } elsif ($i >= 15) {
6129 unlink "/run/qemu-server/$vmid.mirror-$job";
6133 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6134 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
6139 print "create linked clone of drive $drivename ($drive->{file})\n";
6140 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6141 push @$newvollist, $newvolid;
6144 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6145 $storeid = $storage if $storage;
6147 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6149 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6150 $format = qemu_img_format
($scfg, $volname);
6153 # test if requested format is supported - else use default
6154 my $supported = grep { $_ eq $format } @$validFormats;
6155 $format = $defFormat if !$supported;
6157 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6159 print "create full clone of drive $drivename ($drive->{file})\n";
6160 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6161 push @$newvollist, $newvolid;
6163 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
6165 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6166 if (!$running || $snapname) {
6167 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6170 my $kvmver = get_running_qemu_version
($vmid);
6171 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
6172 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6173 if $drive->{iothread
};
6176 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
6180 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6183 $disk->{format
} = undef;
6184 $disk->{file
} = $newvolid;
6185 $disk->{size
} = $size;
6190 # this only works if VM is running
6191 sub get_current_qemu_machine
{
6194 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6195 my $res = vm_qmp_command
($vmid, $cmd);
6197 my ($current, $default);
6198 foreach my $e (@$res) {
6199 $default = $e->{name
} if $e->{'is-default'};
6200 $current = $e->{name
} if $e->{'is-current'};
6203 # fallback to the default machine if current is not supported by qemu
6204 return $current || $default || 'pc';
6207 sub get_running_qemu_version
{
6209 my $cmd = { execute
=> 'query-version', arguments
=> {} };
6210 my $res = vm_qmp_command
($vmid, $cmd);
6211 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6214 sub qemu_machine_feature_enabled
{
6215 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6220 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6222 $current_major = $3;
6223 $current_minor = $4;
6225 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6227 $current_major = $1;
6228 $current_minor = $2;
6231 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6236 sub qemu_machine_pxe
{
6237 my ($vmid, $conf, $machine) = @_;
6239 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6241 foreach my $opt (keys %$conf) {
6242 next if $opt !~ m/^net(\d+)$/;
6243 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6245 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6246 return $machine.".pxe" if $romfile =~ m/pxe/;
6253 sub qemu_use_old_bios_files
{
6254 my ($machine_type) = @_;
6256 return if !$machine_type;
6258 my $use_old_bios_files = undef;
6260 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6262 $use_old_bios_files = 1;
6264 my $kvmver = kvm_user_version
();
6265 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6266 # load new efi bios files on migration. So this hack is required to allow
6267 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6268 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6269 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6272 return ($use_old_bios_files, $machine_type);
6279 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6280 my (undef, $id, $function) = @_;
6281 my $res = { id
=> $id, function
=> $function};
6282 push @{$devices->{$id}}, $res;
6285 # Entries should be sorted by functions.
6286 foreach my $id (keys %$devices) {
6287 my $dev = $devices->{$id};
6288 $devices->{$id} = [ sort { $a->{function
} <=> $b->{function
} } @$dev ];
6294 sub vm_iothreads_list
{
6297 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6300 foreach my $iothread (@$res) {
6301 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6308 my ($conf, $drive) = @_;
6312 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)) {
6314 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6320 my $controller = int($drive->{index} / $maxdev);
6321 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6323 return ($maxdev, $controller, $controller_prefix);
6326 sub add_hyperv_enlighments
{
6327 my ($cpuFlags, $winversion, $machine_type, $kvmver, $nokvm, $bios, $gpu_passthrough) = @_;
6330 return if $winversion < 6;
6331 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6333 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6335 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
6336 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6337 push @$cpuFlags , 'hv_vapic';
6338 push @$cpuFlags , 'hv_time';
6340 push @$cpuFlags , 'hv_spinlocks=0xffff';
6343 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
6344 push @$cpuFlags , 'hv_reset';
6345 push @$cpuFlags , 'hv_vpindex';
6346 push @$cpuFlags , 'hv_runtime';
6349 if ($winversion >= 7) {
6350 push @$cpuFlags , 'hv_relaxed';
6354 sub windows_version
{
6357 return 0 if !$ostype;
6361 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6363 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6365 } elsif ($ostype =~ m/^win(\d+)$/) {
6372 # bash completion helper
6374 sub complete_backup_archives
{
6375 my ($cmdname, $pname, $cvalue) = @_;
6377 my $cfg = PVE
::Storage
::config
();
6381 if ($cvalue =~ m/^([^:]+):/) {
6385 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6388 foreach my $id (keys %$data) {
6389 foreach my $item (@{$data->{$id}}) {
6390 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6391 push @$res, $item->{volid
} if defined($item->{volid
});
6398 my $complete_vmid_full = sub {
6401 my $idlist = vmstatus
();
6405 foreach my $id (keys %$idlist) {
6406 my $d = $idlist->{$id};
6407 if (defined($running)) {
6408 next if $d->{template
};
6409 next if $running && $d->{status
} ne 'running';
6410 next if !$running && $d->{status
} eq 'running';
6419 return &$complete_vmid_full();
6422 sub complete_vmid_stopped
{
6423 return &$complete_vmid_full(0);
6426 sub complete_vmid_running
{
6427 return &$complete_vmid_full(1);
6430 sub complete_storage
{
6432 my $cfg = PVE
::Storage
::config
();
6433 my $ids = $cfg->{ids
};
6436 foreach my $sid (keys %$ids) {
6437 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6438 next if !$ids->{$sid}->{content
}->{images
};
6448 vm_mon_cmd
($vmid, 'nbd-server-stop');