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 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',
1195 sub get_cdrom_path
{
1197 return $cdrom_path if $cdrom_path;
1199 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1200 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1201 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1205 my ($storecfg, $vmid, $cdrom) = @_;
1207 if ($cdrom eq 'cdrom') {
1208 return get_cdrom_path
();
1209 } elsif ($cdrom eq 'none') {
1211 } elsif ($cdrom =~ m
|^/|) {
1214 return PVE
::Storage
::path
($storecfg, $cdrom);
1218 # try to convert old style file names to volume IDs
1219 sub filename_to_volume_id
{
1220 my ($vmid, $file, $media) = @_;
1222 if (!($file eq 'none' || $file eq 'cdrom' ||
1223 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1225 return undef if $file =~ m
|/|;
1227 if ($media && $media eq 'cdrom') {
1228 $file = "local:iso/$file";
1230 $file = "local:$vmid/$file";
1237 sub verify_media_type
{
1238 my ($opt, $vtype, $media) = @_;
1243 if ($media eq 'disk') {
1245 } elsif ($media eq 'cdrom') {
1248 die "internal error";
1251 return if ($vtype eq $etype);
1253 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1256 sub cleanup_drive_path
{
1257 my ($opt, $storecfg, $drive) = @_;
1259 # try to convert filesystem paths to volume IDs
1261 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1262 ($drive->{file
} !~ m
|^/dev/.+|) &&
1263 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1264 ($drive->{file
} !~ m/^\d+$/)) {
1265 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1266 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1267 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1268 verify_media_type
($opt, $vtype, $drive->{media
});
1269 $drive->{file
} = $volid;
1272 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1275 sub parse_hotplug_features
{
1280 return $res if $data eq '0';
1282 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1284 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1285 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1288 die "invalid hotplug feature '$feature'\n";
1294 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1295 sub pve_verify_hotplug_features
{
1296 my ($value, $noerr) = @_;
1298 return $value if parse_hotplug_features
($value);
1300 return undef if $noerr;
1302 die "unable to parse hotplug option\n";
1305 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1306 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1307 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1308 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1309 # [,iothread=on][,serial=serial][,model=model]
1312 my ($key, $data) = @_;
1314 my ($interface, $index);
1316 if ($key =~ m/^([^\d]+)(\d+)$/) {
1323 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1324 : $confdesc->{$key}->{format
};
1326 warn "invalid drive key: $key\n";
1329 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1330 return undef if !$res;
1331 $res->{interface
} = $interface;
1332 $res->{index} = $index;
1335 foreach my $opt (qw(bps bps_rd bps_wr)) {
1336 if (my $bps = defined(delete $res->{$opt})) {
1337 if (defined($res->{"m$opt"})) {
1338 warn "both $opt and m$opt specified\n";
1342 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1346 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1347 for my $requirement (
1348 [bps_max_length
=> 'mbps_max'],
1349 [bps_rd_max_length
=> 'mbps_rd_max'],
1350 [bps_wr_max_length
=> 'mbps_wr_max'],
1351 [iops_max_length
=> 'iops_max'],
1352 [iops_rd_max_length
=> 'iops_rd_max'],
1353 [iops_wr_max_length
=> 'iops_wr_max']) {
1354 my ($option, $requires) = @$requirement;
1355 if ($res->{$option} && !$res->{$requires}) {
1356 warn "$option requires $requires\n";
1361 return undef if $error;
1363 return undef if $res->{mbps_rd
} && $res->{mbps
};
1364 return undef if $res->{mbps_wr
} && $res->{mbps
};
1365 return undef if $res->{iops_rd
} && $res->{iops
};
1366 return undef if $res->{iops_wr
} && $res->{iops
};
1368 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1369 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1370 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1371 return undef if $res->{interface
} eq 'virtio';
1374 if (my $size = $res->{size
}) {
1375 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1382 my ($vmid, $drive) = @_;
1383 my $data = { %$drive };
1384 delete $data->{$_} for qw(index interface);
1385 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1389 my($fh, $noerr) = @_;
1392 my $SG_GET_VERSION_NUM = 0x2282;
1394 my $versionbuf = "\x00" x
8;
1395 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1397 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1400 my $version = unpack("I", $versionbuf);
1401 if ($version < 30000) {
1402 die "scsi generic interface too old\n" if !$noerr;
1406 my $buf = "\x00" x
36;
1407 my $sensebuf = "\x00" x
8;
1408 my $cmd = pack("C x3 C x1", 0x12, 36);
1410 # see /usr/include/scsi/sg.h
1411 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";
1413 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1414 length($sensebuf), 0, length($buf), $buf,
1415 $cmd, $sensebuf, 6000);
1417 $ret = ioctl($fh, $SG_IO, $packet);
1419 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1423 my @res = unpack($sg_io_hdr_t, $packet);
1424 if ($res[17] || $res[18]) {
1425 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1430 (my $byte0, my $byte1, $res->{vendor
},
1431 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1433 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1434 $res->{type
} = $byte0 & 31;
1442 my $fh = IO
::File-
>new("+<$path") || return undef;
1443 my $res = scsi_inquiry
($fh, 1);
1449 sub machine_type_is_q35
{
1452 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1455 sub print_tabletdevice_full
{
1458 my $q35 = machine_type_is_q35
($conf);
1460 # we use uhci for old VMs because tablet driver was buggy in older qemu
1461 my $usbbus = $q35 ?
"ehci" : "uhci";
1463 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1466 sub print_drivedevice_full
{
1467 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1472 if ($drive->{interface
} eq 'virtio') {
1473 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1474 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1475 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1476 } elsif ($drive->{interface
} eq 'scsi') {
1478 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1479 my $unit = $drive->{index} % $maxdev;
1480 my $devicetype = 'hd';
1482 if (drive_is_cdrom
($drive)) {
1485 if ($drive->{file
} =~ m
|^/|) {
1486 $path = $drive->{file
};
1487 if (my $info = path_is_scsi
($path)) {
1488 if ($info->{type
} == 0) {
1489 $devicetype = 'block';
1490 } elsif ($info->{type
} == 1) { # tape
1491 $devicetype = 'generic';
1495 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1498 if($path =~ m/^iscsi\:\/\
//){
1499 $devicetype = 'generic';
1503 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1504 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1506 $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}";
1509 } elsif ($drive->{interface
} eq 'ide'){
1511 my $controller = int($drive->{index} / $maxdev);
1512 my $unit = $drive->{index} % $maxdev;
1513 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1515 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1516 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1517 $model = URI
::Escape
::uri_unescape
($model);
1518 $device .= ",model=$model";
1520 } elsif ($drive->{interface
} eq 'sata'){
1521 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1522 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1523 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1524 } elsif ($drive->{interface
} eq 'usb') {
1526 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1528 die "unsupported interface type";
1531 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1536 sub get_initiator_name
{
1539 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1540 while (defined(my $line = <$fh>)) {
1541 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1550 sub print_drive_full
{
1551 my ($storecfg, $vmid, $drive) = @_;
1554 my $volid = $drive->{file
};
1557 if (drive_is_cdrom
($drive)) {
1558 $path = get_iso_path
($storecfg, $vmid, $volid);
1560 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1562 $path = PVE
::Storage
::path
($storecfg, $volid);
1563 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1564 $format = qemu_img_format
($scfg, $volname);
1572 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);
1573 foreach my $o (@qemu_drive_options) {
1574 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1576 if (my $serial = $drive->{serial
}) {
1577 $serial = URI
::Escape
::uri_unescape
($serial);
1578 $opts .= ",serial=$serial";
1581 $opts .= ",format=$format" if $format && !$drive->{format
};
1583 foreach my $o (qw(bps bps_rd bps_wr)) {
1584 my $v = $drive->{"m$o"};
1585 $opts .= ",$o=" . int($v*1024*1024) if $v;
1588 my $cache_direct = 0;
1590 if (my $cache = $drive->{cache
}) {
1591 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1592 } elsif (!drive_is_cdrom
($drive)) {
1593 $opts .= ",cache=none";
1597 # aio native works only with O_DIRECT
1598 if (!$drive->{aio
}) {
1600 $opts .= ",aio=native";
1602 $opts .= ",aio=threads";
1606 if (!drive_is_cdrom
($drive)) {
1608 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1609 $detectzeroes = 'off';
1610 } elsif ($drive->{discard
}) {
1611 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1613 # This used to be our default with discard not being specified:
1614 $detectzeroes = 'on';
1616 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1619 my $pathinfo = $path ?
"file=$path," : '';
1621 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1624 sub print_netdevice_full
{
1625 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1627 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1629 my $device = $net->{model
};
1630 if ($net->{model
} eq 'virtio') {
1631 $device = 'virtio-net-pci';
1634 my $pciaddr = print_pci_addr
("$netid", $bridges);
1635 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1636 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1637 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1638 my $vectors = $net->{queues
} * 2 + 2;
1639 $tmpstr .= ",vectors=$vectors,mq=on";
1641 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1643 if ($use_old_bios_files) {
1645 if ($device eq 'virtio-net-pci') {
1646 $romfile = 'pxe-virtio.rom';
1647 } elsif ($device eq 'e1000') {
1648 $romfile = 'pxe-e1000.rom';
1649 } elsif ($device eq 'ne2k') {
1650 $romfile = 'pxe-ne2k_pci.rom';
1651 } elsif ($device eq 'pcnet') {
1652 $romfile = 'pxe-pcnet.rom';
1653 } elsif ($device eq 'rtl8139') {
1654 $romfile = 'pxe-rtl8139.rom';
1656 $tmpstr .= ",romfile=$romfile" if $romfile;
1662 sub print_netdev_full
{
1663 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1666 if ($netid =~ m/^net(\d+)$/) {
1670 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1672 my $ifname = "tap${vmid}i$i";
1674 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1675 die "interface name '$ifname' is too long (max 15 character)\n"
1676 if length($ifname) >= 16;
1678 my $vhostparam = '';
1679 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1681 my $vmname = $conf->{name
} || "vm$vmid";
1684 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1686 if ($net->{bridge
}) {
1687 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1689 $netdev = "type=user,id=$netid,hostname=$vmname";
1692 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1698 sub print_cpu_device
{
1699 my ($conf, $id) = @_;
1701 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
1702 my $cpu = $nokvm ?
"qemu64" : "kvm64";
1703 if (my $cputype = $conf->{cpu
}) {
1704 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1705 or die "Cannot parse cpu description: $cputype\n";
1706 $cpu = $cpuconf->{cputype
};
1710 $sockets = $conf->{sockets
} if $conf->{sockets
};
1711 my $cores = $conf->{cores
} || 1;
1713 my $current_core = ($id - 1) % $cores;
1714 my $current_socket = int(($id - $current_core)/$cores);
1716 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1719 sub drive_is_cdrom
{
1722 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1726 sub parse_number_sets
{
1729 foreach my $part (split(/;/, $set)) {
1730 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1731 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1732 push @$res, [ $1, $2 ];
1734 die "invalid range: $part\n";
1743 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1744 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1745 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1752 return undef if !$value;
1754 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1756 my @idlist = split(/;/, $res->{host
});
1757 delete $res->{host
};
1758 foreach my $id (@idlist) {
1759 if ($id =~ /^$PCIRE$/) {
1761 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1763 my $pcidevices = lspci
($1);
1764 $res->{pciid
} = $pcidevices->{$1};
1767 # should have been caught by parse_property_string already
1768 die "failed to parse PCI id: $id\n";
1774 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1778 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1783 if (!defined($res->{macaddr
})) {
1784 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1785 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1793 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1796 sub add_random_macs
{
1797 my ($settings) = @_;
1799 foreach my $opt (keys %$settings) {
1800 next if $opt !~ m/^net(\d+)$/;
1801 my $net = parse_net
($settings->{$opt});
1803 $settings->{$opt} = print_net
($net);
1807 sub vm_is_volid_owner
{
1808 my ($storecfg, $vmid, $volid) = @_;
1810 if ($volid !~ m
|^/|) {
1812 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1813 if ($owner && ($owner == $vmid)) {
1821 sub split_flagged_list
{
1822 my $text = shift || '';
1823 $text =~ s/[,;]/ /g;
1825 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1828 sub join_flagged_list
{
1829 my ($how, $lst) = @_;
1830 join $how, map { $lst->{$_} . $_ } keys %$lst;
1833 sub vmconfig_delete_pending_option
{
1834 my ($conf, $key, $force) = @_;
1836 delete $conf->{pending
}->{$key};
1837 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1838 $pending_delete_hash->{$key} = $force ?
'!' : '';
1839 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1842 sub vmconfig_undelete_pending_option
{
1843 my ($conf, $key) = @_;
1845 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1846 delete $pending_delete_hash->{$key};
1848 if (%$pending_delete_hash) {
1849 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1851 delete $conf->{pending
}->{delete};
1855 sub vmconfig_register_unused_drive
{
1856 my ($storecfg, $vmid, $conf, $drive) = @_;
1858 if (!drive_is_cdrom
($drive)) {
1859 my $volid = $drive->{file
};
1860 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1861 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1866 sub vmconfig_cleanup_pending
{
1869 # remove pending changes when nothing changed
1871 foreach my $opt (keys %{$conf->{pending
}}) {
1872 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1874 delete $conf->{pending
}->{$opt};
1878 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1879 my $pending_delete_hash = {};
1880 while (my ($opt, $force) = each %$current_delete_hash) {
1881 if (defined($conf->{$opt})) {
1882 $pending_delete_hash->{$opt} = $force;
1888 if (%$pending_delete_hash) {
1889 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1891 delete $conf->{pending
}->{delete};
1897 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1901 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1902 format_description
=> 'UUID',
1903 description
=> "Set SMBIOS1 UUID.",
1909 format_description
=> 'string',
1910 description
=> "Set SMBIOS1 version.",
1916 format_description
=> 'string',
1917 description
=> "Set SMBIOS1 serial number.",
1923 format_description
=> 'string',
1924 description
=> "Set SMBIOS1 manufacturer.",
1930 format_description
=> 'string',
1931 description
=> "Set SMBIOS1 product ID.",
1937 format_description
=> 'string',
1938 description
=> "Set SMBIOS1 SKU string.",
1944 format_description
=> 'string',
1945 description
=> "Set SMBIOS1 family string.",
1953 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1960 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1963 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1965 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1966 sub verify_bootdisk
{
1967 my ($value, $noerr) = @_;
1969 return $value if is_valid_drivename
($value);
1971 return undef if $noerr;
1973 die "invalid boot disk '$value'\n";
1976 sub parse_watchdog
{
1979 return undef if !$value;
1981 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1986 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1987 sub verify_usb_device
{
1988 my ($value, $noerr) = @_;
1990 return $value if parse_usb_device
($value);
1992 return undef if $noerr;
1994 die "unable to parse usb device\n";
1997 # add JSON properties for create and set function
1998 sub json_config_properties
{
2001 foreach my $opt (keys %$confdesc) {
2002 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2003 $prop->{$opt} = $confdesc->{$opt};
2010 my ($key, $value) = @_;
2012 die "unknown setting '$key'\n" if !$confdesc->{$key};
2014 my $type = $confdesc->{$key}->{type
};
2016 if (!defined($value)) {
2017 die "got undefined value\n";
2020 if ($value =~ m/[\n\r]/) {
2021 die "property contains a line feed\n";
2024 if ($type eq 'boolean') {
2025 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2026 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2027 die "type check ('boolean') failed - got '$value'\n";
2028 } elsif ($type eq 'integer') {
2029 return int($1) if $value =~ m/^(\d+)$/;
2030 die "type check ('integer') failed - got '$value'\n";
2031 } elsif ($type eq 'number') {
2032 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2033 die "type check ('number') failed - got '$value'\n";
2034 } elsif ($type eq 'string') {
2035 if (my $fmt = $confdesc->{$key}->{format
}) {
2036 PVE
::JSONSchema
::check_format
($fmt, $value);
2039 $value =~ s/^\"(.*)\"$/$1/;
2042 die "internal error"
2046 sub check_iommu_support
{
2047 #fixme : need to check IOMMU support
2048 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2058 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2059 utime undef, undef, $conf;
2063 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2065 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2067 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2069 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2071 # only remove disks owned by this VM
2072 foreach_drive
($conf, sub {
2073 my ($ds, $drive) = @_;
2075 return if drive_is_cdrom
($drive);
2077 my $volid = $drive->{file
};
2079 return if !$volid || $volid =~ m
|^/|;
2081 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2082 return if !$path || !$owner || ($owner != $vmid);
2084 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2087 if ($keep_empty_config) {
2088 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2093 # also remove unused disk
2095 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2098 PVE
::Storage
::foreach_volid
($dl, sub {
2099 my ($volid, $sid, $volname, $d) = @_;
2100 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2109 sub parse_vm_config
{
2110 my ($filename, $raw) = @_;
2112 return undef if !defined($raw);
2115 digest
=> Digest
::SHA
::sha1_hex
($raw),
2120 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2121 || die "got strange filename '$filename'";
2129 my @lines = split(/\n/, $raw);
2130 foreach my $line (@lines) {
2131 next if $line =~ m/^\s*$/;
2133 if ($line =~ m/^\[PENDING\]\s*$/i) {
2134 $section = 'pending';
2135 if (defined($descr)) {
2137 $conf->{description
} = $descr;
2140 $conf = $res->{$section} = {};
2143 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2145 if (defined($descr)) {
2147 $conf->{description
} = $descr;
2150 $conf = $res->{snapshots
}->{$section} = {};
2154 if ($line =~ m/^\#(.*)\s*$/) {
2155 $descr = '' if !defined($descr);
2156 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2160 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2161 $descr = '' if !defined($descr);
2162 $descr .= PVE
::Tools
::decode_text
($2);
2163 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2164 $conf->{snapstate
} = $1;
2165 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2168 $conf->{$key} = $value;
2169 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2171 if ($section eq 'pending') {
2172 $conf->{delete} = $value; # we parse this later
2174 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2176 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2179 eval { $value = check_type
($key, $value); };
2181 warn "vm $vmid - unable to parse value of '$key' - $@";
2183 $key = 'ide2' if $key eq 'cdrom';
2184 my $fmt = $confdesc->{$key}->{format
};
2185 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2186 my $v = parse_drive
($key, $value);
2187 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2188 $v->{file
} = $volid;
2189 $value = print_drive
($vmid, $v);
2191 warn "vm $vmid - unable to parse value of '$key'\n";
2196 $conf->{$key} = $value;
2201 if (defined($descr)) {
2203 $conf->{description
} = $descr;
2205 delete $res->{snapstate
}; # just to be sure
2210 sub write_vm_config
{
2211 my ($filename, $conf) = @_;
2213 delete $conf->{snapstate
}; # just to be sure
2215 if ($conf->{cdrom
}) {
2216 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2217 $conf->{ide2
} = $conf->{cdrom
};
2218 delete $conf->{cdrom
};
2221 # we do not use 'smp' any longer
2222 if ($conf->{sockets
}) {
2223 delete $conf->{smp
};
2224 } elsif ($conf->{smp
}) {
2225 $conf->{sockets
} = $conf->{smp
};
2226 delete $conf->{cores
};
2227 delete $conf->{smp
};
2230 my $used_volids = {};
2232 my $cleanup_config = sub {
2233 my ($cref, $pending, $snapname) = @_;
2235 foreach my $key (keys %$cref) {
2236 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2237 $key eq 'snapstate' || $key eq 'pending';
2238 my $value = $cref->{$key};
2239 if ($key eq 'delete') {
2240 die "propertry 'delete' is only allowed in [PENDING]\n"
2242 # fixme: check syntax?
2245 eval { $value = check_type
($key, $value); };
2246 die "unable to parse value of '$key' - $@" if $@;
2248 $cref->{$key} = $value;
2250 if (!$snapname && is_valid_drivename
($key)) {
2251 my $drive = parse_drive
($key, $value);
2252 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2257 &$cleanup_config($conf);
2259 &$cleanup_config($conf->{pending
}, 1);
2261 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2262 die "internal error" if $snapname eq 'pending';
2263 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2266 # remove 'unusedX' settings if we re-add a volume
2267 foreach my $key (keys %$conf) {
2268 my $value = $conf->{$key};
2269 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2270 delete $conf->{$key};
2274 my $generate_raw_config = sub {
2275 my ($conf, $pending) = @_;
2279 # add description as comment to top of file
2280 if (defined(my $descr = $conf->{description
})) {
2282 foreach my $cl (split(/\n/, $descr)) {
2283 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2286 $raw .= "#\n" if $pending;
2290 foreach my $key (sort keys %$conf) {
2291 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2292 $raw .= "$key: $conf->{$key}\n";
2297 my $raw = &$generate_raw_config($conf);
2299 if (scalar(keys %{$conf->{pending
}})){
2300 $raw .= "\n[PENDING]\n";
2301 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2304 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2305 $raw .= "\n[$snapname]\n";
2306 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2316 # we use static defaults from our JSON schema configuration
2317 foreach my $key (keys %$confdesc) {
2318 if (defined(my $default = $confdesc->{$key}->{default})) {
2319 $res->{$key} = $default;
2323 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2324 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2330 my $vmlist = PVE
::Cluster
::get_vmlist
();
2332 return $res if !$vmlist || !$vmlist->{ids
};
2333 my $ids = $vmlist->{ids
};
2335 foreach my $vmid (keys %$ids) {
2336 my $d = $ids->{$vmid};
2337 next if !$d->{node
} || $d->{node
} ne $nodename;
2338 next if !$d->{type
} || $d->{type
} ne 'qemu';
2339 $res->{$vmid}->{exists} = 1;
2344 # test if VM uses local resources (to prevent migration)
2345 sub check_local_resources
{
2346 my ($conf, $noerr) = @_;
2350 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2351 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2353 foreach my $k (keys %$conf) {
2354 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2355 # sockets are safe: they will recreated be on the target side post-migrate
2356 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2357 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2360 die "VM uses local resources\n" if $loc_res && !$noerr;
2365 # check if used storages are available on all nodes (use by migrate)
2366 sub check_storage_availability
{
2367 my ($storecfg, $conf, $node) = @_;
2369 foreach_drive
($conf, sub {
2370 my ($ds, $drive) = @_;
2372 my $volid = $drive->{file
};
2375 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2378 # check if storage is available on both nodes
2379 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2380 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2384 # list nodes where all VM images are available (used by has_feature API)
2386 my ($conf, $storecfg) = @_;
2388 my $nodelist = PVE
::Cluster
::get_nodelist
();
2389 my $nodehash = { map { $_ => 1 } @$nodelist };
2390 my $nodename = PVE
::INotify
::nodename
();
2392 foreach_drive
($conf, sub {
2393 my ($ds, $drive) = @_;
2395 my $volid = $drive->{file
};
2398 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2400 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2401 if ($scfg->{disable
}) {
2403 } elsif (my $avail = $scfg->{nodes
}) {
2404 foreach my $node (keys %$nodehash) {
2405 delete $nodehash->{$node} if !$avail->{$node};
2407 } elsif (!$scfg->{shared
}) {
2408 foreach my $node (keys %$nodehash) {
2409 delete $nodehash->{$node} if $node ne $nodename
2419 my ($pidfile, $pid) = @_;
2421 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2425 return undef if !$line;
2426 my @param = split(/\0/, $line);
2428 my $cmd = $param[0];
2429 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2431 for (my $i = 0; $i < scalar (@param); $i++) {
2434 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2435 my $p = $param[$i+1];
2436 return 1 if $p && ($p eq $pidfile);
2445 my ($vmid, $nocheck, $node) = @_;
2447 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2449 die "unable to find configuration file for VM $vmid - no such machine\n"
2450 if !$nocheck && ! -f
$filename;
2452 my $pidfile = pidfile_name
($vmid);
2454 if (my $fd = IO
::File-
>new("<$pidfile")) {
2459 my $mtime = $st->mtime;
2460 if ($mtime > time()) {
2461 warn "file '$filename' modified in future\n";
2464 if ($line =~ m/^(\d+)$/) {
2466 if (check_cmdline
($pidfile, $pid)) {
2467 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2479 my $vzlist = config_list
();
2481 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2483 while (defined(my $de = $fd->read)) {
2484 next if $de !~ m/^(\d+)\.pid$/;
2486 next if !defined($vzlist->{$vmid});
2487 if (my $pid = check_running
($vmid)) {
2488 $vzlist->{$vmid}->{pid
} = $pid;
2496 my ($storecfg, $conf) = @_;
2498 my $bootdisk = $conf->{bootdisk
};
2499 return undef if !$bootdisk;
2500 return undef if !is_valid_drivename
($bootdisk);
2502 return undef if !$conf->{$bootdisk};
2504 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2505 return undef if !defined($drive);
2507 return undef if drive_is_cdrom
($drive);
2509 my $volid = $drive->{file
};
2510 return undef if !$volid;
2512 return $drive->{size
};
2515 my $last_proc_pid_stat;
2517 # get VM status information
2518 # This must be fast and should not block ($full == false)
2519 # We only query KVM using QMP if $full == true (this can be slow)
2521 my ($opt_vmid, $full) = @_;
2525 my $storecfg = PVE
::Storage
::config
();
2527 my $list = vzlist
();
2528 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2530 my $cpucount = $cpuinfo->{cpus
} || 1;
2532 foreach my $vmid (keys %$list) {
2533 next if $opt_vmid && ($vmid ne $opt_vmid);
2535 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2536 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2539 $d->{pid
} = $list->{$vmid}->{pid
};
2541 # fixme: better status?
2542 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2544 my $size = disksize
($storecfg, $conf);
2545 if (defined($size)) {
2546 $d->{disk
} = 0; # no info available
2547 $d->{maxdisk
} = $size;
2553 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2554 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2555 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2557 $d->{name
} = $conf->{name
} || "VM $vmid";
2558 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2560 if ($conf->{balloon
}) {
2561 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2562 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2573 $d->{diskwrite
} = 0;
2575 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2580 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2581 foreach my $dev (keys %$netdev) {
2582 next if $dev !~ m/^tap([1-9]\d*)i/;
2584 my $d = $res->{$vmid};
2587 $d->{netout
} += $netdev->{$dev}->{receive
};
2588 $d->{netin
} += $netdev->{$dev}->{transmit
};
2591 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2592 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2597 my $ctime = gettimeofday
;
2599 foreach my $vmid (keys %$list) {
2601 my $d = $res->{$vmid};
2602 my $pid = $d->{pid
};
2605 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2606 next if !$pstat; # not running
2608 my $used = $pstat->{utime} + $pstat->{stime
};
2610 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2612 if ($pstat->{vsize
}) {
2613 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2616 my $old = $last_proc_pid_stat->{$pid};
2618 $last_proc_pid_stat->{$pid} = {
2626 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2628 if ($dtime > 1000) {
2629 my $dutime = $used - $old->{used
};
2631 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2632 $last_proc_pid_stat->{$pid} = {
2638 $d->{cpu
} = $old->{cpu
};
2642 return $res if !$full;
2644 my $qmpclient = PVE
::QMPClient-
>new();
2646 my $ballooncb = sub {
2647 my ($vmid, $resp) = @_;
2649 my $info = $resp->{'return'};
2650 return if !$info->{max_mem
};
2652 my $d = $res->{$vmid};
2654 # use memory assigned to VM
2655 $d->{maxmem
} = $info->{max_mem
};
2656 $d->{balloon
} = $info->{actual
};
2658 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2659 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2660 $d->{freemem
} = $info->{free_mem
};
2663 $d->{ballooninfo
} = $info;
2666 my $blockstatscb = sub {
2667 my ($vmid, $resp) = @_;
2668 my $data = $resp->{'return'} || [];
2669 my $totalrdbytes = 0;
2670 my $totalwrbytes = 0;
2672 for my $blockstat (@$data) {
2673 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2674 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2676 $blockstat->{device
} =~ s/drive-//;
2677 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2679 $res->{$vmid}->{diskread
} = $totalrdbytes;
2680 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2683 my $statuscb = sub {
2684 my ($vmid, $resp) = @_;
2686 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2687 # this fails if ballon driver is not loaded, so this must be
2688 # the last commnand (following command are aborted if this fails).
2689 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2691 my $status = 'unknown';
2692 if (!defined($status = $resp->{'return'}->{status
})) {
2693 warn "unable to get VM status\n";
2697 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2700 foreach my $vmid (keys %$list) {
2701 next if $opt_vmid && ($vmid ne $opt_vmid);
2702 next if !$res->{$vmid}->{pid
}; # not running
2703 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2706 $qmpclient->queue_execute(undef, 1);
2708 foreach my $vmid (keys %$list) {
2709 next if $opt_vmid && ($vmid ne $opt_vmid);
2710 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2717 my ($conf, $func, @param) = @_;
2719 foreach my $ds (valid_drive_names
()) {
2720 next if !defined($conf->{$ds});
2722 my $drive = parse_drive
($ds, $conf->{$ds});
2725 &$func($ds, $drive, @param);
2730 my ($conf, $func, @param) = @_;
2734 my $test_volid = sub {
2735 my ($volid, $is_cdrom) = @_;
2739 $volhash->{$volid} = $is_cdrom || 0;
2742 foreach_drive
($conf, sub {
2743 my ($ds, $drive) = @_;
2744 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2747 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2748 my $snap = $conf->{snapshots
}->{$snapname};
2749 &$test_volid($snap->{vmstate
}, 0);
2750 foreach_drive
($snap, sub {
2751 my ($ds, $drive) = @_;
2752 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2756 foreach my $volid (keys %$volhash) {
2757 &$func($volid, $volhash->{$volid}, @param);
2761 sub vga_conf_has_spice
{
2764 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2769 sub config_to_command
{
2770 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2773 my $globalFlags = [];
2774 my $machineFlags = [];
2780 my $kvmver = kvm_user_version
();
2781 my $vernum = 0; # unknown
2782 my $ostype = $conf->{ostype
};
2783 my $winversion = windows_version
($ostype);
2785 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2786 $vernum = $1*1000000+$2*1000;
2787 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2788 $vernum = $1*1000000+$2*1000+$3;
2791 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2793 my $have_ovz = -f
'/proc/vz/vestat';
2795 my $q35 = machine_type_is_q35
($conf);
2796 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2797 my $machine_type = $forcemachine || $conf->{machine
};
2798 my $use_old_bios_files = undef;
2799 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2801 my $cpuunits = defined($conf->{cpuunits
}) ?
2802 $conf->{cpuunits
} : $defaults->{cpuunits
};
2804 push @$cmd, '/usr/bin/kvm';
2806 push @$cmd, '-id', $vmid;
2810 my $qmpsocket = qmp_socket
($vmid);
2811 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2812 push @$cmd, '-mon', "chardev=qmp,mode=control";
2815 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2817 push @$cmd, '-daemonize';
2819 if ($conf->{smbios1
}) {
2820 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2823 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2826 # prefer the OVMF_CODE variant
2827 if (-f
$OVMF_CODE) {
2828 $ovmfbase = $OVMF_CODE;
2829 } elsif (-f
$OVMF_IMG) {
2830 $ovmfbase = $OVMF_IMG;
2833 die "no uefi base img found\n" if !$ovmfbase;
2834 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$ovmfbase";
2836 if (defined($conf->{efidisk0
}) && ($ovmfbase eq $OVMF_CODE)) {
2837 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $conf->{efidisk0
});
2838 my $format = $d->{format
} // 'raw';
2840 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
2842 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
2843 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2844 $format = qemu_img_format
($scfg, $volname);
2849 push @$cmd, '-drive', "if=pflash,unit=1,id=drive-efidisk0,format=$format,file=$path";
2850 } elsif ($ovmfbase eq $OVMF_CODE) {
2851 warn "using uefi without permanent efivars disk\n";
2852 my $ovmfvar_dst = "/tmp/$vmid-ovmf.fd";
2853 PVE
::Tools
::file_copy
($OVMF_VARS, $ovmfvar_dst, 256*1024);
2854 push @$cmd, '-drive', "if=pflash,unit=1,format=raw,file=$ovmfvar_dst";
2856 # if the base img is not OVMF_CODE, we do not have to bother
2857 # to create/use a vars image, since it will not be used anyway
2858 # this can only happen if someone manually deletes the OVMF_CODE image
2859 # or has an old pve-qemu-kvm version installed.
2860 # both should not happen, but we ignore it here
2865 # add usb controllers
2866 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2867 push @$devices, @usbcontrollers if @usbcontrollers;
2868 my $vga = $conf->{vga
};
2870 my $qxlnum = vga_conf_has_spice
($vga);
2871 $vga = 'qxl' if $qxlnum;
2874 $vga = $winversion >= 6 ?
'std' : 'cirrus';
2877 # enable absolute mouse coordinates (needed by vnc)
2879 if (defined($conf->{tablet
})) {
2880 $tablet = $conf->{tablet
};
2882 $tablet = $defaults->{tablet
};
2883 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2884 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2887 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2890 my $gpu_passthrough;
2893 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2894 my $d = parse_hostpci
($conf->{"hostpci$i"});
2897 my $pcie = $d->{pcie
};
2899 die "q35 machine model is not enabled" if !$q35;
2900 $pciaddr = print_pcie_addr
("hostpci$i");
2902 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2905 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2907 if ($d->{'x-vga'}) {
2908 $xvga = ',x-vga=on';
2911 $gpu_passthrough = 1;
2913 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2917 my $pcidevices = $d->{pciid
};
2918 my $multifunction = 1 if @$pcidevices > 1;
2921 foreach my $pcidevice (@$pcidevices) {
2923 my $id = "hostpci$i";
2924 $id .= ".$j" if $multifunction;
2925 my $addr = $pciaddr;
2926 $addr .= ".$j" if $multifunction;
2927 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2930 $devicestr .= "$rombar$xvga";
2931 $devicestr .= ",multifunction=on" if $multifunction;
2934 push @$devices, '-device', $devicestr;
2940 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
2941 push @$devices, @usbdevices if @usbdevices;
2943 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2944 if (my $path = $conf->{"serial$i"}) {
2945 if ($path eq 'socket') {
2946 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2947 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2948 push @$devices, '-device', "isa-serial,chardev=serial$i";
2950 die "no such serial device\n" if ! -c
$path;
2951 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2952 push @$devices, '-device', "isa-serial,chardev=serial$i";
2958 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2959 if (my $path = $conf->{"parallel$i"}) {
2960 die "no such parallel device\n" if ! -c
$path;
2961 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2962 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2963 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2967 my $vmname = $conf->{name
} || "vm$vmid";
2969 push @$cmd, '-name', $vmname;
2972 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2973 $sockets = $conf->{sockets
} if $conf->{sockets
};
2975 my $cores = $conf->{cores
} || 1;
2977 my $maxcpus = $sockets * $cores;
2979 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2981 my $allowed_vcpus = $cpuinfo->{cpus
};
2983 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2984 if ($allowed_vcpus < $maxcpus);
2986 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
2988 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2989 for (my $i = 2; $i <= $vcpus; $i++) {
2990 my $cpustr = print_cpu_device
($conf,$i);
2991 push @$cmd, '-device', $cpustr;
2996 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2998 push @$cmd, '-nodefaults';
3000 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3002 my $bootindex_hash = {};
3004 foreach my $o (split(//, $bootorder)) {
3005 $bootindex_hash->{$o} = $i*100;
3009 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3011 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3013 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3015 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3017 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3018 my $socket = vnc_socket
($vmid);
3019 push @$cmd, '-vnc', "unix:$socket,x509,password";
3021 push @$cmd, '-nographic';
3025 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3027 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3028 my $useLocaltime = $conf->{localtime};
3030 if ($winversion >= 5) { # windows
3031 $useLocaltime = 1 if !defined($conf->{localtime});
3033 # use time drift fix when acpi is enabled
3034 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3035 $tdf = 1 if !defined($conf->{tdf
});
3039 if ($winversion >= 6) {
3040 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3041 push @$cmd, '-no-hpet';
3044 push @$rtcFlags, 'driftfix=slew' if $tdf;
3047 push @$machineFlags, 'accel=tcg';
3049 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3052 if ($machine_type) {
3053 push @$machineFlags, "type=${machine_type}";
3056 if ($conf->{startdate
}) {
3057 push @$rtcFlags, "base=$conf->{startdate}";
3058 } elsif ($useLocaltime) {
3059 push @$rtcFlags, 'base=localtime';
3062 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3063 if (my $cputype = $conf->{cpu
}) {
3064 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3065 or die "Cannot parse cpu description: $cputype\n";
3066 $cpu = $cpuconf->{cputype
};
3067 $kvm_off = 1 if $cpuconf->{hidden
};
3070 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3072 push @$cpuFlags , '-x2apic'
3073 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3075 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3077 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3079 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3081 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3082 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3085 add_hyperv_enlighments
($cpuFlags, $winversion, $machine_type, $kvmver, $nokvm, $conf->{bios
}, $gpu_passthrough);
3087 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3089 push @$cpuFlags, 'kvm=off' if $kvm_off;
3091 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3092 die "internal error"; # should not happen
3094 push @$cpuFlags, "vendor=${cpu_vendor}"
3095 if $cpu_vendor ne 'default';
3097 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3099 push @$cmd, '-cpu', $cpu;
3101 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3103 push @$cmd, '-S' if $conf->{freeze
};
3105 # set keyboard layout
3106 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3107 push @$cmd, '-k', $kb if $kb;
3110 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3111 #push @$cmd, '-soundhw', 'es1370';
3112 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3114 if($conf->{agent
}) {
3115 my $qgasocket = qmp_socket
($vmid, 1);
3116 my $pciaddr = print_pci_addr
("qga0", $bridges);
3117 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3118 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3119 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3126 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3127 for(my $i = 1; $i < $qxlnum; $i++){
3128 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3129 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3132 # assume other OS works like Linux
3133 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3134 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3138 my $pciaddr = print_pci_addr
("spice", $bridges);
3140 my $nodename = PVE
::INotify
::nodename
();
3141 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3142 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3144 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3146 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3147 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3148 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3151 # enable balloon by default, unless explicitly disabled
3152 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3153 $pciaddr = print_pci_addr
("balloon0", $bridges);
3154 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3157 if ($conf->{watchdog
}) {
3158 my $wdopts = parse_watchdog
($conf->{watchdog
});
3159 $pciaddr = print_pci_addr
("watchdog", $bridges);
3160 my $watchdog = $wdopts->{model
} || 'i6300esb';
3161 push @$devices, '-device', "$watchdog$pciaddr";
3162 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3166 my $scsicontroller = {};
3167 my $ahcicontroller = {};
3168 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3170 # Add iscsi initiator name if available
3171 if (my $initiator = get_initiator_name
()) {
3172 push @$devices, '-iscsi', "initiator-name=$initiator";
3175 foreach_drive
($conf, sub {
3176 my ($ds, $drive) = @_;
3178 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3179 push @$vollist, $drive->{file
};
3182 $use_virtio = 1 if $ds =~ m/^virtio/;
3184 if (drive_is_cdrom
($drive)) {
3185 if ($bootindex_hash->{d
}) {
3186 $drive->{bootindex
} = $bootindex_hash->{d
};
3187 $bootindex_hash->{d
} += 1;
3190 if ($bootindex_hash->{c
}) {
3191 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3192 $bootindex_hash->{c
} += 1;
3196 if($drive->{interface
} eq 'virtio'){
3197 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3200 if ($drive->{interface
} eq 'scsi') {
3202 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3204 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3205 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3208 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3209 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3210 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3211 } elsif ($drive->{iothread
}) {
3212 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3216 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3217 $queues = ",num_queues=$drive->{queues}";
3220 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3221 $scsicontroller->{$controller}=1;
3224 if ($drive->{interface
} eq 'sata') {
3225 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3226 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3227 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3228 $ahcicontroller->{$controller}=1;
3231 if ($drive->{interface
} eq 'efidisk') {
3232 # this will be added somewhere else
3236 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3237 push @$devices, '-drive',$drive_cmd;
3238 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3241 for (my $i = 0; $i < $MAX_NETS; $i++) {
3242 next if !$conf->{"net$i"};
3243 my $d = parse_net
($conf->{"net$i"});
3246 $use_virtio = 1 if $d->{model
} eq 'virtio';
3248 if ($bootindex_hash->{n
}) {
3249 $d->{bootindex
} = $bootindex_hash->{n
};
3250 $bootindex_hash->{n
} += 1;
3253 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3254 push @$devices, '-netdev', $netdevfull;
3256 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3257 push @$devices, '-device', $netdevicefull;
3262 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3267 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3269 while (my ($k, $v) = each %$bridges) {
3270 $pciaddr = print_pci_addr
("pci.$k");
3271 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3276 if ($conf->{args
}) {
3277 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3281 push @$cmd, @$devices;
3282 push @$cmd, '-rtc', join(',', @$rtcFlags)
3283 if scalar(@$rtcFlags);
3284 push @$cmd, '-machine', join(',', @$machineFlags)
3285 if scalar(@$machineFlags);
3286 push @$cmd, '-global', join(',', @$globalFlags)
3287 if scalar(@$globalFlags);
3289 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3294 return "${var_run_tmpdir}/$vmid.vnc";
3300 my $res = vm_mon_cmd
($vmid, 'query-spice');
3302 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3306 my ($vmid, $qga) = @_;
3307 my $sockettype = $qga ?
'qga' : 'qmp';
3308 return "${var_run_tmpdir}/$vmid.$sockettype";
3313 return "${var_run_tmpdir}/$vmid.pid";
3316 sub vm_devices_list
{
3319 my $res = vm_mon_cmd
($vmid, 'query-pci');
3321 foreach my $pcibus (@$res) {
3322 foreach my $device (@{$pcibus->{devices
}}) {
3323 next if !$device->{'qdev_id'};
3324 if ($device->{'pci_bridge'}) {
3325 $devices->{$device->{'qdev_id'}} = 1;
3326 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3327 next if !$bridge_device->{'qdev_id'};
3328 $devices->{$bridge_device->{'qdev_id'}} = 1;
3329 $devices->{$device->{'qdev_id'}}++;
3332 $devices->{$device->{'qdev_id'}} = 1;
3337 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3338 foreach my $block (@$resblock) {
3339 if($block->{device
} =~ m/^drive-(\S+)/){
3344 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3345 foreach my $mice (@$resmice) {
3346 if ($mice->{name
} eq 'QEMU HID Tablet') {
3347 $devices->{tablet
} = 1;
3352 # for usb devices there is no query-usb
3353 # but we can iterate over the entries in
3354 # qom-list path=/machine/peripheral
3355 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3356 foreach my $per (@$resperipheral) {
3357 if ($per->{name
} =~ m/^usb\d+$/) {
3358 $devices->{$per->{name
}} = 1;
3366 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3368 my $q35 = machine_type_is_q35
($conf);
3370 my $devices_list = vm_devices_list
($vmid);
3371 return 1 if defined($devices_list->{$deviceid});
3373 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3375 if ($deviceid eq 'tablet') {
3377 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3379 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3381 die "usb hotplug currently not reliable\n";
3382 # since we can't reliably hot unplug all added usb devices
3383 # and usb passthrough disables live migration
3384 # we disable usb hotplugging for now
3385 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3387 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3389 qemu_iothread_add
($vmid, $deviceid, $device);
3391 qemu_driveadd
($storecfg, $vmid, $device);
3392 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3394 qemu_deviceadd
($vmid, $devicefull);
3395 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3397 eval { qemu_drivedel
($vmid, $deviceid); };
3402 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3405 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3406 my $pciaddr = print_pci_addr
($deviceid);
3407 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3409 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3411 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3412 qemu_iothread_add
($vmid, $deviceid, $device);
3413 $devicefull .= ",iothread=iothread-$deviceid";
3416 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3417 $devicefull .= ",num_queues=$device->{queues}";
3420 qemu_deviceadd
($vmid, $devicefull);
3421 qemu_deviceaddverify
($vmid, $deviceid);
3423 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3425 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3426 qemu_driveadd
($storecfg, $vmid, $device);
3428 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3429 eval { qemu_deviceadd
($vmid, $devicefull); };
3431 eval { qemu_drivedel
($vmid, $deviceid); };
3436 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3438 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3440 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3441 my $use_old_bios_files = undef;
3442 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3444 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3445 qemu_deviceadd
($vmid, $netdevicefull);
3446 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3448 eval { qemu_netdevdel
($vmid, $deviceid); };
3453 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3456 my $pciaddr = print_pci_addr
($deviceid);
3457 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3459 qemu_deviceadd
($vmid, $devicefull);
3460 qemu_deviceaddverify
($vmid, $deviceid);
3463 die "can't hotplug device '$deviceid'\n";
3469 # fixme: this should raise exceptions on error!
3470 sub vm_deviceunplug
{
3471 my ($vmid, $conf, $deviceid) = @_;
3473 my $devices_list = vm_devices_list
($vmid);
3474 return 1 if !defined($devices_list->{$deviceid});
3476 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3478 if ($deviceid eq 'tablet') {
3480 qemu_devicedel
($vmid, $deviceid);
3482 } elsif ($deviceid =~ m/^usb\d+$/) {
3484 die "usb hotplug currently not reliable\n";
3485 # when unplugging usb devices this way,
3486 # there may be remaining usb controllers/hubs
3487 # so we disable it for now
3488 qemu_devicedel
($vmid, $deviceid);
3489 qemu_devicedelverify
($vmid, $deviceid);
3491 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3493 qemu_devicedel
($vmid, $deviceid);
3494 qemu_devicedelverify
($vmid, $deviceid);
3495 qemu_drivedel
($vmid, $deviceid);
3496 qemu_iothread_del
($conf, $vmid, $deviceid);
3498 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3500 qemu_devicedel
($vmid, $deviceid);
3501 qemu_devicedelverify
($vmid, $deviceid);
3502 qemu_iothread_del
($conf, $vmid, $deviceid);
3504 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3506 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3507 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3508 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3510 qemu_devicedel
($vmid, $deviceid);
3511 qemu_drivedel
($vmid, $deviceid);
3512 qemu_deletescsihw
($conf, $vmid, $deviceid);
3514 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3516 qemu_devicedel
($vmid, $deviceid);
3517 qemu_devicedelverify
($vmid, $deviceid);
3518 qemu_netdevdel
($vmid, $deviceid);
3521 die "can't unplug device '$deviceid'\n";
3527 sub qemu_deviceadd
{
3528 my ($vmid, $devicefull) = @_;
3530 $devicefull = "driver=".$devicefull;
3531 my %options = split(/[=,]/, $devicefull);
3533 vm_mon_cmd
($vmid, "device_add" , %options);
3536 sub qemu_devicedel
{
3537 my ($vmid, $deviceid) = @_;
3539 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3542 sub qemu_iothread_add
{
3543 my($vmid, $deviceid, $device) = @_;
3545 if ($device->{iothread
}) {
3546 my $iothreads = vm_iothreads_list
($vmid);
3547 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3551 sub qemu_iothread_del
{
3552 my($conf, $vmid, $deviceid) = @_;
3554 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3555 if ($device->{iothread
}) {
3556 my $iothreads = vm_iothreads_list
($vmid);
3557 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3561 sub qemu_objectadd
{
3562 my($vmid, $objectid, $qomtype) = @_;
3564 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3569 sub qemu_objectdel
{
3570 my($vmid, $objectid) = @_;
3572 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3578 my ($storecfg, $vmid, $device) = @_;
3580 my $drive = print_drive_full
($storecfg, $vmid, $device);
3581 $drive =~ s/\\/\\\\/g;
3582 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3584 # If the command succeeds qemu prints: "OK
"
3585 return 1 if $ret =~ m/OK/s;
3587 die "adding drive failed
: $ret\n";
3591 my($vmid, $deviceid) = @_;
3593 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3596 return 1 if $ret eq "";
3598 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3599 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3601 die "deleting drive
$deviceid failed
: $ret\n";
3604 sub qemu_deviceaddverify {
3605 my ($vmid, $deviceid) = @_;
3607 for (my $i = 0; $i <= 5; $i++) {
3608 my $devices_list = vm_devices_list($vmid);
3609 return 1 if defined($devices_list->{$deviceid});
3613 die "error on hotplug device
'$deviceid'\n";
3617 sub qemu_devicedelverify {
3618 my ($vmid, $deviceid) = @_;
3620 # need to verify that the device is correctly removed as device_del
3621 # is async and empty return is not reliable
3623 for (my $i = 0; $i <= 5; $i++) {
3624 my $devices_list = vm_devices_list($vmid);
3625 return 1 if !defined($devices_list->{$deviceid});
3629 die "error on hot-unplugging device
'$deviceid'\n";
3632 sub qemu_findorcreatescsihw {
3633 my ($storecfg, $conf, $vmid, $device) = @_;
3635 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3637 my $scsihwid="$controller_prefix$controller";
3638 my $devices_list = vm_devices_list($vmid);
3640 if(!defined($devices_list->{$scsihwid})) {
3641 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3647 sub qemu_deletescsihw {
3648 my ($conf, $vmid, $opt) = @_;
3650 my $device = parse_drive($opt, $conf->{$opt});
3652 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3653 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3657 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3659 my $devices_list = vm_devices_list($vmid);
3660 foreach my $opt (keys %{$devices_list}) {
3661 if (PVE::QemuServer::is_valid_drivename($opt)) {
3662 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3663 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3669 my $scsihwid="scsihw
$controller";
3671 vm_deviceunplug($vmid, $conf, $scsihwid);
3676 sub qemu_add_pci_bridge {
3677 my ($storecfg, $conf, $vmid, $device) = @_;
3683 print_pci_addr($device, $bridges);
3685 while (my ($k, $v) = each %$bridges) {
3688 return 1 if !defined($bridgeid) || $bridgeid < 1;
3690 my $bridge = "pci
.$bridgeid";
3691 my $devices_list = vm_devices_list($vmid);
3693 if (!defined($devices_list->{$bridge})) {
3694 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3700 sub qemu_set_link_status {
3701 my ($vmid, $device, $up) = @_;
3703 vm_mon_cmd($vmid, "set_link
", name => $device,
3704 up => $up ? JSON::true : JSON::false);
3707 sub qemu_netdevadd {
3708 my ($vmid, $conf, $device, $deviceid) = @_;
3710 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3711 my %options = split(/[=,]/, $netdev);
3713 vm_mon_cmd($vmid, "netdev_add
", %options);
3717 sub qemu_netdevdel {
3718 my ($vmid, $deviceid) = @_;
3720 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3723 sub qemu_usb_hotplug {
3724 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3728 # remove the old one first
3729 vm_deviceunplug($vmid, $conf, $deviceid);
3731 # check if xhci controller is necessary and available
3732 if ($device->{usb3}) {
3734 my $devicelist = vm_devices_list($vmid);
3736 if (!$devicelist->{xhci}) {
3737 my $pciaddr = print_pci_addr("xhci
");
3738 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3741 my $d = parse_usb_device($device->{host});
3742 $d->{usb3} = $device->{usb3};
3745 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3748 sub qemu_cpu_hotplug {
3749 my ($vmid, $conf, $vcpus) = @_;
3751 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3754 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3755 $sockets = $conf->{sockets} if $conf->{sockets};
3756 my $cores = $conf->{cores} || 1;
3757 my $maxcpus = $sockets * $cores;
3759 $vcpus = $maxcpus if !$vcpus;
3761 die "you can
't add more vcpus than maxcpus\n"
3762 if $vcpus > $maxcpus;
3764 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3766 if ($vcpus < $currentvcpus) {
3768 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3770 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3771 qemu_devicedel($vmid, "cpu$i");
3773 my $currentrunningvcpus = undef;
3775 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3776 last if scalar(@{$currentrunningvcpus}) == $i-1;
3777 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3781 #update conf after each succesfull cpu unplug
3782 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3783 PVE::QemuConfig->write_config($vmid, $conf);
3786 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3792 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3793 die "vcpus in running vm does not match its configuration\n"
3794 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3796 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3798 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3799 my $cpustr = print_cpu_device($conf, $i);
3800 qemu_deviceadd($vmid, $cpustr);
3803 my $currentrunningvcpus = undef;
3805 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3806 last if scalar(@{$currentrunningvcpus}) == $i;
3807 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3811 #update conf after each succesfull cpu hotplug
3812 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3813 PVE::QemuConfig->write_config($vmid, $conf);
3817 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3818 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3823 sub qemu_block_set_io_throttle {
3824 my ($vmid, $deviceid,
3825 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3826 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3827 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3828 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3830 return if !check_running($vmid) ;
3832 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3834 bps_rd => int($bps_rd),
3835 bps_wr => int($bps_wr),
3837 iops_rd => int($iops_rd),
3838 iops_wr => int($iops_wr),
3839 bps_max => int($bps_max),
3840 bps_rd_max => int($bps_rd_max),
3841 bps_wr_max => int($bps_wr_max),
3842 iops_max => int($iops_max),
3843 iops_rd_max => int($iops_rd_max),
3844 iops_wr_max => int($iops_wr_max),
3845 bps_max_length => int($bps_max_length),
3846 bps_rd_max_length => int($bps_rd_max_length),
3847 bps_wr_max_length => int($bps_wr_max_length),
3848 iops_max_length => int($iops_max_length),
3849 iops_rd_max_length => int($iops_rd_max_length),
3850 iops_wr_max_length => int($iops_wr_max_length),
3855 # old code, only used to shutdown old VM after update
3857 my ($fh, $timeout) = @_;
3859 my $sel = new IO::Select;
3866 while (scalar (@ready = $sel->can_read($timeout))) {
3868 if ($count = $fh->sysread($buf, 8192)) {
3869 if ($buf =~ /^(.*)\(qemu\) $/s) {
3876 if (!defined($count)) {
3883 die "monitor read timeout\n" if !scalar(@ready);
3888 # old code, only used to shutdown old VM after update
3889 sub vm_monitor_command {
3890 my ($vmid, $cmdstr, $nocheck) = @_;
3895 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3897 my $sname = "${var_run_tmpdir}/$vmid.mon";
3899 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3900 die "unable to connect to VM $vmid socket - $!\n";
3904 # hack: migrate sometime blocks the monitor (when migrate_downtime
3906 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3907 $timeout = 60*60; # 1 hour
3911 my $data = __read_avail($sock, $timeout);
3913 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3914 die "got unexpected qemu monitor banner\n";
3917 my $sel = new IO::Select;
3920 if (!scalar(my @ready = $sel->can_write($timeout))) {
3921 die "monitor write error - timeout";
3924 my $fullcmd = "$cmdstr\r";
3926 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3929 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3930 die "monitor write error - $!";
3933 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3937 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3938 $timeout = 60*60; # 1 hour
3939 } elsif ($cmdstr =~ m/^(eject|change)/) {
3940 $timeout = 60; # note: cdrom mount command is slow
3942 if ($res = __read_avail($sock, $timeout)) {
3944 my @lines = split("\r?\n", $res);
3946 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3948 $res = join("\n", @lines);
3956 syslog("err", "VM $vmid monitor command failed - $err");
3963 sub qemu_block_resize {
3964 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3966 my $running = check_running($vmid);
3968 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3970 return if !$running;
3972 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3976 sub qemu_volume_snapshot {
3977 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3979 my $running = check_running($vmid);
3981 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3982 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3984 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3988 sub qemu_volume_snapshot_delete {
3989 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3991 my $running = check_running($vmid);
3993 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3995 return if !$running;
3997 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4000 sub set_migration_caps {
4006 "auto-converge" => 1,
4008 "x-rdma-pin-all" => 0,
4013 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4015 for my $supported_capability (@$supported_capabilities) {
4017 capability => $supported_capability->{capability},
4018 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4022 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4025 my $fast_plug_option = {
4035 # hotplug changes in [PENDING]
4036 # $selection hash can be used to only apply specified options, for
4037 # example: { cores => 1 } (only apply changed 'cores
')
4038 # $errors ref is used to return error messages
4039 sub vmconfig_hotplug_pending {
4040 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4042 my $defaults = load_defaults();
4044 # commit values which do not have any impact on running VM first
4045 # Note: those option cannot raise errors, we we do not care about
4046 # $selection and always apply them.
4048 my $add_error = sub {
4049 my ($opt, $msg) = @_;
4050 $errors->{$opt} = "hotplug problem - $msg";
4054 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4055 if ($fast_plug_option->{$opt}) {
4056 $conf->{$opt} = $conf->{pending}->{$opt};
4057 delete $conf->{pending}->{$opt};
4063 PVE::QemuConfig->write_config($vmid, $conf);
4064 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4067 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4069 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4070 while (my ($opt, $force) = each %$pending_delete_hash) {
4071 next if $selection && !$selection->{$opt};
4073 if ($opt eq 'hotplug
') {
4074 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4075 } elsif ($opt eq 'tablet
') {
4076 die "skip\n" if !$hotplug_features->{usb};
4077 if ($defaults->{tablet}) {
4078 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4080 vm_deviceunplug($vmid, $conf, $opt);
4082 } elsif ($opt =~ m/^usb\d+/) {
4084 # since we cannot reliably hot unplug usb devices
4085 # we are disabling it
4086 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4087 vm_deviceunplug($vmid, $conf, $opt);
4088 } elsif ($opt eq 'vcpus
') {
4089 die "skip\n" if !$hotplug_features->{cpu};
4090 qemu_cpu_hotplug($vmid, $conf, undef);
4091 } elsif ($opt eq 'balloon
') {
4092 # enable balloon device is not hotpluggable
4093 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4094 } elsif ($fast_plug_option->{$opt}) {
4096 } elsif ($opt =~ m/^net(\d+)$/) {
4097 die "skip\n" if !$hotplug_features->{network};
4098 vm_deviceunplug($vmid, $conf, $opt);
4099 } elsif (is_valid_drivename($opt)) {
4100 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4101 vm_deviceunplug($vmid, $conf, $opt);
4102 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4103 } elsif ($opt =~ m/^memory$/) {
4104 die "skip\n" if !$hotplug_features->{memory};
4105 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4106 } elsif ($opt eq 'cpuunits
') {
4107 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4108 } elsif ($opt eq 'cpulimit
') {
4109 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4115 &$add_error($opt, $err) if $err ne "skip\n";
4117 # save new config if hotplug was successful
4118 delete $conf->{$opt};
4119 vmconfig_undelete_pending_option($conf, $opt);
4120 PVE::QemuConfig->write_config($vmid, $conf);
4121 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4125 foreach my $opt (keys %{$conf->{pending}}) {
4126 next if $selection && !$selection->{$opt};
4127 my $value = $conf->{pending}->{$opt};
4129 if ($opt eq 'hotplug
') {
4130 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4131 } elsif ($opt eq 'tablet
') {
4132 die "skip\n" if !$hotplug_features->{usb};
4134 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4135 } elsif ($value == 0) {
4136 vm_deviceunplug($vmid, $conf, $opt);
4138 } elsif ($opt =~ m/^usb\d+$/) {
4140 # since we cannot reliably hot unplug usb devices
4141 # we are disabling it
4142 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4143 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4144 die "skip\n" if !$d;
4145 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4146 } elsif ($opt eq 'vcpus
') {
4147 die "skip\n" if !$hotplug_features->{cpu};
4148 qemu_cpu_hotplug($vmid, $conf, $value);
4149 } elsif ($opt eq 'balloon
') {
4150 # enable/disable balloning device is not hotpluggable
4151 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4152 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4153 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4155 # allow manual ballooning if shares is set to zero
4156 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4157 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4158 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4160 } elsif ($opt =~ m/^net(\d+)$/) {
4161 # some changes can be done without hotplug
4162 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4163 $vmid, $opt, $value);
4164 } elsif (is_valid_drivename($opt)) {
4165 # some changes can be done without hotplug
4166 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4167 $vmid, $opt, $value, 1);
4168 } elsif ($opt =~ m/^memory$/) { #dimms
4169 die "skip\n" if !$hotplug_features->{memory};
4170 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4171 } elsif ($opt eq 'cpuunits
') {
4172 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4173 } elsif ($opt eq 'cpulimit
') {
4174 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4175 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4177 die "skip\n"; # skip non-hot-pluggable options
4181 &$add_error($opt, $err) if $err ne "skip\n";
4183 # save new config if hotplug was successful
4184 $conf->{$opt} = $value;
4185 delete $conf->{pending}->{$opt};
4186 PVE::QemuConfig->write_config($vmid, $conf);
4187 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4192 sub try_deallocate_drive {
4193 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4195 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4196 my $volid = $drive->{file};
4197 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4198 my $sid = PVE::Storage::parse_volume_id($volid);
4199 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4201 # check if the disk is really unused
4202 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4203 if is_volume_in_use($storecfg, $conf, $key, $volid);
4204 PVE::Storage::vdisk_free($storecfg, $volid);
4207 # If vm is not owner of this disk remove from config
4215 sub vmconfig_delete_or_detach_drive {
4216 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4218 my $drive = parse_drive($opt, $conf->{$opt});
4220 my $rpcenv = PVE::RPCEnvironment::get();
4221 my $authuser = $rpcenv->get_user();
4224 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4225 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4227 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4231 sub vmconfig_apply_pending {
4232 my ($vmid, $conf, $storecfg) = @_;
4236 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4237 while (my ($opt, $force) = each %$pending_delete_hash) {
4238 die "internal error" if $opt =~ m/^unused/;
4239 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4240 if (!defined($conf->{$opt})) {
4241 vmconfig_undelete_pending_option($conf, $opt);
4242 PVE::QemuConfig->write_config($vmid, $conf);
4243 } elsif (is_valid_drivename($opt)) {
4244 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4245 vmconfig_undelete_pending_option($conf, $opt);
4246 delete $conf->{$opt};
4247 PVE::QemuConfig->write_config($vmid, $conf);
4249 vmconfig_undelete_pending_option($conf, $opt);
4250 delete $conf->{$opt};
4251 PVE::QemuConfig->write_config($vmid, $conf);
4255 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4257 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4258 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4260 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4261 # skip if nothing changed
4262 } elsif (is_valid_drivename($opt)) {
4263 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4264 if defined($conf->{$opt});
4265 $conf->{$opt} = $conf->{pending}->{$opt};
4267 $conf->{$opt} = $conf->{pending}->{$opt};
4270 delete $conf->{pending}->{$opt};
4271 PVE::QemuConfig->write_config($vmid, $conf);
4275 my $safe_num_ne = sub {
4278 return 0 if !defined($a) && !defined($b);
4279 return 1 if !defined($a);
4280 return 1 if !defined($b);
4285 my $safe_string_ne = sub {
4288 return 0 if !defined($a) && !defined($b);
4289 return 1 if !defined($a);
4290 return 1 if !defined($b);
4295 sub vmconfig_update_net {
4296 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4298 my $newnet = parse_net($value);
4300 if ($conf->{$opt}) {
4301 my $oldnet = parse_net($conf->{$opt});
4303 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4304 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4305 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4306 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4308 # for non online change, we try to hot-unplug
4309 die "skip\n" if !$hotplug;
4310 vm_deviceunplug($vmid, $conf, $opt);
4313 die "internal error" if $opt !~ m/net(\d+)/;
4314 my $iface = "tap${vmid}i$1";
4316 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4317 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4318 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4319 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4320 PVE::Network::tap_unplug($iface);
4321 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4322 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4323 # Rate can be applied on its own but any change above needs to
4324 # include the rate in tap_plug since OVS resets everything.
4325 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4328 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4329 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4337 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4343 sub vmconfig_update_disk {
4344 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4346 # fixme: do we need force?
4348 my $drive = parse_drive($opt, $value);
4350 if ($conf->{$opt}) {
4352 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4354 my $media = $drive->{media} || 'disk
';
4355 my $oldmedia = $old_drive->{media} || 'disk
';
4356 die "unable to change media type\n" if $media ne $oldmedia;
4358 if (!drive_is_cdrom($old_drive)) {
4360 if ($drive->{file} ne $old_drive->{file}) {
4362 die "skip\n" if !$hotplug;
4364 # unplug and register as unused
4365 vm_deviceunplug($vmid, $conf, $opt);
4366 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4369 # update existing disk
4371 # skip non hotpluggable value
4372 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4373 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4374 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4375 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4380 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4381 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4382 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4383 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4384 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4385 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4386 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4387 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4388 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4389 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4390 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4391 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4392 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4393 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4394 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4395 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4396 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4397 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4399 qemu_block_set_io_throttle($vmid,"drive-$opt",
4400 ($drive->{mbps} || 0)*1024*1024,
4401 ($drive->{mbps_rd} || 0)*1024*1024,
4402 ($drive->{mbps_wr} || 0)*1024*1024,
4403 $drive->{iops} || 0,
4404 $drive->{iops_rd} || 0,
4405 $drive->{iops_wr} || 0,
4406 ($drive->{mbps_max} || 0)*1024*1024,
4407 ($drive->{mbps_rd_max} || 0)*1024*1024,
4408 ($drive->{mbps_wr_max} || 0)*1024*1024,
4409 $drive->{iops_max} || 0,
4410 $drive->{iops_rd_max} || 0,
4411 $drive->{iops_wr_max} || 0,
4412 $drive->{bps_max_length} || 1,
4413 $drive->{bps_rd_max_length} || 1,
4414 $drive->{bps_wr_max_length} || 1,
4415 $drive->{iops_max_length} || 1,
4416 $drive->{iops_rd_max_length} || 1,
4417 $drive->{iops_wr_max_length} || 1);
4426 if ($drive->{file} eq 'none
') {
4427 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4429 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4430 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4431 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4439 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4441 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4442 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4446 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4447 $forcemachine, $spice_ticket, $migration_network, $migration_type) = @_;
4449 PVE::QemuConfig->lock_config($vmid, sub {
4450 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4452 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4454 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4456 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4458 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4459 vmconfig_apply_pending($vmid, $conf, $storecfg);
4460 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4463 my $defaults = load_defaults();
4465 # set environment variable useful inside network script
4466 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4468 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4470 my $migrate_port = 0;
4473 if ($statefile eq 'tcp
') {
4474 my $localip = "localhost";
4475 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4476 my $nodename = PVE::INotify::nodename();
4478 if ($migration_type eq 'insecure
') {
4479 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4480 if ($migrate_network_addr) {
4481 $localip = $migrate_network_addr;
4483 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4486 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4489 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4490 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4491 $migrate_uri = "tcp:${localip}:${migrate_port}";
4492 push @$cmd, '-incoming
', $migrate_uri;
4495 } elsif ($statefile eq 'unix
') {
4496 # should be default for secure migrations as a ssh TCP forward
4497 # tunnel is not deterministic reliable ready and fails regurarly
4498 # to set up in time, so use UNIX socket forwards
4499 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4500 unlink $socket_addr;
4502 $migrate_uri = "unix:$socket_addr";
4504 push @$cmd, '-incoming
', $migrate_uri;
4508 push @$cmd, '-loadstate
', $statefile;
4515 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4516 my $d = parse_hostpci($conf->{"hostpci$i"});
4518 my $pcidevices = $d->{pciid};
4519 foreach my $pcidevice (@$pcidevices) {
4520 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4522 my $info = pci_device_info("0000:$pciid");
4523 die "IOMMU not present\n" if !check_iommu_support();
4524 die "no pci device info for device '$pciid'\n" if !$info;
4525 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4526 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4530 PVE::Storage::activate_volumes($storecfg, $vollist);
4532 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4534 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4535 eval { run_command($cmd); };
4538 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4539 : $defaults->{cpuunits};
4541 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4544 Slice => 'qemu
.slice
',
4546 CPUShares => $cpuunits
4549 if (my $cpulimit = $conf->{cpulimit}) {
4550 $properties{CPUQuota} = int($cpulimit * 100);
4552 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4554 if ($conf->{hugepages}) {
4557 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4558 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4560 PVE::QemuServer::Memory::hugepages_mount();
4561 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4564 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4565 run_command($cmd, %run_params);
4569 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4573 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4575 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4579 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4580 run_command($cmd, %run_params);
4585 # deactivate volumes if start fails
4586 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4587 die "start failed: $err";
4590 print "migration listens on $migrate_uri\n" if $migrate_uri;
4592 if ($statefile && $statefile ne 'tcp
') {
4593 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4597 if ($migratedfrom) {
4600 set_migration_caps($vmid);
4605 print "spice listens on port $spice_port\n";
4606 if ($spice_ticket) {
4607 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4608 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4614 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4615 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4616 if $conf->{balloon};
4619 foreach my $opt (keys %$conf) {
4620 next if $opt !~ m/^net\d+$/;
4621 my $nicconf = parse_net($conf->{$opt});
4622 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4626 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4627 path => "machine/peripheral/balloon0",
4628 property => "guest-stats-polling-interval",
4629 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4635 my ($vmid, $execute, %params) = @_;
4637 my $cmd = { execute => $execute, arguments => \%params };
4638 vm_qmp_command($vmid, $cmd);
4641 sub vm_mon_cmd_nocheck {
4642 my ($vmid, $execute, %params) = @_;
4644 my $cmd = { execute => $execute, arguments => \%params };
4645 vm_qmp_command($vmid, $cmd, 1);
4648 sub vm_qmp_command {
4649 my ($vmid, $cmd, $nocheck) = @_;
4654 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4655 $timeout = $cmd->{arguments}->{timeout};
4656 delete $cmd->{arguments}->{timeout};
4660 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4661 my $sname = qmp_socket($vmid);
4662 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4663 my $qmpclient = PVE::QMPClient->new();
4665 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4666 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4667 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4668 if scalar(%{$cmd->{arguments}});
4669 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4671 die "unable to
open monitor
socket\n";
4675 syslog("err
", "VM
$vmid qmp command failed
- $err");
4682 sub vm_human_monitor_command {
4683 my ($vmid, $cmdline) = @_;
4688 execute => 'human-monitor-command',
4689 arguments => { 'command-line' => $cmdline},
4692 return vm_qmp_command($vmid, $cmd);
4695 sub vm_commandline {
4696 my ($storecfg, $vmid) = @_;
4698 my $conf = PVE::QemuConfig->load_config($vmid);
4700 my $defaults = load_defaults();
4702 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4704 return PVE::Tools::cmd2string($cmd);
4708 my ($vmid, $skiplock) = @_;
4710 PVE::QemuConfig->lock_config($vmid, sub {
4712 my $conf = PVE::QemuConfig->load_config($vmid);
4714 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4716 vm_mon_cmd($vmid, "system_reset
");
4720 sub get_vm_volumes {
4724 foreach_volid($conf, sub {
4725 my ($volid, $is_cdrom) = @_;
4727 return if $volid =~ m|^/|;
4729 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4732 push @$vollist, $volid;
4738 sub vm_stop_cleanup {
4739 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4744 my $vollist = get_vm_volumes($conf);
4745 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4748 foreach my $ext (qw(mon qmp pid vnc qga)) {
4749 unlink "/var/run/qemu-server/${vmid}.$ext";
4752 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4754 warn $@ if $@; # avoid errors - just warn
4757 # Note: use $nockeck to skip tests if VM configuration file exists.
4758 # We need that when migration VMs to other nodes (files already moved)
4759 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4761 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4763 $force = 1 if !defined($force) && !$shutdown;
4766 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4767 kill 15, $pid if $pid;
4768 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4769 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4773 PVE
::QemuConfig-
>lock_config($vmid, sub {
4775 my $pid = check_running
($vmid, $nocheck);
4780 $conf = PVE
::QemuConfig-
>load_config($vmid);
4781 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4782 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4783 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4784 $timeout = $opts->{down
} if $opts->{down
};
4788 $timeout = 60 if !defined($timeout);
4792 if (defined($conf) && $conf->{agent
}) {
4793 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4795 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4798 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4805 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4810 if ($count >= $timeout) {
4812 warn "VM still running - terminating now with SIGTERM\n";
4815 die "VM quit/powerdown failed - got timeout\n";
4818 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4823 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4826 die "VM quit/powerdown failed\n";
4834 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4839 if ($count >= $timeout) {
4840 warn "VM still running - terminating now with SIGKILL\n";
4845 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4850 my ($vmid, $skiplock) = @_;
4852 PVE
::QemuConfig-
>lock_config($vmid, sub {
4854 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4856 PVE
::QemuConfig-
>check_lock($conf)
4857 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4859 vm_mon_cmd
($vmid, "stop");
4864 my ($vmid, $skiplock, $nocheck) = @_;
4866 PVE
::QemuConfig-
>lock_config($vmid, sub {
4870 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4872 PVE
::QemuConfig-
>check_lock($conf)
4873 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4875 vm_mon_cmd
($vmid, "cont");
4878 vm_mon_cmd_nocheck
($vmid, "cont");
4884 my ($vmid, $skiplock, $key) = @_;
4886 PVE
::QemuConfig-
>lock_config($vmid, sub {
4888 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4890 # there is no qmp command, so we use the human monitor command
4891 vm_human_monitor_command
($vmid, "sendkey $key");
4896 my ($storecfg, $vmid, $skiplock) = @_;
4898 PVE
::QemuConfig-
>lock_config($vmid, sub {
4900 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4902 if (!check_running
($vmid)) {
4903 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4905 die "VM $vmid is running - destroy failed\n";
4913 my ($filename, $buf) = @_;
4915 my $fh = IO
::File-
>new($filename, "w");
4916 return undef if !$fh;
4918 my $res = print $fh $buf;
4925 sub pci_device_info
{
4930 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4931 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4933 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4934 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4936 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4937 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4939 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4940 return undef if !defined($product) || $product !~ s/^0x//;
4945 product
=> $product,
4951 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4960 my $name = $dev->{name
};
4962 my $fn = "$pcisysfs/devices/$name/reset";
4964 return file_write
($fn, "1");
4967 sub pci_dev_bind_to_vfio
{
4970 my $name = $dev->{name
};
4972 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4974 if (!-d
$vfio_basedir) {
4975 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4977 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4979 my $testdir = "$vfio_basedir/$name";
4980 return 1 if -d
$testdir;
4982 my $data = "$dev->{vendor} $dev->{product}";
4983 return undef if !file_write
("$vfio_basedir/new_id", $data);
4985 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4986 if (!file_write
($fn, $name)) {
4987 return undef if -f
$fn;
4990 $fn = "$vfio_basedir/bind";
4991 if (! -d
$testdir) {
4992 return undef if !file_write
($fn, $name);
4998 sub pci_dev_group_bind_to_vfio
{
5001 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5003 if (!-d
$vfio_basedir) {
5004 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5006 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5008 # get IOMMU group devices
5009 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5010 my @devs = grep /^0000:/, readdir($D);
5013 foreach my $pciid (@devs) {
5014 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5016 # pci bridges, switches or root ports are not supported
5017 # they have a pci_bus subdirectory so skip them
5018 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5020 my $info = pci_device_info
($1);
5021 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5027 # vzdump restore implementaion
5029 sub tar_archive_read_firstfile
{
5030 my $archive = shift;
5032 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5034 # try to detect archive type first
5035 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5036 die "unable to open file '$archive'\n";
5037 my $firstfile = <$fh>;
5041 die "ERROR: archive contaions no data\n" if !$firstfile;
5047 sub tar_restore_cleanup
{
5048 my ($storecfg, $statfile) = @_;
5050 print STDERR
"starting cleanup\n";
5052 if (my $fd = IO
::File-
>new($statfile, "r")) {
5053 while (defined(my $line = <$fd>)) {
5054 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5057 if ($volid =~ m
|^/|) {
5058 unlink $volid || die 'unlink failed\n';
5060 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5062 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5064 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5066 print STDERR
"unable to parse line in statfile - $line";
5073 sub restore_archive
{
5074 my ($archive, $vmid, $user, $opts) = @_;
5076 my $format = $opts->{format
};
5079 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5080 $format = 'tar' if !$format;
5082 } elsif ($archive =~ m/\.tar$/) {
5083 $format = 'tar' if !$format;
5084 } elsif ($archive =~ m/.tar.lzo$/) {
5085 $format = 'tar' if !$format;
5087 } elsif ($archive =~ m/\.vma$/) {
5088 $format = 'vma' if !$format;
5089 } elsif ($archive =~ m/\.vma\.gz$/) {
5090 $format = 'vma' if !$format;
5092 } elsif ($archive =~ m/\.vma\.lzo$/) {
5093 $format = 'vma' if !$format;
5096 $format = 'vma' if !$format; # default
5099 # try to detect archive format
5100 if ($format eq 'tar') {
5101 return restore_tar_archive
($archive, $vmid, $user, $opts);
5103 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5107 sub restore_update_config_line
{
5108 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5110 return if $line =~ m/^\#qmdump\#/;
5111 return if $line =~ m/^\#vzdump\#/;
5112 return if $line =~ m/^lock:/;
5113 return if $line =~ m/^unused\d+:/;
5114 return if $line =~ m/^parent:/;
5115 return if $line =~ m/^template:/; # restored VM is never a template
5117 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5118 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5119 # try to convert old 1.X settings
5120 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5121 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5122 my ($model, $macaddr) = split(/\=/, $devconfig);
5123 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5126 bridge
=> "vmbr$ind",
5127 macaddr
=> $macaddr,
5129 my $netstr = print_net
($net);
5131 print $outfd "net$cookie->{netcount}: $netstr\n";
5132 $cookie->{netcount
}++;
5134 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5135 my ($id, $netstr) = ($1, $2);
5136 my $net = parse_net
($netstr);
5137 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5138 $netstr = print_net
($net);
5139 print $outfd "$id: $netstr\n";
5140 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5143 my $di = parse_drive
($virtdev, $value);
5144 if (defined($di->{backup
}) && !$di->{backup
}) {
5145 print $outfd "#$line";
5146 } elsif ($map->{$virtdev}) {
5147 delete $di->{format
}; # format can change on restore
5148 $di->{file
} = $map->{$virtdev};
5149 $value = print_drive
($vmid, $di);
5150 print $outfd "$virtdev: $value\n";
5160 my ($cfg, $vmid) = @_;
5162 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5164 my $volid_hash = {};
5165 foreach my $storeid (keys %$info) {
5166 foreach my $item (@{$info->{$storeid}}) {
5167 next if !($item->{volid
} && $item->{size
});
5168 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5169 $volid_hash->{$item->{volid
}} = $item;
5176 sub is_volume_in_use
{
5177 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5179 my $path = PVE
::Storage
::path
($storecfg, $volid);
5181 my $scan_config = sub {
5182 my ($cref, $snapname) = @_;
5184 foreach my $key (keys %$cref) {
5185 my $value = $cref->{$key};
5186 if (is_valid_drivename
($key)) {
5187 next if $skip_drive && $key eq $skip_drive;
5188 my $drive = parse_drive
($key, $value);
5189 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5190 return 1 if $volid eq $drive->{file
};
5191 if ($drive->{file
} =~ m!^/!) {
5192 return 1 if $drive->{file
} eq $path;
5194 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5196 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5198 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5206 return 1 if &$scan_config($conf);
5210 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5211 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5217 sub update_disksize
{
5218 my ($vmid, $conf, $volid_hash) = @_;
5224 # Note: it is allowed to define multiple storages with same path (alias), so
5225 # we need to check both 'volid' and real 'path' (two different volid can point
5226 # to the same path).
5231 foreach my $opt (keys %$conf) {
5232 if (is_valid_drivename
($opt)) {
5233 my $drive = parse_drive
($opt, $conf->{$opt});
5234 my $volid = $drive->{file
};
5237 $used->{$volid} = 1;
5238 if ($volid_hash->{$volid} &&
5239 (my $path = $volid_hash->{$volid}->{path
})) {
5240 $usedpath->{$path} = 1;
5243 next if drive_is_cdrom
($drive);
5244 next if !$volid_hash->{$volid};
5246 $drive->{size
} = $volid_hash->{$volid}->{size
};
5247 my $new = print_drive
($vmid, $drive);
5248 if ($new ne $conf->{$opt}) {
5250 $conf->{$opt} = $new;
5255 # remove 'unusedX' entry if volume is used
5256 foreach my $opt (keys %$conf) {
5257 next if $opt !~ m/^unused\d+$/;
5258 my $volid = $conf->{$opt};
5259 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5260 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5262 delete $conf->{$opt};
5266 foreach my $volid (sort keys %$volid_hash) {
5267 next if $volid =~ m/vm-$vmid-state-/;
5268 next if $used->{$volid};
5269 my $path = $volid_hash->{$volid}->{path
};
5270 next if !$path; # just to be sure
5271 next if $usedpath->{$path};
5273 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5274 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5281 my ($vmid, $nolock) = @_;
5283 my $cfg = PVE
::Storage
::config
();
5285 my $volid_hash = scan_volids
($cfg, $vmid);
5287 my $updatefn = sub {
5290 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5292 PVE
::QemuConfig-
>check_lock($conf);
5295 foreach my $volid (keys %$volid_hash) {
5296 my $info = $volid_hash->{$volid};
5297 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5300 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5302 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5305 if (defined($vmid)) {
5309 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5312 my $vmlist = config_list
();
5313 foreach my $vmid (keys %$vmlist) {
5317 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5323 sub restore_vma_archive
{
5324 my ($archive, $vmid, $user, $opts, $comp) = @_;
5326 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5327 my $readfrom = $archive;
5332 my $qarchive = PVE
::Tools
::shellquote
($archive);
5333 if ($comp eq 'gzip') {
5334 $uncomp = "zcat $qarchive|";
5335 } elsif ($comp eq 'lzop') {
5336 $uncomp = "lzop -d -c $qarchive|";
5338 die "unknown compression method '$comp'\n";
5343 my $tmpdir = "/var/tmp/vzdumptmp$$";
5346 # disable interrupts (always do cleanups)
5347 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5348 warn "got interrupt - ignored\n";
5351 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5352 POSIX
::mkfifo
($mapfifo, 0600);
5355 my $openfifo = sub {
5356 open($fifofh, '>', $mapfifo) || die $!;
5359 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5366 my $rpcenv = PVE
::RPCEnvironment
::get
();
5368 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5369 my $tmpfn = "$conffile.$$.tmp";
5371 # Note: $oldconf is undef if VM does not exists
5372 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5373 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5375 my $print_devmap = sub {
5376 my $virtdev_hash = {};
5378 my $cfgfn = "$tmpdir/qemu-server.conf";
5380 # we can read the config - that is already extracted
5381 my $fh = IO
::File-
>new($cfgfn, "r") ||
5382 "unable to read qemu-server.conf - $!\n";
5384 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5386 my $pve_firewall_dir = '/etc/pve/firewall';
5387 mkdir $pve_firewall_dir; # make sure the dir exists
5388 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5391 while (defined(my $line = <$fh>)) {
5392 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5393 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5394 die "archive does not contain data for drive '$virtdev'\n"
5395 if !$devinfo->{$devname};
5396 if (defined($opts->{storage
})) {
5397 $storeid = $opts->{storage
} || 'local';
5398 } elsif (!$storeid) {
5401 $format = 'raw' if !$format;
5402 $devinfo->{$devname}->{devname
} = $devname;
5403 $devinfo->{$devname}->{virtdev
} = $virtdev;
5404 $devinfo->{$devname}->{format
} = $format;
5405 $devinfo->{$devname}->{storeid
} = $storeid;
5407 # check permission on storage
5408 my $pool = $opts->{pool
}; # todo: do we need that?
5409 if ($user ne 'root@pam') {
5410 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5413 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5417 foreach my $devname (keys %$devinfo) {
5418 die "found no device mapping information for device '$devname'\n"
5419 if !$devinfo->{$devname}->{virtdev
};
5422 my $cfg = PVE
::Storage
::config
();
5424 # create empty/temp config
5426 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5427 foreach_drive
($oldconf, sub {
5428 my ($ds, $drive) = @_;
5430 return if drive_is_cdrom
($drive);
5432 my $volid = $drive->{file
};
5434 return if !$volid || $volid =~ m
|^/|;
5436 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5437 return if !$path || !$owner || ($owner != $vmid);
5439 # Note: only delete disk we want to restore
5440 # other volumes will become unused
5441 if ($virtdev_hash->{$ds}) {
5442 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5449 # delete vmstate files
5450 # since after the restore we have no snapshots anymore
5451 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5452 my $snap = $oldconf->{snapshots
}->{$snapname};
5453 if ($snap->{vmstate
}) {
5454 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5463 foreach my $virtdev (sort keys %$virtdev_hash) {
5464 my $d = $virtdev_hash->{$virtdev};
5465 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5466 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5468 # test if requested format is supported
5469 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5470 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5471 $d->{format
} = $defFormat if !$supported;
5473 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5474 $d->{format
}, undef, $alloc_size);
5475 print STDERR
"new volume ID is '$volid'\n";
5476 $d->{volid
} = $volid;
5477 my $path = PVE
::Storage
::path
($cfg, $volid);
5479 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5481 my $write_zeros = 1;
5482 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5486 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5488 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5489 $map->{$virtdev} = $volid;
5492 $fh->seek(0, 0) || die "seek failed - $!\n";
5494 my $outfd = new IO
::File
($tmpfn, "w") ||
5495 die "unable to write config for VM $vmid\n";
5497 my $cookie = { netcount
=> 0 };
5498 while (defined(my $line = <$fh>)) {
5499 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5508 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5509 die "interrupted by signal\n";
5511 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5513 $oldtimeout = alarm($timeout);
5520 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5521 my ($dev_id, $size, $devname) = ($1, $2, $3);
5522 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5523 } elsif ($line =~ m/^CTIME: /) {
5524 # we correctly received the vma config, so we can disable
5525 # the timeout now for disk allocation (set to 10 minutes, so
5526 # that we always timeout if something goes wrong)
5529 print $fifofh "done\n";
5530 my $tmp = $oldtimeout || 0;
5531 $oldtimeout = undef;
5537 print "restore vma archive: $cmd\n";
5538 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5542 alarm($oldtimeout) if $oldtimeout;
5545 foreach my $devname (keys %$devinfo) {
5546 my $volid = $devinfo->{$devname}->{volid
};
5547 push @$vollist, $volid if $volid;
5550 my $cfg = PVE
::Storage
::config
();
5551 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5559 foreach my $devname (keys %$devinfo) {
5560 my $volid = $devinfo->{$devname}->{volid
};
5563 if ($volid =~ m
|^/|) {
5564 unlink $volid || die 'unlink failed\n';
5566 PVE
::Storage
::vdisk_free
($cfg, $volid);
5568 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5570 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5577 rename($tmpfn, $conffile) ||
5578 die "unable to commit configuration file '$conffile'\n";
5580 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5582 eval { rescan
($vmid, 1); };
5586 sub restore_tar_archive
{
5587 my ($archive, $vmid, $user, $opts) = @_;
5589 if ($archive ne '-') {
5590 my $firstfile = tar_archive_read_firstfile
($archive);
5591 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5592 if $firstfile ne 'qemu-server.conf';
5595 my $storecfg = PVE
::Storage
::config
();
5597 # destroy existing data - keep empty config
5598 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5599 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5601 my $tocmd = "/usr/lib/qemu-server/qmextract";
5603 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5604 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5605 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5606 $tocmd .= ' --info' if $opts->{info
};
5608 # tar option "xf" does not autodetect compression when read from STDIN,
5609 # so we pipe to zcat
5610 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5611 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5613 my $tmpdir = "/var/tmp/vzdumptmp$$";
5616 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5617 local $ENV{VZDUMP_VMID
} = $vmid;
5618 local $ENV{VZDUMP_USER
} = $user;
5620 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5621 my $tmpfn = "$conffile.$$.tmp";
5623 # disable interrupts (always do cleanups)
5624 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5625 print STDERR
"got interrupt - ignored\n";
5630 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5631 die "interrupted by signal\n";
5634 if ($archive eq '-') {
5635 print "extracting archive from STDIN\n";
5636 run_command
($cmd, input
=> "<&STDIN");
5638 print "extracting archive '$archive'\n";
5642 return if $opts->{info
};
5646 my $statfile = "$tmpdir/qmrestore.stat";
5647 if (my $fd = IO
::File-
>new($statfile, "r")) {
5648 while (defined (my $line = <$fd>)) {
5649 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5650 $map->{$1} = $2 if $1;
5652 print STDERR
"unable to parse line in statfile - $line\n";
5658 my $confsrc = "$tmpdir/qemu-server.conf";
5660 my $srcfd = new IO
::File
($confsrc, "r") ||
5661 die "unable to open file '$confsrc'\n";
5663 my $outfd = new IO
::File
($tmpfn, "w") ||
5664 die "unable to write config for VM $vmid\n";
5666 my $cookie = { netcount
=> 0 };
5667 while (defined (my $line = <$srcfd>)) {
5668 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5680 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5687 rename $tmpfn, $conffile ||
5688 die "unable to commit configuration file '$conffile'\n";
5690 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5692 eval { rescan
($vmid, 1); };
5696 sub foreach_writable_storage
{
5697 my ($conf, $func) = @_;
5701 foreach my $ds (keys %$conf) {
5702 next if !is_valid_drivename
($ds);
5704 my $drive = parse_drive
($ds, $conf->{$ds});
5706 next if drive_is_cdrom
($drive);
5708 my $volid = $drive->{file
};
5710 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5711 $sidhash->{$sid} = $sid if $sid;
5714 foreach my $sid (sort keys %$sidhash) {
5719 sub do_snapshots_with_qemu
{
5720 my ($storecfg, $volid) = @_;
5722 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5724 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5725 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5729 if ($volid =~ m/\.(qcow2|qed)$/){
5736 sub qga_check_running
{
5739 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5741 warn "Qemu Guest Agent are not running - $@";
5747 sub template_create
{
5748 my ($vmid, $conf, $disk) = @_;
5750 my $storecfg = PVE
::Storage
::config
();
5752 foreach_drive
($conf, sub {
5753 my ($ds, $drive) = @_;
5755 return if drive_is_cdrom
($drive);
5756 return if $disk && $ds ne $disk;
5758 my $volid = $drive->{file
};
5759 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5761 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5762 $drive->{file
} = $voliddst;
5763 $conf->{$ds} = print_drive
($vmid, $drive);
5764 PVE
::QemuConfig-
>write_config($vmid, $conf);
5768 sub qemu_img_convert
{
5769 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5771 my $storecfg = PVE
::Storage
::config
();
5772 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5773 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5775 if ($src_storeid && $dst_storeid) {
5777 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5779 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5780 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5782 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5783 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5785 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5786 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5789 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5790 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5791 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5792 if ($is_zero_initialized) {
5793 push @$cmd, "zeroinit:$dst_path";
5795 push @$cmd, $dst_path;
5800 if($line =~ m/\((\S+)\/100\
%\)/){
5802 my $transferred = int($size * $percent / 100);
5803 my $remaining = $size - $transferred;
5805 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5810 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5812 die "copy failed: $err" if $err;
5816 sub qemu_img_format
{
5817 my ($scfg, $volname) = @_;
5819 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5826 sub qemu_drive_mirror
{
5827 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5829 my $storecfg = PVE
::Storage
::config
();
5830 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5832 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5834 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5836 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5838 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5840 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5841 $opts->{format
} = $format if $format;
5843 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5845 my $finish_job = sub {
5847 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5848 my $stat = @$stats[0];
5855 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5857 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5858 my $stat = @$stats[0];
5859 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5860 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5862 my $busy = $stat->{busy
};
5863 my $ready = $stat->{ready
};
5865 if (my $total = $stat->{len
}) {
5866 my $transferred = $stat->{offset
} || 0;
5867 my $remaining = $total - $transferred;
5868 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5870 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5874 if ($stat->{ready
} eq 'true') {
5876 last if $vmiddst != $vmid;
5878 # try to switch the disk if source and destination are on the same guest
5879 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5884 die $@ if $@ !~ m/cannot be completed/;
5893 my $cancel_job = sub {
5894 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5899 eval { &$cancel_job(); };
5900 die "mirroring error: $err";
5903 if ($vmiddst != $vmid) {
5904 # if we clone a disk for a new target vm, we don't switch the disk
5905 &$cancel_job(); # so we call block-job-cancel
5910 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5911 $newvmid, $storage, $format, $full, $newvollist) = @_;
5916 print "create linked clone of drive $drivename ($drive->{file})\n";
5917 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5918 push @$newvollist, $newvolid;
5920 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5921 $storeid = $storage if $storage;
5923 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5925 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5926 $format = qemu_img_format
($scfg, $volname);
5929 # test if requested format is supported - else use default
5930 my $supported = grep { $_ eq $format } @$validFormats;
5931 $format = $defFormat if !$supported;
5933 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5935 print "create full clone of drive $drivename ($drive->{file})\n";
5936 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5937 push @$newvollist, $newvolid;
5939 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
5941 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5942 if (!$running || $snapname) {
5943 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5946 my $kvmver = get_running_qemu_version
($vmid);
5947 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
5948 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
5949 if $drive->{iothread
};
5952 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5956 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5959 $disk->{format
} = undef;
5960 $disk->{file
} = $newvolid;
5961 $disk->{size
} = $size;
5966 # this only works if VM is running
5967 sub get_current_qemu_machine
{
5970 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5971 my $res = vm_qmp_command
($vmid, $cmd);
5973 my ($current, $default);
5974 foreach my $e (@$res) {
5975 $default = $e->{name
} if $e->{'is-default'};
5976 $current = $e->{name
} if $e->{'is-current'};
5979 # fallback to the default machine if current is not supported by qemu
5980 return $current || $default || 'pc';
5983 sub get_running_qemu_version
{
5985 my $cmd = { execute
=> 'query-version', arguments
=> {} };
5986 my $res = vm_qmp_command
($vmid, $cmd);
5987 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
5990 sub qemu_machine_feature_enabled
{
5991 my ($machine, $kvmver, $version_major, $version_minor) = @_;
5996 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
5998 $current_major = $3;
5999 $current_minor = $4;
6001 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6003 $current_major = $1;
6004 $current_minor = $2;
6007 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6012 sub qemu_machine_pxe
{
6013 my ($vmid, $conf, $machine) = @_;
6015 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6017 foreach my $opt (keys %$conf) {
6018 next if $opt !~ m/^net(\d+)$/;
6019 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6021 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6022 return $machine.".pxe" if $romfile =~ m/pxe/;
6029 sub qemu_use_old_bios_files
{
6030 my ($machine_type) = @_;
6032 return if !$machine_type;
6034 my $use_old_bios_files = undef;
6036 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6038 $use_old_bios_files = 1;
6040 my $kvmver = kvm_user_version
();
6041 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6042 # load new efi bios files on migration. So this hack is required to allow
6043 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6044 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6045 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6048 return ($use_old_bios_files, $machine_type);
6055 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6056 my (undef, $id, $function) = @_;
6057 my $res = { id
=> $id, function
=> $function};
6058 push @{$devices->{$id}}, $res;
6064 sub vm_iothreads_list
{
6067 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6070 foreach my $iothread (@$res) {
6071 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6078 my ($conf, $drive) = @_;
6082 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6084 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6090 my $controller = int($drive->{index} / $maxdev);
6091 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6093 return ($maxdev, $controller, $controller_prefix);
6096 sub add_hyperv_enlighments
{
6097 my ($cpuFlags, $winversion, $machine_type, $kvmver, $nokvm, $bios, $gpu_passthrough) = @_;
6100 return if $winversion < 6;
6101 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6103 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
6104 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6105 push @$cpuFlags , 'hv_vapic';
6106 push @$cpuFlags , 'hv_time';
6108 push @$cpuFlags , 'hv_spinlocks=0xffff';
6111 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
6112 push @$cpuFlags , 'hv_reset';
6113 push @$cpuFlags , 'hv_vpindex';
6114 push @$cpuFlags , 'hv_runtime';
6117 if ($winversion >= 7) {
6118 push @$cpuFlags , 'hv_relaxed';
6119 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6123 sub windows_version
{
6126 return 0 if !$ostype;
6130 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6132 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6134 } elsif ($ostype =~ m/^win(\d+)$/) {
6141 # bash completion helper
6143 sub complete_backup_archives
{
6144 my ($cmdname, $pname, $cvalue) = @_;
6146 my $cfg = PVE
::Storage
::config
();
6150 if ($cvalue =~ m/^([^:]+):/) {
6154 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6157 foreach my $id (keys %$data) {
6158 foreach my $item (@{$data->{$id}}) {
6159 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6160 push @$res, $item->{volid
} if defined($item->{volid
});
6167 my $complete_vmid_full = sub {
6170 my $idlist = vmstatus
();
6174 foreach my $id (keys %$idlist) {
6175 my $d = $idlist->{$id};
6176 if (defined($running)) {
6177 next if $d->{template
};
6178 next if $running && $d->{status
} ne 'running';
6179 next if !$running && $d->{status
} eq 'running';
6188 return &$complete_vmid_full();
6191 sub complete_vmid_stopped
{
6192 return &$complete_vmid_full(0);
6195 sub complete_vmid_running
{
6196 return &$complete_vmid_full(1);
6199 sub complete_storage
{
6201 my $cfg = PVE
::Storage
::config
();
6202 my $ids = $cfg->{ids
};
6205 foreach my $sid (keys %$ids) {
6206 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6207 next if !$ids->{$sid}->{content
}->{images
};