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 ],
150 format_description
=> 'cputype',
155 description
=> "Do not identify as a KVM virtual machine.",
166 enum
=> [qw(i6300esb ib700)],
167 description
=> "Watchdog type to emulate.",
168 default => 'i6300esb',
173 enum
=> [qw(reset shutdown poweroff pause debug none)],
174 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
178 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
184 description
=> "Specifies whether a VM will be started during system bootup.",
190 description
=> "Automatic restart after crash (currently ignored).",
195 type
=> 'string', format
=> 'pve-hotplug-features',
196 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'.",
197 default => 'network,disk,usb',
202 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
208 description
=> "Lock/unlock the VM.",
209 enum
=> [qw(migrate backup snapshot rollback)],
214 description
=> "Limit of CPU usage.",
215 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.",
223 description
=> "CPU weight for a VM.",
224 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.",
232 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
239 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
245 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",
253 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.",
254 enum
=> PVE
::Tools
::kvmkeymaplist
(),
259 type
=> 'string', format
=> 'dns-name',
260 description
=> "Set a name for the VM. Only used on the configuration web interface.",
265 description
=> "SCSI controller model",
266 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
272 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
277 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
278 description
=> "Specify guest operating system.",
279 verbose_description
=> <<EODESC,
280 Specify guest operating system. This is used to enable special
281 optimization/features for specific operating systems:
284 other;; unspecified OS
285 wxp;; Microsoft Windows XP
286 w2k;; Microsoft Windows 2000
287 w2k3;; Microsoft Windows 2003
288 w2k8;; Microsoft Windows 2008
289 wvista;; Microsoft Windows Vista
290 win7;; Microsoft Windows 7
291 win8;; Microsoft Windows 8/2012
292 l24;; Linux 2.4 Kernel
293 l26;; Linux 2.6/3.X Kernel
294 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
300 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
301 pattern
=> '[acdn]{1,4}',
306 type
=> 'string', format
=> 'pve-qm-bootdisk',
307 description
=> "Enable booting from specified disk.",
308 pattern
=> '(ide|sata|scsi|virtio)\d+',
313 description
=> "The number of CPUs. Please use option -sockets instead.",
320 description
=> "The number of CPU sockets.",
327 description
=> "The number of cores per socket.",
334 description
=> "Enable/disable NUMA.",
340 description
=> "Enable/disable hugepages memory.",
341 enum
=> [qw(any 2 1024)],
346 description
=> "Number of hotplugged vcpus.",
353 description
=> "Enable/disable ACPI.",
359 description
=> "Enable/disable Qemu GuestAgent.",
365 description
=> "Enable/disable KVM hardware virtualization.",
371 description
=> "Enable/disable time drift fix.",
377 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
382 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
387 description
=> "Select the VGA type.",
388 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
389 " modes (>= 1280x1024x16) then you should use the options " .
390 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
391 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
392 "display sever. For win* OS you can select how many independent " .
393 "displays you want, Linux guests can add displays them self. " .
394 "You can also run without any graphic card, using a serial device" .
396 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
400 type
=> 'string', format
=> 'pve-qm-watchdog',
401 description
=> "Create a virtual hardware watchdog device.",
402 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
403 " (by a guest action), the watchdog must be periodically polled " .
404 "by an agent inside the guest or else the watchdog will reset " .
405 "the guest (or execute the respective action specified)",
410 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
411 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'.",
412 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
415 startup
=> get_standard_option
('pve-startup-order'),
419 description
=> "Enable/disable Template.",
425 description
=> "Arbitrary arguments passed to kvm.",
426 verbose_description
=> <<EODESCR,
427 Arbitrary arguments passed to kvm, for example:
429 args: -no-reboot -no-hpet
431 NOTE: this option is for experts only.
438 description
=> "Enable/disable the USB tablet device.",
439 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
440 "usually needed to allow absolute mouse positioning with VNC. " .
441 "Else the mouse runs out of sync with normal VNC clients. " .
442 "If you're running lots of console-only guests on one host, " .
443 "you may consider disabling this to save some context switches. " .
444 "This is turned off by default if you use spice (-vga=qxl).",
449 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
453 migrate_downtime
=> {
456 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
462 type
=> 'string', format
=> 'pve-qm-ide',
463 typetext
=> 'volume',
464 description
=> "This is an alias for option -ide2",
468 description
=> "Emulated CPU type.",
472 parent
=> get_standard_option
('pve-snapshot-name', {
474 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
478 description
=> "Timestamp for snapshots.",
484 type
=> 'string', format
=> 'pve-volume-id',
485 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
488 description
=> "Specific the Qemu machine type.",
490 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
495 description
=> "Specify SMBIOS type 1 fields.",
496 type
=> 'string', format
=> 'pve-qm-smbios1',
503 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
509 enum
=> [ qw(seabios ovmf) ],
510 description
=> "Select BIOS implementation.",
511 default => 'seabios',
515 # what about other qemu settings ?
517 #machine => 'string',
530 ##soundhw => 'string',
532 while (my ($k, $v) = each %$confdesc) {
533 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
536 my $MAX_IDE_DISKS = 4;
537 my $MAX_SCSI_DISKS = 14;
538 my $MAX_VIRTIO_DISKS = 16;
539 my $MAX_SATA_DISKS = 6;
540 my $MAX_USB_DEVICES = 5;
542 my $MAX_UNUSED_DISKS = 8;
543 my $MAX_HOSTPCI_DEVICES = 4;
544 my $MAX_SERIAL_PORTS = 4;
545 my $MAX_PARALLEL_PORTS = 3;
551 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
552 description
=> "CPUs accessing this NUMA node.",
553 format_description
=> "id[-id];...",
557 description
=> "Amount of memory this NUMA node provides.",
562 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
563 description
=> "Host NUMA nodes to use.",
564 format_description
=> "id[-id];...",
569 enum
=> [qw(preferred bind interleave)],
570 description
=> "NUMA allocation policy.",
574 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
577 type
=> 'string', format
=> $numa_fmt,
578 description
=> "NUMA topology.",
580 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
582 for (my $i = 0; $i < $MAX_NUMA; $i++) {
583 $confdesc->{"numa$i"} = $numadesc;
586 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
587 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
588 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
589 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
591 my $net_fmt_bridge_descr = <<__EOD__;
592 Bridge to attach the network device to. The Proxmox VE standard bridge
595 If you do not specify a bridge, we create a kvm user (NATed) network
596 device, which provides DHCP and DNS services. The following addresses
603 The DHCP server assign addresses to the guest starting from 10.0.2.15.
609 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
610 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
611 format_description
=> "XX:XX:XX:XX:XX:XX",
616 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'.",
617 format_description
=> 'model',
618 enum
=> $nic_model_list,
621 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
624 description
=> $net_fmt_bridge_descr,
625 format_description
=> 'bridge',
630 minimum
=> 0, maximum
=> 16,
631 description
=> 'Number of packet queues to be used on the device.',
637 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
642 minimum
=> 1, maximum
=> 4094,
643 description
=> 'VLAN tag to apply to packets on this interface.',
648 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
649 description
=> 'VLAN trunks to pass through this interface.',
650 format_description
=> 'vlanid[;vlanid...]',
655 description
=> 'Whether this interface should be protected by the firewall.',
660 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
667 type
=> 'string', format
=> $net_fmt,
668 description
=> "Specify network devices.",
671 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
673 for (my $i = 0; $i < $MAX_NETS; $i++) {
674 $confdesc->{"net$i"} = $netdesc;
677 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
678 sub verify_volume_id_or_qm_path
{
679 my ($volid, $noerr) = @_;
681 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
685 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
686 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
688 return undef if $noerr;
696 my %drivedesc_base = (
697 volume
=> { alias
=> 'file' },
700 format
=> 'pve-volume-id-or-qm-path',
702 format_description
=> 'volume',
703 description
=> "The drive's backing volume.",
707 enum
=> [qw(cdrom disk)],
708 description
=> "The drive's media type.",
714 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
719 description
=> "Force the drive's physical geometry to have a specific head count.",
724 description
=> "Force the drive's physical geometry to have a specific sector count.",
729 enum
=> [qw(none lba auto)],
730 description
=> "Force disk geometry bios translation mode.",
735 description
=> "Whether the drive should be included when making snapshots.",
740 enum
=> [qw(none writethrough writeback unsafe directsync)],
741 description
=> "The drive's cache mode",
744 format
=> get_standard_option
('pve-qm-image-format'),
747 format
=> 'disk-size',
748 format_description
=> 'DiskSize',
749 description
=> "Disk size. This is purely informational and has no effect.",
754 description
=> "Whether the drive should be included when making backups.",
759 enum
=> [qw(enospc ignore report stop)],
760 description
=> 'Write error action.',
765 enum
=> [qw(native threads)],
766 description
=> 'AIO type to use.',
771 enum
=> [qw(ignore on)],
772 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
777 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
782 format
=> 'urlencoded',
783 format_description
=> 'serial',
784 maxLength
=> 20*3, # *3 since it's %xx url enoded
785 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
793 enum
=> [qw(ignore report stop)],
794 description
=> 'Read error action.',
799 my %iothread_fmt = ( iothread
=> {
801 description
=> "Whether to use iothreads for this drive",
808 format
=> 'urlencoded',
809 format_description
=> 'model',
810 maxLength
=> 40*3, # *3 since it's %xx url enoded
811 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
819 description
=> "Number of queues.",
825 my $add_throttle_desc = sub {
826 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
829 format_description
=> $unit,
830 description
=> "Maximum $what in $longunit.",
833 $d->{minimum
} = $minimum if defined($minimum);
834 $drivedesc_base{$key} = $d;
836 # throughput: (leaky bucket)
837 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
838 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
839 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
840 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
841 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
842 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
843 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
844 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
845 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
847 # pools: (pool of IO before throttling starts taking effect)
848 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
849 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
850 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
851 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
852 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
853 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
856 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
857 $add_throttle_desc->('bps_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
858 $add_throttle_desc->('bps_wr_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
859 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
860 $add_throttle_desc->('iops_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
861 $add_throttle_desc->('iops_wr_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
868 PVE
::JSONSchema
::register_format
("pve-qm-ide", $ide_fmt);
872 type
=> 'string', format
=> $ide_fmt,
873 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
875 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
884 type
=> 'string', format
=> $scsi_fmt,
885 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
887 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
895 type
=> 'string', format
=> $sata_fmt,
896 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
898 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
907 type
=> 'string', format
=> $virtio_fmt,
908 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
910 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
921 volume
=> { alias
=> 'file' },
924 format
=> 'pve-volume-id-or-qm-path',
926 format_description
=> 'volume',
927 description
=> "The drive's backing volume.",
929 format
=> get_standard_option
('pve-qm-image-format'),
932 format
=> 'disk-size',
933 format_description
=> 'DiskSize',
934 description
=> "Disk size. This is purely informational and has no effect.",
941 type
=> 'string', format
=> $efidisk_fmt,
942 description
=> "Configure a Disk for storing EFI vars",
945 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
950 type
=> 'string', format
=> 'pve-qm-usb-device',
951 format_description
=> 'HOSTUSBDEVICE|spice',
952 description
=> <<EODESCR,
953 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
955 'bus-port(.port)*' (decimal numbers) or
956 'vendor_id:product_id' (hexadeciaml numbers) or
959 You can use the 'lsusb -t' command to list existing usb devices.
961 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
963 The value 'spice' can be used to add a usb redirection devices for spice.
969 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).",
976 type
=> 'string', format
=> $usb_fmt,
977 description
=> "Configure an USB device (n is 0 to 4).",
979 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
981 # NOTE: the match-groups of this regex are used in parse_hostpci
982 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
987 pattern
=> qr/$PCIRE(;$PCIRE)*/,
988 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
989 description
=> <<EODESCR,
990 Host PCI device pass through. The PCI ID of a host's PCI device or a list
991 of PCI virtual functions of the host. HOSTPCIID syntax is:
993 'bus:dev.func' (hexadecimal numbers)
995 You can us the 'lspci' command to list existing PCI devices.
1000 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1006 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1012 description
=> "Enable vfio-vga device support.",
1017 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1021 type
=> 'string', format
=> 'pve-qm-hostpci',
1022 description
=> "Map host PCI devices into guest.",
1023 verbose_description
=> <<EODESCR,
1024 Map host PCI devices into guest.
1026 NOTE: This option allows direct access to host hardware. So it is no longer
1027 possible to migrate such machines - use with special care.
1029 CAUTION: Experimental! User reported problems with this option.
1032 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1037 pattern
=> '(/dev/.+|socket)',
1038 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1039 verbose_description
=> <<EODESCR,
1040 Create a serial device inside the VM (n is 0 to 3), and pass through a
1041 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1042 host side (use 'qm terminal' to open a terminal connection).
1044 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1046 CAUTION: Experimental! User reported problems with this option.
1053 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1054 description
=> "Map host parallel devices (n is 0 to 2).",
1055 verbose_description
=> <<EODESCR,
1056 Map host parallel devices (n is 0 to 2).
1058 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1060 CAUTION: Experimental! User reported problems with this option.
1064 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1065 $confdesc->{"parallel$i"} = $paralleldesc;
1068 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1069 $confdesc->{"serial$i"} = $serialdesc;
1072 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1073 $confdesc->{"hostpci$i"} = $hostpcidesc;
1076 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1077 $drivename_hash->{"ide$i"} = 1;
1078 $confdesc->{"ide$i"} = $idedesc;
1081 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1082 $drivename_hash->{"sata$i"} = 1;
1083 $confdesc->{"sata$i"} = $satadesc;
1086 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1087 $drivename_hash->{"scsi$i"} = 1;
1088 $confdesc->{"scsi$i"} = $scsidesc ;
1091 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1092 $drivename_hash->{"virtio$i"} = 1;
1093 $confdesc->{"virtio$i"} = $virtiodesc;
1096 $drivename_hash->{efidisk0
} = 1;
1097 $confdesc->{efidisk0
} = $efidisk_desc;
1099 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1100 $confdesc->{"usb$i"} = $usbdesc;
1105 type
=> 'string', format
=> 'pve-volume-id',
1106 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1109 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1110 $confdesc->{"unused$i"} = $unuseddesc;
1113 my $kvm_api_version = 0;
1117 return $kvm_api_version if $kvm_api_version;
1119 my $fh = IO
::File-
>new("</dev/kvm") ||
1122 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1123 $kvm_api_version = $v;
1128 return $kvm_api_version;
1131 my $kvm_user_version;
1133 sub kvm_user_version
{
1135 return $kvm_user_version if $kvm_user_version;
1137 $kvm_user_version = 'unknown';
1141 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1142 $kvm_user_version = $2;
1146 eval { run_command
("kvm -version", outfunc
=> $code); };
1149 return $kvm_user_version;
1153 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1155 sub valid_drive_names
{
1156 # order is important - used to autoselect boot disk
1157 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1158 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1159 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1160 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1164 sub is_valid_drivename
{
1167 return defined($drivename_hash->{$dev});
1172 return defined($confdesc->{$key});
1176 return $nic_model_list;
1179 sub os_list_description
{
1183 wxp
=> 'Windows XP',
1184 w2k
=> 'Windows 2000',
1185 w2k3
=>, 'Windows 2003',
1186 w2k8
=> 'Windows 2008',
1187 wvista
=> 'Windows Vista',
1188 win7
=> 'Windows 7',
1189 win8
=> 'Windows 8/2012',
1197 sub get_cdrom_path
{
1199 return $cdrom_path if $cdrom_path;
1201 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1202 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1203 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1207 my ($storecfg, $vmid, $cdrom) = @_;
1209 if ($cdrom eq 'cdrom') {
1210 return get_cdrom_path
();
1211 } elsif ($cdrom eq 'none') {
1213 } elsif ($cdrom =~ m
|^/|) {
1216 return PVE
::Storage
::path
($storecfg, $cdrom);
1220 # try to convert old style file names to volume IDs
1221 sub filename_to_volume_id
{
1222 my ($vmid, $file, $media) = @_;
1224 if (!($file eq 'none' || $file eq 'cdrom' ||
1225 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1227 return undef if $file =~ m
|/|;
1229 if ($media && $media eq 'cdrom') {
1230 $file = "local:iso/$file";
1232 $file = "local:$vmid/$file";
1239 sub verify_media_type
{
1240 my ($opt, $vtype, $media) = @_;
1245 if ($media eq 'disk') {
1247 } elsif ($media eq 'cdrom') {
1250 die "internal error";
1253 return if ($vtype eq $etype);
1255 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1258 sub cleanup_drive_path
{
1259 my ($opt, $storecfg, $drive) = @_;
1261 # try to convert filesystem paths to volume IDs
1263 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1264 ($drive->{file
} !~ m
|^/dev/.+|) &&
1265 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1266 ($drive->{file
} !~ m/^\d+$/)) {
1267 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1268 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1269 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1270 verify_media_type
($opt, $vtype, $drive->{media
});
1271 $drive->{file
} = $volid;
1274 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1277 sub parse_hotplug_features
{
1282 return $res if $data eq '0';
1284 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1286 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1287 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1290 die "invalid hotplug feature '$feature'\n";
1296 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1297 sub pve_verify_hotplug_features
{
1298 my ($value, $noerr) = @_;
1300 return $value if parse_hotplug_features
($value);
1302 return undef if $noerr;
1304 die "unable to parse hotplug option\n";
1307 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1308 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1309 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1310 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1311 # [,iothread=on][,serial=serial][,model=model]
1314 my ($key, $data) = @_;
1316 my ($interface, $index);
1318 if ($key =~ m/^([^\d]+)(\d+)$/) {
1325 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1326 : $confdesc->{$key}->{format
};
1328 warn "invalid drive key: $key\n";
1331 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1332 return undef if !$res;
1333 $res->{interface
} = $interface;
1334 $res->{index} = $index;
1337 foreach my $opt (qw(bps bps_rd bps_wr)) {
1338 if (my $bps = defined(delete $res->{$opt})) {
1339 if (defined($res->{"m$opt"})) {
1340 warn "both $opt and m$opt specified\n";
1344 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1348 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1349 for my $requirement (
1350 [bps_max_length
=> 'mbps_max'],
1351 [bps_rd_max_length
=> 'mbps_rd_max'],
1352 [bps_wr_max_length
=> 'mbps_wr_max'],
1353 [iops_max_length
=> 'iops_max'],
1354 [iops_rd_max_length
=> 'iops_rd_max'],
1355 [iops_wr_max_length
=> 'iops_wr_max']) {
1356 my ($option, $requires) = @$requirement;
1357 if ($res->{$option} && !$res->{$requires}) {
1358 warn "$option requires $requires\n";
1363 return undef if $error;
1365 return undef if $res->{mbps_rd
} && $res->{mbps
};
1366 return undef if $res->{mbps_wr
} && $res->{mbps
};
1367 return undef if $res->{iops_rd
} && $res->{iops
};
1368 return undef if $res->{iops_wr
} && $res->{iops
};
1370 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1371 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1372 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1373 return undef if $res->{interface
} eq 'virtio';
1376 if (my $size = $res->{size
}) {
1377 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1384 my ($vmid, $drive) = @_;
1385 my $data = { %$drive };
1386 delete $data->{$_} for qw(index interface);
1387 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1391 my($fh, $noerr) = @_;
1394 my $SG_GET_VERSION_NUM = 0x2282;
1396 my $versionbuf = "\x00" x
8;
1397 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1399 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1402 my $version = unpack("I", $versionbuf);
1403 if ($version < 30000) {
1404 die "scsi generic interface too old\n" if !$noerr;
1408 my $buf = "\x00" x
36;
1409 my $sensebuf = "\x00" x
8;
1410 my $cmd = pack("C x3 C x1", 0x12, 36);
1412 # see /usr/include/scsi/sg.h
1413 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";
1415 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1416 length($sensebuf), 0, length($buf), $buf,
1417 $cmd, $sensebuf, 6000);
1419 $ret = ioctl($fh, $SG_IO, $packet);
1421 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1425 my @res = unpack($sg_io_hdr_t, $packet);
1426 if ($res[17] || $res[18]) {
1427 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1432 (my $byte0, my $byte1, $res->{vendor
},
1433 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1435 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1436 $res->{type
} = $byte0 & 31;
1444 my $fh = IO
::File-
>new("+<$path") || return undef;
1445 my $res = scsi_inquiry
($fh, 1);
1451 sub machine_type_is_q35
{
1454 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1457 sub print_tabletdevice_full
{
1460 my $q35 = machine_type_is_q35
($conf);
1462 # we use uhci for old VMs because tablet driver was buggy in older qemu
1463 my $usbbus = $q35 ?
"ehci" : "uhci";
1465 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1468 sub print_drivedevice_full
{
1469 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1474 if ($drive->{interface
} eq 'virtio') {
1475 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1476 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1477 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1478 } elsif ($drive->{interface
} eq 'scsi') {
1480 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1481 my $unit = $drive->{index} % $maxdev;
1482 my $devicetype = 'hd';
1484 if (drive_is_cdrom
($drive)) {
1487 if ($drive->{file
} =~ m
|^/|) {
1488 $path = $drive->{file
};
1489 if (my $info = path_is_scsi
($path)) {
1490 if ($info->{type
} == 0) {
1491 $devicetype = 'block';
1492 } elsif ($info->{type
} == 1) { # tape
1493 $devicetype = 'generic';
1497 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1500 if($path =~ m/^iscsi\:\/\
//){
1501 $devicetype = 'generic';
1505 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1506 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1508 $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}";
1511 } elsif ($drive->{interface
} eq 'ide'){
1513 my $controller = int($drive->{index} / $maxdev);
1514 my $unit = $drive->{index} % $maxdev;
1515 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1517 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1518 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1519 $model = URI
::Escape
::uri_unescape
($model);
1520 $device .= ",model=$model";
1522 } elsif ($drive->{interface
} eq 'sata'){
1523 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1524 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1525 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1526 } elsif ($drive->{interface
} eq 'usb') {
1528 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1530 die "unsupported interface type";
1533 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1538 sub get_initiator_name
{
1541 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1542 while (defined(my $line = <$fh>)) {
1543 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1552 sub print_drive_full
{
1553 my ($storecfg, $vmid, $drive) = @_;
1556 my $volid = $drive->{file
};
1559 if (drive_is_cdrom
($drive)) {
1560 $path = get_iso_path
($storecfg, $vmid, $volid);
1562 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1564 $path = PVE
::Storage
::path
($storecfg, $volid);
1565 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1566 $format = qemu_img_format
($scfg, $volname);
1574 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);
1575 foreach my $o (@qemu_drive_options) {
1576 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1578 if (my $serial = $drive->{serial
}) {
1579 $serial = URI
::Escape
::uri_unescape
($serial);
1580 $opts .= ",serial=$serial";
1583 $opts .= ",format=$format" if $format && !$drive->{format
};
1585 foreach my $o (qw(bps bps_rd bps_wr)) {
1586 my $v = $drive->{"m$o"};
1587 $opts .= ",$o=" . int($v*1024*1024) if $v;
1590 my $cache_direct = 0;
1592 if (my $cache = $drive->{cache
}) {
1593 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1594 } elsif (!drive_is_cdrom
($drive)) {
1595 $opts .= ",cache=none";
1599 # aio native works only with O_DIRECT
1600 if (!$drive->{aio
}) {
1602 $opts .= ",aio=native";
1604 $opts .= ",aio=threads";
1608 if (!drive_is_cdrom
($drive)) {
1610 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1611 $detectzeroes = 'off';
1612 } elsif ($drive->{discard
}) {
1613 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1615 # This used to be our default with discard not being specified:
1616 $detectzeroes = 'on';
1618 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1621 my $pathinfo = $path ?
"file=$path," : '';
1623 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1626 sub print_netdevice_full
{
1627 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1629 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1631 my $device = $net->{model
};
1632 if ($net->{model
} eq 'virtio') {
1633 $device = 'virtio-net-pci';
1636 my $pciaddr = print_pci_addr
("$netid", $bridges);
1637 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1638 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1639 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1640 my $vectors = $net->{queues
} * 2 + 2;
1641 $tmpstr .= ",vectors=$vectors,mq=on";
1643 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1645 if ($use_old_bios_files) {
1647 if ($device eq 'virtio-net-pci') {
1648 $romfile = 'pxe-virtio.rom';
1649 } elsif ($device eq 'e1000') {
1650 $romfile = 'pxe-e1000.rom';
1651 } elsif ($device eq 'ne2k') {
1652 $romfile = 'pxe-ne2k_pci.rom';
1653 } elsif ($device eq 'pcnet') {
1654 $romfile = 'pxe-pcnet.rom';
1655 } elsif ($device eq 'rtl8139') {
1656 $romfile = 'pxe-rtl8139.rom';
1658 $tmpstr .= ",romfile=$romfile" if $romfile;
1664 sub print_netdev_full
{
1665 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1668 if ($netid =~ m/^net(\d+)$/) {
1672 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1674 my $ifname = "tap${vmid}i$i";
1676 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1677 die "interface name '$ifname' is too long (max 15 character)\n"
1678 if length($ifname) >= 16;
1680 my $vhostparam = '';
1681 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1683 my $vmname = $conf->{name
} || "vm$vmid";
1686 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1688 if ($net->{bridge
}) {
1689 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1691 $netdev = "type=user,id=$netid,hostname=$vmname";
1694 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1700 sub print_cpu_device
{
1701 my ($conf, $id) = @_;
1703 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
1704 my $cpu = $nokvm ?
"qemu64" : "kvm64";
1705 if (my $cputype = $conf->{cpu
}) {
1706 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1707 or die "Cannot parse cpu description: $cputype\n";
1708 $cpu = $cpuconf->{cputype
};
1712 $sockets = $conf->{sockets
} if $conf->{sockets
};
1713 my $cores = $conf->{cores
} || 1;
1715 my $current_core = ($id - 1) % $cores;
1716 my $current_socket = int(($id - $current_core)/$cores);
1718 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1721 sub drive_is_cdrom
{
1724 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1728 sub parse_number_sets
{
1731 foreach my $part (split(/;/, $set)) {
1732 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1733 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1734 push @$res, [ $1, $2 ];
1736 die "invalid range: $part\n";
1745 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1746 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1747 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1754 return undef if !$value;
1756 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1758 my @idlist = split(/;/, $res->{host
});
1759 delete $res->{host
};
1760 foreach my $id (@idlist) {
1761 if ($id =~ /^$PCIRE$/) {
1763 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1765 my $pcidevices = lspci
($1);
1766 $res->{pciid
} = $pcidevices->{$1};
1769 # should have been caught by parse_property_string already
1770 die "failed to parse PCI id: $id\n";
1776 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1780 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1785 if (!defined($res->{macaddr
})) {
1786 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1787 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1795 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1798 sub add_random_macs
{
1799 my ($settings) = @_;
1801 foreach my $opt (keys %$settings) {
1802 next if $opt !~ m/^net(\d+)$/;
1803 my $net = parse_net
($settings->{$opt});
1805 $settings->{$opt} = print_net
($net);
1809 sub vm_is_volid_owner
{
1810 my ($storecfg, $vmid, $volid) = @_;
1812 if ($volid !~ m
|^/|) {
1814 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1815 if ($owner && ($owner == $vmid)) {
1823 sub split_flagged_list
{
1824 my $text = shift || '';
1825 $text =~ s/[,;]/ /g;
1827 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1830 sub join_flagged_list
{
1831 my ($how, $lst) = @_;
1832 join $how, map { $lst->{$_} . $_ } keys %$lst;
1835 sub vmconfig_delete_pending_option
{
1836 my ($conf, $key, $force) = @_;
1838 delete $conf->{pending
}->{$key};
1839 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1840 $pending_delete_hash->{$key} = $force ?
'!' : '';
1841 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1844 sub vmconfig_undelete_pending_option
{
1845 my ($conf, $key) = @_;
1847 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1848 delete $pending_delete_hash->{$key};
1850 if (%$pending_delete_hash) {
1851 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1853 delete $conf->{pending
}->{delete};
1857 sub vmconfig_register_unused_drive
{
1858 my ($storecfg, $vmid, $conf, $drive) = @_;
1860 if (!drive_is_cdrom
($drive)) {
1861 my $volid = $drive->{file
};
1862 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1863 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1868 sub vmconfig_cleanup_pending
{
1871 # remove pending changes when nothing changed
1873 foreach my $opt (keys %{$conf->{pending
}}) {
1874 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1876 delete $conf->{pending
}->{$opt};
1880 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1881 my $pending_delete_hash = {};
1882 while (my ($opt, $force) = each %$current_delete_hash) {
1883 if (defined($conf->{$opt})) {
1884 $pending_delete_hash->{$opt} = $force;
1890 if (%$pending_delete_hash) {
1891 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1893 delete $conf->{pending
}->{delete};
1899 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1903 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1904 format_description
=> 'UUID',
1905 description
=> "Set SMBIOS1 UUID.",
1911 format_description
=> 'string',
1912 description
=> "Set SMBIOS1 version.",
1918 format_description
=> 'string',
1919 description
=> "Set SMBIOS1 serial number.",
1925 format_description
=> 'string',
1926 description
=> "Set SMBIOS1 manufacturer.",
1932 format_description
=> 'string',
1933 description
=> "Set SMBIOS1 product ID.",
1939 format_description
=> 'string',
1940 description
=> "Set SMBIOS1 SKU string.",
1946 format_description
=> 'string',
1947 description
=> "Set SMBIOS1 family string.",
1955 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1962 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1965 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1967 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1968 sub verify_bootdisk
{
1969 my ($value, $noerr) = @_;
1971 return $value if is_valid_drivename
($value);
1973 return undef if $noerr;
1975 die "invalid boot disk '$value'\n";
1978 sub parse_watchdog
{
1981 return undef if !$value;
1983 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1988 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1989 sub verify_usb_device
{
1990 my ($value, $noerr) = @_;
1992 return $value if parse_usb_device
($value);
1994 return undef if $noerr;
1996 die "unable to parse usb device\n";
1999 # add JSON properties for create and set function
2000 sub json_config_properties
{
2003 foreach my $opt (keys %$confdesc) {
2004 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2005 $prop->{$opt} = $confdesc->{$opt};
2012 my ($key, $value) = @_;
2014 die "unknown setting '$key'\n" if !$confdesc->{$key};
2016 my $type = $confdesc->{$key}->{type
};
2018 if (!defined($value)) {
2019 die "got undefined value\n";
2022 if ($value =~ m/[\n\r]/) {
2023 die "property contains a line feed\n";
2026 if ($type eq 'boolean') {
2027 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2028 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2029 die "type check ('boolean') failed - got '$value'\n";
2030 } elsif ($type eq 'integer') {
2031 return int($1) if $value =~ m/^(\d+)$/;
2032 die "type check ('integer') failed - got '$value'\n";
2033 } elsif ($type eq 'number') {
2034 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2035 die "type check ('number') failed - got '$value'\n";
2036 } elsif ($type eq 'string') {
2037 if (my $fmt = $confdesc->{$key}->{format
}) {
2038 PVE
::JSONSchema
::check_format
($fmt, $value);
2041 $value =~ s/^\"(.*)\"$/$1/;
2044 die "internal error"
2048 sub check_iommu_support
{
2049 #fixme : need to check IOMMU support
2050 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2060 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2061 utime undef, undef, $conf;
2065 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2067 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2069 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2071 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2073 # only remove disks owned by this VM
2074 foreach_drive
($conf, sub {
2075 my ($ds, $drive) = @_;
2077 return if drive_is_cdrom
($drive);
2079 my $volid = $drive->{file
};
2081 return if !$volid || $volid =~ m
|^/|;
2083 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2084 return if !$path || !$owner || ($owner != $vmid);
2086 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2089 if ($keep_empty_config) {
2090 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2095 # also remove unused disk
2097 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2100 PVE
::Storage
::foreach_volid
($dl, sub {
2101 my ($volid, $sid, $volname, $d) = @_;
2102 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2111 sub parse_vm_config
{
2112 my ($filename, $raw) = @_;
2114 return undef if !defined($raw);
2117 digest
=> Digest
::SHA
::sha1_hex
($raw),
2122 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2123 || die "got strange filename '$filename'";
2131 my @lines = split(/\n/, $raw);
2132 foreach my $line (@lines) {
2133 next if $line =~ m/^\s*$/;
2135 if ($line =~ m/^\[PENDING\]\s*$/i) {
2136 $section = 'pending';
2137 if (defined($descr)) {
2139 $conf->{description
} = $descr;
2142 $conf = $res->{$section} = {};
2145 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2147 if (defined($descr)) {
2149 $conf->{description
} = $descr;
2152 $conf = $res->{snapshots
}->{$section} = {};
2156 if ($line =~ m/^\#(.*)\s*$/) {
2157 $descr = '' if !defined($descr);
2158 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2162 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2163 $descr = '' if !defined($descr);
2164 $descr .= PVE
::Tools
::decode_text
($2);
2165 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2166 $conf->{snapstate
} = $1;
2167 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2170 $conf->{$key} = $value;
2171 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2173 if ($section eq 'pending') {
2174 $conf->{delete} = $value; # we parse this later
2176 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2178 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2181 eval { $value = check_type
($key, $value); };
2183 warn "vm $vmid - unable to parse value of '$key' - $@";
2185 $key = 'ide2' if $key eq 'cdrom';
2186 my $fmt = $confdesc->{$key}->{format
};
2187 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2188 my $v = parse_drive
($key, $value);
2189 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2190 $v->{file
} = $volid;
2191 $value = print_drive
($vmid, $v);
2193 warn "vm $vmid - unable to parse value of '$key'\n";
2198 $conf->{$key} = $value;
2203 if (defined($descr)) {
2205 $conf->{description
} = $descr;
2207 delete $res->{snapstate
}; # just to be sure
2212 sub write_vm_config
{
2213 my ($filename, $conf) = @_;
2215 delete $conf->{snapstate
}; # just to be sure
2217 if ($conf->{cdrom
}) {
2218 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2219 $conf->{ide2
} = $conf->{cdrom
};
2220 delete $conf->{cdrom
};
2223 # we do not use 'smp' any longer
2224 if ($conf->{sockets
}) {
2225 delete $conf->{smp
};
2226 } elsif ($conf->{smp
}) {
2227 $conf->{sockets
} = $conf->{smp
};
2228 delete $conf->{cores
};
2229 delete $conf->{smp
};
2232 my $used_volids = {};
2234 my $cleanup_config = sub {
2235 my ($cref, $pending, $snapname) = @_;
2237 foreach my $key (keys %$cref) {
2238 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2239 $key eq 'snapstate' || $key eq 'pending';
2240 my $value = $cref->{$key};
2241 if ($key eq 'delete') {
2242 die "propertry 'delete' is only allowed in [PENDING]\n"
2244 # fixme: check syntax?
2247 eval { $value = check_type
($key, $value); };
2248 die "unable to parse value of '$key' - $@" if $@;
2250 $cref->{$key} = $value;
2252 if (!$snapname && is_valid_drivename
($key)) {
2253 my $drive = parse_drive
($key, $value);
2254 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2259 &$cleanup_config($conf);
2261 &$cleanup_config($conf->{pending
}, 1);
2263 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2264 die "internal error" if $snapname eq 'pending';
2265 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2268 # remove 'unusedX' settings if we re-add a volume
2269 foreach my $key (keys %$conf) {
2270 my $value = $conf->{$key};
2271 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2272 delete $conf->{$key};
2276 my $generate_raw_config = sub {
2277 my ($conf, $pending) = @_;
2281 # add description as comment to top of file
2282 if (defined(my $descr = $conf->{description
})) {
2284 foreach my $cl (split(/\n/, $descr)) {
2285 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2288 $raw .= "#\n" if $pending;
2292 foreach my $key (sort keys %$conf) {
2293 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2294 $raw .= "$key: $conf->{$key}\n";
2299 my $raw = &$generate_raw_config($conf);
2301 if (scalar(keys %{$conf->{pending
}})){
2302 $raw .= "\n[PENDING]\n";
2303 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2306 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2307 $raw .= "\n[$snapname]\n";
2308 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2318 # we use static defaults from our JSON schema configuration
2319 foreach my $key (keys %$confdesc) {
2320 if (defined(my $default = $confdesc->{$key}->{default})) {
2321 $res->{$key} = $default;
2325 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2326 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2332 my $vmlist = PVE
::Cluster
::get_vmlist
();
2334 return $res if !$vmlist || !$vmlist->{ids
};
2335 my $ids = $vmlist->{ids
};
2337 foreach my $vmid (keys %$ids) {
2338 my $d = $ids->{$vmid};
2339 next if !$d->{node
} || $d->{node
} ne $nodename;
2340 next if !$d->{type
} || $d->{type
} ne 'qemu';
2341 $res->{$vmid}->{exists} = 1;
2346 # test if VM uses local resources (to prevent migration)
2347 sub check_local_resources
{
2348 my ($conf, $noerr) = @_;
2352 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2353 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2355 foreach my $k (keys %$conf) {
2356 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2357 # sockets are safe: they will recreated be on the target side post-migrate
2358 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2359 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2362 die "VM uses local resources\n" if $loc_res && !$noerr;
2367 # check if used storages are available on all nodes (use by migrate)
2368 sub check_storage_availability
{
2369 my ($storecfg, $conf, $node) = @_;
2371 foreach_drive
($conf, sub {
2372 my ($ds, $drive) = @_;
2374 my $volid = $drive->{file
};
2377 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2380 # check if storage is available on both nodes
2381 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2382 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2386 # list nodes where all VM images are available (used by has_feature API)
2388 my ($conf, $storecfg) = @_;
2390 my $nodelist = PVE
::Cluster
::get_nodelist
();
2391 my $nodehash = { map { $_ => 1 } @$nodelist };
2392 my $nodename = PVE
::INotify
::nodename
();
2394 foreach_drive
($conf, sub {
2395 my ($ds, $drive) = @_;
2397 my $volid = $drive->{file
};
2400 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2402 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2403 if ($scfg->{disable
}) {
2405 } elsif (my $avail = $scfg->{nodes
}) {
2406 foreach my $node (keys %$nodehash) {
2407 delete $nodehash->{$node} if !$avail->{$node};
2409 } elsif (!$scfg->{shared
}) {
2410 foreach my $node (keys %$nodehash) {
2411 delete $nodehash->{$node} if $node ne $nodename
2421 my ($pidfile, $pid) = @_;
2423 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2427 return undef if !$line;
2428 my @param = split(/\0/, $line);
2430 my $cmd = $param[0];
2431 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2433 for (my $i = 0; $i < scalar (@param); $i++) {
2436 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2437 my $p = $param[$i+1];
2438 return 1 if $p && ($p eq $pidfile);
2447 my ($vmid, $nocheck, $node) = @_;
2449 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2451 die "unable to find configuration file for VM $vmid - no such machine\n"
2452 if !$nocheck && ! -f
$filename;
2454 my $pidfile = pidfile_name
($vmid);
2456 if (my $fd = IO
::File-
>new("<$pidfile")) {
2461 my $mtime = $st->mtime;
2462 if ($mtime > time()) {
2463 warn "file '$filename' modified in future\n";
2466 if ($line =~ m/^(\d+)$/) {
2468 if (check_cmdline
($pidfile, $pid)) {
2469 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2481 my $vzlist = config_list
();
2483 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2485 while (defined(my $de = $fd->read)) {
2486 next if $de !~ m/^(\d+)\.pid$/;
2488 next if !defined($vzlist->{$vmid});
2489 if (my $pid = check_running
($vmid)) {
2490 $vzlist->{$vmid}->{pid
} = $pid;
2498 my ($storecfg, $conf) = @_;
2500 my $bootdisk = $conf->{bootdisk
};
2501 return undef if !$bootdisk;
2502 return undef if !is_valid_drivename
($bootdisk);
2504 return undef if !$conf->{$bootdisk};
2506 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2507 return undef if !defined($drive);
2509 return undef if drive_is_cdrom
($drive);
2511 my $volid = $drive->{file
};
2512 return undef if !$volid;
2514 return $drive->{size
};
2517 my $last_proc_pid_stat;
2519 # get VM status information
2520 # This must be fast and should not block ($full == false)
2521 # We only query KVM using QMP if $full == true (this can be slow)
2523 my ($opt_vmid, $full) = @_;
2527 my $storecfg = PVE
::Storage
::config
();
2529 my $list = vzlist
();
2530 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2532 my $cpucount = $cpuinfo->{cpus
} || 1;
2534 foreach my $vmid (keys %$list) {
2535 next if $opt_vmid && ($vmid ne $opt_vmid);
2537 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2538 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2541 $d->{pid
} = $list->{$vmid}->{pid
};
2543 # fixme: better status?
2544 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2546 my $size = disksize
($storecfg, $conf);
2547 if (defined($size)) {
2548 $d->{disk
} = 0; # no info available
2549 $d->{maxdisk
} = $size;
2555 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2556 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2557 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2559 $d->{name
} = $conf->{name
} || "VM $vmid";
2560 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2562 if ($conf->{balloon
}) {
2563 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2564 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2575 $d->{diskwrite
} = 0;
2577 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2582 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2583 foreach my $dev (keys %$netdev) {
2584 next if $dev !~ m/^tap([1-9]\d*)i/;
2586 my $d = $res->{$vmid};
2589 $d->{netout
} += $netdev->{$dev}->{receive
};
2590 $d->{netin
} += $netdev->{$dev}->{transmit
};
2593 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2594 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2599 my $ctime = gettimeofday
;
2601 foreach my $vmid (keys %$list) {
2603 my $d = $res->{$vmid};
2604 my $pid = $d->{pid
};
2607 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2608 next if !$pstat; # not running
2610 my $used = $pstat->{utime} + $pstat->{stime
};
2612 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2614 if ($pstat->{vsize
}) {
2615 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2618 my $old = $last_proc_pid_stat->{$pid};
2620 $last_proc_pid_stat->{$pid} = {
2628 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2630 if ($dtime > 1000) {
2631 my $dutime = $used - $old->{used
};
2633 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2634 $last_proc_pid_stat->{$pid} = {
2640 $d->{cpu
} = $old->{cpu
};
2644 return $res if !$full;
2646 my $qmpclient = PVE
::QMPClient-
>new();
2648 my $ballooncb = sub {
2649 my ($vmid, $resp) = @_;
2651 my $info = $resp->{'return'};
2652 return if !$info->{max_mem
};
2654 my $d = $res->{$vmid};
2656 # use memory assigned to VM
2657 $d->{maxmem
} = $info->{max_mem
};
2658 $d->{balloon
} = $info->{actual
};
2660 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2661 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2662 $d->{freemem
} = $info->{free_mem
};
2665 $d->{ballooninfo
} = $info;
2668 my $blockstatscb = sub {
2669 my ($vmid, $resp) = @_;
2670 my $data = $resp->{'return'} || [];
2671 my $totalrdbytes = 0;
2672 my $totalwrbytes = 0;
2674 for my $blockstat (@$data) {
2675 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2676 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2678 $blockstat->{device
} =~ s/drive-//;
2679 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2681 $res->{$vmid}->{diskread
} = $totalrdbytes;
2682 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2685 my $statuscb = sub {
2686 my ($vmid, $resp) = @_;
2688 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2689 # this fails if ballon driver is not loaded, so this must be
2690 # the last commnand (following command are aborted if this fails).
2691 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2693 my $status = 'unknown';
2694 if (!defined($status = $resp->{'return'}->{status
})) {
2695 warn "unable to get VM status\n";
2699 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2702 foreach my $vmid (keys %$list) {
2703 next if $opt_vmid && ($vmid ne $opt_vmid);
2704 next if !$res->{$vmid}->{pid
}; # not running
2705 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2708 $qmpclient->queue_execute(undef, 1);
2710 foreach my $vmid (keys %$list) {
2711 next if $opt_vmid && ($vmid ne $opt_vmid);
2712 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2719 my ($conf, $func, @param) = @_;
2721 foreach my $ds (valid_drive_names
()) {
2722 next if !defined($conf->{$ds});
2724 my $drive = parse_drive
($ds, $conf->{$ds});
2727 &$func($ds, $drive, @param);
2732 my ($conf, $func, @param) = @_;
2736 my $test_volid = sub {
2737 my ($volid, $is_cdrom) = @_;
2741 $volhash->{$volid} = $is_cdrom || 0;
2744 foreach_drive
($conf, sub {
2745 my ($ds, $drive) = @_;
2746 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2749 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2750 my $snap = $conf->{snapshots
}->{$snapname};
2751 &$test_volid($snap->{vmstate
}, 0);
2752 foreach_drive
($snap, sub {
2753 my ($ds, $drive) = @_;
2754 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2758 foreach my $volid (keys %$volhash) {
2759 &$func($volid, $volhash->{$volid}, @param);
2763 sub vga_conf_has_spice
{
2766 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2771 sub config_to_command
{
2772 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2775 my $globalFlags = [];
2776 my $machineFlags = [];
2782 my $kvmver = kvm_user_version
();
2783 my $vernum = 0; # unknown
2784 my $ostype = $conf->{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 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2875 $conf->{ostype
} eq 'win7' ||
2876 $conf->{ostype
} eq 'w2k8')) {
2883 # enable absolute mouse coordinates (needed by vnc)
2885 if (defined($conf->{tablet
})) {
2886 $tablet = $conf->{tablet
};
2888 $tablet = $defaults->{tablet
};
2889 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2890 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2893 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2897 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2898 my $d = parse_hostpci
($conf->{"hostpci$i"});
2901 my $pcie = $d->{pcie
};
2903 die "q35 machine model is not enabled" if !$q35;
2904 $pciaddr = print_pcie_addr
("hostpci$i");
2906 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2909 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2911 if ($d->{'x-vga'}) {
2912 $xvga = ',x-vga=on';
2915 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2916 push @$cpuFlags , 'hv_vendor_id=proxmox';
2918 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2922 my $pcidevices = $d->{pciid
};
2923 my $multifunction = 1 if @$pcidevices > 1;
2926 foreach my $pcidevice (@$pcidevices) {
2928 my $id = "hostpci$i";
2929 $id .= ".$j" if $multifunction;
2930 my $addr = $pciaddr;
2931 $addr .= ".$j" if $multifunction;
2932 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2935 $devicestr .= "$rombar$xvga";
2936 $devicestr .= ",multifunction=on" if $multifunction;
2939 push @$devices, '-device', $devicestr;
2945 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
2946 push @$devices, @usbdevices if @usbdevices;
2948 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2949 if (my $path = $conf->{"serial$i"}) {
2950 if ($path eq 'socket') {
2951 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2952 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2953 push @$devices, '-device', "isa-serial,chardev=serial$i";
2955 die "no such serial device\n" if ! -c
$path;
2956 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2957 push @$devices, '-device', "isa-serial,chardev=serial$i";
2963 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2964 if (my $path = $conf->{"parallel$i"}) {
2965 die "no such parallel device\n" if ! -c
$path;
2966 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2967 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2968 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2972 my $vmname = $conf->{name
} || "vm$vmid";
2974 push @$cmd, '-name', $vmname;
2977 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2978 $sockets = $conf->{sockets
} if $conf->{sockets
};
2980 my $cores = $conf->{cores
} || 1;
2982 my $maxcpus = $sockets * $cores;
2984 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2986 my $allowed_vcpus = $cpuinfo->{cpus
};
2988 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2989 if ($allowed_vcpus < $maxcpus);
2991 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
2993 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2994 for (my $i = 2; $i <= $vcpus; $i++) {
2995 my $cpustr = print_cpu_device
($conf,$i);
2996 push @$cmd, '-device', $cpustr;
3001 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3003 push @$cmd, '-nodefaults';
3005 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3007 my $bootindex_hash = {};
3009 foreach my $o (split(//, $bootorder)) {
3010 $bootindex_hash->{$o} = $i*100;
3014 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3016 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3018 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3020 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3022 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3023 my $socket = vnc_socket
($vmid);
3024 push @$cmd, '-vnc', "unix:$socket,x509,password";
3026 push @$cmd, '-nographic';
3030 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3032 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3033 my $useLocaltime = $conf->{localtime};
3036 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3038 if ($ostype =~ m/^w/) { # windows
3039 $useLocaltime = 1 if !defined($conf->{localtime});
3041 # use time drift fix when acpi is enabled
3042 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3043 $tdf = 1 if !defined($conf->{tdf
});
3047 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3048 $ostype eq 'wvista') {
3049 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3050 push @$cmd, '-no-hpet';
3051 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3052 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3053 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3054 push @$cpuFlags , 'hv_time' if !$nokvm;
3056 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
3057 push @$cpuFlags , 'hv_reset' if !$nokvm;
3058 push @$cpuFlags , 'hv_vpindex' if !$nokvm;
3059 push @$cpuFlags , 'hv_runtime' if !$nokvm;
3063 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3067 if ($ostype eq 'win7' || $ostype eq 'win8') {
3068 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3072 push @$rtcFlags, 'driftfix=slew' if $tdf;
3075 push @$machineFlags, 'accel=tcg';
3077 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3080 if ($machine_type) {
3081 push @$machineFlags, "type=${machine_type}";
3084 if ($conf->{startdate
}) {
3085 push @$rtcFlags, "base=$conf->{startdate}";
3086 } elsif ($useLocaltime) {
3087 push @$rtcFlags, 'base=localtime';
3090 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3091 if (my $cputype = $conf->{cpu
}) {
3092 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3093 or die "Cannot parse cpu description: $cputype\n";
3094 $cpu = $cpuconf->{cputype
};
3095 $kvm_off = 1 if $cpuconf->{hidden
};
3098 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3100 push @$cpuFlags , '-x2apic'
3101 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3103 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3105 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3107 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3109 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3110 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3113 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3115 push @$cpuFlags, 'kvm=off' if $kvm_off;
3117 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3118 die "internal error"; # should not happen
3120 push @$cpuFlags, "vendor=${cpu_vendor}"
3121 if $cpu_vendor ne 'default';
3123 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3125 push @$cmd, '-cpu', $cpu;
3127 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3129 push @$cmd, '-S' if $conf->{freeze
};
3131 # set keyboard layout
3132 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3133 push @$cmd, '-k', $kb if $kb;
3136 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3137 #push @$cmd, '-soundhw', 'es1370';
3138 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3140 if($conf->{agent
}) {
3141 my $qgasocket = qmp_socket
($vmid, 1);
3142 my $pciaddr = print_pci_addr
("qga0", $bridges);
3143 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3144 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3145 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3152 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3153 for(my $i = 1; $i < $qxlnum; $i++){
3154 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3155 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3158 # assume other OS works like Linux
3159 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3160 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3164 my $pciaddr = print_pci_addr
("spice", $bridges);
3166 my $nodename = PVE
::INotify
::nodename
();
3167 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3168 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3170 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3172 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3173 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3174 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3177 # enable balloon by default, unless explicitly disabled
3178 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3179 $pciaddr = print_pci_addr
("balloon0", $bridges);
3180 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3183 if ($conf->{watchdog
}) {
3184 my $wdopts = parse_watchdog
($conf->{watchdog
});
3185 $pciaddr = print_pci_addr
("watchdog", $bridges);
3186 my $watchdog = $wdopts->{model
} || 'i6300esb';
3187 push @$devices, '-device', "$watchdog$pciaddr";
3188 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3192 my $scsicontroller = {};
3193 my $ahcicontroller = {};
3194 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3196 # Add iscsi initiator name if available
3197 if (my $initiator = get_initiator_name
()) {
3198 push @$devices, '-iscsi', "initiator-name=$initiator";
3201 foreach_drive
($conf, sub {
3202 my ($ds, $drive) = @_;
3204 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3205 push @$vollist, $drive->{file
};
3208 $use_virtio = 1 if $ds =~ m/^virtio/;
3210 if (drive_is_cdrom
($drive)) {
3211 if ($bootindex_hash->{d
}) {
3212 $drive->{bootindex
} = $bootindex_hash->{d
};
3213 $bootindex_hash->{d
} += 1;
3216 if ($bootindex_hash->{c
}) {
3217 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3218 $bootindex_hash->{c
} += 1;
3222 if($drive->{interface
} eq 'virtio'){
3223 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3226 if ($drive->{interface
} eq 'scsi') {
3228 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3230 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3231 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3234 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3235 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3236 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3237 } elsif ($drive->{iothread
}) {
3238 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3242 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3243 $queues = ",num_queues=$drive->{queues}";
3246 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3247 $scsicontroller->{$controller}=1;
3250 if ($drive->{interface
} eq 'sata') {
3251 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3252 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3253 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3254 $ahcicontroller->{$controller}=1;
3257 if ($drive->{interface
} eq 'efidisk') {
3258 # this will be added somewhere else
3262 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3263 push @$devices, '-drive',$drive_cmd;
3264 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3267 for (my $i = 0; $i < $MAX_NETS; $i++) {
3268 next if !$conf->{"net$i"};
3269 my $d = parse_net
($conf->{"net$i"});
3272 $use_virtio = 1 if $d->{model
} eq 'virtio';
3274 if ($bootindex_hash->{n
}) {
3275 $d->{bootindex
} = $bootindex_hash->{n
};
3276 $bootindex_hash->{n
} += 1;
3279 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3280 push @$devices, '-netdev', $netdevfull;
3282 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3283 push @$devices, '-device', $netdevicefull;
3288 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3293 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3295 while (my ($k, $v) = each %$bridges) {
3296 $pciaddr = print_pci_addr
("pci.$k");
3297 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3302 if ($conf->{args
}) {
3303 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3307 push @$cmd, @$devices;
3308 push @$cmd, '-rtc', join(',', @$rtcFlags)
3309 if scalar(@$rtcFlags);
3310 push @$cmd, '-machine', join(',', @$machineFlags)
3311 if scalar(@$machineFlags);
3312 push @$cmd, '-global', join(',', @$globalFlags)
3313 if scalar(@$globalFlags);
3315 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3320 return "${var_run_tmpdir}/$vmid.vnc";
3326 my $res = vm_mon_cmd
($vmid, 'query-spice');
3328 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3332 my ($vmid, $qga) = @_;
3333 my $sockettype = $qga ?
'qga' : 'qmp';
3334 return "${var_run_tmpdir}/$vmid.$sockettype";
3339 return "${var_run_tmpdir}/$vmid.pid";
3342 sub vm_devices_list
{
3345 my $res = vm_mon_cmd
($vmid, 'query-pci');
3347 foreach my $pcibus (@$res) {
3348 foreach my $device (@{$pcibus->{devices
}}) {
3349 next if !$device->{'qdev_id'};
3350 if ($device->{'pci_bridge'}) {
3351 $devices->{$device->{'qdev_id'}} = 1;
3352 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3353 next if !$bridge_device->{'qdev_id'};
3354 $devices->{$bridge_device->{'qdev_id'}} = 1;
3355 $devices->{$device->{'qdev_id'}}++;
3358 $devices->{$device->{'qdev_id'}} = 1;
3363 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3364 foreach my $block (@$resblock) {
3365 if($block->{device
} =~ m/^drive-(\S+)/){
3370 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3371 foreach my $mice (@$resmice) {
3372 if ($mice->{name
} eq 'QEMU HID Tablet') {
3373 $devices->{tablet
} = 1;
3378 # for usb devices there is no query-usb
3379 # but we can iterate over the entries in
3380 # qom-list path=/machine/peripheral
3381 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3382 foreach my $per (@$resperipheral) {
3383 if ($per->{name
} =~ m/^usb\d+$/) {
3384 $devices->{$per->{name
}} = 1;
3392 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3394 my $q35 = machine_type_is_q35
($conf);
3396 my $devices_list = vm_devices_list
($vmid);
3397 return 1 if defined($devices_list->{$deviceid});
3399 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3401 if ($deviceid eq 'tablet') {
3403 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3405 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3407 die "usb hotplug currently not reliable\n";
3408 # since we can't reliably hot unplug all added usb devices
3409 # and usb passthrough disables live migration
3410 # we disable usb hotplugging for now
3411 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3413 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3415 qemu_iothread_add
($vmid, $deviceid, $device);
3417 qemu_driveadd
($storecfg, $vmid, $device);
3418 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3420 qemu_deviceadd
($vmid, $devicefull);
3421 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3423 eval { qemu_drivedel
($vmid, $deviceid); };
3428 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3431 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3432 my $pciaddr = print_pci_addr
($deviceid);
3433 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3435 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3437 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3438 qemu_iothread_add
($vmid, $deviceid, $device);
3439 $devicefull .= ",iothread=iothread-$deviceid";
3442 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3443 $devicefull .= ",num_queues=$device->{queues}";
3446 qemu_deviceadd
($vmid, $devicefull);
3447 qemu_deviceaddverify
($vmid, $deviceid);
3449 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3451 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3452 qemu_driveadd
($storecfg, $vmid, $device);
3454 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3455 eval { qemu_deviceadd
($vmid, $devicefull); };
3457 eval { qemu_drivedel
($vmid, $deviceid); };
3462 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3464 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3466 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3467 my $use_old_bios_files = undef;
3468 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3470 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3471 qemu_deviceadd
($vmid, $netdevicefull);
3472 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3474 eval { qemu_netdevdel
($vmid, $deviceid); };
3479 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3482 my $pciaddr = print_pci_addr
($deviceid);
3483 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3485 qemu_deviceadd
($vmid, $devicefull);
3486 qemu_deviceaddverify
($vmid, $deviceid);
3489 die "can't hotplug device '$deviceid'\n";
3495 # fixme: this should raise exceptions on error!
3496 sub vm_deviceunplug
{
3497 my ($vmid, $conf, $deviceid) = @_;
3499 my $devices_list = vm_devices_list
($vmid);
3500 return 1 if !defined($devices_list->{$deviceid});
3502 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3504 if ($deviceid eq 'tablet') {
3506 qemu_devicedel
($vmid, $deviceid);
3508 } elsif ($deviceid =~ m/^usb\d+$/) {
3510 die "usb hotplug currently not reliable\n";
3511 # when unplugging usb devices this way,
3512 # there may be remaining usb controllers/hubs
3513 # so we disable it for now
3514 qemu_devicedel
($vmid, $deviceid);
3515 qemu_devicedelverify
($vmid, $deviceid);
3517 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3519 qemu_devicedel
($vmid, $deviceid);
3520 qemu_devicedelverify
($vmid, $deviceid);
3521 qemu_drivedel
($vmid, $deviceid);
3522 qemu_iothread_del
($conf, $vmid, $deviceid);
3524 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3526 qemu_devicedel
($vmid, $deviceid);
3527 qemu_devicedelverify
($vmid, $deviceid);
3528 qemu_iothread_del
($conf, $vmid, $deviceid);
3530 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3532 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3533 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3534 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3536 qemu_devicedel
($vmid, $deviceid);
3537 qemu_drivedel
($vmid, $deviceid);
3538 qemu_deletescsihw
($conf, $vmid, $deviceid);
3540 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3542 qemu_devicedel
($vmid, $deviceid);
3543 qemu_devicedelverify
($vmid, $deviceid);
3544 qemu_netdevdel
($vmid, $deviceid);
3547 die "can't unplug device '$deviceid'\n";
3553 sub qemu_deviceadd
{
3554 my ($vmid, $devicefull) = @_;
3556 $devicefull = "driver=".$devicefull;
3557 my %options = split(/[=,]/, $devicefull);
3559 vm_mon_cmd
($vmid, "device_add" , %options);
3562 sub qemu_devicedel
{
3563 my ($vmid, $deviceid) = @_;
3565 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3568 sub qemu_iothread_add
{
3569 my($vmid, $deviceid, $device) = @_;
3571 if ($device->{iothread
}) {
3572 my $iothreads = vm_iothreads_list
($vmid);
3573 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3577 sub qemu_iothread_del
{
3578 my($conf, $vmid, $deviceid) = @_;
3580 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3581 if ($device->{iothread
}) {
3582 my $iothreads = vm_iothreads_list
($vmid);
3583 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3587 sub qemu_objectadd
{
3588 my($vmid, $objectid, $qomtype) = @_;
3590 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3595 sub qemu_objectdel
{
3596 my($vmid, $objectid) = @_;
3598 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3604 my ($storecfg, $vmid, $device) = @_;
3606 my $drive = print_drive_full
($storecfg, $vmid, $device);
3607 $drive =~ s/\\/\\\\/g;
3608 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3610 # If the command succeeds qemu prints: "OK
"
3611 return 1 if $ret =~ m/OK/s;
3613 die "adding drive failed
: $ret\n";
3617 my($vmid, $deviceid) = @_;
3619 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3622 return 1 if $ret eq "";
3624 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3625 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3627 die "deleting drive
$deviceid failed
: $ret\n";
3630 sub qemu_deviceaddverify {
3631 my ($vmid, $deviceid) = @_;
3633 for (my $i = 0; $i <= 5; $i++) {
3634 my $devices_list = vm_devices_list($vmid);
3635 return 1 if defined($devices_list->{$deviceid});
3639 die "error on hotplug device
'$deviceid'\n";
3643 sub qemu_devicedelverify {
3644 my ($vmid, $deviceid) = @_;
3646 # need to verify that the device is correctly removed as device_del
3647 # is async and empty return is not reliable
3649 for (my $i = 0; $i <= 5; $i++) {
3650 my $devices_list = vm_devices_list($vmid);
3651 return 1 if !defined($devices_list->{$deviceid});
3655 die "error on hot-unplugging device
'$deviceid'\n";
3658 sub qemu_findorcreatescsihw {
3659 my ($storecfg, $conf, $vmid, $device) = @_;
3661 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3663 my $scsihwid="$controller_prefix$controller";
3664 my $devices_list = vm_devices_list($vmid);
3666 if(!defined($devices_list->{$scsihwid})) {
3667 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3673 sub qemu_deletescsihw {
3674 my ($conf, $vmid, $opt) = @_;
3676 my $device = parse_drive($opt, $conf->{$opt});
3678 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3679 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3683 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3685 my $devices_list = vm_devices_list($vmid);
3686 foreach my $opt (keys %{$devices_list}) {
3687 if (PVE::QemuServer::is_valid_drivename($opt)) {
3688 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3689 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3695 my $scsihwid="scsihw
$controller";
3697 vm_deviceunplug($vmid, $conf, $scsihwid);
3702 sub qemu_add_pci_bridge {
3703 my ($storecfg, $conf, $vmid, $device) = @_;
3709 print_pci_addr($device, $bridges);
3711 while (my ($k, $v) = each %$bridges) {
3714 return 1 if !defined($bridgeid) || $bridgeid < 1;
3716 my $bridge = "pci
.$bridgeid";
3717 my $devices_list = vm_devices_list($vmid);
3719 if (!defined($devices_list->{$bridge})) {
3720 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3726 sub qemu_set_link_status {
3727 my ($vmid, $device, $up) = @_;
3729 vm_mon_cmd($vmid, "set_link
", name => $device,
3730 up => $up ? JSON::true : JSON::false);
3733 sub qemu_netdevadd {
3734 my ($vmid, $conf, $device, $deviceid) = @_;
3736 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3737 my %options = split(/[=,]/, $netdev);
3739 vm_mon_cmd($vmid, "netdev_add
", %options);
3743 sub qemu_netdevdel {
3744 my ($vmid, $deviceid) = @_;
3746 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3749 sub qemu_usb_hotplug {
3750 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3754 # remove the old one first
3755 vm_deviceunplug($vmid, $conf, $deviceid);
3757 # check if xhci controller is necessary and available
3758 if ($device->{usb3}) {
3760 my $devicelist = vm_devices_list($vmid);
3762 if (!$devicelist->{xhci}) {
3763 my $pciaddr = print_pci_addr("xhci
");
3764 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3767 my $d = parse_usb_device($device->{host});
3768 $d->{usb3} = $device->{usb3};
3771 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3774 sub qemu_cpu_hotplug {
3775 my ($vmid, $conf, $vcpus) = @_;
3777 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3780 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3781 $sockets = $conf->{sockets} if $conf->{sockets};
3782 my $cores = $conf->{cores} || 1;
3783 my $maxcpus = $sockets * $cores;
3785 $vcpus = $maxcpus if !$vcpus;
3787 die "you can
't add more vcpus than maxcpus\n"
3788 if $vcpus > $maxcpus;
3790 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3792 if ($vcpus < $currentvcpus) {
3794 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3796 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3797 qemu_devicedel($vmid, "cpu$i");
3799 my $currentrunningvcpus = undef;
3801 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3802 last if scalar(@{$currentrunningvcpus}) == $i-1;
3803 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3807 #update conf after each succesfull cpu unplug
3808 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3809 PVE::QemuConfig->write_config($vmid, $conf);
3812 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3818 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3819 die "vcpus in running vm does not match its configuration\n"
3820 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3822 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3824 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3825 my $cpustr = print_cpu_device($conf, $i);
3826 qemu_deviceadd($vmid, $cpustr);
3829 my $currentrunningvcpus = undef;
3831 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3832 last if scalar(@{$currentrunningvcpus}) == $i;
3833 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3837 #update conf after each succesfull cpu hotplug
3838 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3839 PVE::QemuConfig->write_config($vmid, $conf);
3843 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3844 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3849 sub qemu_block_set_io_throttle {
3850 my ($vmid, $deviceid,
3851 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3852 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3853 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3854 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3856 return if !check_running($vmid) ;
3858 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3860 bps_rd => int($bps_rd),
3861 bps_wr => int($bps_wr),
3863 iops_rd => int($iops_rd),
3864 iops_wr => int($iops_wr),
3865 bps_max => int($bps_max),
3866 bps_rd_max => int($bps_rd_max),
3867 bps_wr_max => int($bps_wr_max),
3868 iops_max => int($iops_max),
3869 iops_rd_max => int($iops_rd_max),
3870 iops_wr_max => int($iops_wr_max),
3871 bps_max_length => int($bps_max_length),
3872 bps_rd_max_length => int($bps_rd_max_length),
3873 bps_wr_max_length => int($bps_wr_max_length),
3874 iops_max_length => int($iops_max_length),
3875 iops_rd_max_length => int($iops_rd_max_length),
3876 iops_wr_max_length => int($iops_wr_max_length),
3881 # old code, only used to shutdown old VM after update
3883 my ($fh, $timeout) = @_;
3885 my $sel = new IO::Select;
3892 while (scalar (@ready = $sel->can_read($timeout))) {
3894 if ($count = $fh->sysread($buf, 8192)) {
3895 if ($buf =~ /^(.*)\(qemu\) $/s) {
3902 if (!defined($count)) {
3909 die "monitor read timeout\n" if !scalar(@ready);
3914 # old code, only used to shutdown old VM after update
3915 sub vm_monitor_command {
3916 my ($vmid, $cmdstr, $nocheck) = @_;
3921 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3923 my $sname = "${var_run_tmpdir}/$vmid.mon";
3925 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3926 die "unable to connect to VM $vmid socket - $!\n";
3930 # hack: migrate sometime blocks the monitor (when migrate_downtime
3932 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3933 $timeout = 60*60; # 1 hour
3937 my $data = __read_avail($sock, $timeout);
3939 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3940 die "got unexpected qemu monitor banner\n";
3943 my $sel = new IO::Select;
3946 if (!scalar(my @ready = $sel->can_write($timeout))) {
3947 die "monitor write error - timeout";
3950 my $fullcmd = "$cmdstr\r";
3952 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3955 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3956 die "monitor write error - $!";
3959 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3963 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3964 $timeout = 60*60; # 1 hour
3965 } elsif ($cmdstr =~ m/^(eject|change)/) {
3966 $timeout = 60; # note: cdrom mount command is slow
3968 if ($res = __read_avail($sock, $timeout)) {
3970 my @lines = split("\r?\n", $res);
3972 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3974 $res = join("\n", @lines);
3982 syslog("err", "VM $vmid monitor command failed - $err");
3989 sub qemu_block_resize {
3990 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3992 my $running = check_running($vmid);
3994 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3996 return if !$running;
3998 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4002 sub qemu_volume_snapshot {
4003 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4005 my $running = check_running($vmid);
4007 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4008 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4010 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4014 sub qemu_volume_snapshot_delete {
4015 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4017 my $running = check_running($vmid);
4019 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4021 return if !$running;
4023 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4026 sub set_migration_caps {
4032 "auto-converge" => 1,
4034 "x-rdma-pin-all" => 0,
4039 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4041 for my $supported_capability (@$supported_capabilities) {
4043 capability => $supported_capability->{capability},
4044 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4048 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4051 my $fast_plug_option = {
4061 # hotplug changes in [PENDING]
4062 # $selection hash can be used to only apply specified options, for
4063 # example: { cores => 1 } (only apply changed 'cores
')
4064 # $errors ref is used to return error messages
4065 sub vmconfig_hotplug_pending {
4066 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4068 my $defaults = load_defaults();
4070 # commit values which do not have any impact on running VM first
4071 # Note: those option cannot raise errors, we we do not care about
4072 # $selection and always apply them.
4074 my $add_error = sub {
4075 my ($opt, $msg) = @_;
4076 $errors->{$opt} = "hotplug problem - $msg";
4080 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4081 if ($fast_plug_option->{$opt}) {
4082 $conf->{$opt} = $conf->{pending}->{$opt};
4083 delete $conf->{pending}->{$opt};
4089 PVE::QemuConfig->write_config($vmid, $conf);
4090 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4093 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4095 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4096 while (my ($opt, $force) = each %$pending_delete_hash) {
4097 next if $selection && !$selection->{$opt};
4099 if ($opt eq 'hotplug
') {
4100 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4101 } elsif ($opt eq 'tablet
') {
4102 die "skip\n" if !$hotplug_features->{usb};
4103 if ($defaults->{tablet}) {
4104 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4106 vm_deviceunplug($vmid, $conf, $opt);
4108 } elsif ($opt =~ m/^usb\d+/) {
4110 # since we cannot reliably hot unplug usb devices
4111 # we are disabling it
4112 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4113 vm_deviceunplug($vmid, $conf, $opt);
4114 } elsif ($opt eq 'vcpus
') {
4115 die "skip\n" if !$hotplug_features->{cpu};
4116 qemu_cpu_hotplug($vmid, $conf, undef);
4117 } elsif ($opt eq 'balloon
') {
4118 # enable balloon device is not hotpluggable
4119 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4120 } elsif ($fast_plug_option->{$opt}) {
4122 } elsif ($opt =~ m/^net(\d+)$/) {
4123 die "skip\n" if !$hotplug_features->{network};
4124 vm_deviceunplug($vmid, $conf, $opt);
4125 } elsif (is_valid_drivename($opt)) {
4126 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4127 vm_deviceunplug($vmid, $conf, $opt);
4128 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4129 } elsif ($opt =~ m/^memory$/) {
4130 die "skip\n" if !$hotplug_features->{memory};
4131 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4132 } elsif ($opt eq 'cpuunits
') {
4133 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4134 } elsif ($opt eq 'cpulimit
') {
4135 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4141 &$add_error($opt, $err) if $err ne "skip\n";
4143 # save new config if hotplug was successful
4144 delete $conf->{$opt};
4145 vmconfig_undelete_pending_option($conf, $opt);
4146 PVE::QemuConfig->write_config($vmid, $conf);
4147 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4151 foreach my $opt (keys %{$conf->{pending}}) {
4152 next if $selection && !$selection->{$opt};
4153 my $value = $conf->{pending}->{$opt};
4155 if ($opt eq 'hotplug
') {
4156 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4157 } elsif ($opt eq 'tablet
') {
4158 die "skip\n" if !$hotplug_features->{usb};
4160 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4161 } elsif ($value == 0) {
4162 vm_deviceunplug($vmid, $conf, $opt);
4164 } elsif ($opt =~ m/^usb\d+$/) {
4166 # since we cannot reliably hot unplug usb devices
4167 # we are disabling it
4168 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4169 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4170 die "skip\n" if !$d;
4171 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4172 } elsif ($opt eq 'vcpus
') {
4173 die "skip\n" if !$hotplug_features->{cpu};
4174 qemu_cpu_hotplug($vmid, $conf, $value);
4175 } elsif ($opt eq 'balloon
') {
4176 # enable/disable balloning device is not hotpluggable
4177 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4178 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4179 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4181 # allow manual ballooning if shares is set to zero
4182 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4183 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4184 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4186 } elsif ($opt =~ m/^net(\d+)$/) {
4187 # some changes can be done without hotplug
4188 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4189 $vmid, $opt, $value);
4190 } elsif (is_valid_drivename($opt)) {
4191 # some changes can be done without hotplug
4192 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4193 $vmid, $opt, $value, 1);
4194 } elsif ($opt =~ m/^memory$/) { #dimms
4195 die "skip\n" if !$hotplug_features->{memory};
4196 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4197 } elsif ($opt eq 'cpuunits
') {
4198 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4199 } elsif ($opt eq 'cpulimit
') {
4200 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4201 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4203 die "skip\n"; # skip non-hot-pluggable options
4207 &$add_error($opt, $err) if $err ne "skip\n";
4209 # save new config if hotplug was successful
4210 $conf->{$opt} = $value;
4211 delete $conf->{pending}->{$opt};
4212 PVE::QemuConfig->write_config($vmid, $conf);
4213 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4218 sub try_deallocate_drive {
4219 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4221 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4222 my $volid = $drive->{file};
4223 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4224 my $sid = PVE::Storage::parse_volume_id($volid);
4225 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4227 # check if the disk is really unused
4228 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4229 if is_volume_in_use($storecfg, $conf, $key, $volid);
4230 PVE::Storage::vdisk_free($storecfg, $volid);
4233 # If vm is not owner of this disk remove from config
4241 sub vmconfig_delete_or_detach_drive {
4242 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4244 my $drive = parse_drive($opt, $conf->{$opt});
4246 my $rpcenv = PVE::RPCEnvironment::get();
4247 my $authuser = $rpcenv->get_user();
4250 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4251 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4253 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4257 sub vmconfig_apply_pending {
4258 my ($vmid, $conf, $storecfg) = @_;
4262 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4263 while (my ($opt, $force) = each %$pending_delete_hash) {
4264 die "internal error" if $opt =~ m/^unused/;
4265 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4266 if (!defined($conf->{$opt})) {
4267 vmconfig_undelete_pending_option($conf, $opt);
4268 PVE::QemuConfig->write_config($vmid, $conf);
4269 } elsif (is_valid_drivename($opt)) {
4270 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4271 vmconfig_undelete_pending_option($conf, $opt);
4272 delete $conf->{$opt};
4273 PVE::QemuConfig->write_config($vmid, $conf);
4275 vmconfig_undelete_pending_option($conf, $opt);
4276 delete $conf->{$opt};
4277 PVE::QemuConfig->write_config($vmid, $conf);
4281 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4283 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4284 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4286 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4287 # skip if nothing changed
4288 } elsif (is_valid_drivename($opt)) {
4289 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4290 if defined($conf->{$opt});
4291 $conf->{$opt} = $conf->{pending}->{$opt};
4293 $conf->{$opt} = $conf->{pending}->{$opt};
4296 delete $conf->{pending}->{$opt};
4297 PVE::QemuConfig->write_config($vmid, $conf);
4301 my $safe_num_ne = sub {
4304 return 0 if !defined($a) && !defined($b);
4305 return 1 if !defined($a);
4306 return 1 if !defined($b);
4311 my $safe_string_ne = sub {
4314 return 0 if !defined($a) && !defined($b);
4315 return 1 if !defined($a);
4316 return 1 if !defined($b);
4321 sub vmconfig_update_net {
4322 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4324 my $newnet = parse_net($value);
4326 if ($conf->{$opt}) {
4327 my $oldnet = parse_net($conf->{$opt});
4329 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4330 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4331 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4332 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4334 # for non online change, we try to hot-unplug
4335 die "skip\n" if !$hotplug;
4336 vm_deviceunplug($vmid, $conf, $opt);
4339 die "internal error" if $opt !~ m/net(\d+)/;
4340 my $iface = "tap${vmid}i$1";
4342 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4343 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4344 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4345 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4346 PVE::Network::tap_unplug($iface);
4347 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4348 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4349 # Rate can be applied on its own but any change above needs to
4350 # include the rate in tap_plug since OVS resets everything.
4351 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4354 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4355 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4363 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4369 sub vmconfig_update_disk {
4370 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4372 # fixme: do we need force?
4374 my $drive = parse_drive($opt, $value);
4376 if ($conf->{$opt}) {
4378 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4380 my $media = $drive->{media} || 'disk
';
4381 my $oldmedia = $old_drive->{media} || 'disk
';
4382 die "unable to change media type\n" if $media ne $oldmedia;
4384 if (!drive_is_cdrom($old_drive)) {
4386 if ($drive->{file} ne $old_drive->{file}) {
4388 die "skip\n" if !$hotplug;
4390 # unplug and register as unused
4391 vm_deviceunplug($vmid, $conf, $opt);
4392 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4395 # update existing disk
4397 # skip non hotpluggable value
4398 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4399 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4400 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4401 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4406 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4407 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4408 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4409 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4410 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4411 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4412 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4413 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4414 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4415 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4416 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4417 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4418 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4419 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4420 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4421 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4422 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4423 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4425 qemu_block_set_io_throttle($vmid,"drive-$opt",
4426 ($drive->{mbps} || 0)*1024*1024,
4427 ($drive->{mbps_rd} || 0)*1024*1024,
4428 ($drive->{mbps_wr} || 0)*1024*1024,
4429 $drive->{iops} || 0,
4430 $drive->{iops_rd} || 0,
4431 $drive->{iops_wr} || 0,
4432 ($drive->{mbps_max} || 0)*1024*1024,
4433 ($drive->{mbps_rd_max} || 0)*1024*1024,
4434 ($drive->{mbps_wr_max} || 0)*1024*1024,
4435 $drive->{iops_max} || 0,
4436 $drive->{iops_rd_max} || 0,
4437 $drive->{iops_wr_max} || 0,
4438 $drive->{bps_max_length} || 1,
4439 $drive->{bps_rd_max_length} || 1,
4440 $drive->{bps_wr_max_length} || 1,
4441 $drive->{iops_max_length} || 1,
4442 $drive->{iops_rd_max_length} || 1,
4443 $drive->{iops_wr_max_length} || 1);
4452 if ($drive->{file} eq 'none
') {
4453 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4455 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4456 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4457 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4465 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4467 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4468 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4472 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4473 $forcemachine, $spice_ticket, $migration_network, $migration_type) = @_;
4475 PVE::QemuConfig->lock_config($vmid, sub {
4476 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4478 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4480 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4482 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4484 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4485 vmconfig_apply_pending($vmid, $conf, $storecfg);
4486 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4489 my $defaults = load_defaults();
4491 # set environment variable useful inside network script
4492 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4494 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4496 my $migrate_port = 0;
4499 if ($statefile eq 'tcp
') {
4500 my $localip = "localhost";
4501 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4502 my $nodename = PVE::INotify::nodename();
4504 if ($migration_type eq 'insecure
') {
4505 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4506 if ($migrate_network_addr) {
4507 $localip = $migrate_network_addr;
4509 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4512 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4515 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4516 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4517 $migrate_uri = "tcp:${localip}:${migrate_port}";
4518 push @$cmd, '-incoming
', $migrate_uri;
4521 } elsif ($statefile eq 'unix
') {
4522 # should be default for secure migrations as a ssh TCP forward
4523 # tunnel is not deterministic reliable ready and fails regurarly
4524 # to set up in time, so use UNIX socket forwards
4525 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4526 unlink $socket_addr;
4528 $migrate_uri = "unix:$socket_addr";
4530 push @$cmd, '-incoming
', $migrate_uri;
4534 push @$cmd, '-loadstate
', $statefile;
4541 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4542 my $d = parse_hostpci($conf->{"hostpci$i"});
4544 my $pcidevices = $d->{pciid};
4545 foreach my $pcidevice (@$pcidevices) {
4546 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4548 my $info = pci_device_info("0000:$pciid");
4549 die "IOMMU not present\n" if !check_iommu_support();
4550 die "no pci device info for device '$pciid'\n" if !$info;
4551 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4552 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4556 PVE::Storage::activate_volumes($storecfg, $vollist);
4558 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4560 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4561 eval { run_command($cmd); };
4564 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4565 : $defaults->{cpuunits};
4567 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4570 Slice => 'qemu
.slice
',
4572 CPUShares => $cpuunits
4575 if (my $cpulimit = $conf->{cpulimit}) {
4576 $properties{CPUQuota} = int($cpulimit * 100);
4578 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4580 if ($conf->{hugepages}) {
4583 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4584 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4586 PVE::QemuServer::Memory::hugepages_mount();
4587 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4590 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4591 run_command($cmd, %run_params);
4595 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4599 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4601 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4605 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4606 run_command($cmd, %run_params);
4611 # deactivate volumes if start fails
4612 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4613 die "start failed: $err";
4616 print "migration listens on $migrate_uri\n" if $migrate_uri;
4618 if ($statefile && $statefile ne 'tcp
') {
4619 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4623 if ($migratedfrom) {
4626 set_migration_caps($vmid);
4631 print "spice listens on port $spice_port\n";
4632 if ($spice_ticket) {
4633 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4634 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4640 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4641 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4642 if $conf->{balloon};
4645 foreach my $opt (keys %$conf) {
4646 next if $opt !~ m/^net\d+$/;
4647 my $nicconf = parse_net($conf->{$opt});
4648 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4652 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4653 path => "machine/peripheral/balloon0",
4654 property => "guest-stats-polling-interval",
4655 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4661 my ($vmid, $execute, %params) = @_;
4663 my $cmd = { execute => $execute, arguments => \%params };
4664 vm_qmp_command($vmid, $cmd);
4667 sub vm_mon_cmd_nocheck {
4668 my ($vmid, $execute, %params) = @_;
4670 my $cmd = { execute => $execute, arguments => \%params };
4671 vm_qmp_command($vmid, $cmd, 1);
4674 sub vm_qmp_command {
4675 my ($vmid, $cmd, $nocheck) = @_;
4680 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4681 $timeout = $cmd->{arguments}->{timeout};
4682 delete $cmd->{arguments}->{timeout};
4686 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4687 my $sname = qmp_socket($vmid);
4688 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4689 my $qmpclient = PVE::QMPClient->new();
4691 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4692 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4693 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4694 if scalar(%{$cmd->{arguments}});
4695 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4697 die "unable to
open monitor
socket\n";
4701 syslog("err
", "VM
$vmid qmp command failed
- $err");
4708 sub vm_human_monitor_command {
4709 my ($vmid, $cmdline) = @_;
4714 execute => 'human-monitor-command',
4715 arguments => { 'command-line' => $cmdline},
4718 return vm_qmp_command($vmid, $cmd);
4721 sub vm_commandline {
4722 my ($storecfg, $vmid) = @_;
4724 my $conf = PVE::QemuConfig->load_config($vmid);
4726 my $defaults = load_defaults();
4728 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4730 return PVE::Tools::cmd2string($cmd);
4734 my ($vmid, $skiplock) = @_;
4736 PVE::QemuConfig->lock_config($vmid, sub {
4738 my $conf = PVE::QemuConfig->load_config($vmid);
4740 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4742 vm_mon_cmd($vmid, "system_reset
");
4746 sub get_vm_volumes {
4750 foreach_volid($conf, sub {
4751 my ($volid, $is_cdrom) = @_;
4753 return if $volid =~ m|^/|;
4755 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4758 push @$vollist, $volid;
4764 sub vm_stop_cleanup {
4765 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4770 my $vollist = get_vm_volumes($conf);
4771 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4774 foreach my $ext (qw(mon qmp pid vnc qga)) {
4775 unlink "/var/run/qemu-server/${vmid}.$ext";
4778 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4780 warn $@ if $@; # avoid errors - just warn
4783 # Note: use $nockeck to skip tests if VM configuration file exists.
4784 # We need that when migration VMs to other nodes (files already moved)
4785 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4787 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4789 $force = 1 if !defined($force) && !$shutdown;
4792 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4793 kill 15, $pid if $pid;
4794 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4795 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4799 PVE
::QemuConfig-
>lock_config($vmid, sub {
4801 my $pid = check_running
($vmid, $nocheck);
4806 $conf = PVE
::QemuConfig-
>load_config($vmid);
4807 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4808 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4809 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4810 $timeout = $opts->{down
} if $opts->{down
};
4814 $timeout = 60 if !defined($timeout);
4818 if (defined($conf) && $conf->{agent
}) {
4819 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4821 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4824 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4831 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4836 if ($count >= $timeout) {
4838 warn "VM still running - terminating now with SIGTERM\n";
4841 die "VM quit/powerdown failed - got timeout\n";
4844 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4849 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4852 die "VM quit/powerdown failed\n";
4860 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4865 if ($count >= $timeout) {
4866 warn "VM still running - terminating now with SIGKILL\n";
4871 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4876 my ($vmid, $skiplock) = @_;
4878 PVE
::QemuConfig-
>lock_config($vmid, sub {
4880 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4882 PVE
::QemuConfig-
>check_lock($conf)
4883 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4885 vm_mon_cmd
($vmid, "stop");
4890 my ($vmid, $skiplock, $nocheck) = @_;
4892 PVE
::QemuConfig-
>lock_config($vmid, sub {
4896 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4898 PVE
::QemuConfig-
>check_lock($conf)
4899 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4901 vm_mon_cmd
($vmid, "cont");
4904 vm_mon_cmd_nocheck
($vmid, "cont");
4910 my ($vmid, $skiplock, $key) = @_;
4912 PVE
::QemuConfig-
>lock_config($vmid, sub {
4914 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4916 # there is no qmp command, so we use the human monitor command
4917 vm_human_monitor_command
($vmid, "sendkey $key");
4922 my ($storecfg, $vmid, $skiplock) = @_;
4924 PVE
::QemuConfig-
>lock_config($vmid, sub {
4926 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4928 if (!check_running
($vmid)) {
4929 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4931 die "VM $vmid is running - destroy failed\n";
4939 my ($filename, $buf) = @_;
4941 my $fh = IO
::File-
>new($filename, "w");
4942 return undef if !$fh;
4944 my $res = print $fh $buf;
4951 sub pci_device_info
{
4956 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4957 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4959 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4960 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4962 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4963 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4965 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4966 return undef if !defined($product) || $product !~ s/^0x//;
4971 product
=> $product,
4977 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4986 my $name = $dev->{name
};
4988 my $fn = "$pcisysfs/devices/$name/reset";
4990 return file_write
($fn, "1");
4993 sub pci_dev_bind_to_vfio
{
4996 my $name = $dev->{name
};
4998 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5000 if (!-d
$vfio_basedir) {
5001 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5003 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5005 my $testdir = "$vfio_basedir/$name";
5006 return 1 if -d
$testdir;
5008 my $data = "$dev->{vendor} $dev->{product}";
5009 return undef if !file_write
("$vfio_basedir/new_id", $data);
5011 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5012 if (!file_write
($fn, $name)) {
5013 return undef if -f
$fn;
5016 $fn = "$vfio_basedir/bind";
5017 if (! -d
$testdir) {
5018 return undef if !file_write
($fn, $name);
5024 sub pci_dev_group_bind_to_vfio
{
5027 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5029 if (!-d
$vfio_basedir) {
5030 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5032 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5034 # get IOMMU group devices
5035 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5036 my @devs = grep /^0000:/, readdir($D);
5039 foreach my $pciid (@devs) {
5040 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5042 # pci bridges, switches or root ports are not supported
5043 # they have a pci_bus subdirectory so skip them
5044 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5046 my $info = pci_device_info
($1);
5047 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5053 # vzdump restore implementaion
5055 sub tar_archive_read_firstfile
{
5056 my $archive = shift;
5058 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5060 # try to detect archive type first
5061 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5062 die "unable to open file '$archive'\n";
5063 my $firstfile = <$fh>;
5067 die "ERROR: archive contaions no data\n" if !$firstfile;
5073 sub tar_restore_cleanup
{
5074 my ($storecfg, $statfile) = @_;
5076 print STDERR
"starting cleanup\n";
5078 if (my $fd = IO
::File-
>new($statfile, "r")) {
5079 while (defined(my $line = <$fd>)) {
5080 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5083 if ($volid =~ m
|^/|) {
5084 unlink $volid || die 'unlink failed\n';
5086 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5088 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5090 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5092 print STDERR
"unable to parse line in statfile - $line";
5099 sub restore_archive
{
5100 my ($archive, $vmid, $user, $opts) = @_;
5102 my $format = $opts->{format
};
5105 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5106 $format = 'tar' if !$format;
5108 } elsif ($archive =~ m/\.tar$/) {
5109 $format = 'tar' if !$format;
5110 } elsif ($archive =~ m/.tar.lzo$/) {
5111 $format = 'tar' if !$format;
5113 } elsif ($archive =~ m/\.vma$/) {
5114 $format = 'vma' if !$format;
5115 } elsif ($archive =~ m/\.vma\.gz$/) {
5116 $format = 'vma' if !$format;
5118 } elsif ($archive =~ m/\.vma\.lzo$/) {
5119 $format = 'vma' if !$format;
5122 $format = 'vma' if !$format; # default
5125 # try to detect archive format
5126 if ($format eq 'tar') {
5127 return restore_tar_archive
($archive, $vmid, $user, $opts);
5129 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5133 sub restore_update_config_line
{
5134 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5136 return if $line =~ m/^\#qmdump\#/;
5137 return if $line =~ m/^\#vzdump\#/;
5138 return if $line =~ m/^lock:/;
5139 return if $line =~ m/^unused\d+:/;
5140 return if $line =~ m/^parent:/;
5141 return if $line =~ m/^template:/; # restored VM is never a template
5143 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5144 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5145 # try to convert old 1.X settings
5146 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5147 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5148 my ($model, $macaddr) = split(/\=/, $devconfig);
5149 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5152 bridge
=> "vmbr$ind",
5153 macaddr
=> $macaddr,
5155 my $netstr = print_net
($net);
5157 print $outfd "net$cookie->{netcount}: $netstr\n";
5158 $cookie->{netcount
}++;
5160 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5161 my ($id, $netstr) = ($1, $2);
5162 my $net = parse_net
($netstr);
5163 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5164 $netstr = print_net
($net);
5165 print $outfd "$id: $netstr\n";
5166 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5169 my $di = parse_drive
($virtdev, $value);
5170 if (defined($di->{backup
}) && !$di->{backup
}) {
5171 print $outfd "#$line";
5172 } elsif ($map->{$virtdev}) {
5173 delete $di->{format
}; # format can change on restore
5174 $di->{file
} = $map->{$virtdev};
5175 $value = print_drive
($vmid, $di);
5176 print $outfd "$virtdev: $value\n";
5186 my ($cfg, $vmid) = @_;
5188 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5190 my $volid_hash = {};
5191 foreach my $storeid (keys %$info) {
5192 foreach my $item (@{$info->{$storeid}}) {
5193 next if !($item->{volid
} && $item->{size
});
5194 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5195 $volid_hash->{$item->{volid
}} = $item;
5202 sub is_volume_in_use
{
5203 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5205 my $path = PVE
::Storage
::path
($storecfg, $volid);
5207 my $scan_config = sub {
5208 my ($cref, $snapname) = @_;
5210 foreach my $key (keys %$cref) {
5211 my $value = $cref->{$key};
5212 if (is_valid_drivename
($key)) {
5213 next if $skip_drive && $key eq $skip_drive;
5214 my $drive = parse_drive
($key, $value);
5215 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5216 return 1 if $volid eq $drive->{file
};
5217 if ($drive->{file
} =~ m!^/!) {
5218 return 1 if $drive->{file
} eq $path;
5220 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5222 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5224 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5232 return 1 if &$scan_config($conf);
5236 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5237 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5243 sub update_disksize
{
5244 my ($vmid, $conf, $volid_hash) = @_;
5250 # Note: it is allowed to define multiple storages with same path (alias), so
5251 # we need to check both 'volid' and real 'path' (two different volid can point
5252 # to the same path).
5257 foreach my $opt (keys %$conf) {
5258 if (is_valid_drivename
($opt)) {
5259 my $drive = parse_drive
($opt, $conf->{$opt});
5260 my $volid = $drive->{file
};
5263 $used->{$volid} = 1;
5264 if ($volid_hash->{$volid} &&
5265 (my $path = $volid_hash->{$volid}->{path
})) {
5266 $usedpath->{$path} = 1;
5269 next if drive_is_cdrom
($drive);
5270 next if !$volid_hash->{$volid};
5272 $drive->{size
} = $volid_hash->{$volid}->{size
};
5273 my $new = print_drive
($vmid, $drive);
5274 if ($new ne $conf->{$opt}) {
5276 $conf->{$opt} = $new;
5281 # remove 'unusedX' entry if volume is used
5282 foreach my $opt (keys %$conf) {
5283 next if $opt !~ m/^unused\d+$/;
5284 my $volid = $conf->{$opt};
5285 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5286 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5288 delete $conf->{$opt};
5292 foreach my $volid (sort keys %$volid_hash) {
5293 next if $volid =~ m/vm-$vmid-state-/;
5294 next if $used->{$volid};
5295 my $path = $volid_hash->{$volid}->{path
};
5296 next if !$path; # just to be sure
5297 next if $usedpath->{$path};
5299 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5300 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5307 my ($vmid, $nolock) = @_;
5309 my $cfg = PVE
::Storage
::config
();
5311 my $volid_hash = scan_volids
($cfg, $vmid);
5313 my $updatefn = sub {
5316 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5318 PVE
::QemuConfig-
>check_lock($conf);
5321 foreach my $volid (keys %$volid_hash) {
5322 my $info = $volid_hash->{$volid};
5323 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5326 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5328 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5331 if (defined($vmid)) {
5335 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5338 my $vmlist = config_list
();
5339 foreach my $vmid (keys %$vmlist) {
5343 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5349 sub restore_vma_archive
{
5350 my ($archive, $vmid, $user, $opts, $comp) = @_;
5352 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5353 my $readfrom = $archive;
5358 my $qarchive = PVE
::Tools
::shellquote
($archive);
5359 if ($comp eq 'gzip') {
5360 $uncomp = "zcat $qarchive|";
5361 } elsif ($comp eq 'lzop') {
5362 $uncomp = "lzop -d -c $qarchive|";
5364 die "unknown compression method '$comp'\n";
5369 my $tmpdir = "/var/tmp/vzdumptmp$$";
5372 # disable interrupts (always do cleanups)
5373 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5374 warn "got interrupt - ignored\n";
5377 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5378 POSIX
::mkfifo
($mapfifo, 0600);
5381 my $openfifo = sub {
5382 open($fifofh, '>', $mapfifo) || die $!;
5385 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5392 my $rpcenv = PVE
::RPCEnvironment
::get
();
5394 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5395 my $tmpfn = "$conffile.$$.tmp";
5397 # Note: $oldconf is undef if VM does not exists
5398 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5399 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5401 my $print_devmap = sub {
5402 my $virtdev_hash = {};
5404 my $cfgfn = "$tmpdir/qemu-server.conf";
5406 # we can read the config - that is already extracted
5407 my $fh = IO
::File-
>new($cfgfn, "r") ||
5408 "unable to read qemu-server.conf - $!\n";
5410 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5412 my $pve_firewall_dir = '/etc/pve/firewall';
5413 mkdir $pve_firewall_dir; # make sure the dir exists
5414 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5417 while (defined(my $line = <$fh>)) {
5418 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5419 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5420 die "archive does not contain data for drive '$virtdev'\n"
5421 if !$devinfo->{$devname};
5422 if (defined($opts->{storage
})) {
5423 $storeid = $opts->{storage
} || 'local';
5424 } elsif (!$storeid) {
5427 $format = 'raw' if !$format;
5428 $devinfo->{$devname}->{devname
} = $devname;
5429 $devinfo->{$devname}->{virtdev
} = $virtdev;
5430 $devinfo->{$devname}->{format
} = $format;
5431 $devinfo->{$devname}->{storeid
} = $storeid;
5433 # check permission on storage
5434 my $pool = $opts->{pool
}; # todo: do we need that?
5435 if ($user ne 'root@pam') {
5436 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5439 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5443 foreach my $devname (keys %$devinfo) {
5444 die "found no device mapping information for device '$devname'\n"
5445 if !$devinfo->{$devname}->{virtdev
};
5448 my $cfg = PVE
::Storage
::config
();
5450 # create empty/temp config
5452 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5453 foreach_drive
($oldconf, sub {
5454 my ($ds, $drive) = @_;
5456 return if drive_is_cdrom
($drive);
5458 my $volid = $drive->{file
};
5460 return if !$volid || $volid =~ m
|^/|;
5462 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5463 return if !$path || !$owner || ($owner != $vmid);
5465 # Note: only delete disk we want to restore
5466 # other volumes will become unused
5467 if ($virtdev_hash->{$ds}) {
5468 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5475 # delete vmstate files
5476 # since after the restore we have no snapshots anymore
5477 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5478 my $snap = $oldconf->{snapshots
}->{$snapname};
5479 if ($snap->{vmstate
}) {
5480 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5489 foreach my $virtdev (sort keys %$virtdev_hash) {
5490 my $d = $virtdev_hash->{$virtdev};
5491 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5492 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5494 # test if requested format is supported
5495 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5496 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5497 $d->{format
} = $defFormat if !$supported;
5499 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5500 $d->{format
}, undef, $alloc_size);
5501 print STDERR
"new volume ID is '$volid'\n";
5502 $d->{volid
} = $volid;
5503 my $path = PVE
::Storage
::path
($cfg, $volid);
5505 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5507 my $write_zeros = 1;
5508 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5512 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5514 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5515 $map->{$virtdev} = $volid;
5518 $fh->seek(0, 0) || die "seek failed - $!\n";
5520 my $outfd = new IO
::File
($tmpfn, "w") ||
5521 die "unable to write config for VM $vmid\n";
5523 my $cookie = { netcount
=> 0 };
5524 while (defined(my $line = <$fh>)) {
5525 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5534 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5535 die "interrupted by signal\n";
5537 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5539 $oldtimeout = alarm($timeout);
5546 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5547 my ($dev_id, $size, $devname) = ($1, $2, $3);
5548 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5549 } elsif ($line =~ m/^CTIME: /) {
5550 # we correctly received the vma config, so we can disable
5551 # the timeout now for disk allocation (set to 10 minutes, so
5552 # that we always timeout if something goes wrong)
5555 print $fifofh "done\n";
5556 my $tmp = $oldtimeout || 0;
5557 $oldtimeout = undef;
5563 print "restore vma archive: $cmd\n";
5564 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5568 alarm($oldtimeout) if $oldtimeout;
5571 foreach my $devname (keys %$devinfo) {
5572 my $volid = $devinfo->{$devname}->{volid
};
5573 push @$vollist, $volid if $volid;
5576 my $cfg = PVE
::Storage
::config
();
5577 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5585 foreach my $devname (keys %$devinfo) {
5586 my $volid = $devinfo->{$devname}->{volid
};
5589 if ($volid =~ m
|^/|) {
5590 unlink $volid || die 'unlink failed\n';
5592 PVE
::Storage
::vdisk_free
($cfg, $volid);
5594 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5596 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5603 rename($tmpfn, $conffile) ||
5604 die "unable to commit configuration file '$conffile'\n";
5606 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5608 eval { rescan
($vmid, 1); };
5612 sub restore_tar_archive
{
5613 my ($archive, $vmid, $user, $opts) = @_;
5615 if ($archive ne '-') {
5616 my $firstfile = tar_archive_read_firstfile
($archive);
5617 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5618 if $firstfile ne 'qemu-server.conf';
5621 my $storecfg = PVE
::Storage
::config
();
5623 # destroy existing data - keep empty config
5624 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5625 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5627 my $tocmd = "/usr/lib/qemu-server/qmextract";
5629 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5630 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5631 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5632 $tocmd .= ' --info' if $opts->{info
};
5634 # tar option "xf" does not autodetect compression when read from STDIN,
5635 # so we pipe to zcat
5636 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5637 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5639 my $tmpdir = "/var/tmp/vzdumptmp$$";
5642 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5643 local $ENV{VZDUMP_VMID
} = $vmid;
5644 local $ENV{VZDUMP_USER
} = $user;
5646 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5647 my $tmpfn = "$conffile.$$.tmp";
5649 # disable interrupts (always do cleanups)
5650 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5651 print STDERR
"got interrupt - ignored\n";
5656 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5657 die "interrupted by signal\n";
5660 if ($archive eq '-') {
5661 print "extracting archive from STDIN\n";
5662 run_command
($cmd, input
=> "<&STDIN");
5664 print "extracting archive '$archive'\n";
5668 return if $opts->{info
};
5672 my $statfile = "$tmpdir/qmrestore.stat";
5673 if (my $fd = IO
::File-
>new($statfile, "r")) {
5674 while (defined (my $line = <$fd>)) {
5675 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5676 $map->{$1} = $2 if $1;
5678 print STDERR
"unable to parse line in statfile - $line\n";
5684 my $confsrc = "$tmpdir/qemu-server.conf";
5686 my $srcfd = new IO
::File
($confsrc, "r") ||
5687 die "unable to open file '$confsrc'\n";
5689 my $outfd = new IO
::File
($tmpfn, "w") ||
5690 die "unable to write config for VM $vmid\n";
5692 my $cookie = { netcount
=> 0 };
5693 while (defined (my $line = <$srcfd>)) {
5694 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5706 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5713 rename $tmpfn, $conffile ||
5714 die "unable to commit configuration file '$conffile'\n";
5716 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5718 eval { rescan
($vmid, 1); };
5722 sub foreach_writable_storage
{
5723 my ($conf, $func) = @_;
5727 foreach my $ds (keys %$conf) {
5728 next if !is_valid_drivename
($ds);
5730 my $drive = parse_drive
($ds, $conf->{$ds});
5732 next if drive_is_cdrom
($drive);
5734 my $volid = $drive->{file
};
5736 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5737 $sidhash->{$sid} = $sid if $sid;
5740 foreach my $sid (sort keys %$sidhash) {
5745 sub do_snapshots_with_qemu
{
5746 my ($storecfg, $volid) = @_;
5748 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5750 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5751 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5755 if ($volid =~ m/\.(qcow2|qed)$/){
5762 sub qga_check_running
{
5765 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5767 warn "Qemu Guest Agent are not running - $@";
5773 sub template_create
{
5774 my ($vmid, $conf, $disk) = @_;
5776 my $storecfg = PVE
::Storage
::config
();
5778 foreach_drive
($conf, sub {
5779 my ($ds, $drive) = @_;
5781 return if drive_is_cdrom
($drive);
5782 return if $disk && $ds ne $disk;
5784 my $volid = $drive->{file
};
5785 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5787 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5788 $drive->{file
} = $voliddst;
5789 $conf->{$ds} = print_drive
($vmid, $drive);
5790 PVE
::QemuConfig-
>write_config($vmid, $conf);
5794 sub qemu_img_convert
{
5795 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5797 my $storecfg = PVE
::Storage
::config
();
5798 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5799 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5801 if ($src_storeid && $dst_storeid) {
5803 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5805 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5806 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5808 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5809 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5811 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5812 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5815 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5816 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5817 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5818 if ($is_zero_initialized) {
5819 push @$cmd, "zeroinit:$dst_path";
5821 push @$cmd, $dst_path;
5826 if($line =~ m/\((\S+)\/100\
%\)/){
5828 my $transferred = int($size * $percent / 100);
5829 my $remaining = $size - $transferred;
5831 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5836 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5838 die "copy failed: $err" if $err;
5842 sub qemu_img_format
{
5843 my ($scfg, $volname) = @_;
5845 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5852 sub qemu_drive_mirror
{
5853 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5855 my $storecfg = PVE
::Storage
::config
();
5856 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5858 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5860 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5862 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5864 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5866 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5867 $opts->{format
} = $format if $format;
5869 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5871 my $finish_job = sub {
5873 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5874 my $stat = @$stats[0];
5881 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5883 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5884 my $stat = @$stats[0];
5885 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5886 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5888 my $busy = $stat->{busy
};
5889 my $ready = $stat->{ready
};
5891 if (my $total = $stat->{len
}) {
5892 my $transferred = $stat->{offset
} || 0;
5893 my $remaining = $total - $transferred;
5894 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5896 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5900 if ($stat->{ready
} eq 'true') {
5902 last if $vmiddst != $vmid;
5904 # try to switch the disk if source and destination are on the same guest
5905 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5910 die $@ if $@ !~ m/cannot be completed/;
5919 my $cancel_job = sub {
5920 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5925 eval { &$cancel_job(); };
5926 die "mirroring error: $err";
5929 if ($vmiddst != $vmid) {
5930 # if we clone a disk for a new target vm, we don't switch the disk
5931 &$cancel_job(); # so we call block-job-cancel
5936 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5937 $newvmid, $storage, $format, $full, $newvollist) = @_;
5942 print "create linked clone of drive $drivename ($drive->{file})\n";
5943 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5944 push @$newvollist, $newvolid;
5946 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5947 $storeid = $storage if $storage;
5949 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5951 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5952 $format = qemu_img_format
($scfg, $volname);
5955 # test if requested format is supported - else use default
5956 my $supported = grep { $_ eq $format } @$validFormats;
5957 $format = $defFormat if !$supported;
5959 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5961 print "create full clone of drive $drivename ($drive->{file})\n";
5962 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5963 push @$newvollist, $newvolid;
5965 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
5967 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5968 if (!$running || $snapname) {
5969 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5972 my $kvmver = get_running_qemu_version
($vmid);
5973 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
5974 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
5975 if $drive->{iothread
};
5978 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5982 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5985 $disk->{format
} = undef;
5986 $disk->{file
} = $newvolid;
5987 $disk->{size
} = $size;
5992 # this only works if VM is running
5993 sub get_current_qemu_machine
{
5996 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5997 my $res = vm_qmp_command
($vmid, $cmd);
5999 my ($current, $default);
6000 foreach my $e (@$res) {
6001 $default = $e->{name
} if $e->{'is-default'};
6002 $current = $e->{name
} if $e->{'is-current'};
6005 # fallback to the default machine if current is not supported by qemu
6006 return $current || $default || 'pc';
6009 sub get_running_qemu_version
{
6011 my $cmd = { execute
=> 'query-version', arguments
=> {} };
6012 my $res = vm_qmp_command
($vmid, $cmd);
6013 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6016 sub qemu_machine_feature_enabled
{
6017 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6022 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6024 $current_major = $3;
6025 $current_minor = $4;
6027 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6029 $current_major = $1;
6030 $current_minor = $2;
6033 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6038 sub qemu_machine_pxe
{
6039 my ($vmid, $conf, $machine) = @_;
6041 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6043 foreach my $opt (keys %$conf) {
6044 next if $opt !~ m/^net(\d+)$/;
6045 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6047 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6048 return $machine.".pxe" if $romfile =~ m/pxe/;
6055 sub qemu_use_old_bios_files
{
6056 my ($machine_type) = @_;
6058 return if !$machine_type;
6060 my $use_old_bios_files = undef;
6062 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6064 $use_old_bios_files = 1;
6066 my $kvmver = kvm_user_version
();
6067 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6068 # load new efi bios files on migration. So this hack is required to allow
6069 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6070 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6071 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6074 return ($use_old_bios_files, $machine_type);
6081 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6082 my (undef, $id, $function) = @_;
6083 my $res = { id
=> $id, function
=> $function};
6084 push @{$devices->{$id}}, $res;
6090 sub vm_iothreads_list
{
6093 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6096 foreach my $iothread (@$res) {
6097 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6104 my ($conf, $drive) = @_;
6108 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6110 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6116 my $controller = int($drive->{index} / $maxdev);
6117 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6119 return ($maxdev, $controller, $controller_prefix);
6122 # bash completion helper
6124 sub complete_backup_archives
{
6125 my ($cmdname, $pname, $cvalue) = @_;
6127 my $cfg = PVE
::Storage
::config
();
6131 if ($cvalue =~ m/^([^:]+):/) {
6135 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6138 foreach my $id (keys %$data) {
6139 foreach my $item (@{$data->{$id}}) {
6140 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6141 push @$res, $item->{volid
} if defined($item->{volid
});
6148 my $complete_vmid_full = sub {
6151 my $idlist = vmstatus
();
6155 foreach my $id (keys %$idlist) {
6156 my $d = $idlist->{$id};
6157 if (defined($running)) {
6158 next if $d->{template
};
6159 next if $running && $d->{status
} ne 'running';
6160 next if !$running && $d->{status
} eq 'running';
6169 return &$complete_vmid_full();
6172 sub complete_vmid_stopped
{
6173 return &$complete_vmid_full(0);
6176 sub complete_vmid_running
{
6177 return &$complete_vmid_full(1);
6180 sub complete_storage
{
6182 my $cfg = PVE
::Storage
::config
();
6183 my $ids = $cfg->{ids
};
6186 foreach my $sid (keys %$ids) {
6187 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6188 next if !$ids->{$sid}->{content
}->{images
};