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
('skiplock', {
60 description
=> "Ignore locks - only root is allowed to use this option.",
65 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
66 description
=> "Some command save/restore state from this location.",
72 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
73 description
=> "The name of the snapshot.",
74 type
=> 'string', format
=> 'pve-configid',
78 PVE
::JSONSchema
::register_standard_option
('pve-qm-image-format', {
80 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
81 description
=> "The drive's backing file's data format.",
85 #no warnings 'redefine';
88 my ($controller, $vmid, $option, $value) = @_;
90 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
91 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
95 my $nodename = PVE
::INotify
::nodename
();
97 mkdir "/etc/pve/nodes/$nodename";
98 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
101 my $var_run_tmpdir = "/var/run/qemu-server";
102 mkdir $var_run_tmpdir;
104 my $lock_dir = "/var/lock/qemu-server";
107 my $pcisysfs = "/sys/bus/pci";
109 my $cpu_vendor_list = {
111 486 => 'GenuineIntel',
112 pentium
=> 'GenuineIntel',
113 pentium2
=> 'GenuineIntel',
114 pentium3
=> 'GenuineIntel',
115 coreduo
=> 'GenuineIntel',
116 core2duo
=> 'GenuineIntel',
117 Conroe
=> 'GenuineIntel',
118 Penryn
=> 'GenuineIntel',
119 Nehalem
=> 'GenuineIntel',
120 Westmere
=> 'GenuineIntel',
121 SandyBridge
=> 'GenuineIntel',
122 IvyBridge
=> 'GenuineIntel',
123 Haswell
=> 'GenuineIntel',
124 'Haswell-noTSX' => 'GenuineIntel',
125 Broadwell
=> 'GenuineIntel',
126 'Broadwell-noTSX' => 'GenuineIntel',
129 athlon
=> 'AuthenticAMD',
130 phenom
=> 'AuthenticAMD',
131 Opteron_G1
=> 'AuthenticAMD',
132 Opteron_G2
=> 'AuthenticAMD',
133 Opteron_G3
=> 'AuthenticAMD',
134 Opteron_G4
=> 'AuthenticAMD',
135 Opteron_G5
=> 'AuthenticAMD',
137 # generic types, use vendor from host node
147 description
=> "Emulated CPU type.",
149 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
154 description
=> "Do not identify as a KVM virtual machine.",
165 enum
=> [qw(i6300esb ib700)],
166 description
=> "Watchdog type to emulate.",
167 default => 'i6300esb',
172 enum
=> [qw(reset shutdown poweroff pause debug none)],
173 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
177 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
183 description
=> "Specifies whether a VM will be started during system bootup.",
189 description
=> "Automatic restart after crash (currently ignored).",
194 type
=> 'string', format
=> 'pve-hotplug-features',
195 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'.",
196 default => 'network,disk,usb',
201 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
207 description
=> "Lock/unlock the VM.",
208 enum
=> [qw(migrate backup snapshot rollback)],
213 description
=> "Limit of CPU usage.",
214 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.",
222 description
=> "CPU weight for a VM.",
223 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.",
231 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
238 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
244 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",
252 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.",
253 enum
=> PVE
::Tools
::kvmkeymaplist
(),
258 type
=> 'string', format
=> 'dns-name',
259 description
=> "Set a name for the VM. Only used on the configuration web interface.",
264 description
=> "SCSI controller model",
265 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
271 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
276 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 win10 l24 l26 solaris)],
277 description
=> "Specify guest operating system.",
278 verbose_description
=> <<EODESC,
279 Specify guest operating system. This is used to enable special
280 optimization/features for specific operating systems:
283 other;; unspecified OS
284 wxp;; Microsoft Windows XP
285 w2k;; Microsoft Windows 2000
286 w2k3;; Microsoft Windows 2003
287 w2k8;; Microsoft Windows 2008
288 wvista;; Microsoft Windows Vista
289 win7;; Microsoft Windows 7
290 win8;; Microsoft Windows 8/2012
291 l24;; Linux 2.4 Kernel
292 l26;; Linux 2.6/3.X Kernel
293 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
299 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
300 pattern
=> '[acdn]{1,4}',
305 type
=> 'string', format
=> 'pve-qm-bootdisk',
306 description
=> "Enable booting from specified disk.",
307 pattern
=> '(ide|sata|scsi|virtio)\d+',
312 description
=> "The number of CPUs. Please use option -sockets instead.",
319 description
=> "The number of CPU sockets.",
326 description
=> "The number of cores per socket.",
333 description
=> "Enable/disable NUMA.",
339 description
=> "Enable/disable hugepages memory.",
340 enum
=> [qw(any 2 1024)],
345 description
=> "Number of hotplugged vcpus.",
352 description
=> "Enable/disable ACPI.",
358 description
=> "Enable/disable Qemu GuestAgent.",
364 description
=> "Enable/disable KVM hardware virtualization.",
370 description
=> "Enable/disable time drift fix.",
376 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
381 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
386 description
=> "Select the VGA type.",
387 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
388 " modes (>= 1280x1024x16) then you should use the options " .
389 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
390 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
391 "display sever. For win* OS you can select how many independent " .
392 "displays you want, Linux guests can add displays them self. " .
393 "You can also run without any graphic card, using a serial device" .
395 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
399 type
=> 'string', format
=> 'pve-qm-watchdog',
400 description
=> "Create a virtual hardware watchdog device.",
401 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
402 " (by a guest action), the watchdog must be periodically polled " .
403 "by an agent inside the guest or else the watchdog will reset " .
404 "the guest (or execute the respective action specified)",
409 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
410 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'.",
411 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
414 startup
=> get_standard_option
('pve-startup-order'),
418 description
=> "Enable/disable Template.",
424 description
=> "Arbitrary arguments passed to kvm.",
425 verbose_description
=> <<EODESCR,
426 Arbitrary arguments passed to kvm, for example:
428 args: -no-reboot -no-hpet
430 NOTE: this option is for experts only.
437 description
=> "Enable/disable the USB tablet device.",
438 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
439 "usually needed to allow absolute mouse positioning with VNC. " .
440 "Else the mouse runs out of sync with normal VNC clients. " .
441 "If you're running lots of console-only guests on one host, " .
442 "you may consider disabling this to save some context switches. " .
443 "This is turned off by default if you use spice (-vga=qxl).",
448 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
452 migrate_downtime
=> {
455 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
461 type
=> 'string', format
=> 'pve-qm-ide',
462 typetext
=> '<volume>',
463 description
=> "This is an alias for option -ide2",
467 description
=> "Emulated CPU type.",
471 parent
=> get_standard_option
('pve-snapshot-name', {
473 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
477 description
=> "Timestamp for snapshots.",
483 type
=> 'string', format
=> 'pve-volume-id',
484 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
487 description
=> "Specific the Qemu machine type.",
489 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
494 description
=> "Specify SMBIOS type 1 fields.",
495 type
=> 'string', format
=> 'pve-qm-smbios1',
502 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
508 enum
=> [ qw(seabios ovmf) ],
509 description
=> "Select BIOS implementation.",
510 default => 'seabios',
514 # what about other qemu settings ?
516 #machine => 'string',
529 ##soundhw => 'string',
531 while (my ($k, $v) = each %$confdesc) {
532 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
535 my $MAX_IDE_DISKS = 4;
536 my $MAX_SCSI_DISKS = 14;
537 my $MAX_VIRTIO_DISKS = 16;
538 my $MAX_SATA_DISKS = 6;
539 my $MAX_USB_DEVICES = 5;
541 my $MAX_UNUSED_DISKS = 8;
542 my $MAX_HOSTPCI_DEVICES = 4;
543 my $MAX_SERIAL_PORTS = 4;
544 my $MAX_PARALLEL_PORTS = 3;
550 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
551 description
=> "CPUs accessing this NUMA node.",
552 format_description
=> "id[-id];...",
556 description
=> "Amount of memory this NUMA node provides.",
561 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
562 description
=> "Host NUMA nodes to use.",
563 format_description
=> "id[-id];...",
568 enum
=> [qw(preferred bind interleave)],
569 description
=> "NUMA allocation policy.",
573 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
576 type
=> 'string', format
=> $numa_fmt,
577 description
=> "NUMA topology.",
579 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
581 for (my $i = 0; $i < $MAX_NUMA; $i++) {
582 $confdesc->{"numa$i"} = $numadesc;
585 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
586 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
587 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
588 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
590 my $net_fmt_bridge_descr = <<__EOD__;
591 Bridge to attach the network device to. The Proxmox VE standard bridge
594 If you do not specify a bridge, we create a kvm user (NATed) network
595 device, which provides DHCP and DNS services. The following addresses
602 The DHCP server assign addresses to the guest starting from 10.0.2.15.
608 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
609 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
610 format_description
=> "XX:XX:XX:XX:XX:XX",
615 description
=> "Network Card Model. The 'virtio' model provides the best performance with very low CPU overhead. If your guest does not support this driver, it is usually best to use 'e1000'.",
616 enum
=> $nic_model_list,
619 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
622 description
=> $net_fmt_bridge_descr,
623 format_description
=> 'bridge',
628 minimum
=> 0, maximum
=> 16,
629 description
=> 'Number of packet queues to be used on the device.',
635 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
640 minimum
=> 1, maximum
=> 4094,
641 description
=> 'VLAN tag to apply to packets on this interface.',
646 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
647 description
=> 'VLAN trunks to pass through this interface.',
648 format_description
=> 'vlanid[;vlanid...]',
653 description
=> 'Whether this interface should be protected by the firewall.',
658 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
665 type
=> 'string', format
=> $net_fmt,
666 description
=> "Specify network devices.",
669 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
671 for (my $i = 0; $i < $MAX_NETS; $i++) {
672 $confdesc->{"net$i"} = $netdesc;
675 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
676 sub verify_volume_id_or_qm_path
{
677 my ($volid, $noerr) = @_;
679 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
683 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
684 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
686 return undef if $noerr;
694 my %drivedesc_base = (
695 volume
=> { alias
=> 'file' },
698 format
=> 'pve-volume-id-or-qm-path',
700 format_description
=> 'volume',
701 description
=> "The drive's backing volume.",
705 enum
=> [qw(cdrom disk)],
706 description
=> "The drive's media type.",
712 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
717 description
=> "Force the drive's physical geometry to have a specific head count.",
722 description
=> "Force the drive's physical geometry to have a specific sector count.",
727 enum
=> [qw(none lba auto)],
728 description
=> "Force disk geometry bios translation mode.",
733 description
=> "Whether the drive should be included when making snapshots.",
738 enum
=> [qw(none writethrough writeback unsafe directsync)],
739 description
=> "The drive's cache mode",
742 format
=> get_standard_option
('pve-qm-image-format'),
745 format
=> 'disk-size',
746 format_description
=> 'DiskSize',
747 description
=> "Disk size. This is purely informational and has no effect.",
752 description
=> "Whether the drive should be included when making backups.",
757 enum
=> [qw(enospc ignore report stop)],
758 description
=> 'Write error action.',
763 enum
=> [qw(native threads)],
764 description
=> 'AIO type to use.',
769 enum
=> [qw(ignore on)],
770 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
775 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
780 format
=> 'urlencoded',
781 format_description
=> 'serial',
782 maxLength
=> 20*3, # *3 since it's %xx url enoded
783 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
791 enum
=> [qw(ignore report stop)],
792 description
=> 'Read error action.',
797 my %iothread_fmt = ( iothread
=> {
799 description
=> "Whether to use iothreads for this drive",
806 format
=> 'urlencoded',
807 format_description
=> 'model',
808 maxLength
=> 40*3, # *3 since it's %xx url enoded
809 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
817 description
=> "Number of queues.",
823 my $add_throttle_desc = sub {
824 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
827 format_description
=> $unit,
828 description
=> "Maximum $what in $longunit.",
831 $d->{minimum
} = $minimum if defined($minimum);
832 $drivedesc_base{$key} = $d;
834 # throughput: (leaky bucket)
835 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
836 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
837 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
838 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
839 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
840 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
841 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
842 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
843 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
845 # pools: (pool of IO before throttling starts taking effect)
846 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
847 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
848 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
849 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
850 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
851 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
854 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
855 $add_throttle_desc->('bps_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
856 $add_throttle_desc->('bps_wr_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
857 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
858 $add_throttle_desc->('iops_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
859 $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);
882 type
=> 'string', format
=> $scsi_fmt,
883 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
885 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);
905 type
=> 'string', format
=> $virtio_fmt,
906 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
908 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
919 volume
=> { alias
=> 'file' },
922 format
=> 'pve-volume-id-or-qm-path',
924 format_description
=> 'volume',
925 description
=> "The drive's backing volume.",
927 format
=> get_standard_option
('pve-qm-image-format'),
930 format
=> 'disk-size',
931 format_description
=> 'DiskSize',
932 description
=> "Disk size. This is purely informational and has no effect.",
939 type
=> 'string', format
=> $efidisk_fmt,
940 description
=> "Configure a Disk for storing EFI vars",
943 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
948 type
=> 'string', format
=> 'pve-qm-usb-device',
949 format_description
=> 'HOSTUSBDEVICE|spice',
950 description
=> <<EODESCR,
951 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
953 'bus-port(.port)*' (decimal numbers) or
954 'vendor_id:product_id' (hexadeciaml numbers) or
957 You can use the 'lsusb -t' command to list existing usb devices.
959 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
961 The value 'spice' can be used to add a usb redirection devices for spice.
967 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).",
974 type
=> 'string', format
=> $usb_fmt,
975 description
=> "Configure an USB device (n is 0 to 4).",
977 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
979 # NOTE: the match-groups of this regex are used in parse_hostpci
980 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
985 pattern
=> qr/$PCIRE(;$PCIRE)*/,
986 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
987 description
=> <<EODESCR,
988 Host PCI device pass through. The PCI ID of a host's PCI device or a list
989 of PCI virtual functions of the host. HOSTPCIID syntax is:
991 'bus:dev.func' (hexadecimal numbers)
993 You can us the 'lspci' command to list existing PCI devices.
998 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1004 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1010 description
=> "Enable vfio-vga device support.",
1015 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1019 type
=> 'string', format
=> 'pve-qm-hostpci',
1020 description
=> "Map host PCI devices into guest.",
1021 verbose_description
=> <<EODESCR,
1022 Map host PCI devices into guest.
1024 NOTE: This option allows direct access to host hardware. So it is no longer
1025 possible to migrate such machines - use with special care.
1027 CAUTION: Experimental! User reported problems with this option.
1030 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1035 pattern
=> '(/dev/.+|socket)',
1036 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1037 verbose_description
=> <<EODESCR,
1038 Create a serial device inside the VM (n is 0 to 3), and pass through a
1039 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1040 host side (use 'qm terminal' to open a terminal connection).
1042 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1044 CAUTION: Experimental! User reported problems with this option.
1051 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1052 description
=> "Map host parallel devices (n is 0 to 2).",
1053 verbose_description
=> <<EODESCR,
1054 Map host parallel devices (n is 0 to 2).
1056 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1058 CAUTION: Experimental! User reported problems with this option.
1062 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1063 $confdesc->{"parallel$i"} = $paralleldesc;
1066 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1067 $confdesc->{"serial$i"} = $serialdesc;
1070 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1071 $confdesc->{"hostpci$i"} = $hostpcidesc;
1074 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1075 $drivename_hash->{"ide$i"} = 1;
1076 $confdesc->{"ide$i"} = $idedesc;
1079 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1080 $drivename_hash->{"sata$i"} = 1;
1081 $confdesc->{"sata$i"} = $satadesc;
1084 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1085 $drivename_hash->{"scsi$i"} = 1;
1086 $confdesc->{"scsi$i"} = $scsidesc ;
1089 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1090 $drivename_hash->{"virtio$i"} = 1;
1091 $confdesc->{"virtio$i"} = $virtiodesc;
1094 $drivename_hash->{efidisk0
} = 1;
1095 $confdesc->{efidisk0
} = $efidisk_desc;
1097 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1098 $confdesc->{"usb$i"} = $usbdesc;
1103 type
=> 'string', format
=> 'pve-volume-id',
1104 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1107 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1108 $confdesc->{"unused$i"} = $unuseddesc;
1111 my $kvm_api_version = 0;
1115 return $kvm_api_version if $kvm_api_version;
1117 my $fh = IO
::File-
>new("</dev/kvm") ||
1120 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1121 $kvm_api_version = $v;
1126 return $kvm_api_version;
1129 my $kvm_user_version;
1131 sub kvm_user_version
{
1133 return $kvm_user_version if $kvm_user_version;
1135 $kvm_user_version = 'unknown';
1139 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1140 $kvm_user_version = $2;
1144 eval { run_command
("kvm -version", outfunc
=> $code); };
1147 return $kvm_user_version;
1151 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1153 sub valid_drive_names
{
1154 # order is important - used to autoselect boot disk
1155 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1156 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1157 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1158 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1162 sub is_valid_drivename
{
1165 return defined($drivename_hash->{$dev});
1170 return defined($confdesc->{$key});
1174 return $nic_model_list;
1177 sub os_list_description
{
1181 wxp
=> 'Windows XP',
1182 w2k
=> 'Windows 2000',
1183 w2k3
=>, 'Windows 2003',
1184 w2k8
=> 'Windows 2008',
1185 wvista
=> 'Windows Vista',
1186 win7
=> 'Windows 7',
1187 win8
=> 'Windows 8/2012',
1188 win10
=> 'Windows 10/2016',
1196 sub get_cdrom_path
{
1198 return $cdrom_path if $cdrom_path;
1200 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1201 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1202 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1206 my ($storecfg, $vmid, $cdrom) = @_;
1208 if ($cdrom eq 'cdrom') {
1209 return get_cdrom_path
();
1210 } elsif ($cdrom eq 'none') {
1212 } elsif ($cdrom =~ m
|^/|) {
1215 return PVE
::Storage
::path
($storecfg, $cdrom);
1219 # try to convert old style file names to volume IDs
1220 sub filename_to_volume_id
{
1221 my ($vmid, $file, $media) = @_;
1223 if (!($file eq 'none' || $file eq 'cdrom' ||
1224 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1226 return undef if $file =~ m
|/|;
1228 if ($media && $media eq 'cdrom') {
1229 $file = "local:iso/$file";
1231 $file = "local:$vmid/$file";
1238 sub verify_media_type
{
1239 my ($opt, $vtype, $media) = @_;
1244 if ($media eq 'disk') {
1246 } elsif ($media eq 'cdrom') {
1249 die "internal error";
1252 return if ($vtype eq $etype);
1254 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1257 sub cleanup_drive_path
{
1258 my ($opt, $storecfg, $drive) = @_;
1260 # try to convert filesystem paths to volume IDs
1262 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1263 ($drive->{file
} !~ m
|^/dev/.+|) &&
1264 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1265 ($drive->{file
} !~ m/^\d+$/)) {
1266 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1267 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1268 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1269 verify_media_type
($opt, $vtype, $drive->{media
});
1270 $drive->{file
} = $volid;
1273 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1276 sub parse_hotplug_features
{
1281 return $res if $data eq '0';
1283 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1285 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1286 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1289 die "invalid hotplug feature '$feature'\n";
1295 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1296 sub pve_verify_hotplug_features
{
1297 my ($value, $noerr) = @_;
1299 return $value if parse_hotplug_features
($value);
1301 return undef if $noerr;
1303 die "unable to parse hotplug option\n";
1306 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1307 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1308 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1309 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1310 # [,iothread=on][,serial=serial][,model=model]
1313 my ($key, $data) = @_;
1315 my ($interface, $index);
1317 if ($key =~ m/^([^\d]+)(\d+)$/) {
1324 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1325 : $confdesc->{$key}->{format
};
1327 warn "invalid drive key: $key\n";
1330 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1331 return undef if !$res;
1332 $res->{interface
} = $interface;
1333 $res->{index} = $index;
1336 foreach my $opt (qw(bps bps_rd bps_wr)) {
1337 if (my $bps = defined(delete $res->{$opt})) {
1338 if (defined($res->{"m$opt"})) {
1339 warn "both $opt and m$opt specified\n";
1343 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1347 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1348 for my $requirement (
1349 [bps_max_length
=> 'mbps_max'],
1350 [bps_rd_max_length
=> 'mbps_rd_max'],
1351 [bps_wr_max_length
=> 'mbps_wr_max'],
1352 [iops_max_length
=> 'iops_max'],
1353 [iops_rd_max_length
=> 'iops_rd_max'],
1354 [iops_wr_max_length
=> 'iops_wr_max']) {
1355 my ($option, $requires) = @$requirement;
1356 if ($res->{$option} && !$res->{$requires}) {
1357 warn "$option requires $requires\n";
1362 return undef if $error;
1364 return undef if $res->{mbps_rd
} && $res->{mbps
};
1365 return undef if $res->{mbps_wr
} && $res->{mbps
};
1366 return undef if $res->{iops_rd
} && $res->{iops
};
1367 return undef if $res->{iops_wr
} && $res->{iops
};
1369 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1370 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1371 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1372 return undef if $res->{interface
} eq 'virtio';
1375 if (my $size = $res->{size
}) {
1376 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1383 my ($vmid, $drive) = @_;
1384 my $data = { %$drive };
1385 delete $data->{$_} for qw(index interface);
1386 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1390 my($fh, $noerr) = @_;
1393 my $SG_GET_VERSION_NUM = 0x2282;
1395 my $versionbuf = "\x00" x
8;
1396 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1398 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1401 my $version = unpack("I", $versionbuf);
1402 if ($version < 30000) {
1403 die "scsi generic interface too old\n" if !$noerr;
1407 my $buf = "\x00" x
36;
1408 my $sensebuf = "\x00" x
8;
1409 my $cmd = pack("C x3 C x1", 0x12, 36);
1411 # see /usr/include/scsi/sg.h
1412 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";
1414 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1415 length($sensebuf), 0, length($buf), $buf,
1416 $cmd, $sensebuf, 6000);
1418 $ret = ioctl($fh, $SG_IO, $packet);
1420 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1424 my @res = unpack($sg_io_hdr_t, $packet);
1425 if ($res[17] || $res[18]) {
1426 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1431 (my $byte0, my $byte1, $res->{vendor
},
1432 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1434 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1435 $res->{type
} = $byte0 & 31;
1443 my $fh = IO
::File-
>new("+<$path") || return undef;
1444 my $res = scsi_inquiry
($fh, 1);
1450 sub machine_type_is_q35
{
1453 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1456 sub print_tabletdevice_full
{
1459 my $q35 = machine_type_is_q35
($conf);
1461 # we use uhci for old VMs because tablet driver was buggy in older qemu
1462 my $usbbus = $q35 ?
"ehci" : "uhci";
1464 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1467 sub print_drivedevice_full
{
1468 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1473 if ($drive->{interface
} eq 'virtio') {
1474 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1475 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1476 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1477 } elsif ($drive->{interface
} eq 'scsi') {
1479 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1480 my $unit = $drive->{index} % $maxdev;
1481 my $devicetype = 'hd';
1483 if (drive_is_cdrom
($drive)) {
1486 if ($drive->{file
} =~ m
|^/|) {
1487 $path = $drive->{file
};
1488 if (my $info = path_is_scsi
($path)) {
1489 if ($info->{type
} == 0) {
1490 $devicetype = 'block';
1491 } elsif ($info->{type
} == 1) { # tape
1492 $devicetype = 'generic';
1496 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1499 if($path =~ m/^iscsi\:\/\
//){
1500 $devicetype = 'generic';
1504 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1505 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1507 $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}";
1510 } elsif ($drive->{interface
} eq 'ide'){
1512 my $controller = int($drive->{index} / $maxdev);
1513 my $unit = $drive->{index} % $maxdev;
1514 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1516 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1517 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1518 $model = URI
::Escape
::uri_unescape
($model);
1519 $device .= ",model=$model";
1521 } elsif ($drive->{interface
} eq 'sata'){
1522 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1523 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1524 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1525 } elsif ($drive->{interface
} eq 'usb') {
1527 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1529 die "unsupported interface type";
1532 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1537 sub get_initiator_name
{
1540 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1541 while (defined(my $line = <$fh>)) {
1542 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1551 sub print_drive_full
{
1552 my ($storecfg, $vmid, $drive) = @_;
1555 my $volid = $drive->{file
};
1558 if (drive_is_cdrom
($drive)) {
1559 $path = get_iso_path
($storecfg, $vmid, $volid);
1561 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1563 $path = PVE
::Storage
::path
($storecfg, $volid);
1564 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1565 $format = qemu_img_format
($scfg, $volname);
1573 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);
1574 foreach my $o (@qemu_drive_options) {
1575 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1577 if (my $serial = $drive->{serial
}) {
1578 $serial = URI
::Escape
::uri_unescape
($serial);
1579 $opts .= ",serial=$serial";
1582 $opts .= ",format=$format" if $format && !$drive->{format
};
1584 foreach my $o (qw(bps bps_rd bps_wr)) {
1585 my $v = $drive->{"m$o"};
1586 $opts .= ",$o=" . int($v*1024*1024) if $v;
1589 my $cache_direct = 0;
1591 if (my $cache = $drive->{cache
}) {
1592 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1593 } elsif (!drive_is_cdrom
($drive)) {
1594 $opts .= ",cache=none";
1598 # aio native works only with O_DIRECT
1599 if (!$drive->{aio
}) {
1601 $opts .= ",aio=native";
1603 $opts .= ",aio=threads";
1607 if (!drive_is_cdrom
($drive)) {
1609 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1610 $detectzeroes = 'off';
1611 } elsif ($drive->{discard
}) {
1612 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1614 # This used to be our default with discard not being specified:
1615 $detectzeroes = 'on';
1617 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1620 my $pathinfo = $path ?
"file=$path," : '';
1622 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1625 sub print_netdevice_full
{
1626 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1628 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1630 my $device = $net->{model
};
1631 if ($net->{model
} eq 'virtio') {
1632 $device = 'virtio-net-pci';
1635 my $pciaddr = print_pci_addr
("$netid", $bridges);
1636 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1637 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1638 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1639 my $vectors = $net->{queues
} * 2 + 2;
1640 $tmpstr .= ",vectors=$vectors,mq=on";
1642 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1644 if ($use_old_bios_files) {
1646 if ($device eq 'virtio-net-pci') {
1647 $romfile = 'pxe-virtio.rom';
1648 } elsif ($device eq 'e1000') {
1649 $romfile = 'pxe-e1000.rom';
1650 } elsif ($device eq 'ne2k') {
1651 $romfile = 'pxe-ne2k_pci.rom';
1652 } elsif ($device eq 'pcnet') {
1653 $romfile = 'pxe-pcnet.rom';
1654 } elsif ($device eq 'rtl8139') {
1655 $romfile = 'pxe-rtl8139.rom';
1657 $tmpstr .= ",romfile=$romfile" if $romfile;
1663 sub print_netdev_full
{
1664 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1667 if ($netid =~ m/^net(\d+)$/) {
1671 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1673 my $ifname = "tap${vmid}i$i";
1675 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1676 die "interface name '$ifname' is too long (max 15 character)\n"
1677 if length($ifname) >= 16;
1679 my $vhostparam = '';
1680 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1682 my $vmname = $conf->{name
} || "vm$vmid";
1685 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1687 if ($net->{bridge
}) {
1688 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1690 $netdev = "type=user,id=$netid,hostname=$vmname";
1693 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1699 sub print_cpu_device
{
1700 my ($conf, $id) = @_;
1702 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
1703 my $cpu = $nokvm ?
"qemu64" : "kvm64";
1704 if (my $cputype = $conf->{cpu
}) {
1705 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1706 or die "Cannot parse cpu description: $cputype\n";
1707 $cpu = $cpuconf->{cputype
};
1711 $sockets = $conf->{sockets
} if $conf->{sockets
};
1712 my $cores = $conf->{cores
} || 1;
1714 my $current_core = ($id - 1) % $cores;
1715 my $current_socket = int(($id - $current_core)/$cores);
1717 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1720 sub drive_is_cdrom
{
1723 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1727 sub parse_number_sets
{
1730 foreach my $part (split(/;/, $set)) {
1731 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1732 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1733 push @$res, [ $1, $2 ];
1735 die "invalid range: $part\n";
1744 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1745 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1746 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1753 return undef if !$value;
1755 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1757 my @idlist = split(/;/, $res->{host
});
1758 delete $res->{host
};
1759 foreach my $id (@idlist) {
1760 if ($id =~ /^$PCIRE$/) {
1762 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1764 my $pcidevices = lspci
($1);
1765 $res->{pciid
} = $pcidevices->{$1};
1768 # should have been caught by parse_property_string already
1769 die "failed to parse PCI id: $id\n";
1775 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1779 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1784 if (!defined($res->{macaddr
})) {
1785 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1786 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1794 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1797 sub add_random_macs
{
1798 my ($settings) = @_;
1800 foreach my $opt (keys %$settings) {
1801 next if $opt !~ m/^net(\d+)$/;
1802 my $net = parse_net
($settings->{$opt});
1804 $settings->{$opt} = print_net
($net);
1808 sub vm_is_volid_owner
{
1809 my ($storecfg, $vmid, $volid) = @_;
1811 if ($volid !~ m
|^/|) {
1813 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1814 if ($owner && ($owner == $vmid)) {
1822 sub split_flagged_list
{
1823 my $text = shift || '';
1824 $text =~ s/[,;]/ /g;
1826 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1829 sub join_flagged_list
{
1830 my ($how, $lst) = @_;
1831 join $how, map { $lst->{$_} . $_ } keys %$lst;
1834 sub vmconfig_delete_pending_option
{
1835 my ($conf, $key, $force) = @_;
1837 delete $conf->{pending
}->{$key};
1838 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1839 $pending_delete_hash->{$key} = $force ?
'!' : '';
1840 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1843 sub vmconfig_undelete_pending_option
{
1844 my ($conf, $key) = @_;
1846 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1847 delete $pending_delete_hash->{$key};
1849 if (%$pending_delete_hash) {
1850 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1852 delete $conf->{pending
}->{delete};
1856 sub vmconfig_register_unused_drive
{
1857 my ($storecfg, $vmid, $conf, $drive) = @_;
1859 if (!drive_is_cdrom
($drive)) {
1860 my $volid = $drive->{file
};
1861 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1862 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1867 sub vmconfig_cleanup_pending
{
1870 # remove pending changes when nothing changed
1872 foreach my $opt (keys %{$conf->{pending
}}) {
1873 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1875 delete $conf->{pending
}->{$opt};
1879 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1880 my $pending_delete_hash = {};
1881 while (my ($opt, $force) = each %$current_delete_hash) {
1882 if (defined($conf->{$opt})) {
1883 $pending_delete_hash->{$opt} = $force;
1889 if (%$pending_delete_hash) {
1890 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1892 delete $conf->{pending
}->{delete};
1898 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1902 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1903 format_description
=> 'UUID',
1904 description
=> "Set SMBIOS1 UUID.",
1910 format_description
=> 'string',
1911 description
=> "Set SMBIOS1 version.",
1917 format_description
=> 'string',
1918 description
=> "Set SMBIOS1 serial number.",
1924 format_description
=> 'string',
1925 description
=> "Set SMBIOS1 manufacturer.",
1931 format_description
=> 'string',
1932 description
=> "Set SMBIOS1 product ID.",
1938 format_description
=> 'string',
1939 description
=> "Set SMBIOS1 SKU string.",
1945 format_description
=> 'string',
1946 description
=> "Set SMBIOS1 family string.",
1954 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1961 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1964 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1966 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1967 sub verify_bootdisk
{
1968 my ($value, $noerr) = @_;
1970 return $value if is_valid_drivename
($value);
1972 return undef if $noerr;
1974 die "invalid boot disk '$value'\n";
1977 sub parse_watchdog
{
1980 return undef if !$value;
1982 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1987 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1988 sub verify_usb_device
{
1989 my ($value, $noerr) = @_;
1991 return $value if parse_usb_device
($value);
1993 return undef if $noerr;
1995 die "unable to parse usb device\n";
1998 # add JSON properties for create and set function
1999 sub json_config_properties
{
2002 foreach my $opt (keys %$confdesc) {
2003 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2004 $prop->{$opt} = $confdesc->{$opt};
2011 my ($key, $value) = @_;
2013 die "unknown setting '$key'\n" if !$confdesc->{$key};
2015 my $type = $confdesc->{$key}->{type
};
2017 if (!defined($value)) {
2018 die "got undefined value\n";
2021 if ($value =~ m/[\n\r]/) {
2022 die "property contains a line feed\n";
2025 if ($type eq 'boolean') {
2026 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2027 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2028 die "type check ('boolean') failed - got '$value'\n";
2029 } elsif ($type eq 'integer') {
2030 return int($1) if $value =~ m/^(\d+)$/;
2031 die "type check ('integer') failed - got '$value'\n";
2032 } elsif ($type eq 'number') {
2033 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2034 die "type check ('number') failed - got '$value'\n";
2035 } elsif ($type eq 'string') {
2036 if (my $fmt = $confdesc->{$key}->{format
}) {
2037 PVE
::JSONSchema
::check_format
($fmt, $value);
2040 $value =~ s/^\"(.*)\"$/$1/;
2043 die "internal error"
2047 sub check_iommu_support
{
2048 #fixme : need to check IOMMU support
2049 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2059 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2060 utime undef, undef, $conf;
2064 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2066 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2068 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2070 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2072 # only remove disks owned by this VM
2073 foreach_drive
($conf, sub {
2074 my ($ds, $drive) = @_;
2076 return if drive_is_cdrom
($drive);
2078 my $volid = $drive->{file
};
2080 return if !$volid || $volid =~ m
|^/|;
2082 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2083 return if !$path || !$owner || ($owner != $vmid);
2085 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2088 if ($keep_empty_config) {
2089 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2094 # also remove unused disk
2096 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2099 PVE
::Storage
::foreach_volid
($dl, sub {
2100 my ($volid, $sid, $volname, $d) = @_;
2101 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2110 sub parse_vm_config
{
2111 my ($filename, $raw) = @_;
2113 return undef if !defined($raw);
2116 digest
=> Digest
::SHA
::sha1_hex
($raw),
2121 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2122 || die "got strange filename '$filename'";
2130 my @lines = split(/\n/, $raw);
2131 foreach my $line (@lines) {
2132 next if $line =~ m/^\s*$/;
2134 if ($line =~ m/^\[PENDING\]\s*$/i) {
2135 $section = 'pending';
2136 if (defined($descr)) {
2138 $conf->{description
} = $descr;
2141 $conf = $res->{$section} = {};
2144 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2146 if (defined($descr)) {
2148 $conf->{description
} = $descr;
2151 $conf = $res->{snapshots
}->{$section} = {};
2155 if ($line =~ m/^\#(.*)\s*$/) {
2156 $descr = '' if !defined($descr);
2157 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2161 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2162 $descr = '' if !defined($descr);
2163 $descr .= PVE
::Tools
::decode_text
($2);
2164 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2165 $conf->{snapstate
} = $1;
2166 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2169 $conf->{$key} = $value;
2170 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2172 if ($section eq 'pending') {
2173 $conf->{delete} = $value; # we parse this later
2175 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2177 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2180 eval { $value = check_type
($key, $value); };
2182 warn "vm $vmid - unable to parse value of '$key' - $@";
2184 $key = 'ide2' if $key eq 'cdrom';
2185 my $fmt = $confdesc->{$key}->{format
};
2186 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2187 my $v = parse_drive
($key, $value);
2188 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2189 $v->{file
} = $volid;
2190 $value = print_drive
($vmid, $v);
2192 warn "vm $vmid - unable to parse value of '$key'\n";
2197 $conf->{$key} = $value;
2202 if (defined($descr)) {
2204 $conf->{description
} = $descr;
2206 delete $res->{snapstate
}; # just to be sure
2211 sub write_vm_config
{
2212 my ($filename, $conf) = @_;
2214 delete $conf->{snapstate
}; # just to be sure
2216 if ($conf->{cdrom
}) {
2217 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2218 $conf->{ide2
} = $conf->{cdrom
};
2219 delete $conf->{cdrom
};
2222 # we do not use 'smp' any longer
2223 if ($conf->{sockets
}) {
2224 delete $conf->{smp
};
2225 } elsif ($conf->{smp
}) {
2226 $conf->{sockets
} = $conf->{smp
};
2227 delete $conf->{cores
};
2228 delete $conf->{smp
};
2231 my $used_volids = {};
2233 my $cleanup_config = sub {
2234 my ($cref, $pending, $snapname) = @_;
2236 foreach my $key (keys %$cref) {
2237 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2238 $key eq 'snapstate' || $key eq 'pending';
2239 my $value = $cref->{$key};
2240 if ($key eq 'delete') {
2241 die "propertry 'delete' is only allowed in [PENDING]\n"
2243 # fixme: check syntax?
2246 eval { $value = check_type
($key, $value); };
2247 die "unable to parse value of '$key' - $@" if $@;
2249 $cref->{$key} = $value;
2251 if (!$snapname && is_valid_drivename
($key)) {
2252 my $drive = parse_drive
($key, $value);
2253 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2258 &$cleanup_config($conf);
2260 &$cleanup_config($conf->{pending
}, 1);
2262 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2263 die "internal error" if $snapname eq 'pending';
2264 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2267 # remove 'unusedX' settings if we re-add a volume
2268 foreach my $key (keys %$conf) {
2269 my $value = $conf->{$key};
2270 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2271 delete $conf->{$key};
2275 my $generate_raw_config = sub {
2276 my ($conf, $pending) = @_;
2280 # add description as comment to top of file
2281 if (defined(my $descr = $conf->{description
})) {
2283 foreach my $cl (split(/\n/, $descr)) {
2284 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2287 $raw .= "#\n" if $pending;
2291 foreach my $key (sort keys %$conf) {
2292 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2293 $raw .= "$key: $conf->{$key}\n";
2298 my $raw = &$generate_raw_config($conf);
2300 if (scalar(keys %{$conf->{pending
}})){
2301 $raw .= "\n[PENDING]\n";
2302 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2305 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2306 $raw .= "\n[$snapname]\n";
2307 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2317 # we use static defaults from our JSON schema configuration
2318 foreach my $key (keys %$confdesc) {
2319 if (defined(my $default = $confdesc->{$key}->{default})) {
2320 $res->{$key} = $default;
2324 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2325 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2331 my $vmlist = PVE
::Cluster
::get_vmlist
();
2333 return $res if !$vmlist || !$vmlist->{ids
};
2334 my $ids = $vmlist->{ids
};
2336 foreach my $vmid (keys %$ids) {
2337 my $d = $ids->{$vmid};
2338 next if !$d->{node
} || $d->{node
} ne $nodename;
2339 next if !$d->{type
} || $d->{type
} ne 'qemu';
2340 $res->{$vmid}->{exists} = 1;
2345 # test if VM uses local resources (to prevent migration)
2346 sub check_local_resources
{
2347 my ($conf, $noerr) = @_;
2351 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2352 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2354 foreach my $k (keys %$conf) {
2355 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2356 # sockets are safe: they will recreated be on the target side post-migrate
2357 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2358 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2361 die "VM uses local resources\n" if $loc_res && !$noerr;
2366 # check if used storages are available on all nodes (use by migrate)
2367 sub check_storage_availability
{
2368 my ($storecfg, $conf, $node) = @_;
2370 foreach_drive
($conf, sub {
2371 my ($ds, $drive) = @_;
2373 my $volid = $drive->{file
};
2376 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2379 # check if storage is available on both nodes
2380 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2381 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2385 # list nodes where all VM images are available (used by has_feature API)
2387 my ($conf, $storecfg) = @_;
2389 my $nodelist = PVE
::Cluster
::get_nodelist
();
2390 my $nodehash = { map { $_ => 1 } @$nodelist };
2391 my $nodename = PVE
::INotify
::nodename
();
2393 foreach_drive
($conf, sub {
2394 my ($ds, $drive) = @_;
2396 my $volid = $drive->{file
};
2399 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2401 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2402 if ($scfg->{disable
}) {
2404 } elsif (my $avail = $scfg->{nodes
}) {
2405 foreach my $node (keys %$nodehash) {
2406 delete $nodehash->{$node} if !$avail->{$node};
2408 } elsif (!$scfg->{shared
}) {
2409 foreach my $node (keys %$nodehash) {
2410 delete $nodehash->{$node} if $node ne $nodename
2420 my ($pidfile, $pid) = @_;
2422 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2426 return undef if !$line;
2427 my @param = split(/\0/, $line);
2429 my $cmd = $param[0];
2430 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2432 for (my $i = 0; $i < scalar (@param); $i++) {
2435 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2436 my $p = $param[$i+1];
2437 return 1 if $p && ($p eq $pidfile);
2446 my ($vmid, $nocheck, $node) = @_;
2448 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2450 die "unable to find configuration file for VM $vmid - no such machine\n"
2451 if !$nocheck && ! -f
$filename;
2453 my $pidfile = pidfile_name
($vmid);
2455 if (my $fd = IO
::File-
>new("<$pidfile")) {
2460 my $mtime = $st->mtime;
2461 if ($mtime > time()) {
2462 warn "file '$filename' modified in future\n";
2465 if ($line =~ m/^(\d+)$/) {
2467 if (check_cmdline
($pidfile, $pid)) {
2468 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2480 my $vzlist = config_list
();
2482 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2484 while (defined(my $de = $fd->read)) {
2485 next if $de !~ m/^(\d+)\.pid$/;
2487 next if !defined($vzlist->{$vmid});
2488 if (my $pid = check_running
($vmid)) {
2489 $vzlist->{$vmid}->{pid
} = $pid;
2497 my ($storecfg, $conf) = @_;
2499 my $bootdisk = $conf->{bootdisk
};
2500 return undef if !$bootdisk;
2501 return undef if !is_valid_drivename
($bootdisk);
2503 return undef if !$conf->{$bootdisk};
2505 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2506 return undef if !defined($drive);
2508 return undef if drive_is_cdrom
($drive);
2510 my $volid = $drive->{file
};
2511 return undef if !$volid;
2513 return $drive->{size
};
2516 my $last_proc_pid_stat;
2518 # get VM status information
2519 # This must be fast and should not block ($full == false)
2520 # We only query KVM using QMP if $full == true (this can be slow)
2522 my ($opt_vmid, $full) = @_;
2526 my $storecfg = PVE
::Storage
::config
();
2528 my $list = vzlist
();
2529 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2531 my $cpucount = $cpuinfo->{cpus
} || 1;
2533 foreach my $vmid (keys %$list) {
2534 next if $opt_vmid && ($vmid ne $opt_vmid);
2536 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2537 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2540 $d->{pid
} = $list->{$vmid}->{pid
};
2542 # fixme: better status?
2543 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2545 my $size = disksize
($storecfg, $conf);
2546 if (defined($size)) {
2547 $d->{disk
} = 0; # no info available
2548 $d->{maxdisk
} = $size;
2554 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2555 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2556 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2558 $d->{name
} = $conf->{name
} || "VM $vmid";
2559 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2561 if ($conf->{balloon
}) {
2562 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2563 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2574 $d->{diskwrite
} = 0;
2576 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2581 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2582 foreach my $dev (keys %$netdev) {
2583 next if $dev !~ m/^tap([1-9]\d*)i/;
2585 my $d = $res->{$vmid};
2588 $d->{netout
} += $netdev->{$dev}->{receive
};
2589 $d->{netin
} += $netdev->{$dev}->{transmit
};
2592 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2593 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2598 my $ctime = gettimeofday
;
2600 foreach my $vmid (keys %$list) {
2602 my $d = $res->{$vmid};
2603 my $pid = $d->{pid
};
2606 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2607 next if !$pstat; # not running
2609 my $used = $pstat->{utime} + $pstat->{stime
};
2611 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2613 if ($pstat->{vsize
}) {
2614 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2617 my $old = $last_proc_pid_stat->{$pid};
2619 $last_proc_pid_stat->{$pid} = {
2627 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2629 if ($dtime > 1000) {
2630 my $dutime = $used - $old->{used
};
2632 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2633 $last_proc_pid_stat->{$pid} = {
2639 $d->{cpu
} = $old->{cpu
};
2643 return $res if !$full;
2645 my $qmpclient = PVE
::QMPClient-
>new();
2647 my $ballooncb = sub {
2648 my ($vmid, $resp) = @_;
2650 my $info = $resp->{'return'};
2651 return if !$info->{max_mem
};
2653 my $d = $res->{$vmid};
2655 # use memory assigned to VM
2656 $d->{maxmem
} = $info->{max_mem
};
2657 $d->{balloon
} = $info->{actual
};
2659 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2660 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2661 $d->{freemem
} = $info->{free_mem
};
2664 $d->{ballooninfo
} = $info;
2667 my $blockstatscb = sub {
2668 my ($vmid, $resp) = @_;
2669 my $data = $resp->{'return'} || [];
2670 my $totalrdbytes = 0;
2671 my $totalwrbytes = 0;
2673 for my $blockstat (@$data) {
2674 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2675 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2677 $blockstat->{device
} =~ s/drive-//;
2678 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2680 $res->{$vmid}->{diskread
} = $totalrdbytes;
2681 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2684 my $statuscb = sub {
2685 my ($vmid, $resp) = @_;
2687 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2688 # this fails if ballon driver is not loaded, so this must be
2689 # the last commnand (following command are aborted if this fails).
2690 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2692 my $status = 'unknown';
2693 if (!defined($status = $resp->{'return'}->{status
})) {
2694 warn "unable to get VM status\n";
2698 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2701 foreach my $vmid (keys %$list) {
2702 next if $opt_vmid && ($vmid ne $opt_vmid);
2703 next if !$res->{$vmid}->{pid
}; # not running
2704 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2707 $qmpclient->queue_execute(undef, 1);
2709 foreach my $vmid (keys %$list) {
2710 next if $opt_vmid && ($vmid ne $opt_vmid);
2711 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2718 my ($conf, $func, @param) = @_;
2720 foreach my $ds (valid_drive_names
()) {
2721 next if !defined($conf->{$ds});
2723 my $drive = parse_drive
($ds, $conf->{$ds});
2726 &$func($ds, $drive, @param);
2731 my ($conf, $func, @param) = @_;
2735 my $test_volid = sub {
2736 my ($volid, $is_cdrom) = @_;
2740 $volhash->{$volid} = $is_cdrom || 0;
2743 foreach_drive
($conf, sub {
2744 my ($ds, $drive) = @_;
2745 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2748 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2749 my $snap = $conf->{snapshots
}->{$snapname};
2750 &$test_volid($snap->{vmstate
}, 0);
2751 foreach_drive
($snap, sub {
2752 my ($ds, $drive) = @_;
2753 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2757 foreach my $volid (keys %$volhash) {
2758 &$func($volid, $volhash->{$volid}, @param);
2762 sub vga_conf_has_spice
{
2765 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2770 sub config_to_command
{
2771 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2774 my $globalFlags = [];
2775 my $machineFlags = [];
2781 my $kvmver = kvm_user_version
();
2782 my $vernum = 0; # unknown
2783 my $ostype = $conf->{ostype
};
2784 my $winversion = windows_version
($ostype);
2786 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2787 $vernum = $1*1000000+$2*1000;
2788 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2789 $vernum = $1*1000000+$2*1000+$3;
2792 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2794 my $have_ovz = -f
'/proc/vz/vestat';
2796 my $q35 = machine_type_is_q35
($conf);
2797 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2798 my $machine_type = $forcemachine || $conf->{machine
};
2799 my $use_old_bios_files = undef;
2800 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2802 my $cpuunits = defined($conf->{cpuunits
}) ?
2803 $conf->{cpuunits
} : $defaults->{cpuunits
};
2805 push @$cmd, '/usr/bin/kvm';
2807 push @$cmd, '-id', $vmid;
2811 my $qmpsocket = qmp_socket
($vmid);
2812 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2813 push @$cmd, '-mon', "chardev=qmp,mode=control";
2816 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2818 push @$cmd, '-daemonize';
2820 if ($conf->{smbios1
}) {
2821 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2824 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2827 # prefer the OVMF_CODE variant
2828 if (-f
$OVMF_CODE) {
2829 $ovmfbase = $OVMF_CODE;
2830 } elsif (-f
$OVMF_IMG) {
2831 $ovmfbase = $OVMF_IMG;
2834 die "no uefi base img found\n" if !$ovmfbase;
2835 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$ovmfbase";
2837 if (defined($conf->{efidisk0
}) && ($ovmfbase eq $OVMF_CODE)) {
2838 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $conf->{efidisk0
});
2839 my $format = $d->{format
} // 'raw';
2841 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
2843 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
2844 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2845 $format = qemu_img_format
($scfg, $volname);
2850 push @$cmd, '-drive', "if=pflash,unit=1,id=drive-efidisk0,format=$format,file=$path";
2851 } elsif ($ovmfbase eq $OVMF_CODE) {
2852 warn "using uefi without permanent efivars disk\n";
2853 my $ovmfvar_dst = "/tmp/$vmid-ovmf.fd";
2854 PVE
::Tools
::file_copy
($OVMF_VARS, $ovmfvar_dst, 256*1024);
2855 push @$cmd, '-drive', "if=pflash,unit=1,format=raw,file=$ovmfvar_dst";
2857 # if the base img is not OVMF_CODE, we do not have to bother
2858 # to create/use a vars image, since it will not be used anyway
2859 # this can only happen if someone manually deletes the OVMF_CODE image
2860 # or has an old pve-qemu-kvm version installed.
2861 # both should not happen, but we ignore it here
2866 # add usb controllers
2867 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2868 push @$devices, @usbcontrollers if @usbcontrollers;
2869 my $vga = $conf->{vga
};
2871 my $qxlnum = vga_conf_has_spice
($vga);
2872 $vga = 'qxl' if $qxlnum;
2875 $vga = $winversion >= 6 ?
'std' : 'cirrus';
2878 # enable absolute mouse coordinates (needed by vnc)
2880 if (defined($conf->{tablet
})) {
2881 $tablet = $conf->{tablet
};
2883 $tablet = $defaults->{tablet
};
2884 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2885 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2888 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2891 my $gpu_passthrough;
2894 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2895 my $d = parse_hostpci
($conf->{"hostpci$i"});
2898 my $pcie = $d->{pcie
};
2900 die "q35 machine model is not enabled" if !$q35;
2901 $pciaddr = print_pcie_addr
("hostpci$i");
2903 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2906 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2908 if ($d->{'x-vga'}) {
2909 $xvga = ',x-vga=on';
2912 $gpu_passthrough = 1;
2914 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2918 my $pcidevices = $d->{pciid
};
2919 my $multifunction = 1 if @$pcidevices > 1;
2922 foreach my $pcidevice (@$pcidevices) {
2924 my $id = "hostpci$i";
2925 $id .= ".$j" if $multifunction;
2926 my $addr = $pciaddr;
2927 $addr .= ".$j" if $multifunction;
2928 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2931 $devicestr .= "$rombar$xvga";
2932 $devicestr .= ",multifunction=on" if $multifunction;
2935 push @$devices, '-device', $devicestr;
2941 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
2942 push @$devices, @usbdevices if @usbdevices;
2944 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2945 if (my $path = $conf->{"serial$i"}) {
2946 if ($path eq 'socket') {
2947 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2948 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2949 push @$devices, '-device', "isa-serial,chardev=serial$i";
2951 die "no such serial device\n" if ! -c
$path;
2952 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2953 push @$devices, '-device', "isa-serial,chardev=serial$i";
2959 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2960 if (my $path = $conf->{"parallel$i"}) {
2961 die "no such parallel device\n" if ! -c
$path;
2962 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2963 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2964 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2968 my $vmname = $conf->{name
} || "vm$vmid";
2970 push @$cmd, '-name', $vmname;
2973 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2974 $sockets = $conf->{sockets
} if $conf->{sockets
};
2976 my $cores = $conf->{cores
} || 1;
2978 my $maxcpus = $sockets * $cores;
2980 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2982 my $allowed_vcpus = $cpuinfo->{cpus
};
2984 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2985 if ($allowed_vcpus < $maxcpus);
2987 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
2989 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2990 for (my $i = 2; $i <= $vcpus; $i++) {
2991 my $cpustr = print_cpu_device
($conf,$i);
2992 push @$cmd, '-device', $cpustr;
2997 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2999 push @$cmd, '-nodefaults';
3001 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3003 my $bootindex_hash = {};
3005 foreach my $o (split(//, $bootorder)) {
3006 $bootindex_hash->{$o} = $i*100;
3010 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3012 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3014 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3016 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3018 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3019 my $socket = vnc_socket
($vmid);
3020 push @$cmd, '-vnc', "unix:$socket,x509,password";
3022 push @$cmd, '-nographic';
3026 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3028 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3029 my $useLocaltime = $conf->{localtime};
3031 if ($winversion >= 5) { # windows
3032 $useLocaltime = 1 if !defined($conf->{localtime});
3034 # use time drift fix when acpi is enabled
3035 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3036 $tdf = 1 if !defined($conf->{tdf
});
3040 if ($winversion >= 6) {
3041 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3042 push @$cmd, '-no-hpet';
3045 push @$rtcFlags, 'driftfix=slew' if $tdf;
3048 push @$machineFlags, 'accel=tcg';
3050 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3053 if ($machine_type) {
3054 push @$machineFlags, "type=${machine_type}";
3057 if ($conf->{startdate
}) {
3058 push @$rtcFlags, "base=$conf->{startdate}";
3059 } elsif ($useLocaltime) {
3060 push @$rtcFlags, 'base=localtime';
3063 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3064 if (my $cputype = $conf->{cpu
}) {
3065 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3066 or die "Cannot parse cpu description: $cputype\n";
3067 $cpu = $cpuconf->{cputype
};
3068 $kvm_off = 1 if $cpuconf->{hidden
};
3071 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3073 push @$cpuFlags , '-x2apic'
3074 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3076 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3078 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3080 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3082 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3083 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3086 add_hyperv_enlighments
($cpuFlags, $winversion, $machine_type, $kvmver, $nokvm, $conf->{bios
}, $gpu_passthrough);
3088 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3090 push @$cpuFlags, 'kvm=off' if $kvm_off;
3092 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3093 die "internal error"; # should not happen
3095 push @$cpuFlags, "vendor=${cpu_vendor}"
3096 if $cpu_vendor ne 'default';
3098 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3100 push @$cmd, '-cpu', $cpu;
3102 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3104 push @$cmd, '-S' if $conf->{freeze
};
3106 # set keyboard layout
3107 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3108 push @$cmd, '-k', $kb if $kb;
3111 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3112 #push @$cmd, '-soundhw', 'es1370';
3113 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3115 if($conf->{agent
}) {
3116 my $qgasocket = qmp_socket
($vmid, 1);
3117 my $pciaddr = print_pci_addr
("qga0", $bridges);
3118 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3119 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3120 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3128 for(my $i = 1; $i < $qxlnum; $i++){
3129 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3130 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3133 # assume other OS works like Linux
3134 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3135 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3139 my $pciaddr = print_pci_addr
("spice", $bridges);
3141 my $nodename = PVE
::INotify
::nodename
();
3142 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3143 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3145 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3147 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3148 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3149 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3152 # enable balloon by default, unless explicitly disabled
3153 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3154 $pciaddr = print_pci_addr
("balloon0", $bridges);
3155 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3158 if ($conf->{watchdog
}) {
3159 my $wdopts = parse_watchdog
($conf->{watchdog
});
3160 $pciaddr = print_pci_addr
("watchdog", $bridges);
3161 my $watchdog = $wdopts->{model
} || 'i6300esb';
3162 push @$devices, '-device', "$watchdog$pciaddr";
3163 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3167 my $scsicontroller = {};
3168 my $ahcicontroller = {};
3169 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3171 # Add iscsi initiator name if available
3172 if (my $initiator = get_initiator_name
()) {
3173 push @$devices, '-iscsi', "initiator-name=$initiator";
3176 foreach_drive
($conf, sub {
3177 my ($ds, $drive) = @_;
3179 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3180 push @$vollist, $drive->{file
};
3183 $use_virtio = 1 if $ds =~ m/^virtio/;
3185 if (drive_is_cdrom
($drive)) {
3186 if ($bootindex_hash->{d
}) {
3187 $drive->{bootindex
} = $bootindex_hash->{d
};
3188 $bootindex_hash->{d
} += 1;
3191 if ($bootindex_hash->{c
}) {
3192 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3193 $bootindex_hash->{c
} += 1;
3197 if($drive->{interface
} eq 'virtio'){
3198 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3201 if ($drive->{interface
} eq 'scsi') {
3203 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3205 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3206 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3209 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3210 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3211 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3212 } elsif ($drive->{iothread
}) {
3213 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3217 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3218 $queues = ",num_queues=$drive->{queues}";
3221 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3222 $scsicontroller->{$controller}=1;
3225 if ($drive->{interface
} eq 'sata') {
3226 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3227 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3228 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3229 $ahcicontroller->{$controller}=1;
3232 if ($drive->{interface
} eq 'efidisk') {
3233 # this will be added somewhere else
3237 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3238 push @$devices, '-drive',$drive_cmd;
3239 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3242 for (my $i = 0; $i < $MAX_NETS; $i++) {
3243 next if !$conf->{"net$i"};
3244 my $d = parse_net
($conf->{"net$i"});
3247 $use_virtio = 1 if $d->{model
} eq 'virtio';
3249 if ($bootindex_hash->{n
}) {
3250 $d->{bootindex
} = $bootindex_hash->{n
};
3251 $bootindex_hash->{n
} += 1;
3254 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3255 push @$devices, '-netdev', $netdevfull;
3257 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3258 push @$devices, '-device', $netdevicefull;
3263 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3268 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3270 while (my ($k, $v) = each %$bridges) {
3271 $pciaddr = print_pci_addr
("pci.$k");
3272 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3277 if ($conf->{args
}) {
3278 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3282 push @$cmd, @$devices;
3283 push @$cmd, '-rtc', join(',', @$rtcFlags)
3284 if scalar(@$rtcFlags);
3285 push @$cmd, '-machine', join(',', @$machineFlags)
3286 if scalar(@$machineFlags);
3287 push @$cmd, '-global', join(',', @$globalFlags)
3288 if scalar(@$globalFlags);
3290 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3295 return "${var_run_tmpdir}/$vmid.vnc";
3301 my $res = vm_mon_cmd
($vmid, 'query-spice');
3303 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3307 my ($vmid, $qga) = @_;
3308 my $sockettype = $qga ?
'qga' : 'qmp';
3309 return "${var_run_tmpdir}/$vmid.$sockettype";
3314 return "${var_run_tmpdir}/$vmid.pid";
3317 sub vm_devices_list
{
3320 my $res = vm_mon_cmd
($vmid, 'query-pci');
3322 foreach my $pcibus (@$res) {
3323 foreach my $device (@{$pcibus->{devices
}}) {
3324 next if !$device->{'qdev_id'};
3325 if ($device->{'pci_bridge'}) {
3326 $devices->{$device->{'qdev_id'}} = 1;
3327 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3328 next if !$bridge_device->{'qdev_id'};
3329 $devices->{$bridge_device->{'qdev_id'}} = 1;
3330 $devices->{$device->{'qdev_id'}}++;
3333 $devices->{$device->{'qdev_id'}} = 1;
3338 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3339 foreach my $block (@$resblock) {
3340 if($block->{device
} =~ m/^drive-(\S+)/){
3345 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3346 foreach my $mice (@$resmice) {
3347 if ($mice->{name
} eq 'QEMU HID Tablet') {
3348 $devices->{tablet
} = 1;
3353 # for usb devices there is no query-usb
3354 # but we can iterate over the entries in
3355 # qom-list path=/machine/peripheral
3356 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3357 foreach my $per (@$resperipheral) {
3358 if ($per->{name
} =~ m/^usb\d+$/) {
3359 $devices->{$per->{name
}} = 1;
3367 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3369 my $q35 = machine_type_is_q35
($conf);
3371 my $devices_list = vm_devices_list
($vmid);
3372 return 1 if defined($devices_list->{$deviceid});
3374 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3376 if ($deviceid eq 'tablet') {
3378 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3380 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3382 die "usb hotplug currently not reliable\n";
3383 # since we can't reliably hot unplug all added usb devices
3384 # and usb passthrough disables live migration
3385 # we disable usb hotplugging for now
3386 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3388 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3390 qemu_iothread_add
($vmid, $deviceid, $device);
3392 qemu_driveadd
($storecfg, $vmid, $device);
3393 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3395 qemu_deviceadd
($vmid, $devicefull);
3396 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3398 eval { qemu_drivedel
($vmid, $deviceid); };
3403 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3406 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3407 my $pciaddr = print_pci_addr
($deviceid);
3408 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3410 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3412 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3413 qemu_iothread_add
($vmid, $deviceid, $device);
3414 $devicefull .= ",iothread=iothread-$deviceid";
3417 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3418 $devicefull .= ",num_queues=$device->{queues}";
3421 qemu_deviceadd
($vmid, $devicefull);
3422 qemu_deviceaddverify
($vmid, $deviceid);
3424 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3426 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3427 qemu_driveadd
($storecfg, $vmid, $device);
3429 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3430 eval { qemu_deviceadd
($vmid, $devicefull); };
3432 eval { qemu_drivedel
($vmid, $deviceid); };
3437 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3439 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3441 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3442 my $use_old_bios_files = undef;
3443 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3445 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3446 qemu_deviceadd
($vmid, $netdevicefull);
3447 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3449 eval { qemu_netdevdel
($vmid, $deviceid); };
3454 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3457 my $pciaddr = print_pci_addr
($deviceid);
3458 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3460 qemu_deviceadd
($vmid, $devicefull);
3461 qemu_deviceaddverify
($vmid, $deviceid);
3464 die "can't hotplug device '$deviceid'\n";
3470 # fixme: this should raise exceptions on error!
3471 sub vm_deviceunplug
{
3472 my ($vmid, $conf, $deviceid) = @_;
3474 my $devices_list = vm_devices_list
($vmid);
3475 return 1 if !defined($devices_list->{$deviceid});
3477 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3479 if ($deviceid eq 'tablet') {
3481 qemu_devicedel
($vmid, $deviceid);
3483 } elsif ($deviceid =~ m/^usb\d+$/) {
3485 die "usb hotplug currently not reliable\n";
3486 # when unplugging usb devices this way,
3487 # there may be remaining usb controllers/hubs
3488 # so we disable it for now
3489 qemu_devicedel
($vmid, $deviceid);
3490 qemu_devicedelverify
($vmid, $deviceid);
3492 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3494 qemu_devicedel
($vmid, $deviceid);
3495 qemu_devicedelverify
($vmid, $deviceid);
3496 qemu_drivedel
($vmid, $deviceid);
3497 qemu_iothread_del
($conf, $vmid, $deviceid);
3499 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3501 qemu_devicedel
($vmid, $deviceid);
3502 qemu_devicedelverify
($vmid, $deviceid);
3503 qemu_iothread_del
($conf, $vmid, $deviceid);
3505 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3507 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3508 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3509 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3511 qemu_devicedel
($vmid, $deviceid);
3512 qemu_drivedel
($vmid, $deviceid);
3513 qemu_deletescsihw
($conf, $vmid, $deviceid);
3515 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3517 qemu_devicedel
($vmid, $deviceid);
3518 qemu_devicedelverify
($vmid, $deviceid);
3519 qemu_netdevdel
($vmid, $deviceid);
3522 die "can't unplug device '$deviceid'\n";
3528 sub qemu_deviceadd
{
3529 my ($vmid, $devicefull) = @_;
3531 $devicefull = "driver=".$devicefull;
3532 my %options = split(/[=,]/, $devicefull);
3534 vm_mon_cmd
($vmid, "device_add" , %options);
3537 sub qemu_devicedel
{
3538 my ($vmid, $deviceid) = @_;
3540 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3543 sub qemu_iothread_add
{
3544 my($vmid, $deviceid, $device) = @_;
3546 if ($device->{iothread
}) {
3547 my $iothreads = vm_iothreads_list
($vmid);
3548 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3552 sub qemu_iothread_del
{
3553 my($conf, $vmid, $deviceid) = @_;
3555 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3556 if ($device->{iothread
}) {
3557 my $iothreads = vm_iothreads_list
($vmid);
3558 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3562 sub qemu_objectadd
{
3563 my($vmid, $objectid, $qomtype) = @_;
3565 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3570 sub qemu_objectdel
{
3571 my($vmid, $objectid) = @_;
3573 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3579 my ($storecfg, $vmid, $device) = @_;
3581 my $drive = print_drive_full
($storecfg, $vmid, $device);
3582 $drive =~ s/\\/\\\\/g;
3583 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3585 # If the command succeeds qemu prints: "OK
"
3586 return 1 if $ret =~ m/OK/s;
3588 die "adding drive failed
: $ret\n";
3592 my($vmid, $deviceid) = @_;
3594 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3597 return 1 if $ret eq "";
3599 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3600 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3602 die "deleting drive
$deviceid failed
: $ret\n";
3605 sub qemu_deviceaddverify {
3606 my ($vmid, $deviceid) = @_;
3608 for (my $i = 0; $i <= 5; $i++) {
3609 my $devices_list = vm_devices_list($vmid);
3610 return 1 if defined($devices_list->{$deviceid});
3614 die "error on hotplug device
'$deviceid'\n";
3618 sub qemu_devicedelverify {
3619 my ($vmid, $deviceid) = @_;
3621 # need to verify that the device is correctly removed as device_del
3622 # is async and empty return is not reliable
3624 for (my $i = 0; $i <= 5; $i++) {
3625 my $devices_list = vm_devices_list($vmid);
3626 return 1 if !defined($devices_list->{$deviceid});
3630 die "error on hot-unplugging device
'$deviceid'\n";
3633 sub qemu_findorcreatescsihw {
3634 my ($storecfg, $conf, $vmid, $device) = @_;
3636 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3638 my $scsihwid="$controller_prefix$controller";
3639 my $devices_list = vm_devices_list($vmid);
3641 if(!defined($devices_list->{$scsihwid})) {
3642 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3648 sub qemu_deletescsihw {
3649 my ($conf, $vmid, $opt) = @_;
3651 my $device = parse_drive($opt, $conf->{$opt});
3653 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3654 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3658 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3660 my $devices_list = vm_devices_list($vmid);
3661 foreach my $opt (keys %{$devices_list}) {
3662 if (PVE::QemuServer::is_valid_drivename($opt)) {
3663 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3664 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3670 my $scsihwid="scsihw
$controller";
3672 vm_deviceunplug($vmid, $conf, $scsihwid);
3677 sub qemu_add_pci_bridge {
3678 my ($storecfg, $conf, $vmid, $device) = @_;
3684 print_pci_addr($device, $bridges);
3686 while (my ($k, $v) = each %$bridges) {
3689 return 1 if !defined($bridgeid) || $bridgeid < 1;
3691 my $bridge = "pci
.$bridgeid";
3692 my $devices_list = vm_devices_list($vmid);
3694 if (!defined($devices_list->{$bridge})) {
3695 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3701 sub qemu_set_link_status {
3702 my ($vmid, $device, $up) = @_;
3704 vm_mon_cmd($vmid, "set_link
", name => $device,
3705 up => $up ? JSON::true : JSON::false);
3708 sub qemu_netdevadd {
3709 my ($vmid, $conf, $device, $deviceid) = @_;
3711 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3712 my %options = split(/[=,]/, $netdev);
3714 vm_mon_cmd($vmid, "netdev_add
", %options);
3718 sub qemu_netdevdel {
3719 my ($vmid, $deviceid) = @_;
3721 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3724 sub qemu_usb_hotplug {
3725 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3729 # remove the old one first
3730 vm_deviceunplug($vmid, $conf, $deviceid);
3732 # check if xhci controller is necessary and available
3733 if ($device->{usb3}) {
3735 my $devicelist = vm_devices_list($vmid);
3737 if (!$devicelist->{xhci}) {
3738 my $pciaddr = print_pci_addr("xhci
");
3739 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3742 my $d = parse_usb_device($device->{host});
3743 $d->{usb3} = $device->{usb3};
3746 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3749 sub qemu_cpu_hotplug {
3750 my ($vmid, $conf, $vcpus) = @_;
3752 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3755 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3756 $sockets = $conf->{sockets} if $conf->{sockets};
3757 my $cores = $conf->{cores} || 1;
3758 my $maxcpus = $sockets * $cores;
3760 $vcpus = $maxcpus if !$vcpus;
3762 die "you can
't add more vcpus than maxcpus\n"
3763 if $vcpus > $maxcpus;
3765 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3767 if ($vcpus < $currentvcpus) {
3769 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3771 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3772 qemu_devicedel($vmid, "cpu$i");
3774 my $currentrunningvcpus = undef;
3776 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3777 last if scalar(@{$currentrunningvcpus}) == $i-1;
3778 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3782 #update conf after each succesfull cpu unplug
3783 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3784 PVE::QemuConfig->write_config($vmid, $conf);
3787 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3793 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3794 die "vcpus in running vm does not match its configuration\n"
3795 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3797 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3799 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3800 my $cpustr = print_cpu_device($conf, $i);
3801 qemu_deviceadd($vmid, $cpustr);
3804 my $currentrunningvcpus = undef;
3806 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3807 last if scalar(@{$currentrunningvcpus}) == $i;
3808 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3812 #update conf after each succesfull cpu hotplug
3813 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3814 PVE::QemuConfig->write_config($vmid, $conf);
3818 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3819 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3824 sub qemu_block_set_io_throttle {
3825 my ($vmid, $deviceid,
3826 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3827 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3828 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3829 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3831 return if !check_running($vmid) ;
3833 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3835 bps_rd => int($bps_rd),
3836 bps_wr => int($bps_wr),
3838 iops_rd => int($iops_rd),
3839 iops_wr => int($iops_wr),
3840 bps_max => int($bps_max),
3841 bps_rd_max => int($bps_rd_max),
3842 bps_wr_max => int($bps_wr_max),
3843 iops_max => int($iops_max),
3844 iops_rd_max => int($iops_rd_max),
3845 iops_wr_max => int($iops_wr_max),
3846 bps_max_length => int($bps_max_length),
3847 bps_rd_max_length => int($bps_rd_max_length),
3848 bps_wr_max_length => int($bps_wr_max_length),
3849 iops_max_length => int($iops_max_length),
3850 iops_rd_max_length => int($iops_rd_max_length),
3851 iops_wr_max_length => int($iops_wr_max_length),
3856 # old code, only used to shutdown old VM after update
3858 my ($fh, $timeout) = @_;
3860 my $sel = new IO::Select;
3867 while (scalar (@ready = $sel->can_read($timeout))) {
3869 if ($count = $fh->sysread($buf, 8192)) {
3870 if ($buf =~ /^(.*)\(qemu\) $/s) {
3877 if (!defined($count)) {
3884 die "monitor read timeout\n" if !scalar(@ready);
3889 # old code, only used to shutdown old VM after update
3890 sub vm_monitor_command {
3891 my ($vmid, $cmdstr, $nocheck) = @_;
3896 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3898 my $sname = "${var_run_tmpdir}/$vmid.mon";
3900 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3901 die "unable to connect to VM $vmid socket - $!\n";
3905 # hack: migrate sometime blocks the monitor (when migrate_downtime
3907 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3908 $timeout = 60*60; # 1 hour
3912 my $data = __read_avail($sock, $timeout);
3914 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3915 die "got unexpected qemu monitor banner\n";
3918 my $sel = new IO::Select;
3921 if (!scalar(my @ready = $sel->can_write($timeout))) {
3922 die "monitor write error - timeout";
3925 my $fullcmd = "$cmdstr\r";
3927 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3930 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3931 die "monitor write error - $!";
3934 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3938 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3939 $timeout = 60*60; # 1 hour
3940 } elsif ($cmdstr =~ m/^(eject|change)/) {
3941 $timeout = 60; # note: cdrom mount command is slow
3943 if ($res = __read_avail($sock, $timeout)) {
3945 my @lines = split("\r?\n", $res);
3947 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3949 $res = join("\n", @lines);
3957 syslog("err", "VM $vmid monitor command failed - $err");
3964 sub qemu_block_resize {
3965 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3967 my $running = check_running($vmid);
3969 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3971 return if !$running;
3973 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3977 sub qemu_volume_snapshot {
3978 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3980 my $running = check_running($vmid);
3982 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3983 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3985 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3989 sub qemu_volume_snapshot_delete {
3990 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3992 my $running = check_running($vmid);
3994 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3995 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
3997 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4001 sub set_migration_caps {
4007 "auto-converge" => 1,
4009 "x-rdma-pin-all" => 0,
4014 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4016 for my $supported_capability (@$supported_capabilities) {
4018 capability => $supported_capability->{capability},
4019 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4023 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4026 my $fast_plug_option = {
4036 # hotplug changes in [PENDING]
4037 # $selection hash can be used to only apply specified options, for
4038 # example: { cores => 1 } (only apply changed 'cores
')
4039 # $errors ref is used to return error messages
4040 sub vmconfig_hotplug_pending {
4041 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4043 my $defaults = load_defaults();
4045 # commit values which do not have any impact on running VM first
4046 # Note: those option cannot raise errors, we we do not care about
4047 # $selection and always apply them.
4049 my $add_error = sub {
4050 my ($opt, $msg) = @_;
4051 $errors->{$opt} = "hotplug problem - $msg";
4055 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4056 if ($fast_plug_option->{$opt}) {
4057 $conf->{$opt} = $conf->{pending}->{$opt};
4058 delete $conf->{pending}->{$opt};
4064 PVE::QemuConfig->write_config($vmid, $conf);
4065 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4068 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4070 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4071 while (my ($opt, $force) = each %$pending_delete_hash) {
4072 next if $selection && !$selection->{$opt};
4074 if ($opt eq 'hotplug
') {
4075 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4076 } elsif ($opt eq 'tablet
') {
4077 die "skip\n" if !$hotplug_features->{usb};
4078 if ($defaults->{tablet}) {
4079 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4081 vm_deviceunplug($vmid, $conf, $opt);
4083 } elsif ($opt =~ m/^usb\d+/) {
4085 # since we cannot reliably hot unplug usb devices
4086 # we are disabling it
4087 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4088 vm_deviceunplug($vmid, $conf, $opt);
4089 } elsif ($opt eq 'vcpus
') {
4090 die "skip\n" if !$hotplug_features->{cpu};
4091 qemu_cpu_hotplug($vmid, $conf, undef);
4092 } elsif ($opt eq 'balloon
') {
4093 # enable balloon device is not hotpluggable
4094 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4095 } elsif ($fast_plug_option->{$opt}) {
4097 } elsif ($opt =~ m/^net(\d+)$/) {
4098 die "skip\n" if !$hotplug_features->{network};
4099 vm_deviceunplug($vmid, $conf, $opt);
4100 } elsif (is_valid_drivename($opt)) {
4101 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4102 vm_deviceunplug($vmid, $conf, $opt);
4103 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4104 } elsif ($opt =~ m/^memory$/) {
4105 die "skip\n" if !$hotplug_features->{memory};
4106 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4107 } elsif ($opt eq 'cpuunits
') {
4108 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4109 } elsif ($opt eq 'cpulimit
') {
4110 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4116 &$add_error($opt, $err) if $err ne "skip\n";
4118 # save new config if hotplug was successful
4119 delete $conf->{$opt};
4120 vmconfig_undelete_pending_option($conf, $opt);
4121 PVE::QemuConfig->write_config($vmid, $conf);
4122 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4126 foreach my $opt (keys %{$conf->{pending}}) {
4127 next if $selection && !$selection->{$opt};
4128 my $value = $conf->{pending}->{$opt};
4130 if ($opt eq 'hotplug
') {
4131 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4132 } elsif ($opt eq 'tablet
') {
4133 die "skip\n" if !$hotplug_features->{usb};
4135 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4136 } elsif ($value == 0) {
4137 vm_deviceunplug($vmid, $conf, $opt);
4139 } elsif ($opt =~ m/^usb\d+$/) {
4141 # since we cannot reliably hot unplug usb devices
4142 # we are disabling it
4143 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4144 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4145 die "skip\n" if !$d;
4146 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4147 } elsif ($opt eq 'vcpus
') {
4148 die "skip\n" if !$hotplug_features->{cpu};
4149 qemu_cpu_hotplug($vmid, $conf, $value);
4150 } elsif ($opt eq 'balloon
') {
4151 # enable/disable balloning device is not hotpluggable
4152 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4153 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4154 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4156 # allow manual ballooning if shares is set to zero
4157 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4158 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4159 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4161 } elsif ($opt =~ m/^net(\d+)$/) {
4162 # some changes can be done without hotplug
4163 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4164 $vmid, $opt, $value);
4165 } elsif (is_valid_drivename($opt)) {
4166 # some changes can be done without hotplug
4167 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4168 $vmid, $opt, $value, 1);
4169 } elsif ($opt =~ m/^memory$/) { #dimms
4170 die "skip\n" if !$hotplug_features->{memory};
4171 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4172 } elsif ($opt eq 'cpuunits
') {
4173 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4174 } elsif ($opt eq 'cpulimit
') {
4175 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4176 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4178 die "skip\n"; # skip non-hot-pluggable options
4182 &$add_error($opt, $err) if $err ne "skip\n";
4184 # save new config if hotplug was successful
4185 $conf->{$opt} = $value;
4186 delete $conf->{pending}->{$opt};
4187 PVE::QemuConfig->write_config($vmid, $conf);
4188 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4193 sub try_deallocate_drive {
4194 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4196 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4197 my $volid = $drive->{file};
4198 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4199 my $sid = PVE::Storage::parse_volume_id($volid);
4200 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4202 # check if the disk is really unused
4203 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4204 if is_volume_in_use($storecfg, $conf, $key, $volid);
4205 PVE::Storage::vdisk_free($storecfg, $volid);
4208 # If vm is not owner of this disk remove from config
4216 sub vmconfig_delete_or_detach_drive {
4217 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4219 my $drive = parse_drive($opt, $conf->{$opt});
4221 my $rpcenv = PVE::RPCEnvironment::get();
4222 my $authuser = $rpcenv->get_user();
4225 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4226 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4228 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4232 sub vmconfig_apply_pending {
4233 my ($vmid, $conf, $storecfg) = @_;
4237 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4238 while (my ($opt, $force) = each %$pending_delete_hash) {
4239 die "internal error" if $opt =~ m/^unused/;
4240 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4241 if (!defined($conf->{$opt})) {
4242 vmconfig_undelete_pending_option($conf, $opt);
4243 PVE::QemuConfig->write_config($vmid, $conf);
4244 } elsif (is_valid_drivename($opt)) {
4245 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4246 vmconfig_undelete_pending_option($conf, $opt);
4247 delete $conf->{$opt};
4248 PVE::QemuConfig->write_config($vmid, $conf);
4250 vmconfig_undelete_pending_option($conf, $opt);
4251 delete $conf->{$opt};
4252 PVE::QemuConfig->write_config($vmid, $conf);
4256 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4258 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4259 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4261 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4262 # skip if nothing changed
4263 } elsif (is_valid_drivename($opt)) {
4264 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4265 if defined($conf->{$opt});
4266 $conf->{$opt} = $conf->{pending}->{$opt};
4268 $conf->{$opt} = $conf->{pending}->{$opt};
4271 delete $conf->{pending}->{$opt};
4272 PVE::QemuConfig->write_config($vmid, $conf);
4276 my $safe_num_ne = sub {
4279 return 0 if !defined($a) && !defined($b);
4280 return 1 if !defined($a);
4281 return 1 if !defined($b);
4286 my $safe_string_ne = sub {
4289 return 0 if !defined($a) && !defined($b);
4290 return 1 if !defined($a);
4291 return 1 if !defined($b);
4296 sub vmconfig_update_net {
4297 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4299 my $newnet = parse_net($value);
4301 if ($conf->{$opt}) {
4302 my $oldnet = parse_net($conf->{$opt});
4304 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4305 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4306 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4307 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4309 # for non online change, we try to hot-unplug
4310 die "skip\n" if !$hotplug;
4311 vm_deviceunplug($vmid, $conf, $opt);
4314 die "internal error" if $opt !~ m/net(\d+)/;
4315 my $iface = "tap${vmid}i$1";
4317 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4318 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4319 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4320 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4321 PVE::Network::tap_unplug($iface);
4322 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4323 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4324 # Rate can be applied on its own but any change above needs to
4325 # include the rate in tap_plug since OVS resets everything.
4326 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4329 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4330 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4338 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4344 sub vmconfig_update_disk {
4345 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4347 # fixme: do we need force?
4349 my $drive = parse_drive($opt, $value);
4351 if ($conf->{$opt}) {
4353 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4355 my $media = $drive->{media} || 'disk
';
4356 my $oldmedia = $old_drive->{media} || 'disk
';
4357 die "unable to change media type\n" if $media ne $oldmedia;
4359 if (!drive_is_cdrom($old_drive)) {
4361 if ($drive->{file} ne $old_drive->{file}) {
4363 die "skip\n" if !$hotplug;
4365 # unplug and register as unused
4366 vm_deviceunplug($vmid, $conf, $opt);
4367 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4370 # update existing disk
4372 # skip non hotpluggable value
4373 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4374 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4375 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4376 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4381 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4382 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4383 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4384 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4385 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4386 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4387 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4388 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4389 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4390 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4391 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4392 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4393 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4394 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4395 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4396 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4397 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4398 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4400 qemu_block_set_io_throttle($vmid,"drive-$opt",
4401 ($drive->{mbps} || 0)*1024*1024,
4402 ($drive->{mbps_rd} || 0)*1024*1024,
4403 ($drive->{mbps_wr} || 0)*1024*1024,
4404 $drive->{iops} || 0,
4405 $drive->{iops_rd} || 0,
4406 $drive->{iops_wr} || 0,
4407 ($drive->{mbps_max} || 0)*1024*1024,
4408 ($drive->{mbps_rd_max} || 0)*1024*1024,
4409 ($drive->{mbps_wr_max} || 0)*1024*1024,
4410 $drive->{iops_max} || 0,
4411 $drive->{iops_rd_max} || 0,
4412 $drive->{iops_wr_max} || 0,
4413 $drive->{bps_max_length} || 1,
4414 $drive->{bps_rd_max_length} || 1,
4415 $drive->{bps_wr_max_length} || 1,
4416 $drive->{iops_max_length} || 1,
4417 $drive->{iops_rd_max_length} || 1,
4418 $drive->{iops_wr_max_length} || 1);
4427 if ($drive->{file} eq 'none
') {
4428 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4430 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4431 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4432 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4440 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4442 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4443 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4447 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4448 $forcemachine, $spice_ticket, $migration_network, $migration_type) = @_;
4450 PVE::QemuConfig->lock_config($vmid, sub {
4451 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4453 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4455 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4457 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4459 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4460 vmconfig_apply_pending($vmid, $conf, $storecfg);
4461 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4464 my $defaults = load_defaults();
4466 # set environment variable useful inside network script
4467 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4469 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4471 my $migrate_port = 0;
4474 if ($statefile eq 'tcp
') {
4475 my $localip = "localhost";
4476 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4477 my $nodename = PVE::INotify::nodename();
4479 if (!defined($migration_type)) {
4480 if (defined($datacenterconf->{migration}->{type})) {
4481 $migration_type = $datacenterconf->{migration}->{type};
4483 $migration_type = 'secure
';
4487 if ($migration_type eq 'insecure
') {
4488 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4489 if ($migrate_network_addr) {
4490 $localip = $migrate_network_addr;
4492 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4495 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4498 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4499 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4500 $migrate_uri = "tcp:${localip}:${migrate_port}";
4501 push @$cmd, '-incoming
', $migrate_uri;
4504 } elsif ($statefile eq 'unix
') {
4505 # should be default for secure migrations as a ssh TCP forward
4506 # tunnel is not deterministic reliable ready and fails regurarly
4507 # to set up in time, so use UNIX socket forwards
4508 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4509 unlink $socket_addr;
4511 $migrate_uri = "unix:$socket_addr";
4513 push @$cmd, '-incoming
', $migrate_uri;
4517 push @$cmd, '-loadstate
', $statefile;
4524 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4525 my $d = parse_hostpci($conf->{"hostpci$i"});
4527 my $pcidevices = $d->{pciid};
4528 foreach my $pcidevice (@$pcidevices) {
4529 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4531 my $info = pci_device_info("0000:$pciid");
4532 die "IOMMU not present\n" if !check_iommu_support();
4533 die "no pci device info for device '$pciid'\n" if !$info;
4534 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4535 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4539 PVE::Storage::activate_volumes($storecfg, $vollist);
4541 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4543 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4544 eval { run_command($cmd); };
4547 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4548 : $defaults->{cpuunits};
4550 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4553 Slice => 'qemu
.slice
',
4555 CPUShares => $cpuunits
4558 if (my $cpulimit = $conf->{cpulimit}) {
4559 $properties{CPUQuota} = int($cpulimit * 100);
4561 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4563 if ($conf->{hugepages}) {
4566 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4567 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4569 PVE::QemuServer::Memory::hugepages_mount();
4570 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4573 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4574 run_command($cmd, %run_params);
4578 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4582 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4584 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4588 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4589 run_command($cmd, %run_params);
4594 # deactivate volumes if start fails
4595 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4596 die "start failed: $err";
4599 print "migration listens on $migrate_uri\n" if $migrate_uri;
4601 if ($statefile && $statefile ne 'tcp
') {
4602 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4606 if ($migratedfrom) {
4609 set_migration_caps($vmid);
4614 print "spice listens on port $spice_port\n";
4615 if ($spice_ticket) {
4616 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4617 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4623 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4624 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4625 if $conf->{balloon};
4628 foreach my $opt (keys %$conf) {
4629 next if $opt !~ m/^net\d+$/;
4630 my $nicconf = parse_net($conf->{$opt});
4631 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4635 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4636 path => "machine/peripheral/balloon0",
4637 property => "guest-stats-polling-interval",
4638 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4644 my ($vmid, $execute, %params) = @_;
4646 my $cmd = { execute => $execute, arguments => \%params };
4647 vm_qmp_command($vmid, $cmd);
4650 sub vm_mon_cmd_nocheck {
4651 my ($vmid, $execute, %params) = @_;
4653 my $cmd = { execute => $execute, arguments => \%params };
4654 vm_qmp_command($vmid, $cmd, 1);
4657 sub vm_qmp_command {
4658 my ($vmid, $cmd, $nocheck) = @_;
4663 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4664 $timeout = $cmd->{arguments}->{timeout};
4665 delete $cmd->{arguments}->{timeout};
4669 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4670 my $sname = qmp_socket($vmid);
4671 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4672 my $qmpclient = PVE::QMPClient->new();
4674 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4675 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4676 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4677 if scalar(%{$cmd->{arguments}});
4678 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4680 die "unable to
open monitor
socket\n";
4684 syslog("err
", "VM
$vmid qmp command failed
- $err");
4691 sub vm_human_monitor_command {
4692 my ($vmid, $cmdline) = @_;
4697 execute => 'human-monitor-command',
4698 arguments => { 'command-line' => $cmdline},
4701 return vm_qmp_command($vmid, $cmd);
4704 sub vm_commandline {
4705 my ($storecfg, $vmid) = @_;
4707 my $conf = PVE::QemuConfig->load_config($vmid);
4709 my $defaults = load_defaults();
4711 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4713 return PVE::Tools::cmd2string($cmd);
4717 my ($vmid, $skiplock) = @_;
4719 PVE::QemuConfig->lock_config($vmid, sub {
4721 my $conf = PVE::QemuConfig->load_config($vmid);
4723 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4725 vm_mon_cmd($vmid, "system_reset
");
4729 sub get_vm_volumes {
4733 foreach_volid($conf, sub {
4734 my ($volid, $is_cdrom) = @_;
4736 return if $volid =~ m|^/|;
4738 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4741 push @$vollist, $volid;
4747 sub vm_stop_cleanup {
4748 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4753 my $vollist = get_vm_volumes($conf);
4754 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4757 foreach my $ext (qw(mon qmp pid vnc qga)) {
4758 unlink "/var/run/qemu-server/${vmid}.$ext";
4761 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4763 warn $@ if $@; # avoid errors - just warn
4766 # Note: use $nockeck to skip tests if VM configuration file exists.
4767 # We need that when migration VMs to other nodes (files already moved)
4768 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4770 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4772 $force = 1 if !defined($force) && !$shutdown;
4775 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4776 kill 15, $pid if $pid;
4777 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4778 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4782 PVE
::QemuConfig-
>lock_config($vmid, sub {
4784 my $pid = check_running
($vmid, $nocheck);
4789 $conf = PVE
::QemuConfig-
>load_config($vmid);
4790 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4791 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4792 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4793 $timeout = $opts->{down
} if $opts->{down
};
4797 $timeout = 60 if !defined($timeout);
4801 if (defined($conf) && $conf->{agent
}) {
4802 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4804 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4807 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4814 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4819 if ($count >= $timeout) {
4821 warn "VM still running - terminating now with SIGTERM\n";
4824 die "VM quit/powerdown failed - got timeout\n";
4827 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4832 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4835 die "VM quit/powerdown failed\n";
4843 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4848 if ($count >= $timeout) {
4849 warn "VM still running - terminating now with SIGKILL\n";
4854 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4859 my ($vmid, $skiplock) = @_;
4861 PVE
::QemuConfig-
>lock_config($vmid, sub {
4863 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4865 PVE
::QemuConfig-
>check_lock($conf)
4866 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4868 vm_mon_cmd
($vmid, "stop");
4873 my ($vmid, $skiplock, $nocheck) = @_;
4875 PVE
::QemuConfig-
>lock_config($vmid, sub {
4879 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4881 PVE
::QemuConfig-
>check_lock($conf)
4882 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4884 vm_mon_cmd
($vmid, "cont");
4887 vm_mon_cmd_nocheck
($vmid, "cont");
4893 my ($vmid, $skiplock, $key) = @_;
4895 PVE
::QemuConfig-
>lock_config($vmid, sub {
4897 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4899 # there is no qmp command, so we use the human monitor command
4900 vm_human_monitor_command
($vmid, "sendkey $key");
4905 my ($storecfg, $vmid, $skiplock) = @_;
4907 PVE
::QemuConfig-
>lock_config($vmid, sub {
4909 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4911 if (!check_running
($vmid)) {
4912 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4914 die "VM $vmid is running - destroy failed\n";
4922 my ($filename, $buf) = @_;
4924 my $fh = IO
::File-
>new($filename, "w");
4925 return undef if !$fh;
4927 my $res = print $fh $buf;
4934 sub pci_device_info
{
4939 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4940 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4942 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4943 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4945 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4946 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4948 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4949 return undef if !defined($product) || $product !~ s/^0x//;
4954 product
=> $product,
4960 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4969 my $name = $dev->{name
};
4971 my $fn = "$pcisysfs/devices/$name/reset";
4973 return file_write
($fn, "1");
4976 sub pci_dev_bind_to_vfio
{
4979 my $name = $dev->{name
};
4981 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4983 if (!-d
$vfio_basedir) {
4984 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4986 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4988 my $testdir = "$vfio_basedir/$name";
4989 return 1 if -d
$testdir;
4991 my $data = "$dev->{vendor} $dev->{product}";
4992 return undef if !file_write
("$vfio_basedir/new_id", $data);
4994 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4995 if (!file_write
($fn, $name)) {
4996 return undef if -f
$fn;
4999 $fn = "$vfio_basedir/bind";
5000 if (! -d
$testdir) {
5001 return undef if !file_write
($fn, $name);
5007 sub pci_dev_group_bind_to_vfio
{
5010 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5012 if (!-d
$vfio_basedir) {
5013 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5015 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5017 # get IOMMU group devices
5018 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5019 my @devs = grep /^0000:/, readdir($D);
5022 foreach my $pciid (@devs) {
5023 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5025 # pci bridges, switches or root ports are not supported
5026 # they have a pci_bus subdirectory so skip them
5027 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5029 my $info = pci_device_info
($1);
5030 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5036 # vzdump restore implementaion
5038 sub tar_archive_read_firstfile
{
5039 my $archive = shift;
5041 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5043 # try to detect archive type first
5044 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5045 die "unable to open file '$archive'\n";
5046 my $firstfile = <$fh>;
5050 die "ERROR: archive contaions no data\n" if !$firstfile;
5056 sub tar_restore_cleanup
{
5057 my ($storecfg, $statfile) = @_;
5059 print STDERR
"starting cleanup\n";
5061 if (my $fd = IO
::File-
>new($statfile, "r")) {
5062 while (defined(my $line = <$fd>)) {
5063 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5066 if ($volid =~ m
|^/|) {
5067 unlink $volid || die 'unlink failed\n';
5069 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5071 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5073 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5075 print STDERR
"unable to parse line in statfile - $line";
5082 sub restore_archive
{
5083 my ($archive, $vmid, $user, $opts) = @_;
5085 my $format = $opts->{format
};
5088 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5089 $format = 'tar' if !$format;
5091 } elsif ($archive =~ m/\.tar$/) {
5092 $format = 'tar' if !$format;
5093 } elsif ($archive =~ m/.tar.lzo$/) {
5094 $format = 'tar' if !$format;
5096 } elsif ($archive =~ m/\.vma$/) {
5097 $format = 'vma' if !$format;
5098 } elsif ($archive =~ m/\.vma\.gz$/) {
5099 $format = 'vma' if !$format;
5101 } elsif ($archive =~ m/\.vma\.lzo$/) {
5102 $format = 'vma' if !$format;
5105 $format = 'vma' if !$format; # default
5108 # try to detect archive format
5109 if ($format eq 'tar') {
5110 return restore_tar_archive
($archive, $vmid, $user, $opts);
5112 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5116 sub restore_update_config_line
{
5117 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5119 return if $line =~ m/^\#qmdump\#/;
5120 return if $line =~ m/^\#vzdump\#/;
5121 return if $line =~ m/^lock:/;
5122 return if $line =~ m/^unused\d+:/;
5123 return if $line =~ m/^parent:/;
5124 return if $line =~ m/^template:/; # restored VM is never a template
5126 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5127 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5128 # try to convert old 1.X settings
5129 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5130 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5131 my ($model, $macaddr) = split(/\=/, $devconfig);
5132 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5135 bridge
=> "vmbr$ind",
5136 macaddr
=> $macaddr,
5138 my $netstr = print_net
($net);
5140 print $outfd "net$cookie->{netcount}: $netstr\n";
5141 $cookie->{netcount
}++;
5143 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5144 my ($id, $netstr) = ($1, $2);
5145 my $net = parse_net
($netstr);
5146 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5147 $netstr = print_net
($net);
5148 print $outfd "$id: $netstr\n";
5149 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5152 my $di = parse_drive
($virtdev, $value);
5153 if (defined($di->{backup
}) && !$di->{backup
}) {
5154 print $outfd "#$line";
5155 } elsif ($map->{$virtdev}) {
5156 delete $di->{format
}; # format can change on restore
5157 $di->{file
} = $map->{$virtdev};
5158 $value = print_drive
($vmid, $di);
5159 print $outfd "$virtdev: $value\n";
5169 my ($cfg, $vmid) = @_;
5171 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5173 my $volid_hash = {};
5174 foreach my $storeid (keys %$info) {
5175 foreach my $item (@{$info->{$storeid}}) {
5176 next if !($item->{volid
} && $item->{size
});
5177 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5178 $volid_hash->{$item->{volid
}} = $item;
5185 sub is_volume_in_use
{
5186 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5188 my $path = PVE
::Storage
::path
($storecfg, $volid);
5190 my $scan_config = sub {
5191 my ($cref, $snapname) = @_;
5193 foreach my $key (keys %$cref) {
5194 my $value = $cref->{$key};
5195 if (is_valid_drivename
($key)) {
5196 next if $skip_drive && $key eq $skip_drive;
5197 my $drive = parse_drive
($key, $value);
5198 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5199 return 1 if $volid eq $drive->{file
};
5200 if ($drive->{file
} =~ m!^/!) {
5201 return 1 if $drive->{file
} eq $path;
5203 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5205 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5207 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5215 return 1 if &$scan_config($conf);
5219 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5220 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5226 sub update_disksize
{
5227 my ($vmid, $conf, $volid_hash) = @_;
5233 # Note: it is allowed to define multiple storages with same path (alias), so
5234 # we need to check both 'volid' and real 'path' (two different volid can point
5235 # to the same path).
5240 foreach my $opt (keys %$conf) {
5241 if (is_valid_drivename
($opt)) {
5242 my $drive = parse_drive
($opt, $conf->{$opt});
5243 my $volid = $drive->{file
};
5246 $used->{$volid} = 1;
5247 if ($volid_hash->{$volid} &&
5248 (my $path = $volid_hash->{$volid}->{path
})) {
5249 $usedpath->{$path} = 1;
5252 next if drive_is_cdrom
($drive);
5253 next if !$volid_hash->{$volid};
5255 $drive->{size
} = $volid_hash->{$volid}->{size
};
5256 my $new = print_drive
($vmid, $drive);
5257 if ($new ne $conf->{$opt}) {
5259 $conf->{$opt} = $new;
5264 # remove 'unusedX' entry if volume is used
5265 foreach my $opt (keys %$conf) {
5266 next if $opt !~ m/^unused\d+$/;
5267 my $volid = $conf->{$opt};
5268 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5269 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5271 delete $conf->{$opt};
5275 foreach my $volid (sort keys %$volid_hash) {
5276 next if $volid =~ m/vm-$vmid-state-/;
5277 next if $used->{$volid};
5278 my $path = $volid_hash->{$volid}->{path
};
5279 next if !$path; # just to be sure
5280 next if $usedpath->{$path};
5282 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5283 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5290 my ($vmid, $nolock) = @_;
5292 my $cfg = PVE
::Storage
::config
();
5294 my $volid_hash = scan_volids
($cfg, $vmid);
5296 my $updatefn = sub {
5299 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5301 PVE
::QemuConfig-
>check_lock($conf);
5304 foreach my $volid (keys %$volid_hash) {
5305 my $info = $volid_hash->{$volid};
5306 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5309 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5311 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5314 if (defined($vmid)) {
5318 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5321 my $vmlist = config_list
();
5322 foreach my $vmid (keys %$vmlist) {
5326 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5332 sub restore_vma_archive
{
5333 my ($archive, $vmid, $user, $opts, $comp) = @_;
5335 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5336 my $readfrom = $archive;
5341 my $qarchive = PVE
::Tools
::shellquote
($archive);
5342 if ($comp eq 'gzip') {
5343 $uncomp = "zcat $qarchive|";
5344 } elsif ($comp eq 'lzop') {
5345 $uncomp = "lzop -d -c $qarchive|";
5347 die "unknown compression method '$comp'\n";
5352 my $tmpdir = "/var/tmp/vzdumptmp$$";
5355 # disable interrupts (always do cleanups)
5356 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5357 warn "got interrupt - ignored\n";
5360 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5361 POSIX
::mkfifo
($mapfifo, 0600);
5364 my $openfifo = sub {
5365 open($fifofh, '>', $mapfifo) || die $!;
5368 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5375 my $rpcenv = PVE
::RPCEnvironment
::get
();
5377 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5378 my $tmpfn = "$conffile.$$.tmp";
5380 # Note: $oldconf is undef if VM does not exists
5381 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5382 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5384 my $print_devmap = sub {
5385 my $virtdev_hash = {};
5387 my $cfgfn = "$tmpdir/qemu-server.conf";
5389 # we can read the config - that is already extracted
5390 my $fh = IO
::File-
>new($cfgfn, "r") ||
5391 "unable to read qemu-server.conf - $!\n";
5393 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5395 my $pve_firewall_dir = '/etc/pve/firewall';
5396 mkdir $pve_firewall_dir; # make sure the dir exists
5397 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5400 while (defined(my $line = <$fh>)) {
5401 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5402 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5403 die "archive does not contain data for drive '$virtdev'\n"
5404 if !$devinfo->{$devname};
5405 if (defined($opts->{storage
})) {
5406 $storeid = $opts->{storage
} || 'local';
5407 } elsif (!$storeid) {
5410 $format = 'raw' if !$format;
5411 $devinfo->{$devname}->{devname
} = $devname;
5412 $devinfo->{$devname}->{virtdev
} = $virtdev;
5413 $devinfo->{$devname}->{format
} = $format;
5414 $devinfo->{$devname}->{storeid
} = $storeid;
5416 # check permission on storage
5417 my $pool = $opts->{pool
}; # todo: do we need that?
5418 if ($user ne 'root@pam') {
5419 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5422 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5426 foreach my $devname (keys %$devinfo) {
5427 die "found no device mapping information for device '$devname'\n"
5428 if !$devinfo->{$devname}->{virtdev
};
5431 my $cfg = PVE
::Storage
::config
();
5433 # create empty/temp config
5435 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5436 foreach_drive
($oldconf, sub {
5437 my ($ds, $drive) = @_;
5439 return if drive_is_cdrom
($drive);
5441 my $volid = $drive->{file
};
5443 return if !$volid || $volid =~ m
|^/|;
5445 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5446 return if !$path || !$owner || ($owner != $vmid);
5448 # Note: only delete disk we want to restore
5449 # other volumes will become unused
5450 if ($virtdev_hash->{$ds}) {
5451 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5458 # delete vmstate files
5459 # since after the restore we have no snapshots anymore
5460 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5461 my $snap = $oldconf->{snapshots
}->{$snapname};
5462 if ($snap->{vmstate
}) {
5463 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5472 foreach my $virtdev (sort keys %$virtdev_hash) {
5473 my $d = $virtdev_hash->{$virtdev};
5474 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5475 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5477 # test if requested format is supported
5478 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5479 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5480 $d->{format
} = $defFormat if !$supported;
5482 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5483 $d->{format
}, undef, $alloc_size);
5484 print STDERR
"new volume ID is '$volid'\n";
5485 $d->{volid
} = $volid;
5486 my $path = PVE
::Storage
::path
($cfg, $volid);
5488 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5490 my $write_zeros = 1;
5491 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5495 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5497 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5498 $map->{$virtdev} = $volid;
5501 $fh->seek(0, 0) || die "seek failed - $!\n";
5503 my $outfd = new IO
::File
($tmpfn, "w") ||
5504 die "unable to write config for VM $vmid\n";
5506 my $cookie = { netcount
=> 0 };
5507 while (defined(my $line = <$fh>)) {
5508 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5517 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5518 die "interrupted by signal\n";
5520 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5522 $oldtimeout = alarm($timeout);
5529 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5530 my ($dev_id, $size, $devname) = ($1, $2, $3);
5531 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5532 } elsif ($line =~ m/^CTIME: /) {
5533 # we correctly received the vma config, so we can disable
5534 # the timeout now for disk allocation (set to 10 minutes, so
5535 # that we always timeout if something goes wrong)
5538 print $fifofh "done\n";
5539 my $tmp = $oldtimeout || 0;
5540 $oldtimeout = undef;
5546 print "restore vma archive: $cmd\n";
5547 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5551 alarm($oldtimeout) if $oldtimeout;
5554 foreach my $devname (keys %$devinfo) {
5555 my $volid = $devinfo->{$devname}->{volid
};
5556 push @$vollist, $volid if $volid;
5559 my $cfg = PVE
::Storage
::config
();
5560 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5568 foreach my $devname (keys %$devinfo) {
5569 my $volid = $devinfo->{$devname}->{volid
};
5572 if ($volid =~ m
|^/|) {
5573 unlink $volid || die 'unlink failed\n';
5575 PVE
::Storage
::vdisk_free
($cfg, $volid);
5577 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5579 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5586 rename($tmpfn, $conffile) ||
5587 die "unable to commit configuration file '$conffile'\n";
5589 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5591 eval { rescan
($vmid, 1); };
5595 sub restore_tar_archive
{
5596 my ($archive, $vmid, $user, $opts) = @_;
5598 if ($archive ne '-') {
5599 my $firstfile = tar_archive_read_firstfile
($archive);
5600 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5601 if $firstfile ne 'qemu-server.conf';
5604 my $storecfg = PVE
::Storage
::config
();
5606 # destroy existing data - keep empty config
5607 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5608 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5610 my $tocmd = "/usr/lib/qemu-server/qmextract";
5612 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5613 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5614 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5615 $tocmd .= ' --info' if $opts->{info
};
5617 # tar option "xf" does not autodetect compression when read from STDIN,
5618 # so we pipe to zcat
5619 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5620 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5622 my $tmpdir = "/var/tmp/vzdumptmp$$";
5625 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5626 local $ENV{VZDUMP_VMID
} = $vmid;
5627 local $ENV{VZDUMP_USER
} = $user;
5629 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5630 my $tmpfn = "$conffile.$$.tmp";
5632 # disable interrupts (always do cleanups)
5633 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5634 print STDERR
"got interrupt - ignored\n";
5639 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5640 die "interrupted by signal\n";
5643 if ($archive eq '-') {
5644 print "extracting archive from STDIN\n";
5645 run_command
($cmd, input
=> "<&STDIN");
5647 print "extracting archive '$archive'\n";
5651 return if $opts->{info
};
5655 my $statfile = "$tmpdir/qmrestore.stat";
5656 if (my $fd = IO
::File-
>new($statfile, "r")) {
5657 while (defined (my $line = <$fd>)) {
5658 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5659 $map->{$1} = $2 if $1;
5661 print STDERR
"unable to parse line in statfile - $line\n";
5667 my $confsrc = "$tmpdir/qemu-server.conf";
5669 my $srcfd = new IO
::File
($confsrc, "r") ||
5670 die "unable to open file '$confsrc'\n";
5672 my $outfd = new IO
::File
($tmpfn, "w") ||
5673 die "unable to write config for VM $vmid\n";
5675 my $cookie = { netcount
=> 0 };
5676 while (defined (my $line = <$srcfd>)) {
5677 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5689 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5696 rename $tmpfn, $conffile ||
5697 die "unable to commit configuration file '$conffile'\n";
5699 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5701 eval { rescan
($vmid, 1); };
5705 sub foreach_writable_storage
{
5706 my ($conf, $func) = @_;
5710 foreach my $ds (keys %$conf) {
5711 next if !is_valid_drivename
($ds);
5713 my $drive = parse_drive
($ds, $conf->{$ds});
5715 next if drive_is_cdrom
($drive);
5717 my $volid = $drive->{file
};
5719 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5720 $sidhash->{$sid} = $sid if $sid;
5723 foreach my $sid (sort keys %$sidhash) {
5728 sub do_snapshots_with_qemu
{
5729 my ($storecfg, $volid) = @_;
5731 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5733 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5734 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5738 if ($volid =~ m/\.(qcow2|qed)$/){
5745 sub qga_check_running
{
5748 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5750 warn "Qemu Guest Agent are not running - $@";
5756 sub template_create
{
5757 my ($vmid, $conf, $disk) = @_;
5759 my $storecfg = PVE
::Storage
::config
();
5761 foreach_drive
($conf, sub {
5762 my ($ds, $drive) = @_;
5764 return if drive_is_cdrom
($drive);
5765 return if $disk && $ds ne $disk;
5767 my $volid = $drive->{file
};
5768 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5770 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5771 $drive->{file
} = $voliddst;
5772 $conf->{$ds} = print_drive
($vmid, $drive);
5773 PVE
::QemuConfig-
>write_config($vmid, $conf);
5777 sub qemu_img_convert
{
5778 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5780 my $storecfg = PVE
::Storage
::config
();
5781 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5782 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5784 if ($src_storeid && $dst_storeid) {
5786 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5788 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5789 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5791 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5792 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5794 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5795 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5798 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5799 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5800 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5801 if ($is_zero_initialized) {
5802 push @$cmd, "zeroinit:$dst_path";
5804 push @$cmd, $dst_path;
5809 if($line =~ m/\((\S+)\/100\
%\)/){
5811 my $transferred = int($size * $percent / 100);
5812 my $remaining = $size - $transferred;
5814 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5819 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5821 die "copy failed: $err" if $err;
5825 sub qemu_img_format
{
5826 my ($scfg, $volname) = @_;
5828 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5835 sub qemu_drive_mirror
{
5836 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5838 my $storecfg = PVE
::Storage
::config
();
5839 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5841 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5843 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5845 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5847 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5849 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5850 $opts->{format
} = $format if $format;
5852 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5854 my $finish_job = sub {
5856 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5857 my $stat = @$stats[0];
5864 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5866 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5867 my $stat = @$stats[0];
5868 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5869 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5871 my $busy = $stat->{busy
};
5872 my $ready = $stat->{ready
};
5874 if (my $total = $stat->{len
}) {
5875 my $transferred = $stat->{offset
} || 0;
5876 my $remaining = $total - $transferred;
5877 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5879 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5883 if ($stat->{ready
} eq 'true') {
5885 last if $vmiddst != $vmid;
5887 # try to switch the disk if source and destination are on the same guest
5888 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5893 die $@ if $@ !~ m/cannot be completed/;
5902 my $cancel_job = sub {
5903 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5908 eval { &$cancel_job(); };
5909 die "mirroring error: $err";
5912 if ($vmiddst != $vmid) {
5913 # if we clone a disk for a new target vm, we don't switch the disk
5914 &$cancel_job(); # so we call block-job-cancel
5919 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5920 $newvmid, $storage, $format, $full, $newvollist) = @_;
5925 print "create linked clone of drive $drivename ($drive->{file})\n";
5926 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5927 push @$newvollist, $newvolid;
5929 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5930 $storeid = $storage if $storage;
5932 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5934 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5935 $format = qemu_img_format
($scfg, $volname);
5938 # test if requested format is supported - else use default
5939 my $supported = grep { $_ eq $format } @$validFormats;
5940 $format = $defFormat if !$supported;
5942 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5944 print "create full clone of drive $drivename ($drive->{file})\n";
5945 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5946 push @$newvollist, $newvolid;
5948 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
5950 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5951 if (!$running || $snapname) {
5952 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5955 my $kvmver = get_running_qemu_version
($vmid);
5956 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
5957 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
5958 if $drive->{iothread
};
5961 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5965 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5968 $disk->{format
} = undef;
5969 $disk->{file
} = $newvolid;
5970 $disk->{size
} = $size;
5975 # this only works if VM is running
5976 sub get_current_qemu_machine
{
5979 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5980 my $res = vm_qmp_command
($vmid, $cmd);
5982 my ($current, $default);
5983 foreach my $e (@$res) {
5984 $default = $e->{name
} if $e->{'is-default'};
5985 $current = $e->{name
} if $e->{'is-current'};
5988 # fallback to the default machine if current is not supported by qemu
5989 return $current || $default || 'pc';
5992 sub get_running_qemu_version
{
5994 my $cmd = { execute
=> 'query-version', arguments
=> {} };
5995 my $res = vm_qmp_command
($vmid, $cmd);
5996 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
5999 sub qemu_machine_feature_enabled
{
6000 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6005 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6007 $current_major = $3;
6008 $current_minor = $4;
6010 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6012 $current_major = $1;
6013 $current_minor = $2;
6016 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6021 sub qemu_machine_pxe
{
6022 my ($vmid, $conf, $machine) = @_;
6024 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6026 foreach my $opt (keys %$conf) {
6027 next if $opt !~ m/^net(\d+)$/;
6028 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6030 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6031 return $machine.".pxe" if $romfile =~ m/pxe/;
6038 sub qemu_use_old_bios_files
{
6039 my ($machine_type) = @_;
6041 return if !$machine_type;
6043 my $use_old_bios_files = undef;
6045 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6047 $use_old_bios_files = 1;
6049 my $kvmver = kvm_user_version
();
6050 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6051 # load new efi bios files on migration. So this hack is required to allow
6052 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6053 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6054 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6057 return ($use_old_bios_files, $machine_type);
6064 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6065 my (undef, $id, $function) = @_;
6066 my $res = { id
=> $id, function
=> $function};
6067 push @{$devices->{$id}}, $res;
6073 sub vm_iothreads_list
{
6076 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6079 foreach my $iothread (@$res) {
6080 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6087 my ($conf, $drive) = @_;
6091 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6093 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6099 my $controller = int($drive->{index} / $maxdev);
6100 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6102 return ($maxdev, $controller, $controller_prefix);
6105 sub add_hyperv_enlighments
{
6106 my ($cpuFlags, $winversion, $machine_type, $kvmver, $nokvm, $bios, $gpu_passthrough) = @_;
6109 return if $winversion < 6;
6110 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6112 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6114 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
6115 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6116 push @$cpuFlags , 'hv_vapic';
6117 push @$cpuFlags , 'hv_time';
6119 push @$cpuFlags , 'hv_spinlocks=0xffff';
6122 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
6123 push @$cpuFlags , 'hv_reset';
6124 push @$cpuFlags , 'hv_vpindex';
6125 push @$cpuFlags , 'hv_runtime';
6128 if ($winversion >= 7) {
6129 push @$cpuFlags , 'hv_relaxed';
6133 sub windows_version
{
6136 return 0 if !$ostype;
6140 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6142 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6144 } elsif ($ostype =~ m/^win(\d+)$/) {
6151 # bash completion helper
6153 sub complete_backup_archives
{
6154 my ($cmdname, $pname, $cvalue) = @_;
6156 my $cfg = PVE
::Storage
::config
();
6160 if ($cvalue =~ m/^([^:]+):/) {
6164 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6167 foreach my $id (keys %$data) {
6168 foreach my $item (@{$data->{$id}}) {
6169 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6170 push @$res, $item->{volid
} if defined($item->{volid
});
6177 my $complete_vmid_full = sub {
6180 my $idlist = vmstatus
();
6184 foreach my $id (keys %$idlist) {
6185 my $d = $idlist->{$id};
6186 if (defined($running)) {
6187 next if $d->{template
};
6188 next if $running && $d->{status
} ne 'running';
6189 next if !$running && $d->{status
} eq 'running';
6198 return &$complete_vmid_full();
6201 sub complete_vmid_stopped
{
6202 return &$complete_vmid_full(0);
6205 sub complete_vmid_running
{
6206 return &$complete_vmid_full(1);
6209 sub complete_storage
{
6211 my $cfg = PVE
::Storage
::config
();
6212 my $ids = $cfg->{ids
};
6215 foreach my $sid (keys %$ids) {
6216 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6217 next if !$ids->{$sid}->{content
}->{images
};