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
::Memory
;
34 use Time
::HiRes
qw(gettimeofday);
35 use File
::Copy
qw(copy);
38 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
40 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
42 # Note about locking: we use flock on the config file protect
43 # against concurent actions.
44 # Aditionaly, we have a 'lock' setting in the config file. This
45 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
46 # allowed when such lock is set. But you can ignore this kind of
47 # lock with the --skiplock flag.
49 cfs_register_file
('/qemu-server/',
53 PVE
::JSONSchema
::register_standard_option
('skiplock', {
54 description
=> "Ignore locks - only root is allowed to use this option.",
59 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
60 description
=> "Some command save/restore state from this location.",
66 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
67 description
=> "The name of the snapshot.",
68 type
=> 'string', format
=> 'pve-configid',
72 #no warnings 'redefine';
75 my ($controller, $vmid, $option, $value) = @_;
77 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
78 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
82 my $nodename = PVE
::INotify
::nodename
();
84 mkdir "/etc/pve/nodes/$nodename";
85 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
88 my $var_run_tmpdir = "/var/run/qemu-server";
89 mkdir $var_run_tmpdir;
91 my $lock_dir = "/var/lock/qemu-server";
94 my $pcisysfs = "/sys/bus/pci";
96 my $cpu_vendor_list = {
98 486 => 'GenuineIntel',
99 pentium
=> 'GenuineIntel',
100 pentium2
=> 'GenuineIntel',
101 pentium3
=> 'GenuineIntel',
102 coreduo
=> 'GenuineIntel',
103 core2duo
=> 'GenuineIntel',
104 Conroe
=> 'GenuineIntel',
105 Penryn
=> 'GenuineIntel',
106 Nehalem
=> 'GenuineIntel',
107 Westmere
=> 'GenuineIntel',
108 SandyBridge
=> 'GenuineIntel',
109 IvyBridge
=> 'GenuineIntel',
110 Haswell
=> 'GenuineIntel',
111 'Haswell-noTSX' => 'GenuineIntel',
112 Broadwell
=> 'GenuineIntel',
113 'Broadwell-noTSX' => 'GenuineIntel',
116 athlon
=> 'AuthenticAMD',
117 phenom
=> 'AuthenticAMD',
118 Opteron_G1
=> 'AuthenticAMD',
119 Opteron_G2
=> 'AuthenticAMD',
120 Opteron_G3
=> 'AuthenticAMD',
121 Opteron_G4
=> 'AuthenticAMD',
122 Opteron_G5
=> 'AuthenticAMD',
124 # generic types, use vendor from host node
134 description
=> "Emulated CPU type.",
136 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
137 format_description
=> 'cputype',
142 description
=> "Do not identify as a KVM virtual machine.",
153 enum
=> [qw(i6300esb ib700)],
154 description
=> "Watchdog type to emulate.",
155 default => 'i6300esb',
160 enum
=> [qw(reset shutdown poweroff pause debug none)],
161 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
165 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
171 description
=> "Specifies whether a VM will be started during system bootup.",
177 description
=> "Automatic restart after crash (currently ignored).",
182 type
=> 'string', format
=> 'pve-hotplug-features',
183 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'.",
184 default => 'network,disk,usb',
189 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
195 description
=> "Lock/unlock the VM.",
196 enum
=> [qw(migrate backup snapshot rollback)],
201 description
=> "Limit of CPU usage.",
202 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.",
210 description
=> "CPU weight for a VM.",
211 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.",
219 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
226 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
232 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",
240 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.",
241 enum
=> PVE
::Tools
::kvmkeymaplist
(),
246 type
=> 'string', format
=> 'dns-name',
247 description
=> "Set a name for the VM. Only used on the configuration web interface.",
252 description
=> "SCSI controller model",
253 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
259 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
264 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
265 description
=> "Specify guest operating system.",
266 verbose_description
=> <<EODESC,
267 Specify guest operating system. This is used to enable special
268 optimization/features for specific operating systems:
271 other;; unspecified OS
272 wxp;; Microsoft Windows XP
273 w2k;; Microsoft Windows 2000
274 w2k3;; Microsoft Windows 2003
275 w2k8;; Microsoft Windows 2008
276 wvista;; Microsoft Windows Vista
277 win7;; Microsoft Windows 7
278 win8;; Microsoft Windows 8/2012
279 l24;; Linux 2.4 Kernel
280 l26;; Linux 2.6/3.X Kernel
281 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
287 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
288 pattern
=> '[acdn]{1,4}',
293 type
=> 'string', format
=> 'pve-qm-bootdisk',
294 description
=> "Enable booting from specified disk.",
295 pattern
=> '(ide|sata|scsi|virtio)\d+',
300 description
=> "The number of CPUs. Please use option -sockets instead.",
307 description
=> "The number of CPU sockets.",
314 description
=> "The number of cores per socket.",
321 description
=> "Enable/disable NUMA.",
327 description
=> "Number of hotplugged vcpus.",
334 description
=> "Enable/disable ACPI.",
340 description
=> "Enable/disable Qemu GuestAgent.",
346 description
=> "Enable/disable KVM hardware virtualization.",
352 description
=> "Enable/disable time drift fix.",
358 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
363 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
368 description
=> "Select the VGA type.",
369 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
370 " modes (>= 1280x1024x16) then you should use the options " .
371 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
372 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
373 "display sever. For win* OS you can select how many independent " .
374 "displays you want, Linux guests can add displays them self. " .
375 "You can also run without any graphic card, using a serial device" .
377 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
381 type
=> 'string', format
=> 'pve-qm-watchdog',
382 description
=> "Create a virtual hardware watchdog device.",
383 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
384 " (by a guest action), the watchdog must be periodically polled " .
385 "by an agent inside the guest or else the watchdog will reset " .
386 "the guest (or execute the respective action specified)",
391 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
392 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'.",
393 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
396 startup
=> get_standard_option
('pve-startup-order'),
400 description
=> "Enable/disable Template.",
406 description
=> "Arbitrary arguments passed to kvm.",
407 verbose_description
=> <<EODESCR,
408 Arbitrary arguments passed to kvm, for example:
410 args: -no-reboot -no-hpet
412 NOTE: this option is for experts only.
419 description
=> "Enable/disable the USB tablet device.",
420 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
421 "usually needed to allow absolute mouse positioning with VNC. " .
422 "Else the mouse runs out of sync with normal VNC clients. " .
423 "If you're running lots of console-only guests on one host, " .
424 "you may consider disabling this to save some context switches. " .
425 "This is turned off by default if you use spice (-vga=qxl).",
430 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
434 migrate_downtime
=> {
437 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
443 type
=> 'string', format
=> 'pve-qm-drive',
444 typetext
=> 'volume',
445 description
=> "This is an alias for option -ide2",
449 description
=> "Emulated CPU type.",
453 parent
=> get_standard_option
('pve-snapshot-name', {
455 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
459 description
=> "Timestamp for snapshots.",
465 type
=> 'string', format
=> 'pve-volume-id',
466 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
469 description
=> "Specific the Qemu machine type.",
471 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
476 description
=> "Specify SMBIOS type 1 fields.",
477 type
=> 'string', format
=> 'pve-qm-smbios1',
484 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
490 enum
=> [ qw(seabios ovmf) ],
491 description
=> "Select BIOS implementation.",
492 default => 'seabios',
496 # what about other qemu settings ?
498 #machine => 'string',
511 ##soundhw => 'string',
513 while (my ($k, $v) = each %$confdesc) {
514 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
517 my $MAX_IDE_DISKS = 4;
518 my $MAX_SCSI_DISKS = 14;
519 my $MAX_VIRTIO_DISKS = 16;
520 my $MAX_SATA_DISKS = 6;
521 my $MAX_USB_DEVICES = 5;
523 my $MAX_UNUSED_DISKS = 8;
524 my $MAX_HOSTPCI_DEVICES = 4;
525 my $MAX_SERIAL_PORTS = 4;
526 my $MAX_PARALLEL_PORTS = 3;
528 my $MAX_MEM = 4194304;
529 my $STATICMEM = 1024;
534 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
535 description
=> "CPUs accessing this NUMA node.",
536 format_description
=> "id[-id];...",
540 description
=> "Amount of memory this NUMA node provides.",
545 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
546 description
=> "Host NUMA nodes to use.",
547 format_description
=> "id[-id];...",
552 enum
=> [qw(preferred bind interleave)],
553 description
=> "NUMA allocation policy.",
557 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
560 type
=> 'string', format
=> $numa_fmt,
561 description
=> "NUMA topology.",
563 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
565 for (my $i = 0; $i < $MAX_NUMA; $i++) {
566 $confdesc->{"numa$i"} = $numadesc;
569 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
570 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
571 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
572 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
574 my $net_fmt_bridge_descr = <<__EOD__;
575 Bridge to attach the network device to. The Proxmox VE standard bridge
578 If you do not specify a bridge, we create a kvm user (NATed) network
579 device, which provides DHCP and DNS services. The following addresses
586 The DHCP server assign addresses to the guest starting from 10.0.2.15.
592 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
593 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
594 format_description
=> "XX:XX:XX:XX:XX:XX",
599 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'.",
600 format_description
=> 'model',
601 enum
=> $nic_model_list,
604 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
607 description
=> $net_fmt_bridge_descr,
608 format_description
=> 'bridge',
613 minimum
=> 0, maximum
=> 16,
614 description
=> 'Number of packet queues to be used on the device.',
620 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
625 minimum
=> 1, maximum
=> 4094,
626 description
=> 'VLAN tag to apply to packets on this interface.',
631 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
632 description
=> 'VLAN trunks to pass through this interface.',
633 format_description
=> 'vlanid[;vlanid...]',
638 description
=> 'Whether this interface should be protected by the firewall.',
643 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
650 type
=> 'string', format
=> $net_fmt,
651 description
=> "Specify network devices.",
654 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
656 for (my $i = 0; $i < $MAX_NETS; $i++) {
657 $confdesc->{"net$i"} = $netdesc;
660 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
661 sub verify_volume_id_or_qm_path
{
662 my ($volid, $noerr) = @_;
664 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
668 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
669 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
671 return undef if $noerr;
679 my %drivedesc_base = (
680 volume
=> { alias
=> 'file' },
683 format
=> 'pve-volume-id-or-qm-path',
685 format_description
=> 'volume',
686 description
=> "The drive's backing volume.",
690 enum
=> [qw(cdrom disk)],
691 description
=> "The drive's media type.",
697 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
702 description
=> "Force the drive's physical geometry to have a specific head count.",
707 description
=> "Force the drive's physical geometry to have a specific sector count.",
712 enum
=> [qw(none lba auto)],
713 description
=> "Force disk geometry bios translation mode.",
718 description
=> "Whether the drive should be included when making snapshots.",
723 enum
=> [qw(none writethrough writeback unsafe directsync)],
724 description
=> "The drive's cache mode",
729 format_description
=> 'image format',
730 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
731 description
=> "The drive's backing file's data format.",
736 format
=> 'disk-size',
737 format_description
=> 'DiskSize',
738 description
=> "Disk size. This is purely informational and has no effect.",
743 description
=> "Whether the drive should be included when making backups.",
748 enum
=> [qw(enospc ignore report stop)],
749 description
=> 'Write error action.',
754 enum
=> [qw(native threads)],
755 description
=> 'AIO type to use.',
760 enum
=> [qw(ignore on)],
761 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
766 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
771 format
=> 'urlencoded',
772 format_description
=> 'serial',
773 maxLength
=> 20*3, # *3 since it's %xx url enoded
774 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
782 enum
=> [qw(ignore report stop)],
783 description
=> 'Read error action.',
788 my %iothread_fmt = ( iothread
=> {
790 description
=> "Whether to use iothreads for this drive",
797 format
=> 'urlencoded',
798 format_description
=> 'model',
799 maxLength
=> 40*3, # *3 since it's %xx url enoded
800 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
808 description
=> "Number of queues.",
814 my $add_throttle_desc = sub {
815 my ($key, $type, $what, $unit, $longunit) = @_;
816 $drivedesc_base{$key} = {
818 format_description
=> $unit,
819 description
=> "Maximum $what speed in $longunit per second.",
823 # throughput: (leaky bucket)
824 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
825 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
826 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
827 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
828 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
829 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
830 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
831 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
832 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
834 # pools: (pool of IO before throttling starts taking effect)
835 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
836 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
837 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
838 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
839 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
840 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
850 type
=> 'string', format
=> $ide_fmt,
851 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
853 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
862 type
=> 'string', format
=> $scsi_fmt,
863 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
865 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
873 type
=> 'string', format
=> $sata_fmt,
874 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
876 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
885 type
=> 'string', format
=> $virtio_fmt,
886 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
888 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
901 type
=> 'string', format
=> 'pve-qm-usb-device',
902 format_description
=> 'HOSTUSBDEVICE|spice',
903 description
=> <<EODESCR,
904 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
906 'bus-port(.port)*' (decimal numbers) or
907 'vendor_id:product_id' (hexadeciaml numbers) or
910 You can use the 'lsusb -t' command to list existing usb devices.
912 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
914 The value 'spice' can be used to add a usb redirection devices for spice.
920 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).",
927 type
=> 'string', format
=> $usb_fmt,
928 description
=> "Configure an USB device (n is 0 to 4).",
930 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
932 # NOTE: the match-groups of this regex are used in parse_hostpci
933 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
938 pattern
=> qr/$PCIRE(;$PCIRE)*/,
939 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
940 description
=> <<EODESCR,
941 Host PCI device pass through. The PCI ID of a host's PCI device or a list
942 of PCI virtual functions of the host. HOSTPCIID syntax is:
944 'bus:dev.func' (hexadecimal numbers)
946 You can us the 'lspci' command to list existing PCI devices.
951 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
957 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
963 description
=> "Enable vfio-vga device support.",
968 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
972 type
=> 'string', format
=> 'pve-qm-hostpci',
973 description
=> "Map host PCI devices into guest.",
974 verbose_description
=> <<EODESCR,
975 Map host PCI devices into guest.
977 NOTE: This option allows direct access to host hardware. So it is no longer
978 possible to migrate such machines - use with special care.
980 CAUTION: Experimental! User reported problems with this option.
983 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
988 pattern
=> '(/dev/.+|socket)',
989 description
=> "Create a serial device inside the VM (n is 0 to 3)",
990 verbose_description
=> <<EODESCR,
991 Create a serial device inside the VM (n is 0 to 3), and pass through a
992 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
993 host side (use 'qm terminal' to open a terminal connection).
995 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
997 CAUTION: Experimental! User reported problems with this option.
1004 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1005 description
=> "Map host parallel devices (n is 0 to 2).",
1006 verbose_description
=> <<EODESCR,
1007 Map host parallel devices (n is 0 to 2).
1009 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1011 CAUTION: Experimental! User reported problems with this option.
1015 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1016 $confdesc->{"parallel$i"} = $paralleldesc;
1019 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1020 $confdesc->{"serial$i"} = $serialdesc;
1023 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1024 $confdesc->{"hostpci$i"} = $hostpcidesc;
1027 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1028 $drivename_hash->{"ide$i"} = 1;
1029 $confdesc->{"ide$i"} = $idedesc;
1032 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1033 $drivename_hash->{"sata$i"} = 1;
1034 $confdesc->{"sata$i"} = $satadesc;
1037 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1038 $drivename_hash->{"scsi$i"} = 1;
1039 $confdesc->{"scsi$i"} = $scsidesc ;
1042 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1043 $drivename_hash->{"virtio$i"} = 1;
1044 $confdesc->{"virtio$i"} = $virtiodesc;
1047 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1048 $confdesc->{"usb$i"} = $usbdesc;
1053 type
=> 'string', format
=> 'pve-volume-id',
1054 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1057 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1058 $confdesc->{"unused$i"} = $unuseddesc;
1061 my $kvm_api_version = 0;
1065 return $kvm_api_version if $kvm_api_version;
1067 my $fh = IO
::File-
>new("</dev/kvm") ||
1070 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1071 $kvm_api_version = $v;
1076 return $kvm_api_version;
1079 my $kvm_user_version;
1081 sub kvm_user_version
{
1083 return $kvm_user_version if $kvm_user_version;
1085 $kvm_user_version = 'unknown';
1089 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1090 $kvm_user_version = $2;
1094 eval { run_command
("kvm -version", outfunc
=> $code); };
1097 return $kvm_user_version;
1101 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1103 sub valid_drive_names
{
1104 # order is important - used to autoselect boot disk
1105 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1106 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1107 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1108 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1111 sub is_valid_drivename
{
1114 return defined($drivename_hash->{$dev});
1119 return defined($confdesc->{$key});
1123 return $nic_model_list;
1126 sub os_list_description
{
1130 wxp
=> 'Windows XP',
1131 w2k
=> 'Windows 2000',
1132 w2k3
=>, 'Windows 2003',
1133 w2k8
=> 'Windows 2008',
1134 wvista
=> 'Windows Vista',
1135 win7
=> 'Windows 7',
1136 win8
=> 'Windows 8/2012',
1144 sub get_cdrom_path
{
1146 return $cdrom_path if $cdrom_path;
1148 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1149 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1150 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1154 my ($storecfg, $vmid, $cdrom) = @_;
1156 if ($cdrom eq 'cdrom') {
1157 return get_cdrom_path
();
1158 } elsif ($cdrom eq 'none') {
1160 } elsif ($cdrom =~ m
|^/|) {
1163 return PVE
::Storage
::path
($storecfg, $cdrom);
1167 # try to convert old style file names to volume IDs
1168 sub filename_to_volume_id
{
1169 my ($vmid, $file, $media) = @_;
1171 if (!($file eq 'none' || $file eq 'cdrom' ||
1172 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1174 return undef if $file =~ m
|/|;
1176 if ($media && $media eq 'cdrom') {
1177 $file = "local:iso/$file";
1179 $file = "local:$vmid/$file";
1186 sub verify_media_type
{
1187 my ($opt, $vtype, $media) = @_;
1192 if ($media eq 'disk') {
1194 } elsif ($media eq 'cdrom') {
1197 die "internal error";
1200 return if ($vtype eq $etype);
1202 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1205 sub cleanup_drive_path
{
1206 my ($opt, $storecfg, $drive) = @_;
1208 # try to convert filesystem paths to volume IDs
1210 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1211 ($drive->{file
} !~ m
|^/dev/.+|) &&
1212 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1213 ($drive->{file
} !~ m/^\d+$/)) {
1214 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1215 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1216 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1217 verify_media_type
($opt, $vtype, $drive->{media
});
1218 $drive->{file
} = $volid;
1221 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1224 sub parse_hotplug_features
{
1229 return $res if $data eq '0';
1231 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1233 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1234 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1237 warn "ignoring unknown hotplug feature '$feature'\n";
1243 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1244 sub pve_verify_hotplug_features
{
1245 my ($value, $noerr) = @_;
1247 return $value if parse_hotplug_features
($value);
1249 return undef if $noerr;
1251 die "unable to parse hotplug option\n";
1254 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1255 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1256 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1257 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1258 # [,iothread=on][,serial=serial][,model=model]
1261 my ($key, $data) = @_;
1263 my ($interface, $index);
1265 if ($key =~ m/^([^\d]+)(\d+)$/) {
1272 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1273 : $confdesc->{$key}->{format
};
1275 warn "invalid drive key: $key\n";
1278 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1279 return undef if !$res;
1280 $res->{interface
} = $interface;
1281 $res->{index} = $index;
1284 foreach my $opt (qw(bps bps_rd bps_wr)) {
1285 if (my $bps = defined(delete $res->{$opt})) {
1286 if (defined($res->{"m$opt"})) {
1287 warn "both $opt and m$opt specified\n";
1291 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1294 return undef if $error;
1296 return undef if $res->{mbps_rd
} && $res->{mbps
};
1297 return undef if $res->{mbps_wr
} && $res->{mbps
};
1298 return undef if $res->{iops_rd
} && $res->{iops
};
1299 return undef if $res->{iops_wr
} && $res->{iops
};
1301 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1302 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1303 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1304 return undef if $res->{interface
} eq 'virtio';
1307 if (my $size = $res->{size
}) {
1308 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1315 my ($vmid, $drive) = @_;
1316 my $data = { %$drive };
1317 delete $data->{$_} for qw(index interface);
1318 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1322 my($fh, $noerr) = @_;
1325 my $SG_GET_VERSION_NUM = 0x2282;
1327 my $versionbuf = "\x00" x
8;
1328 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1330 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1333 my $version = unpack("I", $versionbuf);
1334 if ($version < 30000) {
1335 die "scsi generic interface too old\n" if !$noerr;
1339 my $buf = "\x00" x
36;
1340 my $sensebuf = "\x00" x
8;
1341 my $cmd = pack("C x3 C x1", 0x12, 36);
1343 # see /usr/include/scsi/sg.h
1344 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";
1346 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1347 length($sensebuf), 0, length($buf), $buf,
1348 $cmd, $sensebuf, 6000);
1350 $ret = ioctl($fh, $SG_IO, $packet);
1352 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1356 my @res = unpack($sg_io_hdr_t, $packet);
1357 if ($res[17] || $res[18]) {
1358 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1363 (my $byte0, my $byte1, $res->{vendor
},
1364 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1366 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1367 $res->{type
} = $byte0 & 31;
1375 my $fh = IO
::File-
>new("+<$path") || return undef;
1376 my $res = scsi_inquiry
($fh, 1);
1382 sub machine_type_is_q35
{
1385 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1388 sub print_tabletdevice_full
{
1391 my $q35 = machine_type_is_q35
($conf);
1393 # we use uhci for old VMs because tablet driver was buggy in older qemu
1394 my $usbbus = $q35 ?
"ehci" : "uhci";
1396 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1399 sub print_drivedevice_full
{
1400 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1405 if ($drive->{interface
} eq 'virtio') {
1406 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1407 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1408 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1409 } elsif ($drive->{interface
} eq 'scsi') {
1411 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1412 my $unit = $drive->{index} % $maxdev;
1413 my $devicetype = 'hd';
1415 if (drive_is_cdrom
($drive)) {
1418 if ($drive->{file
} =~ m
|^/|) {
1419 $path = $drive->{file
};
1420 if (my $info = path_is_scsi
($path)) {
1421 if ($info->{type
} == 0) {
1422 $devicetype = 'block';
1423 } elsif ($info->{type
} == 1) { # tape
1424 $devicetype = 'generic';
1428 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1431 if($path =~ m/^iscsi\:\/\
//){
1432 $devicetype = 'generic';
1436 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1437 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1439 $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}";
1442 } elsif ($drive->{interface
} eq 'ide'){
1444 my $controller = int($drive->{index} / $maxdev);
1445 my $unit = $drive->{index} % $maxdev;
1446 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1448 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1449 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1450 $model = URI
::Escape
::uri_unescape
($model);
1451 $device .= ",model=$model";
1453 } elsif ($drive->{interface
} eq 'sata'){
1454 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1455 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1456 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1457 } elsif ($drive->{interface
} eq 'usb') {
1459 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1461 die "unsupported interface type";
1464 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1469 sub get_initiator_name
{
1472 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1473 while (defined(my $line = <$fh>)) {
1474 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1483 sub print_drive_full
{
1484 my ($storecfg, $vmid, $drive) = @_;
1487 my $volid = $drive->{file
};
1490 if (drive_is_cdrom
($drive)) {
1491 $path = get_iso_path
($storecfg, $vmid, $volid);
1493 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1495 $path = PVE
::Storage
::path
($storecfg, $volid);
1496 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1497 $format = qemu_img_format
($scfg, $volname);
1505 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);
1506 foreach my $o (@qemu_drive_options) {
1507 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1509 if (my $serial = $drive->{serial
}) {
1510 $serial = URI
::Escape
::uri_unescape
($serial);
1511 $opts .= ",serial=$serial";
1514 $opts .= ",format=$format" if $format && !$drive->{format
};
1516 foreach my $o (qw(bps bps_rd bps_wr)) {
1517 my $v = $drive->{"m$o"};
1518 $opts .= ",$o=" . int($v*1024*1024) if $v;
1521 my $cache_direct = 0;
1523 if (my $cache = $drive->{cache
}) {
1524 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1525 } elsif (!drive_is_cdrom
($drive)) {
1526 $opts .= ",cache=none";
1530 # aio native works only with O_DIRECT
1531 if (!$drive->{aio
}) {
1533 $opts .= ",aio=native";
1535 $opts .= ",aio=threads";
1539 if (!drive_is_cdrom
($drive)) {
1541 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1542 $detectzeroes = 'off';
1543 } elsif ($drive->{discard
}) {
1544 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1546 # This used to be our default with discard not being specified:
1547 $detectzeroes = 'on';
1549 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1552 my $pathinfo = $path ?
"file=$path," : '';
1554 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1557 sub print_netdevice_full
{
1558 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1560 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1562 my $device = $net->{model
};
1563 if ($net->{model
} eq 'virtio') {
1564 $device = 'virtio-net-pci';
1567 my $pciaddr = print_pci_addr
("$netid", $bridges);
1568 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1569 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1570 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1571 my $vectors = $net->{queues
} * 2 + 2;
1572 $tmpstr .= ",vectors=$vectors,mq=on";
1574 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1576 if ($use_old_bios_files) {
1578 if ($device eq 'virtio-net-pci') {
1579 $romfile = 'pxe-virtio.rom';
1580 } elsif ($device eq 'e1000') {
1581 $romfile = 'pxe-e1000.rom';
1582 } elsif ($device eq 'ne2k') {
1583 $romfile = 'pxe-ne2k_pci.rom';
1584 } elsif ($device eq 'pcnet') {
1585 $romfile = 'pxe-pcnet.rom';
1586 } elsif ($device eq 'rtl8139') {
1587 $romfile = 'pxe-rtl8139.rom';
1589 $tmpstr .= ",romfile=$romfile" if $romfile;
1595 sub print_netdev_full
{
1596 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1599 if ($netid =~ m/^net(\d+)$/) {
1603 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1605 my $ifname = "tap${vmid}i$i";
1607 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1608 die "interface name '$ifname' is too long (max 15 character)\n"
1609 if length($ifname) >= 16;
1611 my $vhostparam = '';
1612 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1614 my $vmname = $conf->{name
} || "vm$vmid";
1617 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1619 if ($net->{bridge
}) {
1620 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1622 $netdev = "type=user,id=$netid,hostname=$vmname";
1625 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1630 sub drive_is_cdrom
{
1633 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1637 sub parse_number_sets
{
1640 foreach my $part (split(/;/, $set)) {
1641 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1642 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1643 push @$res, [ $1, $2 ];
1645 die "invalid range: $part\n";
1654 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1655 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1656 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1663 return undef if !$value;
1665 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1667 my @idlist = split(/;/, $res->{host
});
1668 delete $res->{host
};
1669 foreach my $id (@idlist) {
1670 if ($id =~ /^$PCIRE$/) {
1671 push @{$res->{pciid
}}, { id
=> $1, function
=> ($2//'0') };
1673 # should have been caught by parse_property_string already
1674 die "failed to parse PCI id: $id\n";
1680 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1684 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1689 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
() if !defined($res->{macaddr
});
1696 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1699 sub add_random_macs
{
1700 my ($settings) = @_;
1702 foreach my $opt (keys %$settings) {
1703 next if $opt !~ m/^net(\d+)$/;
1704 my $net = parse_net
($settings->{$opt});
1706 $settings->{$opt} = print_net
($net);
1710 sub vm_is_volid_owner
{
1711 my ($storecfg, $vmid, $volid) = @_;
1713 if ($volid !~ m
|^/|) {
1715 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1716 if ($owner && ($owner == $vmid)) {
1724 sub split_flagged_list
{
1725 my $text = shift || '';
1726 $text =~ s/[,;]/ /g;
1728 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1731 sub join_flagged_list
{
1732 my ($how, $lst) = @_;
1733 join $how, map { $lst->{$_} . $_ } keys %$lst;
1736 sub vmconfig_delete_pending_option
{
1737 my ($conf, $key, $force) = @_;
1739 delete $conf->{pending
}->{$key};
1740 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1741 $pending_delete_hash->{$key} = $force ?
'!' : '';
1742 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1745 sub vmconfig_undelete_pending_option
{
1746 my ($conf, $key) = @_;
1748 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1749 delete $pending_delete_hash->{$key};
1751 if (%$pending_delete_hash) {
1752 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1754 delete $conf->{pending
}->{delete};
1758 sub vmconfig_register_unused_drive
{
1759 my ($storecfg, $vmid, $conf, $drive) = @_;
1761 if (!drive_is_cdrom
($drive)) {
1762 my $volid = $drive->{file
};
1763 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1764 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1769 sub vmconfig_cleanup_pending
{
1772 # remove pending changes when nothing changed
1774 foreach my $opt (keys %{$conf->{pending
}}) {
1775 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1777 delete $conf->{pending
}->{$opt};
1781 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1782 my $pending_delete_hash = {};
1783 while (my ($opt, $force) = each %$current_delete_hash) {
1784 if (defined($conf->{$opt})) {
1785 $pending_delete_hash->{$opt} = $force;
1791 if (%$pending_delete_hash) {
1792 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1794 delete $conf->{pending
}->{delete};
1800 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1804 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1805 format_description
=> 'UUID',
1806 description
=> "Set SMBIOS1 UUID.",
1812 format_description
=> 'string',
1813 description
=> "Set SMBIOS1 version.",
1819 format_description
=> 'string',
1820 description
=> "Set SMBIOS1 serial number.",
1826 format_description
=> 'string',
1827 description
=> "Set SMBIOS1 manufacturer.",
1833 format_description
=> 'string',
1834 description
=> "Set SMBIOS1 product ID.",
1840 format_description
=> 'string',
1841 description
=> "Set SMBIOS1 SKU string.",
1847 format_description
=> 'string',
1848 description
=> "Set SMBIOS1 family string.",
1856 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1863 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1866 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1868 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1869 sub verify_bootdisk
{
1870 my ($value, $noerr) = @_;
1872 return $value if is_valid_drivename
($value);
1874 return undef if $noerr;
1876 die "invalid boot disk '$value'\n";
1879 sub parse_watchdog
{
1882 return undef if !$value;
1884 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1889 sub parse_usb_device
{
1892 return undef if !$value;
1895 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1896 $res->{vendorid
} = $2;
1897 $res->{productid
} = $4;
1898 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1899 $res->{hostbus
} = $1;
1900 $res->{hostport
} = $2;
1901 } elsif ($value =~ m/^spice$/i) {
1910 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1911 sub verify_usb_device
{
1912 my ($value, $noerr) = @_;
1914 return $value if parse_usb_device
($value);
1916 return undef if $noerr;
1918 die "unable to parse usb device\n";
1921 # add JSON properties for create and set function
1922 sub json_config_properties
{
1925 foreach my $opt (keys %$confdesc) {
1926 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1927 $prop->{$opt} = $confdesc->{$opt};
1934 my ($key, $value) = @_;
1936 die "unknown setting '$key'\n" if !$confdesc->{$key};
1938 my $type = $confdesc->{$key}->{type
};
1940 if (!defined($value)) {
1941 die "got undefined value\n";
1944 if ($value =~ m/[\n\r]/) {
1945 die "property contains a line feed\n";
1948 if ($type eq 'boolean') {
1949 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1950 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1951 die "type check ('boolean') failed - got '$value'\n";
1952 } elsif ($type eq 'integer') {
1953 return int($1) if $value =~ m/^(\d+)$/;
1954 die "type check ('integer') failed - got '$value'\n";
1955 } elsif ($type eq 'number') {
1956 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1957 die "type check ('number') failed - got '$value'\n";
1958 } elsif ($type eq 'string') {
1959 if (my $fmt = $confdesc->{$key}->{format
}) {
1960 if ($fmt eq 'pve-qm-drive') {
1961 # special case - we need to pass $key to parse_drive()
1962 my $drive = parse_drive
($key, $value);
1963 return $value if $drive;
1964 die "unable to parse drive options\n";
1966 PVE
::JSONSchema
::check_format
($fmt, $value);
1969 $value =~ s/^\"(.*)\"$/$1/;
1972 die "internal error"
1976 sub check_iommu_support
{
1977 #fixme : need to check IOMMU support
1978 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1988 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1989 utime undef, undef, $conf;
1993 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1995 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1997 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1999 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2001 # only remove disks owned by this VM
2002 foreach_drive
($conf, sub {
2003 my ($ds, $drive) = @_;
2005 return if drive_is_cdrom
($drive);
2007 my $volid = $drive->{file
};
2009 return if !$volid || $volid =~ m
|^/|;
2011 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2012 return if !$path || !$owner || ($owner != $vmid);
2014 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2017 if ($keep_empty_config) {
2018 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2023 # also remove unused disk
2025 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2028 PVE
::Storage
::foreach_volid
($dl, sub {
2029 my ($volid, $sid, $volname, $d) = @_;
2030 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2039 sub parse_vm_config
{
2040 my ($filename, $raw) = @_;
2042 return undef if !defined($raw);
2045 digest
=> Digest
::SHA
::sha1_hex
($raw),
2050 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2051 || die "got strange filename '$filename'";
2059 my @lines = split(/\n/, $raw);
2060 foreach my $line (@lines) {
2061 next if $line =~ m/^\s*$/;
2063 if ($line =~ m/^\[PENDING\]\s*$/i) {
2064 $section = 'pending';
2065 if (defined($descr)) {
2067 $conf->{description
} = $descr;
2070 $conf = $res->{$section} = {};
2073 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2075 if (defined($descr)) {
2077 $conf->{description
} = $descr;
2080 $conf = $res->{snapshots
}->{$section} = {};
2084 if ($line =~ m/^\#(.*)\s*$/) {
2085 $descr = '' if !defined($descr);
2086 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2090 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2091 $descr = '' if !defined($descr);
2092 $descr .= PVE
::Tools
::decode_text
($2);
2093 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2094 $conf->{snapstate
} = $1;
2095 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2098 $conf->{$key} = $value;
2099 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2101 if ($section eq 'pending') {
2102 $conf->{delete} = $value; # we parse this later
2104 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2106 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2109 eval { $value = check_type
($key, $value); };
2111 warn "vm $vmid - unable to parse value of '$key' - $@";
2113 my $fmt = $confdesc->{$key}->{format
};
2114 if ($fmt && $fmt eq 'pve-qm-drive') {
2115 my $v = parse_drive
($key, $value);
2116 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2117 $v->{file
} = $volid;
2118 $value = print_drive
($vmid, $v);
2120 warn "vm $vmid - unable to parse value of '$key'\n";
2125 if ($key eq 'cdrom') {
2126 $conf->{ide2
} = $value;
2128 $conf->{$key} = $value;
2134 if (defined($descr)) {
2136 $conf->{description
} = $descr;
2138 delete $res->{snapstate
}; # just to be sure
2143 sub write_vm_config
{
2144 my ($filename, $conf) = @_;
2146 delete $conf->{snapstate
}; # just to be sure
2148 if ($conf->{cdrom
}) {
2149 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2150 $conf->{ide2
} = $conf->{cdrom
};
2151 delete $conf->{cdrom
};
2154 # we do not use 'smp' any longer
2155 if ($conf->{sockets
}) {
2156 delete $conf->{smp
};
2157 } elsif ($conf->{smp
}) {
2158 $conf->{sockets
} = $conf->{smp
};
2159 delete $conf->{cores
};
2160 delete $conf->{smp
};
2163 my $used_volids = {};
2165 my $cleanup_config = sub {
2166 my ($cref, $pending, $snapname) = @_;
2168 foreach my $key (keys %$cref) {
2169 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2170 $key eq 'snapstate' || $key eq 'pending';
2171 my $value = $cref->{$key};
2172 if ($key eq 'delete') {
2173 die "propertry 'delete' is only allowed in [PENDING]\n"
2175 # fixme: check syntax?
2178 eval { $value = check_type
($key, $value); };
2179 die "unable to parse value of '$key' - $@" if $@;
2181 $cref->{$key} = $value;
2183 if (!$snapname && is_valid_drivename
($key)) {
2184 my $drive = parse_drive
($key, $value);
2185 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2190 &$cleanup_config($conf);
2192 &$cleanup_config($conf->{pending
}, 1);
2194 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2195 die "internal error" if $snapname eq 'pending';
2196 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2199 # remove 'unusedX' settings if we re-add a volume
2200 foreach my $key (keys %$conf) {
2201 my $value = $conf->{$key};
2202 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2203 delete $conf->{$key};
2207 my $generate_raw_config = sub {
2208 my ($conf, $pending) = @_;
2212 # add description as comment to top of file
2213 if (defined(my $descr = $conf->{description
})) {
2215 foreach my $cl (split(/\n/, $descr)) {
2216 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2219 $raw .= "#\n" if $pending;
2223 foreach my $key (sort keys %$conf) {
2224 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2225 $raw .= "$key: $conf->{$key}\n";
2230 my $raw = &$generate_raw_config($conf);
2232 if (scalar(keys %{$conf->{pending
}})){
2233 $raw .= "\n[PENDING]\n";
2234 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2237 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2238 $raw .= "\n[$snapname]\n";
2239 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2249 # we use static defaults from our JSON schema configuration
2250 foreach my $key (keys %$confdesc) {
2251 if (defined(my $default = $confdesc->{$key}->{default})) {
2252 $res->{$key} = $default;
2256 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2257 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2263 my $vmlist = PVE
::Cluster
::get_vmlist
();
2265 return $res if !$vmlist || !$vmlist->{ids
};
2266 my $ids = $vmlist->{ids
};
2268 foreach my $vmid (keys %$ids) {
2269 my $d = $ids->{$vmid};
2270 next if !$d->{node
} || $d->{node
} ne $nodename;
2271 next if !$d->{type
} || $d->{type
} ne 'qemu';
2272 $res->{$vmid}->{exists} = 1;
2277 # test if VM uses local resources (to prevent migration)
2278 sub check_local_resources
{
2279 my ($conf, $noerr) = @_;
2283 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2284 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2286 foreach my $k (keys %$conf) {
2287 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2288 # sockets are safe: they will recreated be on the target side post-migrate
2289 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2290 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2293 die "VM uses local resources\n" if $loc_res && !$noerr;
2298 # check if used storages are available on all nodes (use by migrate)
2299 sub check_storage_availability
{
2300 my ($storecfg, $conf, $node) = @_;
2302 foreach_drive
($conf, sub {
2303 my ($ds, $drive) = @_;
2305 my $volid = $drive->{file
};
2308 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2311 # check if storage is available on both nodes
2312 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2313 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2317 # list nodes where all VM images are available (used by has_feature API)
2319 my ($conf, $storecfg) = @_;
2321 my $nodelist = PVE
::Cluster
::get_nodelist
();
2322 my $nodehash = { map { $_ => 1 } @$nodelist };
2323 my $nodename = PVE
::INotify
::nodename
();
2325 foreach_drive
($conf, sub {
2326 my ($ds, $drive) = @_;
2328 my $volid = $drive->{file
};
2331 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2333 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2334 if ($scfg->{disable
}) {
2336 } elsif (my $avail = $scfg->{nodes
}) {
2337 foreach my $node (keys %$nodehash) {
2338 delete $nodehash->{$node} if !$avail->{$node};
2340 } elsif (!$scfg->{shared
}) {
2341 foreach my $node (keys %$nodehash) {
2342 delete $nodehash->{$node} if $node ne $nodename
2352 my ($pidfile, $pid) = @_;
2354 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2358 return undef if !$line;
2359 my @param = split(/\0/, $line);
2361 my $cmd = $param[0];
2362 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2364 for (my $i = 0; $i < scalar (@param); $i++) {
2367 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2368 my $p = $param[$i+1];
2369 return 1 if $p && ($p eq $pidfile);
2378 my ($vmid, $nocheck, $node) = @_;
2380 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2382 die "unable to find configuration file for VM $vmid - no such machine\n"
2383 if !$nocheck && ! -f
$filename;
2385 my $pidfile = pidfile_name
($vmid);
2387 if (my $fd = IO
::File-
>new("<$pidfile")) {
2392 my $mtime = $st->mtime;
2393 if ($mtime > time()) {
2394 warn "file '$filename' modified in future\n";
2397 if ($line =~ m/^(\d+)$/) {
2399 if (check_cmdline
($pidfile, $pid)) {
2400 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2412 my $vzlist = config_list
();
2414 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2416 while (defined(my $de = $fd->read)) {
2417 next if $de !~ m/^(\d+)\.pid$/;
2419 next if !defined($vzlist->{$vmid});
2420 if (my $pid = check_running
($vmid)) {
2421 $vzlist->{$vmid}->{pid
} = $pid;
2429 my ($storecfg, $conf) = @_;
2431 my $bootdisk = $conf->{bootdisk
};
2432 return undef if !$bootdisk;
2433 return undef if !is_valid_drivename
($bootdisk);
2435 return undef if !$conf->{$bootdisk};
2437 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2438 return undef if !defined($drive);
2440 return undef if drive_is_cdrom
($drive);
2442 my $volid = $drive->{file
};
2443 return undef if !$volid;
2445 return $drive->{size
};
2448 my $last_proc_pid_stat;
2450 # get VM status information
2451 # This must be fast and should not block ($full == false)
2452 # We only query KVM using QMP if $full == true (this can be slow)
2454 my ($opt_vmid, $full) = @_;
2458 my $storecfg = PVE
::Storage
::config
();
2460 my $list = vzlist
();
2461 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2463 my $cpucount = $cpuinfo->{cpus
} || 1;
2465 foreach my $vmid (keys %$list) {
2466 next if $opt_vmid && ($vmid ne $opt_vmid);
2468 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2469 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2472 $d->{pid
} = $list->{$vmid}->{pid
};
2474 # fixme: better status?
2475 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2477 my $size = disksize
($storecfg, $conf);
2478 if (defined($size)) {
2479 $d->{disk
} = 0; # no info available
2480 $d->{maxdisk
} = $size;
2486 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2487 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2488 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2490 $d->{name
} = $conf->{name
} || "VM $vmid";
2491 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2493 if ($conf->{balloon
}) {
2494 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2495 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2506 $d->{diskwrite
} = 0;
2508 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2513 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2514 foreach my $dev (keys %$netdev) {
2515 next if $dev !~ m/^tap([1-9]\d*)i/;
2517 my $d = $res->{$vmid};
2520 $d->{netout
} += $netdev->{$dev}->{receive
};
2521 $d->{netin
} += $netdev->{$dev}->{transmit
};
2524 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2525 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2530 my $ctime = gettimeofday
;
2532 foreach my $vmid (keys %$list) {
2534 my $d = $res->{$vmid};
2535 my $pid = $d->{pid
};
2538 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2539 next if !$pstat; # not running
2541 my $used = $pstat->{utime} + $pstat->{stime
};
2543 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2545 if ($pstat->{vsize
}) {
2546 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2549 my $old = $last_proc_pid_stat->{$pid};
2551 $last_proc_pid_stat->{$pid} = {
2559 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2561 if ($dtime > 1000) {
2562 my $dutime = $used - $old->{used
};
2564 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2565 $last_proc_pid_stat->{$pid} = {
2571 $d->{cpu
} = $old->{cpu
};
2575 return $res if !$full;
2577 my $qmpclient = PVE
::QMPClient-
>new();
2579 my $ballooncb = sub {
2580 my ($vmid, $resp) = @_;
2582 my $info = $resp->{'return'};
2583 return if !$info->{max_mem
};
2585 my $d = $res->{$vmid};
2587 # use memory assigned to VM
2588 $d->{maxmem
} = $info->{max_mem
};
2589 $d->{balloon
} = $info->{actual
};
2591 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2592 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2593 $d->{freemem
} = $info->{free_mem
};
2596 $d->{ballooninfo
} = $info;
2599 my $blockstatscb = sub {
2600 my ($vmid, $resp) = @_;
2601 my $data = $resp->{'return'} || [];
2602 my $totalrdbytes = 0;
2603 my $totalwrbytes = 0;
2605 for my $blockstat (@$data) {
2606 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2607 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2609 $blockstat->{device
} =~ s/drive-//;
2610 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2612 $res->{$vmid}->{diskread
} = $totalrdbytes;
2613 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2616 my $statuscb = sub {
2617 my ($vmid, $resp) = @_;
2619 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2620 # this fails if ballon driver is not loaded, so this must be
2621 # the last commnand (following command are aborted if this fails).
2622 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2624 my $status = 'unknown';
2625 if (!defined($status = $resp->{'return'}->{status
})) {
2626 warn "unable to get VM status\n";
2630 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2633 foreach my $vmid (keys %$list) {
2634 next if $opt_vmid && ($vmid ne $opt_vmid);
2635 next if !$res->{$vmid}->{pid
}; # not running
2636 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2639 $qmpclient->queue_execute(undef, 1);
2641 foreach my $vmid (keys %$list) {
2642 next if $opt_vmid && ($vmid ne $opt_vmid);
2643 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2650 my ($conf, $func) = @_;
2652 foreach my $ds (valid_drive_names
()) {
2653 next if !defined($conf->{$ds});
2655 my $drive = parse_drive
($ds, $conf->{$ds});
2658 &$func($ds, $drive);
2663 my ($conf, $func) = @_;
2667 my $test_volid = sub {
2668 my ($volid, $is_cdrom) = @_;
2672 $volhash->{$volid} = $is_cdrom || 0;
2675 foreach_drive
($conf, sub {
2676 my ($ds, $drive) = @_;
2677 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2680 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2681 my $snap = $conf->{snapshots
}->{$snapname};
2682 &$test_volid($snap->{vmstate
}, 0);
2683 foreach_drive
($snap, sub {
2684 my ($ds, $drive) = @_;
2685 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2689 foreach my $volid (keys %$volhash) {
2690 &$func($volid, $volhash->{$volid});
2694 sub vga_conf_has_spice
{
2697 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2702 sub config_to_command
{
2703 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2706 my $globalFlags = [];
2707 my $machineFlags = [];
2713 my $kvmver = kvm_user_version
();
2714 my $vernum = 0; # unknown
2715 my $ostype = $conf->{ostype
};
2716 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2717 $vernum = $1*1000000+$2*1000;
2718 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2719 $vernum = $1*1000000+$2*1000+$3;
2722 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2724 my $have_ovz = -f
'/proc/vz/vestat';
2726 my $q35 = machine_type_is_q35
($conf);
2727 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2728 my $machine_type = $forcemachine || $conf->{machine
};
2729 my $use_old_bios_files = undef;
2730 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2732 my $cpuunits = defined($conf->{cpuunits
}) ?
2733 $conf->{cpuunits
} : $defaults->{cpuunits
};
2735 push @$cmd, '/usr/bin/systemd-run';
2736 push @$cmd, '--scope';
2737 push @$cmd, '--slice', "qemu";
2738 push @$cmd, '--unit', $vmid;
2739 push @$cmd, '--description', "'Proxmox VE VM $vmid'";
2740 # set KillMode=none, so that systemd don't kill those scopes
2741 # at shutdown (pve-manager service should stop the VMs instead)
2742 push @$cmd, '-p', "KillMode=none";
2743 push @$cmd, '-p', "CPUShares=$cpuunits";
2744 if ($conf->{cpulimit
}) {
2745 my $cpulimit = int($conf->{cpulimit
} * 100);
2746 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2749 push @$cmd, '/usr/bin/kvm';
2751 push @$cmd, '-id', $vmid;
2755 my $qmpsocket = qmp_socket
($vmid);
2756 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2757 push @$cmd, '-mon', "chardev=qmp,mode=control";
2760 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2762 push @$cmd, '-daemonize';
2764 if ($conf->{smbios1
}) {
2765 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2768 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2769 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2770 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2771 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2772 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2773 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2774 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2778 # the q35 chipset support native usb2, so we enable usb controller
2779 # by default for this machine type
2780 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2782 $pciaddr = print_pci_addr
("piix3", $bridges);
2783 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2786 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2787 next if !$conf->{"usb$i"};
2788 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2789 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2792 # include usb device config
2793 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2796 # add usb3 controller if needed
2799 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2800 next if !$conf->{"usb$i"};
2801 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2802 next if !$d || !$d->{usb3
};
2806 $pciaddr = print_pci_addr
("xhci", $bridges);
2807 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2809 my $vga = $conf->{vga
};
2811 my $qxlnum = vga_conf_has_spice
($vga);
2812 $vga = 'qxl' if $qxlnum;
2815 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2816 $conf->{ostype
} eq 'win7' ||
2817 $conf->{ostype
} eq 'w2k8')) {
2824 # enable absolute mouse coordinates (needed by vnc)
2826 if (defined($conf->{tablet
})) {
2827 $tablet = $conf->{tablet
};
2829 $tablet = $defaults->{tablet
};
2830 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2831 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2834 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2838 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2839 my $d = parse_hostpci
($conf->{"hostpci$i"});
2842 my $pcie = $d->{pcie
};
2844 die "q35 machine model is not enabled" if !$q35;
2845 $pciaddr = print_pcie_addr
("hostpci$i");
2847 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2850 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2852 if ($d->{'x-vga'}) {
2853 $xvga = ',x-vga=on';
2856 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2857 push @$cpuFlags , 'hv_vendor_id=proxmox';
2859 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2863 my $pcidevices = $d->{pciid
};
2864 my $multifunction = 1 if @$pcidevices > 1;
2867 foreach my $pcidevice (@$pcidevices) {
2869 my $id = "hostpci$i";
2870 $id .= ".$j" if $multifunction;
2871 my $addr = $pciaddr;
2872 $addr .= ".$j" if $multifunction;
2873 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2876 $devicestr .= "$rombar$xvga";
2877 $devicestr .= ",multifunction=on" if $multifunction;
2880 push @$devices, '-device', $devicestr;
2886 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2887 next if !$conf->{"usb$i"};
2888 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2891 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2893 if (defined($d->{usb3
}) && $d->{usb3
}) {
2894 $usbbus = ',bus=xhci.0';
2897 if (defined($d->{host
})) {
2898 $d = parse_usb_device
($d->{host
});
2899 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2900 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2901 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2902 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2903 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2904 # usb redir support for spice, currently no usb3
2905 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2906 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2912 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2913 if (my $path = $conf->{"serial$i"}) {
2914 if ($path eq 'socket') {
2915 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2916 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2917 push @$devices, '-device', "isa-serial,chardev=serial$i";
2919 die "no such serial device\n" if ! -c
$path;
2920 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2921 push @$devices, '-device', "isa-serial,chardev=serial$i";
2927 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2928 if (my $path = $conf->{"parallel$i"}) {
2929 die "no such parallel device\n" if ! -c
$path;
2930 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2931 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2932 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2936 my $vmname = $conf->{name
} || "vm$vmid";
2938 push @$cmd, '-name', $vmname;
2941 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2942 $sockets = $conf->{sockets
} if $conf->{sockets
};
2944 my $cores = $conf->{cores
} || 1;
2946 my $maxcpus = $sockets * $cores;
2948 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2950 my $allowed_vcpus = $cpuinfo->{cpus
};
2952 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2953 if ($allowed_vcpus < $maxcpus);
2955 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2957 push @$cmd, '-nodefaults';
2959 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2961 my $bootindex_hash = {};
2963 foreach my $o (split(//, $bootorder)) {
2964 $bootindex_hash->{$o} = $i*100;
2968 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2970 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2972 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2974 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2976 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2977 my $socket = vnc_socket
($vmid);
2978 push @$cmd, '-vnc', "unix:$socket,x509,password";
2980 push @$cmd, '-nographic';
2984 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2986 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2987 my $useLocaltime = $conf->{localtime};
2990 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2992 if ($ostype =~ m/^w/) { # windows
2993 $useLocaltime = 1 if !defined($conf->{localtime});
2995 # use time drift fix when acpi is enabled
2996 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2997 $tdf = 1 if !defined($conf->{tdf
});
3001 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3002 $ostype eq 'wvista') {
3003 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3004 push @$cmd, '-no-hpet';
3005 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3006 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3007 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3008 push @$cpuFlags , 'hv_time' if !$nokvm;
3011 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3015 if ($ostype eq 'win7' || $ostype eq 'win8') {
3016 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3020 push @$rtcFlags, 'driftfix=slew' if $tdf;
3023 push @$machineFlags, 'accel=tcg';
3025 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3028 if ($machine_type) {
3029 push @$machineFlags, "type=${machine_type}";
3032 if ($conf->{startdate
}) {
3033 push @$rtcFlags, "base=$conf->{startdate}";
3034 } elsif ($useLocaltime) {
3035 push @$rtcFlags, 'base=localtime';
3038 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3039 if (my $cputype = $conf->{cpu
}) {
3040 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3041 or die "Cannot parse cpu description: $cputype\n";
3042 $cpu = $cpuconf->{cputype
};
3043 $kvm_off = 1 if $cpuconf->{hidden
};
3046 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3048 push @$cpuFlags , '-x2apic'
3049 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3051 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3053 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3055 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3057 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3058 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3061 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3063 push @$cpuFlags, 'kvm=off' if $kvm_off;
3065 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3066 die "internal error"; # should not happen
3068 push @$cpuFlags, "vendor=${cpu_vendor}"
3069 if $cpu_vendor ne 'default';
3071 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3073 push @$cmd, '-cpu', $cpu;
3075 my $memory = $conf->{memory
} || $defaults->{memory
};
3076 my $static_memory = 0;
3077 my $dimm_memory = 0;
3079 if ($hotplug_features->{memory
}) {
3080 die "NUMA need to be enabled for memory hotplug\n" if !$conf->{numa
};
3081 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3082 $static_memory = $STATICMEM;
3083 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3084 $dimm_memory = $memory - $static_memory;
3085 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3089 $static_memory = $memory;
3090 push @$cmd, '-m', $static_memory;
3093 if ($conf->{numa
}) {
3095 my $numa_totalmemory = undef;
3096 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3097 next if !$conf->{"numa$i"};
3098 my $numa = parse_numa
($conf->{"numa$i"});
3101 die "missing NUMA node$i memory value\n" if !$numa->{memory
};
3102 my $numa_memory = $numa->{memory
};
3103 $numa_totalmemory += $numa_memory;
3104 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3107 my $cpulists = $numa->{cpus
};
3108 die "missing NUMA node$i cpus\n" if !defined($cpulists);
3109 my $cpus = join(',', map {
3110 my ($start, $end) = @$_;
3111 defined($end) ?
"$start-$end" : $start
3115 my $hostnodelists = $numa->{hostnodes
};
3116 if (defined($hostnodelists)) {
3118 foreach my $hostnoderange (@$hostnodelists) {
3119 my ($start, $end) = @$hostnoderange;
3120 $hostnodes .= ',' if $hostnodes;
3121 $hostnodes .= $start;
3122 $hostnodes .= "-$end" if defined($end);
3124 for (my $i = $start; $i <= $end; ++$i ) {
3125 die "host NUMA node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3130 my $policy = $numa->{policy
};
3131 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3132 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3135 push @$cmd, '-object', $numa_object;
3136 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3139 die "total memory for NUMA nodes must be equal to vm static memory\n"
3140 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3142 #if no custom tology, we split memory and cores across numa nodes
3143 if(!$numa_totalmemory) {
3145 my $numa_memory = ($static_memory / $sockets) . "M";
3147 for (my $i = 0; $i < $sockets; $i++) {
3149 my $cpustart = ($cores * $i);
3150 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3151 my $cpus = $cpustart;
3152 $cpus .= "-$cpuend" if $cpuend;
3154 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3155 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3160 if ($hotplug_features->{memory
}) {
3161 PVE
::QemuServer
::Memory
::foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3162 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3163 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3164 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3166 #if dimm_memory is not aligned to dimm map
3167 if($current_size > $memory) {
3168 $conf->{memory
} = $current_size;
3169 PVE
::QemuConfig-
>write_config($vmid, $conf);
3174 push @$cmd, '-S' if $conf->{freeze
};
3176 # set keyboard layout
3177 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3178 push @$cmd, '-k', $kb if $kb;
3181 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3182 #push @$cmd, '-soundhw', 'es1370';
3183 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3185 if($conf->{agent
}) {
3186 my $qgasocket = qmp_socket
($vmid, 1);
3187 my $pciaddr = print_pci_addr
("qga0", $bridges);
3188 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3189 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3190 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3197 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3198 for(my $i = 1; $i < $qxlnum; $i++){
3199 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3200 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3203 # assume other OS works like Linux
3204 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3205 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3209 my $pciaddr = print_pci_addr
("spice", $bridges);
3211 my $nodename = PVE
::INotify
::nodename
();
3212 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3213 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3215 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3217 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3218 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3219 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3222 # enable balloon by default, unless explicitly disabled
3223 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3224 $pciaddr = print_pci_addr
("balloon0", $bridges);
3225 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3228 if ($conf->{watchdog
}) {
3229 my $wdopts = parse_watchdog
($conf->{watchdog
});
3230 $pciaddr = print_pci_addr
("watchdog", $bridges);
3231 my $watchdog = $wdopts->{model
} || 'i6300esb';
3232 push @$devices, '-device', "$watchdog$pciaddr";
3233 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3237 my $scsicontroller = {};
3238 my $ahcicontroller = {};
3239 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3241 # Add iscsi initiator name if available
3242 if (my $initiator = get_initiator_name
()) {
3243 push @$devices, '-iscsi', "initiator-name=$initiator";
3246 foreach_drive
($conf, sub {
3247 my ($ds, $drive) = @_;
3249 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3250 push @$vollist, $drive->{file
};
3253 $use_virtio = 1 if $ds =~ m/^virtio/;
3255 if (drive_is_cdrom
($drive)) {
3256 if ($bootindex_hash->{d
}) {
3257 $drive->{bootindex
} = $bootindex_hash->{d
};
3258 $bootindex_hash->{d
} += 1;
3261 if ($bootindex_hash->{c
}) {
3262 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3263 $bootindex_hash->{c
} += 1;
3267 if($drive->{interface
} eq 'virtio'){
3268 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3271 if ($drive->{interface
} eq 'scsi') {
3273 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3275 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3276 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3279 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3280 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3281 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3282 } elsif ($drive->{iothread
}) {
3283 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3287 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3288 $queues = ",num_queues=$drive->{queues}";
3291 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3292 $scsicontroller->{$controller}=1;
3295 if ($drive->{interface
} eq 'sata') {
3296 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3297 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3298 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3299 $ahcicontroller->{$controller}=1;
3302 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3303 push @$devices, '-drive',$drive_cmd;
3304 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3307 for (my $i = 0; $i < $MAX_NETS; $i++) {
3308 next if !$conf->{"net$i"};
3309 my $d = parse_net
($conf->{"net$i"});
3312 $use_virtio = 1 if $d->{model
} eq 'virtio';
3314 if ($bootindex_hash->{n
}) {
3315 $d->{bootindex
} = $bootindex_hash->{n
};
3316 $bootindex_hash->{n
} += 1;
3319 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3320 push @$devices, '-netdev', $netdevfull;
3322 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3323 push @$devices, '-device', $netdevicefull;
3328 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3333 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3335 while (my ($k, $v) = each %$bridges) {
3336 $pciaddr = print_pci_addr
("pci.$k");
3337 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3342 if ($conf->{args
}) {
3343 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3347 push @$cmd, @$devices;
3348 push @$cmd, '-rtc', join(',', @$rtcFlags)
3349 if scalar(@$rtcFlags);
3350 push @$cmd, '-machine', join(',', @$machineFlags)
3351 if scalar(@$machineFlags);
3352 push @$cmd, '-global', join(',', @$globalFlags)
3353 if scalar(@$globalFlags);
3355 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3360 return "${var_run_tmpdir}/$vmid.vnc";
3366 my $res = vm_mon_cmd
($vmid, 'query-spice');
3368 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3372 my ($vmid, $qga) = @_;
3373 my $sockettype = $qga ?
'qga' : 'qmp';
3374 return "${var_run_tmpdir}/$vmid.$sockettype";
3379 return "${var_run_tmpdir}/$vmid.pid";
3382 sub vm_devices_list
{
3385 my $res = vm_mon_cmd
($vmid, 'query-pci');
3387 foreach my $pcibus (@$res) {
3388 foreach my $device (@{$pcibus->{devices
}}) {
3389 next if !$device->{'qdev_id'};
3390 if ($device->{'pci_bridge'}) {
3391 $devices->{$device->{'qdev_id'}} = 1;
3392 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3393 next if !$bridge_device->{'qdev_id'};
3394 $devices->{$bridge_device->{'qdev_id'}} = 1;
3395 $devices->{$device->{'qdev_id'}}++;
3398 $devices->{$device->{'qdev_id'}} = 1;
3403 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3404 foreach my $block (@$resblock) {
3405 if($block->{device
} =~ m/^drive-(\S+)/){
3410 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3411 foreach my $mice (@$resmice) {
3412 if ($mice->{name
} eq 'QEMU HID Tablet') {
3413 $devices->{tablet
} = 1;
3422 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3424 my $q35 = machine_type_is_q35
($conf);
3426 my $devices_list = vm_devices_list
($vmid);
3427 return 1 if defined($devices_list->{$deviceid});
3429 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3431 if ($deviceid eq 'tablet') {
3433 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3435 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3437 qemu_iothread_add
($vmid, $deviceid, $device);
3439 qemu_driveadd
($storecfg, $vmid, $device);
3440 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3442 qemu_deviceadd
($vmid, $devicefull);
3443 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3445 eval { qemu_drivedel
($vmid, $deviceid); };
3450 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3453 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3454 my $pciaddr = print_pci_addr
($deviceid);
3455 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3457 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3459 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3460 qemu_iothread_add
($vmid, $deviceid, $device);
3461 $devicefull .= ",iothread=iothread-$deviceid";
3464 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3465 $devicefull .= ",num_queues=$device->{queues}";
3468 qemu_deviceadd
($vmid, $devicefull);
3469 qemu_deviceaddverify
($vmid, $deviceid);
3471 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3473 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3474 qemu_driveadd
($storecfg, $vmid, $device);
3476 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3477 eval { qemu_deviceadd
($vmid, $devicefull); };
3479 eval { qemu_drivedel
($vmid, $deviceid); };
3484 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3486 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3488 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3489 my $use_old_bios_files = undef;
3490 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3492 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3493 qemu_deviceadd
($vmid, $netdevicefull);
3494 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3496 eval { qemu_netdevdel
($vmid, $deviceid); };
3501 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3504 my $pciaddr = print_pci_addr
($deviceid);
3505 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3507 qemu_deviceadd
($vmid, $devicefull);
3508 qemu_deviceaddverify
($vmid, $deviceid);
3511 die "can't hotplug device '$deviceid'\n";
3517 # fixme: this should raise exceptions on error!
3518 sub vm_deviceunplug
{
3519 my ($vmid, $conf, $deviceid) = @_;
3521 my $devices_list = vm_devices_list
($vmid);
3522 return 1 if !defined($devices_list->{$deviceid});
3524 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3526 if ($deviceid eq 'tablet') {
3528 qemu_devicedel
($vmid, $deviceid);
3530 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3532 qemu_devicedel
($vmid, $deviceid);
3533 qemu_devicedelverify
($vmid, $deviceid);
3534 qemu_drivedel
($vmid, $deviceid);
3535 qemu_iothread_del
($conf, $vmid, $deviceid);
3537 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3539 qemu_devicedel
($vmid, $deviceid);
3540 qemu_devicedelverify
($vmid, $deviceid);
3541 qemu_iothread_del
($conf, $vmid, $deviceid);
3543 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3545 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3546 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3547 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3549 qemu_devicedel
($vmid, $deviceid);
3550 qemu_drivedel
($vmid, $deviceid);
3551 qemu_deletescsihw
($conf, $vmid, $deviceid);
3553 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3555 qemu_devicedel
($vmid, $deviceid);
3556 qemu_devicedelverify
($vmid, $deviceid);
3557 qemu_netdevdel
($vmid, $deviceid);
3560 die "can't unplug device '$deviceid'\n";
3566 sub qemu_deviceadd
{
3567 my ($vmid, $devicefull) = @_;
3569 $devicefull = "driver=".$devicefull;
3570 my %options = split(/[=,]/, $devicefull);
3572 vm_mon_cmd
($vmid, "device_add" , %options);
3575 sub qemu_devicedel
{
3576 my ($vmid, $deviceid) = @_;
3578 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3581 sub qemu_iothread_add
{
3582 my($vmid, $deviceid, $device) = @_;
3584 if ($device->{iothread
}) {
3585 my $iothreads = vm_iothreads_list
($vmid);
3586 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3590 sub qemu_iothread_del
{
3591 my($conf, $vmid, $deviceid) = @_;
3593 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3594 if ($device->{iothread
}) {
3595 my $iothreads = vm_iothreads_list
($vmid);
3596 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3600 sub qemu_objectadd
{
3601 my($vmid, $objectid, $qomtype) = @_;
3603 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3608 sub qemu_objectdel
{
3609 my($vmid, $objectid) = @_;
3611 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3617 my ($storecfg, $vmid, $device) = @_;
3619 my $drive = print_drive_full
($storecfg, $vmid, $device);
3620 $drive =~ s/\\/\\\\/g;
3621 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3623 # If the command succeeds qemu prints: "OK
"
3624 return 1 if $ret =~ m/OK/s;
3626 die "adding drive failed
: $ret\n";
3630 my($vmid, $deviceid) = @_;
3632 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3635 return 1 if $ret eq "";
3637 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3638 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3640 die "deleting drive
$deviceid failed
: $ret\n";
3643 sub qemu_deviceaddverify {
3644 my ($vmid, $deviceid) = @_;
3646 for (my $i = 0; $i <= 5; $i++) {
3647 my $devices_list = vm_devices_list($vmid);
3648 return 1 if defined($devices_list->{$deviceid});
3652 die "error on hotplug device
'$deviceid'\n";
3656 sub qemu_devicedelverify {
3657 my ($vmid, $deviceid) = @_;
3659 # need to verify that the device is correctly removed as device_del
3660 # is async and empty return is not reliable
3662 for (my $i = 0; $i <= 5; $i++) {
3663 my $devices_list = vm_devices_list($vmid);
3664 return 1 if !defined($devices_list->{$deviceid});
3668 die "error on hot-unplugging device
'$deviceid'\n";
3671 sub qemu_findorcreatescsihw {
3672 my ($storecfg, $conf, $vmid, $device) = @_;
3674 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3676 my $scsihwid="$controller_prefix$controller";
3677 my $devices_list = vm_devices_list($vmid);
3679 if(!defined($devices_list->{$scsihwid})) {
3680 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3686 sub qemu_deletescsihw {
3687 my ($conf, $vmid, $opt) = @_;
3689 my $device = parse_drive($opt, $conf->{$opt});
3691 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3692 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3696 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3698 my $devices_list = vm_devices_list($vmid);
3699 foreach my $opt (keys %{$devices_list}) {
3700 if (PVE::QemuServer::is_valid_drivename($opt)) {
3701 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3702 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3708 my $scsihwid="scsihw
$controller";
3710 vm_deviceunplug($vmid, $conf, $scsihwid);
3715 sub qemu_add_pci_bridge {
3716 my ($storecfg, $conf, $vmid, $device) = @_;
3722 print_pci_addr($device, $bridges);
3724 while (my ($k, $v) = each %$bridges) {
3727 return 1 if !defined($bridgeid) || $bridgeid < 1;
3729 my $bridge = "pci
.$bridgeid";
3730 my $devices_list = vm_devices_list($vmid);
3732 if (!defined($devices_list->{$bridge})) {
3733 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3739 sub qemu_set_link_status {
3740 my ($vmid, $device, $up) = @_;
3742 vm_mon_cmd($vmid, "set_link
", name => $device,
3743 up => $up ? JSON::true : JSON::false);
3746 sub qemu_netdevadd {
3747 my ($vmid, $conf, $device, $deviceid) = @_;
3749 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3750 my %options = split(/[=,]/, $netdev);
3752 vm_mon_cmd($vmid, "netdev_add
", %options);
3756 sub qemu_netdevdel {
3757 my ($vmid, $deviceid) = @_;
3759 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3762 sub qemu_cpu_hotplug {
3763 my ($vmid, $conf, $vcpus) = @_;
3766 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3767 $sockets = $conf->{sockets} if $conf->{sockets};
3768 my $cores = $conf->{cores} || 1;
3769 my $maxcpus = $sockets * $cores;
3771 $vcpus = $maxcpus if !$vcpus;
3773 die "you can
't add more vcpus than maxcpus\n"
3774 if $vcpus > $maxcpus;
3776 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3777 die "online cpu unplug is not yet possible\n"
3778 if $vcpus < $currentvcpus;
3780 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3781 die "vcpus in running vm is different than configuration\n"
3782 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3784 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3785 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3789 sub qemu_block_set_io_throttle {
3790 my ($vmid, $deviceid,
3791 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3792 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3794 return if !check_running($vmid) ;
3796 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3798 bps_rd => int($bps_rd),
3799 bps_wr => int($bps_wr),
3801 iops_rd => int($iops_rd),
3802 iops_wr => int($iops_wr),
3803 bps_max => int($bps_max),
3804 bps_rd_max => int($bps_rd_max),
3805 bps_wr_max => int($bps_wr_max),
3806 iops_max => int($iops_max),
3807 iops_rd_max => int($iops_rd_max),
3808 iops_wr_max => int($iops_wr_max)
3813 # old code, only used to shutdown old VM after update
3815 my ($fh, $timeout) = @_;
3817 my $sel = new IO::Select;
3824 while (scalar (@ready = $sel->can_read($timeout))) {
3826 if ($count = $fh->sysread($buf, 8192)) {
3827 if ($buf =~ /^(.*)\(qemu\) $/s) {
3834 if (!defined($count)) {
3841 die "monitor read timeout\n" if !scalar(@ready);
3846 # old code, only used to shutdown old VM after update
3847 sub vm_monitor_command {
3848 my ($vmid, $cmdstr, $nocheck) = @_;
3853 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3855 my $sname = "${var_run_tmpdir}/$vmid.mon";
3857 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3858 die "unable to connect to VM $vmid socket - $!\n";
3862 # hack: migrate sometime blocks the monitor (when migrate_downtime
3864 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3865 $timeout = 60*60; # 1 hour
3869 my $data = __read_avail($sock, $timeout);
3871 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3872 die "got unexpected qemu monitor banner\n";
3875 my $sel = new IO::Select;
3878 if (!scalar(my @ready = $sel->can_write($timeout))) {
3879 die "monitor write error - timeout";
3882 my $fullcmd = "$cmdstr\r";
3884 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3887 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3888 die "monitor write error - $!";
3891 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3895 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3896 $timeout = 60*60; # 1 hour
3897 } elsif ($cmdstr =~ m/^(eject|change)/) {
3898 $timeout = 60; # note: cdrom mount command is slow
3900 if ($res = __read_avail($sock, $timeout)) {
3902 my @lines = split("\r?\n", $res);
3904 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3906 $res = join("\n", @lines);
3914 syslog("err", "VM $vmid monitor command failed - $err");
3921 sub qemu_block_resize {
3922 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3924 my $running = check_running($vmid);
3926 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3928 return if !$running;
3930 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3934 sub qemu_volume_snapshot {
3935 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3937 my $running = check_running($vmid);
3939 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3940 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3942 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3946 sub qemu_volume_snapshot_delete {
3947 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3949 my $running = check_running($vmid);
3951 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3953 return if !$running;
3955 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
3958 sub set_migration_caps {
3964 "auto-converge" => 1,
3966 "x-rdma-pin-all" => 0,
3971 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
3973 for my $supported_capability (@$supported_capabilities) {
3975 capability => $supported_capability->{capability},
3976 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3980 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
3983 my $fast_plug_option = {
3992 # hotplug changes in [PENDING]
3993 # $selection hash can be used to only apply specified options, for
3994 # example: { cores => 1 } (only apply changed 'cores
')
3995 # $errors ref is used to return error messages
3996 sub vmconfig_hotplug_pending {
3997 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3999 my $defaults = load_defaults();
4001 # commit values which do not have any impact on running VM first
4002 # Note: those option cannot raise errors, we we do not care about
4003 # $selection and always apply them.
4005 my $add_error = sub {
4006 my ($opt, $msg) = @_;
4007 $errors->{$opt} = "hotplug problem - $msg";
4011 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4012 if ($fast_plug_option->{$opt}) {
4013 $conf->{$opt} = $conf->{pending}->{$opt};
4014 delete $conf->{pending}->{$opt};
4020 PVE::QemuConfig->write_config($vmid, $conf);
4021 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4024 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4026 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4027 while (my ($opt, $force) = each %$pending_delete_hash) {
4028 next if $selection && !$selection->{$opt};
4030 if ($opt eq 'hotplug
') {
4031 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4032 } elsif ($opt eq 'tablet
') {
4033 die "skip\n" if !$hotplug_features->{usb};
4034 if ($defaults->{tablet}) {
4035 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4037 vm_deviceunplug($vmid, $conf, $opt);
4039 } elsif ($opt eq 'vcpus
') {
4040 die "skip\n" if !$hotplug_features->{cpu};
4041 qemu_cpu_hotplug($vmid, $conf, undef);
4042 } elsif ($opt eq 'balloon
') {
4043 # enable balloon device is not hotpluggable
4044 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4045 } elsif ($fast_plug_option->{$opt}) {
4047 } elsif ($opt =~ m/^net(\d+)$/) {
4048 die "skip\n" if !$hotplug_features->{network};
4049 vm_deviceunplug($vmid, $conf, $opt);
4050 } elsif (is_valid_drivename($opt)) {
4051 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4052 vm_deviceunplug($vmid, $conf, $opt);
4053 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4054 } elsif ($opt =~ m/^memory$/) {
4055 die "skip\n" if !$hotplug_features->{memory};
4056 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4057 } elsif ($opt eq 'cpuunits
') {
4058 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4059 } elsif ($opt eq 'cpulimit
') {
4060 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4066 &$add_error($opt, $err) if $err ne "skip\n";
4068 # save new config if hotplug was successful
4069 delete $conf->{$opt};
4070 vmconfig_undelete_pending_option($conf, $opt);
4071 PVE::QemuConfig->write_config($vmid, $conf);
4072 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4076 foreach my $opt (keys %{$conf->{pending}}) {
4077 next if $selection && !$selection->{$opt};
4078 my $value = $conf->{pending}->{$opt};
4080 if ($opt eq 'hotplug
') {
4081 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4082 } elsif ($opt eq 'tablet
') {
4083 die "skip\n" if !$hotplug_features->{usb};
4085 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4086 } elsif ($value == 0) {
4087 vm_deviceunplug($vmid, $conf, $opt);
4089 } elsif ($opt eq 'vcpus
') {
4090 die "skip\n" if !$hotplug_features->{cpu};
4091 qemu_cpu_hotplug($vmid, $conf, $value);
4092 } elsif ($opt eq 'balloon
') {
4093 # enable/disable balloning device is not hotpluggable
4094 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4095 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4096 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4098 # allow manual ballooning if shares is set to zero
4099 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4100 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4101 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4103 } elsif ($opt =~ m/^net(\d+)$/) {
4104 # some changes can be done without hotplug
4105 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4106 $vmid, $opt, $value);
4107 } elsif (is_valid_drivename($opt)) {
4108 # some changes can be done without hotplug
4109 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4110 $vmid, $opt, $value, 1);
4111 } elsif ($opt =~ m/^memory$/) { #dimms
4112 die "skip\n" if !$hotplug_features->{memory};
4113 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4114 } elsif ($opt eq 'cpuunits
') {
4115 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4116 } elsif ($opt eq 'cpulimit
') {
4117 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4118 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4120 die "skip\n"; # skip non-hot-pluggable options
4124 &$add_error($opt, $err) if $err ne "skip\n";
4126 # save new config if hotplug was successful
4127 $conf->{$opt} = $value;
4128 delete $conf->{pending}->{$opt};
4129 PVE::QemuConfig->write_config($vmid, $conf);
4130 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4135 sub try_deallocate_drive {
4136 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4138 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4139 my $volid = $drive->{file};
4140 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4141 my $sid = PVE::Storage::parse_volume_id($volid);
4142 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4144 # check if the disk is really unused
4145 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4146 if is_volume_in_use($storecfg, $conf, $key, $volid);
4147 PVE::Storage::vdisk_free($storecfg, $volid);
4150 # If vm is not owner of this disk remove from config
4158 sub vmconfig_delete_or_detach_drive {
4159 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4161 my $drive = parse_drive($opt, $conf->{$opt});
4163 my $rpcenv = PVE::RPCEnvironment::get();
4164 my $authuser = $rpcenv->get_user();
4167 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4168 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4170 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4174 sub vmconfig_apply_pending {
4175 my ($vmid, $conf, $storecfg) = @_;
4179 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4180 while (my ($opt, $force) = each %$pending_delete_hash) {
4181 die "internal error" if $opt =~ m/^unused/;
4182 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4183 if (!defined($conf->{$opt})) {
4184 vmconfig_undelete_pending_option($conf, $opt);
4185 PVE::QemuConfig->write_config($vmid, $conf);
4186 } elsif (is_valid_drivename($opt)) {
4187 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4188 vmconfig_undelete_pending_option($conf, $opt);
4189 delete $conf->{$opt};
4190 PVE::QemuConfig->write_config($vmid, $conf);
4192 vmconfig_undelete_pending_option($conf, $opt);
4193 delete $conf->{$opt};
4194 PVE::QemuConfig->write_config($vmid, $conf);
4198 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4200 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4201 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4203 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4204 # skip if nothing changed
4205 } elsif (is_valid_drivename($opt)) {
4206 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4207 if defined($conf->{$opt});
4208 $conf->{$opt} = $conf->{pending}->{$opt};
4210 $conf->{$opt} = $conf->{pending}->{$opt};
4213 delete $conf->{pending}->{$opt};
4214 PVE::QemuConfig->write_config($vmid, $conf);
4218 my $safe_num_ne = sub {
4221 return 0 if !defined($a) && !defined($b);
4222 return 1 if !defined($a);
4223 return 1 if !defined($b);
4228 my $safe_string_ne = sub {
4231 return 0 if !defined($a) && !defined($b);
4232 return 1 if !defined($a);
4233 return 1 if !defined($b);
4238 sub vmconfig_update_net {
4239 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4241 my $newnet = parse_net($value);
4243 if ($conf->{$opt}) {
4244 my $oldnet = parse_net($conf->{$opt});
4246 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4247 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4248 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4249 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4251 # for non online change, we try to hot-unplug
4252 die "skip\n" if !$hotplug;
4253 vm_deviceunplug($vmid, $conf, $opt);
4256 die "internal error" if $opt !~ m/net(\d+)/;
4257 my $iface = "tap${vmid}i$1";
4259 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4260 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4261 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4262 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4263 PVE::Network::tap_unplug($iface);
4264 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4265 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4266 # Rate can be applied on its own but any change above needs to
4267 # include the rate in tap_plug since OVS resets everything.
4268 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4271 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4272 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4280 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4286 sub vmconfig_update_disk {
4287 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4289 # fixme: do we need force?
4291 my $drive = parse_drive($opt, $value);
4293 if ($conf->{$opt}) {
4295 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4297 my $media = $drive->{media} || 'disk
';
4298 my $oldmedia = $old_drive->{media} || 'disk
';
4299 die "unable to change media type\n" if $media ne $oldmedia;
4301 if (!drive_is_cdrom($old_drive)) {
4303 if ($drive->{file} ne $old_drive->{file}) {
4305 die "skip\n" if !$hotplug;
4307 # unplug and register as unused
4308 vm_deviceunplug($vmid, $conf, $opt);
4309 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4312 # update existing disk
4314 # skip non hotpluggable value
4315 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4316 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4317 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4318 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4323 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4324 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4325 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4326 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4327 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4328 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4329 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4330 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4331 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4332 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4333 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4334 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4336 qemu_block_set_io_throttle($vmid,"drive-$opt",
4337 ($drive->{mbps} || 0)*1024*1024,
4338 ($drive->{mbps_rd} || 0)*1024*1024,
4339 ($drive->{mbps_wr} || 0)*1024*1024,
4340 $drive->{iops} || 0,
4341 $drive->{iops_rd} || 0,
4342 $drive->{iops_wr} || 0,
4343 ($drive->{mbps_max} || 0)*1024*1024,
4344 ($drive->{mbps_rd_max} || 0)*1024*1024,
4345 ($drive->{mbps_wr_max} || 0)*1024*1024,
4346 $drive->{iops_max} || 0,
4347 $drive->{iops_rd_max} || 0,
4348 $drive->{iops_wr_max} || 0);
4357 if ($drive->{file} eq 'none
') {
4358 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4360 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4361 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4362 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4370 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4372 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4373 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4377 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4378 $forcemachine, $spice_ticket) = @_;
4380 PVE::QemuConfig->lock_config($vmid, sub {
4381 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4383 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4385 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4387 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4389 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4390 vmconfig_apply_pending($vmid, $conf, $storecfg);
4391 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4394 my $defaults = load_defaults();
4396 # set environment variable useful inside network script
4397 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4399 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4401 my $migrate_port = 0;
4404 if ($statefile eq 'tcp
') {
4405 my $localip = "localhost";
4406 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4407 my $nodename = PVE::INotify::nodename();
4408 if ($datacenterconf->{migration_unsecure}) {
4409 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4410 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4412 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4413 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4414 $migrate_uri = "tcp:${localip}:${migrate_port}";
4415 push @$cmd, '-incoming
', $migrate_uri;
4418 push @$cmd, '-loadstate
', $statefile;
4425 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4426 my $d = parse_hostpci($conf->{"hostpci$i"});
4428 my $pcidevices = $d->{pciid};
4429 foreach my $pcidevice (@$pcidevices) {
4430 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4432 my $info = pci_device_info("0000:$pciid");
4433 die "IOMMU not present\n" if !check_iommu_support();
4434 die "no pci device info for device '$pciid'\n" if !$info;
4435 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4436 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4440 PVE::Storage::activate_volumes($storecfg, $vollist);
4442 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4444 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4445 eval { run_command($cmd); };
4448 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4452 # deactivate volumes if start fails
4453 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4454 die "start failed: $err";
4457 print "migration listens on $migrate_uri\n" if $migrate_uri;
4459 if ($statefile && $statefile ne 'tcp
') {
4460 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4464 if ($migratedfrom) {
4467 set_migration_caps($vmid);
4472 print "spice listens on port $spice_port\n";
4473 if ($spice_ticket) {
4474 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4475 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4481 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4482 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4483 if $conf->{balloon};
4486 foreach my $opt (keys %$conf) {
4487 next if $opt !~ m/^net\d+$/;
4488 my $nicconf = parse_net($conf->{$opt});
4489 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4493 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4494 path => "machine/peripheral/balloon0",
4495 property => "guest-stats-polling-interval",
4496 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4502 my ($vmid, $execute, %params) = @_;
4504 my $cmd = { execute => $execute, arguments => \%params };
4505 vm_qmp_command($vmid, $cmd);
4508 sub vm_mon_cmd_nocheck {
4509 my ($vmid, $execute, %params) = @_;
4511 my $cmd = { execute => $execute, arguments => \%params };
4512 vm_qmp_command($vmid, $cmd, 1);
4515 sub vm_qmp_command {
4516 my ($vmid, $cmd, $nocheck) = @_;
4521 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4522 $timeout = $cmd->{arguments}->{timeout};
4523 delete $cmd->{arguments}->{timeout};
4527 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4528 my $sname = qmp_socket($vmid);
4529 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4530 my $qmpclient = PVE::QMPClient->new();
4532 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4533 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4534 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4535 if scalar(%{$cmd->{arguments}});
4536 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4538 die "unable to
open monitor
socket\n";
4542 syslog("err
", "VM
$vmid qmp command failed
- $err");
4549 sub vm_human_monitor_command {
4550 my ($vmid, $cmdline) = @_;
4555 execute => 'human-monitor-command',
4556 arguments => { 'command-line' => $cmdline},
4559 return vm_qmp_command($vmid, $cmd);
4562 sub vm_commandline {
4563 my ($storecfg, $vmid) = @_;
4565 my $conf = PVE::QemuConfig->load_config($vmid);
4567 my $defaults = load_defaults();
4569 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4571 return join(' ', @$cmd);
4575 my ($vmid, $skiplock) = @_;
4577 PVE::QemuConfig->lock_config($vmid, sub {
4579 my $conf = PVE::QemuConfig->load_config($vmid);
4581 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4583 vm_mon_cmd($vmid, "system_reset
");
4587 sub get_vm_volumes {
4591 foreach_volid($conf, sub {
4592 my ($volid, $is_cdrom) = @_;
4594 return if $volid =~ m|^/|;
4596 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4599 push @$vollist, $volid;
4605 sub vm_stop_cleanup {
4606 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4611 my $vollist = get_vm_volumes($conf);
4612 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4615 foreach my $ext (qw(mon qmp pid vnc qga)) {
4616 unlink "/var/run/qemu-server/${vmid}.$ext";
4619 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4621 warn $@ if $@; # avoid errors - just warn
4624 # Note: use $nockeck to skip tests if VM configuration file exists.
4625 # We need that when migration VMs to other nodes (files already moved)
4626 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4628 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4630 $force = 1 if !defined($force) && !$shutdown;
4633 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4634 kill 15, $pid if $pid;
4635 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4636 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4640 PVE
::QemuConfig-
>lock_config($vmid, sub {
4642 my $pid = check_running
($vmid, $nocheck);
4647 $conf = PVE
::QemuConfig-
>load_config($vmid);
4648 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4649 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4650 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4651 $timeout = $opts->{down
} if $opts->{down
};
4655 $timeout = 60 if !defined($timeout);
4659 if (defined($conf) && $conf->{agent
}) {
4660 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4662 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4665 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4672 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4677 if ($count >= $timeout) {
4679 warn "VM still running - terminating now with SIGTERM\n";
4682 die "VM quit/powerdown failed - got timeout\n";
4685 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4690 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4693 die "VM quit/powerdown failed\n";
4701 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4706 if ($count >= $timeout) {
4707 warn "VM still running - terminating now with SIGKILL\n";
4712 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4717 my ($vmid, $skiplock) = @_;
4719 PVE
::QemuConfig-
>lock_config($vmid, sub {
4721 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4723 PVE
::QemuConfig-
>check_lock($conf)
4724 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4726 vm_mon_cmd
($vmid, "stop");
4731 my ($vmid, $skiplock, $nocheck) = @_;
4733 PVE
::QemuConfig-
>lock_config($vmid, sub {
4737 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4739 PVE
::QemuConfig-
>check_lock($conf)
4740 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4742 vm_mon_cmd
($vmid, "cont");
4745 vm_mon_cmd_nocheck
($vmid, "cont");
4751 my ($vmid, $skiplock, $key) = @_;
4753 PVE
::QemuConfig-
>lock_config($vmid, sub {
4755 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4757 # there is no qmp command, so we use the human monitor command
4758 vm_human_monitor_command
($vmid, "sendkey $key");
4763 my ($storecfg, $vmid, $skiplock) = @_;
4765 PVE
::QemuConfig-
>lock_config($vmid, sub {
4767 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4769 if (!check_running
($vmid)) {
4770 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4772 die "VM $vmid is running - destroy failed\n";
4780 my ($filename, $buf) = @_;
4782 my $fh = IO
::File-
>new($filename, "w");
4783 return undef if !$fh;
4785 my $res = print $fh $buf;
4792 sub pci_device_info
{
4797 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4798 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4800 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4801 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4803 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4804 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4806 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4807 return undef if !defined($product) || $product !~ s/^0x//;
4812 product
=> $product,
4818 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4827 my $name = $dev->{name
};
4829 my $fn = "$pcisysfs/devices/$name/reset";
4831 return file_write
($fn, "1");
4834 sub pci_dev_bind_to_vfio
{
4837 my $name = $dev->{name
};
4839 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4841 if (!-d
$vfio_basedir) {
4842 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4844 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4846 my $testdir = "$vfio_basedir/$name";
4847 return 1 if -d
$testdir;
4849 my $data = "$dev->{vendor} $dev->{product}";
4850 return undef if !file_write
("$vfio_basedir/new_id", $data);
4852 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4853 if (!file_write
($fn, $name)) {
4854 return undef if -f
$fn;
4857 $fn = "$vfio_basedir/bind";
4858 if (! -d
$testdir) {
4859 return undef if !file_write
($fn, $name);
4865 sub pci_dev_group_bind_to_vfio
{
4868 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4870 if (!-d
$vfio_basedir) {
4871 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4873 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4875 # get IOMMU group devices
4876 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4877 my @devs = grep /^0000:/, readdir($D);
4880 foreach my $pciid (@devs) {
4881 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4883 # pci bridges, switches or root ports are not supported
4884 # they have a pci_bus subdirectory so skip them
4885 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4887 my $info = pci_device_info
($1);
4888 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4894 sub print_pci_addr
{
4895 my ($id, $bridges) = @_;
4899 piix3
=> { bus
=> 0, addr
=> 1 },
4900 #addr2 : first videocard
4901 balloon0
=> { bus
=> 0, addr
=> 3 },
4902 watchdog
=> { bus
=> 0, addr
=> 4 },
4903 scsihw0
=> { bus
=> 0, addr
=> 5 },
4904 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4905 scsihw1
=> { bus
=> 0, addr
=> 6 },
4906 ahci0
=> { bus
=> 0, addr
=> 7 },
4907 qga0
=> { bus
=> 0, addr
=> 8 },
4908 spice
=> { bus
=> 0, addr
=> 9 },
4909 virtio0
=> { bus
=> 0, addr
=> 10 },
4910 virtio1
=> { bus
=> 0, addr
=> 11 },
4911 virtio2
=> { bus
=> 0, addr
=> 12 },
4912 virtio3
=> { bus
=> 0, addr
=> 13 },
4913 virtio4
=> { bus
=> 0, addr
=> 14 },
4914 virtio5
=> { bus
=> 0, addr
=> 15 },
4915 hostpci0
=> { bus
=> 0, addr
=> 16 },
4916 hostpci1
=> { bus
=> 0, addr
=> 17 },
4917 net0
=> { bus
=> 0, addr
=> 18 },
4918 net1
=> { bus
=> 0, addr
=> 19 },
4919 net2
=> { bus
=> 0, addr
=> 20 },
4920 net3
=> { bus
=> 0, addr
=> 21 },
4921 net4
=> { bus
=> 0, addr
=> 22 },
4922 net5
=> { bus
=> 0, addr
=> 23 },
4923 vga1
=> { bus
=> 0, addr
=> 24 },
4924 vga2
=> { bus
=> 0, addr
=> 25 },
4925 vga3
=> { bus
=> 0, addr
=> 26 },
4926 hostpci2
=> { bus
=> 0, addr
=> 27 },
4927 hostpci3
=> { bus
=> 0, addr
=> 28 },
4928 #addr29 : usb-host (pve-usb.cfg)
4929 'pci.1' => { bus
=> 0, addr
=> 30 },
4930 'pci.2' => { bus
=> 0, addr
=> 31 },
4931 'net6' => { bus
=> 1, addr
=> 1 },
4932 'net7' => { bus
=> 1, addr
=> 2 },
4933 'net8' => { bus
=> 1, addr
=> 3 },
4934 'net9' => { bus
=> 1, addr
=> 4 },
4935 'net10' => { bus
=> 1, addr
=> 5 },
4936 'net11' => { bus
=> 1, addr
=> 6 },
4937 'net12' => { bus
=> 1, addr
=> 7 },
4938 'net13' => { bus
=> 1, addr
=> 8 },
4939 'net14' => { bus
=> 1, addr
=> 9 },
4940 'net15' => { bus
=> 1, addr
=> 10 },
4941 'net16' => { bus
=> 1, addr
=> 11 },
4942 'net17' => { bus
=> 1, addr
=> 12 },
4943 'net18' => { bus
=> 1, addr
=> 13 },
4944 'net19' => { bus
=> 1, addr
=> 14 },
4945 'net20' => { bus
=> 1, addr
=> 15 },
4946 'net21' => { bus
=> 1, addr
=> 16 },
4947 'net22' => { bus
=> 1, addr
=> 17 },
4948 'net23' => { bus
=> 1, addr
=> 18 },
4949 'net24' => { bus
=> 1, addr
=> 19 },
4950 'net25' => { bus
=> 1, addr
=> 20 },
4951 'net26' => { bus
=> 1, addr
=> 21 },
4952 'net27' => { bus
=> 1, addr
=> 22 },
4953 'net28' => { bus
=> 1, addr
=> 23 },
4954 'net29' => { bus
=> 1, addr
=> 24 },
4955 'net30' => { bus
=> 1, addr
=> 25 },
4956 'net31' => { bus
=> 1, addr
=> 26 },
4957 'xhci' => { bus
=> 1, addr
=> 27 },
4958 'virtio6' => { bus
=> 2, addr
=> 1 },
4959 'virtio7' => { bus
=> 2, addr
=> 2 },
4960 'virtio8' => { bus
=> 2, addr
=> 3 },
4961 'virtio9' => { bus
=> 2, addr
=> 4 },
4962 'virtio10' => { bus
=> 2, addr
=> 5 },
4963 'virtio11' => { bus
=> 2, addr
=> 6 },
4964 'virtio12' => { bus
=> 2, addr
=> 7 },
4965 'virtio13' => { bus
=> 2, addr
=> 8 },
4966 'virtio14' => { bus
=> 2, addr
=> 9 },
4967 'virtio15' => { bus
=> 2, addr
=> 10 },
4968 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4969 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4970 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4971 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4972 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4973 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4974 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4975 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4976 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4977 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4978 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4979 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4980 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4981 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4982 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4983 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4984 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4985 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4986 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4987 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4988 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4989 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4990 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4991 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4992 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4993 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4994 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4995 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4996 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4997 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4998 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5002 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5003 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5004 my $bus = $devices->{$id}->{bus
};
5005 $res = ",bus=pci.$bus,addr=$addr";
5006 $bridges->{$bus} = 1 if $bridges;
5012 sub print_pcie_addr
{
5017 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5018 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5019 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5020 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5023 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5024 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5025 my $bus = $devices->{$id}->{bus
};
5026 $res = ",bus=$bus,addr=$addr";
5032 # vzdump restore implementaion
5034 sub tar_archive_read_firstfile
{
5035 my $archive = shift;
5037 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5039 # try to detect archive type first
5040 my $pid = open (TMP
, "tar tf '$archive'|") ||
5041 die "unable to open file '$archive'\n";
5042 my $firstfile = <TMP
>;
5046 die "ERROR: archive contaions no data\n" if !$firstfile;
5052 sub tar_restore_cleanup
{
5053 my ($storecfg, $statfile) = @_;
5055 print STDERR
"starting cleanup\n";
5057 if (my $fd = IO
::File-
>new($statfile, "r")) {
5058 while (defined(my $line = <$fd>)) {
5059 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5062 if ($volid =~ m
|^/|) {
5063 unlink $volid || die 'unlink failed\n';
5065 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5067 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5069 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5071 print STDERR
"unable to parse line in statfile - $line";
5078 sub restore_archive
{
5079 my ($archive, $vmid, $user, $opts) = @_;
5081 my $format = $opts->{format
};
5084 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5085 $format = 'tar' if !$format;
5087 } elsif ($archive =~ m/\.tar$/) {
5088 $format = 'tar' if !$format;
5089 } elsif ($archive =~ m/.tar.lzo$/) {
5090 $format = 'tar' if !$format;
5092 } elsif ($archive =~ m/\.vma$/) {
5093 $format = 'vma' if !$format;
5094 } elsif ($archive =~ m/\.vma\.gz$/) {
5095 $format = 'vma' if !$format;
5097 } elsif ($archive =~ m/\.vma\.lzo$/) {
5098 $format = 'vma' if !$format;
5101 $format = 'vma' if !$format; # default
5104 # try to detect archive format
5105 if ($format eq 'tar') {
5106 return restore_tar_archive
($archive, $vmid, $user, $opts);
5108 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5112 sub restore_update_config_line
{
5113 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5115 return if $line =~ m/^\#qmdump\#/;
5116 return if $line =~ m/^\#vzdump\#/;
5117 return if $line =~ m/^lock:/;
5118 return if $line =~ m/^unused\d+:/;
5119 return if $line =~ m/^parent:/;
5120 return if $line =~ m/^template:/; # restored VM is never a template
5122 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5123 # try to convert old 1.X settings
5124 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5125 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5126 my ($model, $macaddr) = split(/\=/, $devconfig);
5127 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5130 bridge
=> "vmbr$ind",
5131 macaddr
=> $macaddr,
5133 my $netstr = print_net
($net);
5135 print $outfd "net$cookie->{netcount}: $netstr\n";
5136 $cookie->{netcount
}++;
5138 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5139 my ($id, $netstr) = ($1, $2);
5140 my $net = parse_net
($netstr);
5141 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5142 $netstr = print_net
($net);
5143 print $outfd "$id: $netstr\n";
5144 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5147 my $di = parse_drive
($virtdev, $value);
5148 if (defined($di->{backup
}) && !$di->{backup
}) {
5149 print $outfd "#$line";
5150 } elsif ($map->{$virtdev}) {
5151 delete $di->{format
}; # format can change on restore
5152 $di->{file
} = $map->{$virtdev};
5153 $value = print_drive
($vmid, $di);
5154 print $outfd "$virtdev: $value\n";
5164 my ($cfg, $vmid) = @_;
5166 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5168 my $volid_hash = {};
5169 foreach my $storeid (keys %$info) {
5170 foreach my $item (@{$info->{$storeid}}) {
5171 next if !($item->{volid
} && $item->{size
});
5172 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5173 $volid_hash->{$item->{volid
}} = $item;
5180 sub is_volume_in_use
{
5181 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5183 my $path = PVE
::Storage
::path
($storecfg, $volid);
5185 my $scan_config = sub {
5186 my ($cref, $snapname) = @_;
5188 foreach my $key (keys %$cref) {
5189 my $value = $cref->{$key};
5190 if (is_valid_drivename
($key)) {
5191 next if $skip_drive && $key eq $skip_drive;
5192 my $drive = parse_drive
($key, $value);
5193 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5194 return 1 if $volid eq $drive->{file
};
5195 if ($drive->{file
} =~ m!^/!) {
5196 return 1 if $drive->{file
} eq $path;
5198 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5200 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5202 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5210 return 1 if &$scan_config($conf);
5214 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5215 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5221 sub update_disksize
{
5222 my ($vmid, $conf, $volid_hash) = @_;
5228 # Note: it is allowed to define multiple storages with same path (alias), so
5229 # we need to check both 'volid' and real 'path' (two different volid can point
5230 # to the same path).
5235 foreach my $opt (keys %$conf) {
5236 if (is_valid_drivename
($opt)) {
5237 my $drive = parse_drive
($opt, $conf->{$opt});
5238 my $volid = $drive->{file
};
5241 $used->{$volid} = 1;
5242 if ($volid_hash->{$volid} &&
5243 (my $path = $volid_hash->{$volid}->{path
})) {
5244 $usedpath->{$path} = 1;
5247 next if drive_is_cdrom
($drive);
5248 next if !$volid_hash->{$volid};
5250 $drive->{size
} = $volid_hash->{$volid}->{size
};
5251 my $new = print_drive
($vmid, $drive);
5252 if ($new ne $conf->{$opt}) {
5254 $conf->{$opt} = $new;
5259 # remove 'unusedX' entry if volume is used
5260 foreach my $opt (keys %$conf) {
5261 next if $opt !~ m/^unused\d+$/;
5262 my $volid = $conf->{$opt};
5263 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5264 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5266 delete $conf->{$opt};
5270 foreach my $volid (sort keys %$volid_hash) {
5271 next if $volid =~ m/vm-$vmid-state-/;
5272 next if $used->{$volid};
5273 my $path = $volid_hash->{$volid}->{path
};
5274 next if !$path; # just to be sure
5275 next if $usedpath->{$path};
5277 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5278 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5285 my ($vmid, $nolock) = @_;
5287 my $cfg = PVE
::Storage
::config
();
5289 my $volid_hash = scan_volids
($cfg, $vmid);
5291 my $updatefn = sub {
5294 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5296 PVE
::QemuConfig-
>check_lock($conf);
5299 foreach my $volid (keys %$volid_hash) {
5300 my $info = $volid_hash->{$volid};
5301 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5304 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5306 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5309 if (defined($vmid)) {
5313 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5316 my $vmlist = config_list
();
5317 foreach my $vmid (keys %$vmlist) {
5321 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5327 sub restore_vma_archive
{
5328 my ($archive, $vmid, $user, $opts, $comp) = @_;
5330 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5331 my $readfrom = $archive;
5336 my $qarchive = PVE
::Tools
::shellquote
($archive);
5337 if ($comp eq 'gzip') {
5338 $uncomp = "zcat $qarchive|";
5339 } elsif ($comp eq 'lzop') {
5340 $uncomp = "lzop -d -c $qarchive|";
5342 die "unknown compression method '$comp'\n";
5347 my $tmpdir = "/var/tmp/vzdumptmp$$";
5350 # disable interrupts (always do cleanups)
5351 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5352 warn "got interrupt - ignored\n";
5355 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5356 POSIX
::mkfifo
($mapfifo, 0600);
5359 my $openfifo = sub {
5360 open($fifofh, '>', $mapfifo) || die $!;
5363 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5370 my $rpcenv = PVE
::RPCEnvironment
::get
();
5372 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5373 my $tmpfn = "$conffile.$$.tmp";
5375 # Note: $oldconf is undef if VM does not exists
5376 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5377 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5379 my $print_devmap = sub {
5380 my $virtdev_hash = {};
5382 my $cfgfn = "$tmpdir/qemu-server.conf";
5384 # we can read the config - that is already extracted
5385 my $fh = IO
::File-
>new($cfgfn, "r") ||
5386 "unable to read qemu-server.conf - $!\n";
5388 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5390 my $pve_firewall_dir = '/etc/pve/firewall';
5391 mkdir $pve_firewall_dir; # make sure the dir exists
5392 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5395 while (defined(my $line = <$fh>)) {
5396 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5397 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5398 die "archive does not contain data for drive '$virtdev'\n"
5399 if !$devinfo->{$devname};
5400 if (defined($opts->{storage
})) {
5401 $storeid = $opts->{storage
} || 'local';
5402 } elsif (!$storeid) {
5405 $format = 'raw' if !$format;
5406 $devinfo->{$devname}->{devname
} = $devname;
5407 $devinfo->{$devname}->{virtdev
} = $virtdev;
5408 $devinfo->{$devname}->{format
} = $format;
5409 $devinfo->{$devname}->{storeid
} = $storeid;
5411 # check permission on storage
5412 my $pool = $opts->{pool
}; # todo: do we need that?
5413 if ($user ne 'root@pam') {
5414 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5417 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5421 foreach my $devname (keys %$devinfo) {
5422 die "found no device mapping information for device '$devname'\n"
5423 if !$devinfo->{$devname}->{virtdev
};
5426 my $cfg = PVE
::Storage
::config
();
5428 # create empty/temp config
5430 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5431 foreach_drive
($oldconf, sub {
5432 my ($ds, $drive) = @_;
5434 return if drive_is_cdrom
($drive);
5436 my $volid = $drive->{file
};
5438 return if !$volid || $volid =~ m
|^/|;
5440 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5441 return if !$path || !$owner || ($owner != $vmid);
5443 # Note: only delete disk we want to restore
5444 # other volumes will become unused
5445 if ($virtdev_hash->{$ds}) {
5446 PVE
::Storage
::vdisk_free
($cfg, $volid);
5450 # delete vmstate files
5451 # since after the restore we have no snapshots anymore
5452 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5453 my $snap = $oldconf->{snapshots
}->{$snapname};
5454 if ($snap->{vmstate
}) {
5455 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5464 foreach my $virtdev (sort keys %$virtdev_hash) {
5465 my $d = $virtdev_hash->{$virtdev};
5466 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5467 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5469 # test if requested format is supported
5470 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5471 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5472 $d->{format
} = $defFormat if !$supported;
5474 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5475 $d->{format
}, undef, $alloc_size);
5476 print STDERR
"new volume ID is '$volid'\n";
5477 $d->{volid
} = $volid;
5478 my $path = PVE
::Storage
::path
($cfg, $volid);
5480 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5482 my $write_zeros = 1;
5483 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5487 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5489 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5490 $map->{$virtdev} = $volid;
5493 $fh->seek(0, 0) || die "seek failed - $!\n";
5495 my $outfd = new IO
::File
($tmpfn, "w") ||
5496 die "unable to write config for VM $vmid\n";
5498 my $cookie = { netcount
=> 0 };
5499 while (defined(my $line = <$fh>)) {
5500 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5509 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5510 die "interrupted by signal\n";
5512 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5514 $oldtimeout = alarm($timeout);
5521 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5522 my ($dev_id, $size, $devname) = ($1, $2, $3);
5523 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5524 } elsif ($line =~ m/^CTIME: /) {
5525 # we correctly received the vma config, so we can disable
5526 # the timeout now for disk allocation (set to 10 minutes, so
5527 # that we always timeout if something goes wrong)
5530 print $fifofh "done\n";
5531 my $tmp = $oldtimeout || 0;
5532 $oldtimeout = undef;
5538 print "restore vma archive: $cmd\n";
5539 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5543 alarm($oldtimeout) if $oldtimeout;
5546 foreach my $devname (keys %$devinfo) {
5547 my $volid = $devinfo->{$devname}->{volid
};
5548 push @$vollist, $volid if $volid;
5551 my $cfg = PVE
::Storage
::config
();
5552 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5560 foreach my $devname (keys %$devinfo) {
5561 my $volid = $devinfo->{$devname}->{volid
};
5564 if ($volid =~ m
|^/|) {
5565 unlink $volid || die 'unlink failed\n';
5567 PVE
::Storage
::vdisk_free
($cfg, $volid);
5569 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5571 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5578 rename($tmpfn, $conffile) ||
5579 die "unable to commit configuration file '$conffile'\n";
5581 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5583 eval { rescan
($vmid, 1); };
5587 sub restore_tar_archive
{
5588 my ($archive, $vmid, $user, $opts) = @_;
5590 if ($archive ne '-') {
5591 my $firstfile = tar_archive_read_firstfile
($archive);
5592 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5593 if $firstfile ne 'qemu-server.conf';
5596 my $storecfg = PVE
::Storage
::config
();
5598 # destroy existing data - keep empty config
5599 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5600 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5602 my $tocmd = "/usr/lib/qemu-server/qmextract";
5604 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5605 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5606 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5607 $tocmd .= ' --info' if $opts->{info
};
5609 # tar option "xf" does not autodetect compression when read from STDIN,
5610 # so we pipe to zcat
5611 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5612 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5614 my $tmpdir = "/var/tmp/vzdumptmp$$";
5617 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5618 local $ENV{VZDUMP_VMID
} = $vmid;
5619 local $ENV{VZDUMP_USER
} = $user;
5621 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5622 my $tmpfn = "$conffile.$$.tmp";
5624 # disable interrupts (always do cleanups)
5625 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5626 print STDERR
"got interrupt - ignored\n";
5631 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5632 die "interrupted by signal\n";
5635 if ($archive eq '-') {
5636 print "extracting archive from STDIN\n";
5637 run_command
($cmd, input
=> "<&STDIN");
5639 print "extracting archive '$archive'\n";
5643 return if $opts->{info
};
5647 my $statfile = "$tmpdir/qmrestore.stat";
5648 if (my $fd = IO
::File-
>new($statfile, "r")) {
5649 while (defined (my $line = <$fd>)) {
5650 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5651 $map->{$1} = $2 if $1;
5653 print STDERR
"unable to parse line in statfile - $line\n";
5659 my $confsrc = "$tmpdir/qemu-server.conf";
5661 my $srcfd = new IO
::File
($confsrc, "r") ||
5662 die "unable to open file '$confsrc'\n";
5664 my $outfd = new IO
::File
($tmpfn, "w") ||
5665 die "unable to write config for VM $vmid\n";
5667 my $cookie = { netcount
=> 0 };
5668 while (defined (my $line = <$srcfd>)) {
5669 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5681 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5688 rename $tmpfn, $conffile ||
5689 die "unable to commit configuration file '$conffile'\n";
5691 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5693 eval { rescan
($vmid, 1); };
5697 sub foreach_writable_storage
{
5698 my ($conf, $func) = @_;
5702 foreach my $ds (keys %$conf) {
5703 next if !is_valid_drivename
($ds);
5705 my $drive = parse_drive
($ds, $conf->{$ds});
5707 next if drive_is_cdrom
($drive);
5709 my $volid = $drive->{file
};
5711 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5712 $sidhash->{$sid} = $sid if $sid;
5715 foreach my $sid (sort keys %$sidhash) {
5720 sub do_snapshots_with_qemu
{
5721 my ($storecfg, $volid) = @_;
5723 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5725 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5726 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5730 if ($volid =~ m/\.(qcow2|qed)$/){
5737 sub qga_check_running
{
5740 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5742 warn "Qemu Guest Agent are not running - $@";
5748 sub template_create
{
5749 my ($vmid, $conf, $disk) = @_;
5751 my $storecfg = PVE
::Storage
::config
();
5753 foreach_drive
($conf, sub {
5754 my ($ds, $drive) = @_;
5756 return if drive_is_cdrom
($drive);
5757 return if $disk && $ds ne $disk;
5759 my $volid = $drive->{file
};
5760 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5762 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5763 $drive->{file
} = $voliddst;
5764 $conf->{$ds} = print_drive
($vmid, $drive);
5765 PVE
::QemuConfig-
>write_config($vmid, $conf);
5769 sub qemu_img_convert
{
5770 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5772 my $storecfg = PVE
::Storage
::config
();
5773 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5774 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5776 if ($src_storeid && $dst_storeid) {
5778 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5780 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5781 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5783 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5784 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5786 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5787 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5790 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5791 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5792 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5793 if ($is_zero_initialized) {
5794 push @$cmd, "zeroinit:$dst_path";
5796 push @$cmd, $dst_path;
5801 if($line =~ m/\((\S+)\/100\
%\)/){
5803 my $transferred = int($size * $percent / 100);
5804 my $remaining = $size - $transferred;
5806 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5811 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5813 die "copy failed: $err" if $err;
5817 sub qemu_img_format
{
5818 my ($scfg, $volname) = @_;
5820 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5827 sub qemu_drive_mirror
{
5828 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5830 my $storecfg = PVE
::Storage
::config
();
5831 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5833 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5835 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5837 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5839 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5841 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5842 $opts->{format
} = $format if $format;
5844 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5846 my $finish_job = sub {
5848 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5849 my $stat = @$stats[0];
5856 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5858 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5859 my $stat = @$stats[0];
5860 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5861 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5863 my $busy = $stat->{busy
};
5864 my $ready = $stat->{ready
};
5866 if (my $total = $stat->{len
}) {
5867 my $transferred = $stat->{offset
} || 0;
5868 my $remaining = $total - $transferred;
5869 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5871 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5875 if ($stat->{ready
} eq 'true') {
5877 last if $vmiddst != $vmid;
5879 # try to switch the disk if source and destination are on the same guest
5880 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5885 die $@ if $@ !~ m/cannot be completed/;
5894 my $cancel_job = sub {
5895 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5900 eval { &$cancel_job(); };
5901 die "mirroring error: $err";
5904 if ($vmiddst != $vmid) {
5905 # if we clone a disk for a new target vm, we don't switch the disk
5906 &$cancel_job(); # so we call block-job-cancel
5911 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5912 $newvmid, $storage, $format, $full, $newvollist) = @_;
5917 print "create linked clone of drive $drivename ($drive->{file})\n";
5918 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5919 push @$newvollist, $newvolid;
5921 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5922 $storeid = $storage if $storage;
5924 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5926 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5927 $format = qemu_img_format
($scfg, $volname);
5930 # test if requested format is supported - else use default
5931 my $supported = grep { $_ eq $format } @$validFormats;
5932 $format = $defFormat if !$supported;
5934 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5936 print "create full clone of drive $drivename ($drive->{file})\n";
5937 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5938 push @$newvollist, $newvolid;
5940 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5942 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5943 if (!$running || $snapname) {
5944 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5946 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5950 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5953 $disk->{format
} = undef;
5954 $disk->{file
} = $newvolid;
5955 $disk->{size
} = $size;
5960 # this only works if VM is running
5961 sub get_current_qemu_machine
{
5964 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5965 my $res = vm_qmp_command
($vmid, $cmd);
5967 my ($current, $default);
5968 foreach my $e (@$res) {
5969 $default = $e->{name
} if $e->{'is-default'};
5970 $current = $e->{name
} if $e->{'is-current'};
5973 # fallback to the default machine if current is not supported by qemu
5974 return $current || $default || 'pc';
5977 sub qemu_machine_feature_enabled
{
5978 my ($machine, $kvmver, $version_major, $version_minor) = @_;
5983 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
5985 $current_major = $3;
5986 $current_minor = $4;
5988 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
5990 $current_major = $1;
5991 $current_minor = $2;
5994 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
5999 sub qemu_machine_pxe
{
6000 my ($vmid, $conf, $machine) = @_;
6002 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6004 foreach my $opt (keys %$conf) {
6005 next if $opt !~ m/^net(\d+)$/;
6006 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6008 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6009 return $machine.".pxe" if $romfile =~ m/pxe/;
6016 sub qemu_use_old_bios_files
{
6017 my ($machine_type) = @_;
6019 return if !$machine_type;
6021 my $use_old_bios_files = undef;
6023 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6025 $use_old_bios_files = 1;
6027 my $kvmver = kvm_user_version
();
6028 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6029 # load new efi bios files on migration. So this hack is required to allow
6030 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6031 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6032 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6035 return ($use_old_bios_files, $machine_type);
6042 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6043 my (undef, $id, $function) = @_;
6044 my $res = { id
=> $id, function
=> $function};
6045 push @{$devices->{$id}}, $res;
6051 sub vm_iothreads_list
{
6054 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6057 foreach my $iothread (@$res) {
6058 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6065 my ($conf, $drive) = @_;
6069 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6071 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6077 my $controller = int($drive->{index} / $maxdev);
6078 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6080 return ($maxdev, $controller, $controller_prefix);
6083 # bash completion helper
6085 sub complete_backup_archives
{
6086 my ($cmdname, $pname, $cvalue) = @_;
6088 my $cfg = PVE
::Storage
::config
();
6092 if ($cvalue =~ m/^([^:]+):/) {
6096 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6099 foreach my $id (keys %$data) {
6100 foreach my $item (@{$data->{$id}}) {
6101 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6102 push @$res, $item->{volid
} if defined($item->{volid
});
6109 my $complete_vmid_full = sub {
6112 my $idlist = vmstatus
();
6116 foreach my $id (keys %$idlist) {
6117 my $d = $idlist->{$id};
6118 if (defined($running)) {
6119 next if $d->{template
};
6120 next if $running && $d->{status
} ne 'running';
6121 next if !$running && $d->{status
} eq 'running';
6130 return &$complete_vmid_full();
6133 sub complete_vmid_stopped
{
6134 return &$complete_vmid_full(0);
6137 sub complete_vmid_running
{
6138 return &$complete_vmid_full(1);
6141 sub complete_storage
{
6143 my $cfg = PVE
::Storage
::config
();
6144 my $ids = $cfg->{ids
};
6147 foreach my $sid (keys %$ids) {
6148 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6149 next if !$ids->{$sid}->{content
}->{images
};