1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
32 use PVE
::RPCEnvironment
;
33 use PVE
::QemuServer
::PCI
qw(print_pci_addr print_pcie_addr);
34 use PVE
::QemuServer
::Memory
;
35 use PVE
::QemuServer
::USB
qw(parse_usb_device);
36 use Time
::HiRes
qw(gettimeofday);
37 use File
::Copy
qw(copy);
40 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
42 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
44 # Note about locking: we use flock on the config file protect
45 # against concurent actions.
46 # Aditionaly, we have a 'lock' setting in the config file. This
47 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
48 # allowed when such lock is set. But you can ignore this kind of
49 # lock with the --skiplock flag.
51 cfs_register_file
('/qemu-server/',
55 PVE
::JSONSchema
::register_standard_option
('skiplock', {
56 description
=> "Ignore locks - only root is allowed to use this option.",
61 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
62 description
=> "Some command save/restore state from this location.",
68 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
69 description
=> "The name of the snapshot.",
70 type
=> 'string', format
=> 'pve-configid',
74 #no warnings 'redefine';
77 my ($controller, $vmid, $option, $value) = @_;
79 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
80 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
84 my $nodename = PVE
::INotify
::nodename
();
86 mkdir "/etc/pve/nodes/$nodename";
87 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
90 my $var_run_tmpdir = "/var/run/qemu-server";
91 mkdir $var_run_tmpdir;
93 my $lock_dir = "/var/lock/qemu-server";
96 my $pcisysfs = "/sys/bus/pci";
98 my $cpu_vendor_list = {
100 486 => 'GenuineIntel',
101 pentium
=> 'GenuineIntel',
102 pentium2
=> 'GenuineIntel',
103 pentium3
=> 'GenuineIntel',
104 coreduo
=> 'GenuineIntel',
105 core2duo
=> 'GenuineIntel',
106 Conroe
=> 'GenuineIntel',
107 Penryn
=> 'GenuineIntel',
108 Nehalem
=> 'GenuineIntel',
109 Westmere
=> 'GenuineIntel',
110 SandyBridge
=> 'GenuineIntel',
111 IvyBridge
=> 'GenuineIntel',
112 Haswell
=> 'GenuineIntel',
113 'Haswell-noTSX' => 'GenuineIntel',
114 Broadwell
=> 'GenuineIntel',
115 'Broadwell-noTSX' => 'GenuineIntel',
118 athlon
=> 'AuthenticAMD',
119 phenom
=> 'AuthenticAMD',
120 Opteron_G1
=> 'AuthenticAMD',
121 Opteron_G2
=> 'AuthenticAMD',
122 Opteron_G3
=> 'AuthenticAMD',
123 Opteron_G4
=> 'AuthenticAMD',
124 Opteron_G5
=> 'AuthenticAMD',
126 # generic types, use vendor from host node
136 description
=> "Emulated CPU type.",
138 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
139 format_description
=> 'cputype',
144 description
=> "Do not identify as a KVM virtual machine.",
155 enum
=> [qw(i6300esb ib700)],
156 description
=> "Watchdog type to emulate.",
157 default => 'i6300esb',
162 enum
=> [qw(reset shutdown poweroff pause debug none)],
163 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
167 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
173 description
=> "Specifies whether a VM will be started during system bootup.",
179 description
=> "Automatic restart after crash (currently ignored).",
184 type
=> 'string', format
=> 'pve-hotplug-features',
185 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'.",
186 default => 'network,disk,usb',
191 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
197 description
=> "Lock/unlock the VM.",
198 enum
=> [qw(migrate backup snapshot rollback)],
203 description
=> "Limit of CPU usage.",
204 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.",
212 description
=> "CPU weight for a VM.",
213 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.",
221 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
228 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
234 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",
242 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.",
243 enum
=> PVE
::Tools
::kvmkeymaplist
(),
248 type
=> 'string', format
=> 'dns-name',
249 description
=> "Set a name for the VM. Only used on the configuration web interface.",
254 description
=> "SCSI controller model",
255 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
261 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
266 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
267 description
=> "Specify guest operating system.",
268 verbose_description
=> <<EODESC,
269 Specify guest operating system. This is used to enable special
270 optimization/features for specific operating systems:
273 other;; unspecified OS
274 wxp;; Microsoft Windows XP
275 w2k;; Microsoft Windows 2000
276 w2k3;; Microsoft Windows 2003
277 w2k8;; Microsoft Windows 2008
278 wvista;; Microsoft Windows Vista
279 win7;; Microsoft Windows 7
280 win8;; Microsoft Windows 8/2012
281 l24;; Linux 2.4 Kernel
282 l26;; Linux 2.6/3.X Kernel
283 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
289 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
290 pattern
=> '[acdn]{1,4}',
295 type
=> 'string', format
=> 'pve-qm-bootdisk',
296 description
=> "Enable booting from specified disk.",
297 pattern
=> '(ide|sata|scsi|virtio)\d+',
302 description
=> "The number of CPUs. Please use option -sockets instead.",
309 description
=> "The number of CPU sockets.",
316 description
=> "The number of cores per socket.",
323 description
=> "Enable/disable NUMA.",
329 description
=> "Enable/disable hugepages memory.",
330 enum
=> [qw(any 2 1024)],
335 description
=> "Number of hotplugged vcpus.",
342 description
=> "Enable/disable ACPI.",
348 description
=> "Enable/disable Qemu GuestAgent.",
354 description
=> "Enable/disable KVM hardware virtualization.",
360 description
=> "Enable/disable time drift fix.",
366 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
371 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
376 description
=> "Select the VGA type.",
377 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
378 " modes (>= 1280x1024x16) then you should use the options " .
379 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
380 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
381 "display sever. For win* OS you can select how many independent " .
382 "displays you want, Linux guests can add displays them self. " .
383 "You can also run without any graphic card, using a serial device" .
385 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
389 type
=> 'string', format
=> 'pve-qm-watchdog',
390 description
=> "Create a virtual hardware watchdog device.",
391 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
392 " (by a guest action), the watchdog must be periodically polled " .
393 "by an agent inside the guest or else the watchdog will reset " .
394 "the guest (or execute the respective action specified)",
399 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
400 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'.",
401 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
404 startup
=> get_standard_option
('pve-startup-order'),
408 description
=> "Enable/disable Template.",
414 description
=> "Arbitrary arguments passed to kvm.",
415 verbose_description
=> <<EODESCR,
416 Arbitrary arguments passed to kvm, for example:
418 args: -no-reboot -no-hpet
420 NOTE: this option is for experts only.
427 description
=> "Enable/disable the USB tablet device.",
428 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
429 "usually needed to allow absolute mouse positioning with VNC. " .
430 "Else the mouse runs out of sync with normal VNC clients. " .
431 "If you're running lots of console-only guests on one host, " .
432 "you may consider disabling this to save some context switches. " .
433 "This is turned off by default if you use spice (-vga=qxl).",
438 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
442 migrate_downtime
=> {
445 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
451 type
=> 'string', format
=> 'pve-qm-drive',
452 typetext
=> 'volume',
453 description
=> "This is an alias for option -ide2",
457 description
=> "Emulated CPU type.",
461 parent
=> get_standard_option
('pve-snapshot-name', {
463 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
467 description
=> "Timestamp for snapshots.",
473 type
=> 'string', format
=> 'pve-volume-id',
474 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
477 description
=> "Specific the Qemu machine type.",
479 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
484 description
=> "Specify SMBIOS type 1 fields.",
485 type
=> 'string', format
=> 'pve-qm-smbios1',
492 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
498 enum
=> [ qw(seabios ovmf) ],
499 description
=> "Select BIOS implementation.",
500 default => 'seabios',
504 # what about other qemu settings ?
506 #machine => 'string',
519 ##soundhw => 'string',
521 while (my ($k, $v) = each %$confdesc) {
522 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
525 my $MAX_IDE_DISKS = 4;
526 my $MAX_SCSI_DISKS = 14;
527 my $MAX_VIRTIO_DISKS = 16;
528 my $MAX_SATA_DISKS = 6;
529 my $MAX_USB_DEVICES = 5;
531 my $MAX_UNUSED_DISKS = 8;
532 my $MAX_HOSTPCI_DEVICES = 4;
533 my $MAX_SERIAL_PORTS = 4;
534 my $MAX_PARALLEL_PORTS = 3;
540 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
541 description
=> "CPUs accessing this NUMA node.",
542 format_description
=> "id[-id];...",
546 description
=> "Amount of memory this NUMA node provides.",
551 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
552 description
=> "Host NUMA nodes to use.",
553 format_description
=> "id[-id];...",
558 enum
=> [qw(preferred bind interleave)],
559 description
=> "NUMA allocation policy.",
563 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
566 type
=> 'string', format
=> $numa_fmt,
567 description
=> "NUMA topology.",
569 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
571 for (my $i = 0; $i < $MAX_NUMA; $i++) {
572 $confdesc->{"numa$i"} = $numadesc;
575 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
576 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
577 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
578 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
580 my $net_fmt_bridge_descr = <<__EOD__;
581 Bridge to attach the network device to. The Proxmox VE standard bridge
584 If you do not specify a bridge, we create a kvm user (NATed) network
585 device, which provides DHCP and DNS services. The following addresses
592 The DHCP server assign addresses to the guest starting from 10.0.2.15.
598 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
599 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
600 format_description
=> "XX:XX:XX:XX:XX:XX",
605 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'.",
606 format_description
=> 'model',
607 enum
=> $nic_model_list,
610 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
613 description
=> $net_fmt_bridge_descr,
614 format_description
=> 'bridge',
619 minimum
=> 0, maximum
=> 16,
620 description
=> 'Number of packet queues to be used on the device.',
626 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
631 minimum
=> 1, maximum
=> 4094,
632 description
=> 'VLAN tag to apply to packets on this interface.',
637 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
638 description
=> 'VLAN trunks to pass through this interface.',
639 format_description
=> 'vlanid[;vlanid...]',
644 description
=> 'Whether this interface should be protected by the firewall.',
649 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
656 type
=> 'string', format
=> $net_fmt,
657 description
=> "Specify network devices.",
660 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
662 for (my $i = 0; $i < $MAX_NETS; $i++) {
663 $confdesc->{"net$i"} = $netdesc;
666 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
667 sub verify_volume_id_or_qm_path
{
668 my ($volid, $noerr) = @_;
670 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
674 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
675 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
677 return undef if $noerr;
685 my %drivedesc_base = (
686 volume
=> { alias
=> 'file' },
689 format
=> 'pve-volume-id-or-qm-path',
691 format_description
=> 'volume',
692 description
=> "The drive's backing volume.",
696 enum
=> [qw(cdrom disk)],
697 description
=> "The drive's media type.",
703 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
708 description
=> "Force the drive's physical geometry to have a specific head count.",
713 description
=> "Force the drive's physical geometry to have a specific sector count.",
718 enum
=> [qw(none lba auto)],
719 description
=> "Force disk geometry bios translation mode.",
724 description
=> "Whether the drive should be included when making snapshots.",
729 enum
=> [qw(none writethrough writeback unsafe directsync)],
730 description
=> "The drive's cache mode",
735 format_description
=> 'image format',
736 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
737 description
=> "The drive's backing file's data format.",
742 format
=> 'disk-size',
743 format_description
=> 'DiskSize',
744 description
=> "Disk size. This is purely informational and has no effect.",
749 description
=> "Whether the drive should be included when making backups.",
754 enum
=> [qw(enospc ignore report stop)],
755 description
=> 'Write error action.',
760 enum
=> [qw(native threads)],
761 description
=> 'AIO type to use.',
766 enum
=> [qw(ignore on)],
767 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
772 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
777 format
=> 'urlencoded',
778 format_description
=> 'serial',
779 maxLength
=> 20*3, # *3 since it's %xx url enoded
780 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
788 enum
=> [qw(ignore report stop)],
789 description
=> 'Read error action.',
794 my %iothread_fmt = ( iothread
=> {
796 description
=> "Whether to use iothreads for this drive",
803 format
=> 'urlencoded',
804 format_description
=> 'model',
805 maxLength
=> 40*3, # *3 since it's %xx url enoded
806 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
814 description
=> "Number of queues.",
820 my $add_throttle_desc = sub {
821 my ($key, $type, $what, $unit, $longunit) = @_;
822 $drivedesc_base{$key} = {
824 format_description
=> $unit,
825 description
=> "Maximum $what speed in $longunit per second.",
829 # throughput: (leaky bucket)
830 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
831 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
832 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
833 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
834 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
835 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
836 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
837 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
838 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
840 # pools: (pool of IO before throttling starts taking effect)
841 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
842 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
843 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
844 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
845 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
846 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
856 type
=> 'string', format
=> $ide_fmt,
857 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
859 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
868 type
=> 'string', format
=> $scsi_fmt,
869 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
871 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
879 type
=> 'string', format
=> $sata_fmt,
880 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
882 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
891 type
=> 'string', format
=> $virtio_fmt,
892 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
894 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
905 volume
=> { alias
=> 'file' },
908 format
=> 'pve-volume-id-or-qm-path',
910 format_description
=> 'volume',
911 description
=> "The drive's backing volume.",
915 format_description
=> 'image format',
916 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
917 description
=> "The drive's backing file's data format.",
922 format
=> 'disk-size',
923 format_description
=> 'DiskSize',
924 description
=> "Disk size. This is purely informational and has no effect.",
931 type
=> 'string', format
=> $efidisk_fmt,
932 description
=> "Configure a Disk for storing EFI vars",
935 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
940 type
=> 'string', format
=> 'pve-qm-usb-device',
941 format_description
=> 'HOSTUSBDEVICE|spice',
942 description
=> <<EODESCR,
943 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
945 'bus-port(.port)*' (decimal numbers) or
946 'vendor_id:product_id' (hexadeciaml numbers) or
949 You can use the 'lsusb -t' command to list existing usb devices.
951 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
953 The value 'spice' can be used to add a usb redirection devices for spice.
959 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).",
966 type
=> 'string', format
=> $usb_fmt,
967 description
=> "Configure an USB device (n is 0 to 4).",
969 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
971 # NOTE: the match-groups of this regex are used in parse_hostpci
972 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
977 pattern
=> qr/$PCIRE(;$PCIRE)*/,
978 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
979 description
=> <<EODESCR,
980 Host PCI device pass through. The PCI ID of a host's PCI device or a list
981 of PCI virtual functions of the host. HOSTPCIID syntax is:
983 'bus:dev.func' (hexadecimal numbers)
985 You can us the 'lspci' command to list existing PCI devices.
990 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
996 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1002 description
=> "Enable vfio-vga device support.",
1007 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1011 type
=> 'string', format
=> 'pve-qm-hostpci',
1012 description
=> "Map host PCI devices into guest.",
1013 verbose_description
=> <<EODESCR,
1014 Map host PCI devices into guest.
1016 NOTE: This option allows direct access to host hardware. So it is no longer
1017 possible to migrate such machines - use with special care.
1019 CAUTION: Experimental! User reported problems with this option.
1022 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1027 pattern
=> '(/dev/.+|socket)',
1028 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1029 verbose_description
=> <<EODESCR,
1030 Create a serial device inside the VM (n is 0 to 3), and pass through a
1031 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1032 host side (use 'qm terminal' to open a terminal connection).
1034 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1036 CAUTION: Experimental! User reported problems with this option.
1043 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1044 description
=> "Map host parallel devices (n is 0 to 2).",
1045 verbose_description
=> <<EODESCR,
1046 Map host parallel devices (n is 0 to 2).
1048 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1050 CAUTION: Experimental! User reported problems with this option.
1054 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1055 $confdesc->{"parallel$i"} = $paralleldesc;
1058 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1059 $confdesc->{"serial$i"} = $serialdesc;
1062 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1063 $confdesc->{"hostpci$i"} = $hostpcidesc;
1066 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1067 $drivename_hash->{"ide$i"} = 1;
1068 $confdesc->{"ide$i"} = $idedesc;
1071 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1072 $drivename_hash->{"sata$i"} = 1;
1073 $confdesc->{"sata$i"} = $satadesc;
1076 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1077 $drivename_hash->{"scsi$i"} = 1;
1078 $confdesc->{"scsi$i"} = $scsidesc ;
1081 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1082 $drivename_hash->{"virtio$i"} = 1;
1083 $confdesc->{"virtio$i"} = $virtiodesc;
1086 $drivename_hash->{efidisk0
} = 1;
1087 $confdesc->{efidisk0
} = $efidisk_desc;
1089 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1090 $confdesc->{"usb$i"} = $usbdesc;
1095 type
=> 'string', format
=> 'pve-volume-id',
1096 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1099 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1100 $confdesc->{"unused$i"} = $unuseddesc;
1103 my $kvm_api_version = 0;
1107 return $kvm_api_version if $kvm_api_version;
1109 my $fh = IO
::File-
>new("</dev/kvm") ||
1112 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1113 $kvm_api_version = $v;
1118 return $kvm_api_version;
1121 my $kvm_user_version;
1123 sub kvm_user_version
{
1125 return $kvm_user_version if $kvm_user_version;
1127 $kvm_user_version = 'unknown';
1131 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1132 $kvm_user_version = $2;
1136 eval { run_command
("kvm -version", outfunc
=> $code); };
1139 return $kvm_user_version;
1143 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1145 sub valid_drive_names
{
1146 # order is important - used to autoselect boot disk
1147 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1148 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1149 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1150 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1154 sub is_valid_drivename
{
1157 return defined($drivename_hash->{$dev});
1162 return defined($confdesc->{$key});
1166 return $nic_model_list;
1169 sub os_list_description
{
1173 wxp
=> 'Windows XP',
1174 w2k
=> 'Windows 2000',
1175 w2k3
=>, 'Windows 2003',
1176 w2k8
=> 'Windows 2008',
1177 wvista
=> 'Windows Vista',
1178 win7
=> 'Windows 7',
1179 win8
=> 'Windows 8/2012',
1187 sub get_cdrom_path
{
1189 return $cdrom_path if $cdrom_path;
1191 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1192 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1193 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1197 my ($storecfg, $vmid, $cdrom) = @_;
1199 if ($cdrom eq 'cdrom') {
1200 return get_cdrom_path
();
1201 } elsif ($cdrom eq 'none') {
1203 } elsif ($cdrom =~ m
|^/|) {
1206 return PVE
::Storage
::path
($storecfg, $cdrom);
1210 # try to convert old style file names to volume IDs
1211 sub filename_to_volume_id
{
1212 my ($vmid, $file, $media) = @_;
1214 if (!($file eq 'none' || $file eq 'cdrom' ||
1215 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1217 return undef if $file =~ m
|/|;
1219 if ($media && $media eq 'cdrom') {
1220 $file = "local:iso/$file";
1222 $file = "local:$vmid/$file";
1229 sub verify_media_type
{
1230 my ($opt, $vtype, $media) = @_;
1235 if ($media eq 'disk') {
1237 } elsif ($media eq 'cdrom') {
1240 die "internal error";
1243 return if ($vtype eq $etype);
1245 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1248 sub cleanup_drive_path
{
1249 my ($opt, $storecfg, $drive) = @_;
1251 # try to convert filesystem paths to volume IDs
1253 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1254 ($drive->{file
} !~ m
|^/dev/.+|) &&
1255 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1256 ($drive->{file
} !~ m/^\d+$/)) {
1257 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1258 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1259 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1260 verify_media_type
($opt, $vtype, $drive->{media
});
1261 $drive->{file
} = $volid;
1264 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1267 sub parse_hotplug_features
{
1272 return $res if $data eq '0';
1274 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1276 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1277 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1280 die "invalid hotplug feature '$feature'\n";
1286 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1287 sub pve_verify_hotplug_features
{
1288 my ($value, $noerr) = @_;
1290 return $value if parse_hotplug_features
($value);
1292 return undef if $noerr;
1294 die "unable to parse hotplug option\n";
1297 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1298 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1299 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1300 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1301 # [,iothread=on][,serial=serial][,model=model]
1304 my ($key, $data) = @_;
1306 my ($interface, $index);
1308 if ($key =~ m/^([^\d]+)(\d+)$/) {
1315 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1316 : $confdesc->{$key}->{format
};
1318 warn "invalid drive key: $key\n";
1321 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1322 return undef if !$res;
1323 $res->{interface
} = $interface;
1324 $res->{index} = $index;
1327 foreach my $opt (qw(bps bps_rd bps_wr)) {
1328 if (my $bps = defined(delete $res->{$opt})) {
1329 if (defined($res->{"m$opt"})) {
1330 warn "both $opt and m$opt specified\n";
1334 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1337 return undef if $error;
1339 return undef if $res->{mbps_rd
} && $res->{mbps
};
1340 return undef if $res->{mbps_wr
} && $res->{mbps
};
1341 return undef if $res->{iops_rd
} && $res->{iops
};
1342 return undef if $res->{iops_wr
} && $res->{iops
};
1344 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1345 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1346 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1347 return undef if $res->{interface
} eq 'virtio';
1350 if (my $size = $res->{size
}) {
1351 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1358 my ($vmid, $drive) = @_;
1359 my $data = { %$drive };
1360 delete $data->{$_} for qw(index interface);
1361 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1365 my($fh, $noerr) = @_;
1368 my $SG_GET_VERSION_NUM = 0x2282;
1370 my $versionbuf = "\x00" x
8;
1371 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1373 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1376 my $version = unpack("I", $versionbuf);
1377 if ($version < 30000) {
1378 die "scsi generic interface too old\n" if !$noerr;
1382 my $buf = "\x00" x
36;
1383 my $sensebuf = "\x00" x
8;
1384 my $cmd = pack("C x3 C x1", 0x12, 36);
1386 # see /usr/include/scsi/sg.h
1387 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";
1389 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1390 length($sensebuf), 0, length($buf), $buf,
1391 $cmd, $sensebuf, 6000);
1393 $ret = ioctl($fh, $SG_IO, $packet);
1395 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1399 my @res = unpack($sg_io_hdr_t, $packet);
1400 if ($res[17] || $res[18]) {
1401 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1406 (my $byte0, my $byte1, $res->{vendor
},
1407 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1409 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1410 $res->{type
} = $byte0 & 31;
1418 my $fh = IO
::File-
>new("+<$path") || return undef;
1419 my $res = scsi_inquiry
($fh, 1);
1425 sub machine_type_is_q35
{
1428 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1431 sub print_tabletdevice_full
{
1434 my $q35 = machine_type_is_q35
($conf);
1436 # we use uhci for old VMs because tablet driver was buggy in older qemu
1437 my $usbbus = $q35 ?
"ehci" : "uhci";
1439 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1442 sub print_drivedevice_full
{
1443 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1448 if ($drive->{interface
} eq 'virtio') {
1449 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1450 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1451 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1452 } elsif ($drive->{interface
} eq 'scsi') {
1454 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1455 my $unit = $drive->{index} % $maxdev;
1456 my $devicetype = 'hd';
1458 if (drive_is_cdrom
($drive)) {
1461 if ($drive->{file
} =~ m
|^/|) {
1462 $path = $drive->{file
};
1463 if (my $info = path_is_scsi
($path)) {
1464 if ($info->{type
} == 0) {
1465 $devicetype = 'block';
1466 } elsif ($info->{type
} == 1) { # tape
1467 $devicetype = 'generic';
1471 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1474 if($path =~ m/^iscsi\:\/\
//){
1475 $devicetype = 'generic';
1479 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1480 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1482 $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}";
1485 } elsif ($drive->{interface
} eq 'ide'){
1487 my $controller = int($drive->{index} / $maxdev);
1488 my $unit = $drive->{index} % $maxdev;
1489 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1491 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1492 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1493 $model = URI
::Escape
::uri_unescape
($model);
1494 $device .= ",model=$model";
1496 } elsif ($drive->{interface
} eq 'sata'){
1497 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1498 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1499 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1500 } elsif ($drive->{interface
} eq 'usb') {
1502 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1504 die "unsupported interface type";
1507 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1512 sub get_initiator_name
{
1515 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1516 while (defined(my $line = <$fh>)) {
1517 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1526 sub print_drive_full
{
1527 my ($storecfg, $vmid, $drive) = @_;
1530 my $volid = $drive->{file
};
1533 if (drive_is_cdrom
($drive)) {
1534 $path = get_iso_path
($storecfg, $vmid, $volid);
1536 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1538 $path = PVE
::Storage
::path
($storecfg, $volid);
1539 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1540 $format = qemu_img_format
($scfg, $volname);
1548 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);
1549 foreach my $o (@qemu_drive_options) {
1550 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1552 if (my $serial = $drive->{serial
}) {
1553 $serial = URI
::Escape
::uri_unescape
($serial);
1554 $opts .= ",serial=$serial";
1557 $opts .= ",format=$format" if $format && !$drive->{format
};
1559 foreach my $o (qw(bps bps_rd bps_wr)) {
1560 my $v = $drive->{"m$o"};
1561 $opts .= ",$o=" . int($v*1024*1024) if $v;
1564 my $cache_direct = 0;
1566 if (my $cache = $drive->{cache
}) {
1567 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1568 } elsif (!drive_is_cdrom
($drive)) {
1569 $opts .= ",cache=none";
1573 # aio native works only with O_DIRECT
1574 if (!$drive->{aio
}) {
1576 $opts .= ",aio=native";
1578 $opts .= ",aio=threads";
1582 if (!drive_is_cdrom
($drive)) {
1584 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1585 $detectzeroes = 'off';
1586 } elsif ($drive->{discard
}) {
1587 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1589 # This used to be our default with discard not being specified:
1590 $detectzeroes = 'on';
1592 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1595 my $pathinfo = $path ?
"file=$path," : '';
1597 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1600 sub print_netdevice_full
{
1601 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1603 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1605 my $device = $net->{model
};
1606 if ($net->{model
} eq 'virtio') {
1607 $device = 'virtio-net-pci';
1610 my $pciaddr = print_pci_addr
("$netid", $bridges);
1611 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1612 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1613 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1614 my $vectors = $net->{queues
} * 2 + 2;
1615 $tmpstr .= ",vectors=$vectors,mq=on";
1617 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1619 if ($use_old_bios_files) {
1621 if ($device eq 'virtio-net-pci') {
1622 $romfile = 'pxe-virtio.rom';
1623 } elsif ($device eq 'e1000') {
1624 $romfile = 'pxe-e1000.rom';
1625 } elsif ($device eq 'ne2k') {
1626 $romfile = 'pxe-ne2k_pci.rom';
1627 } elsif ($device eq 'pcnet') {
1628 $romfile = 'pxe-pcnet.rom';
1629 } elsif ($device eq 'rtl8139') {
1630 $romfile = 'pxe-rtl8139.rom';
1632 $tmpstr .= ",romfile=$romfile" if $romfile;
1638 sub print_netdev_full
{
1639 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1642 if ($netid =~ m/^net(\d+)$/) {
1646 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1648 my $ifname = "tap${vmid}i$i";
1650 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1651 die "interface name '$ifname' is too long (max 15 character)\n"
1652 if length($ifname) >= 16;
1654 my $vhostparam = '';
1655 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1657 my $vmname = $conf->{name
} || "vm$vmid";
1660 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1662 if ($net->{bridge
}) {
1663 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1665 $netdev = "type=user,id=$netid,hostname=$vmname";
1668 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1673 sub drive_is_cdrom
{
1676 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1680 sub parse_number_sets
{
1683 foreach my $part (split(/;/, $set)) {
1684 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1685 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1686 push @$res, [ $1, $2 ];
1688 die "invalid range: $part\n";
1697 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1698 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1699 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1706 return undef if !$value;
1708 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1710 my @idlist = split(/;/, $res->{host
});
1711 delete $res->{host
};
1712 foreach my $id (@idlist) {
1713 if ($id =~ /^$PCIRE$/) {
1715 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1717 my $pcidevices = lspci
($1);
1718 $res->{pciid
} = $pcidevices->{$1};
1721 # should have been caught by parse_property_string already
1722 die "failed to parse PCI id: $id\n";
1728 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1732 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1737 if (!defined($res->{macaddr
})) {
1738 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1739 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1747 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1750 sub add_random_macs
{
1751 my ($settings) = @_;
1753 foreach my $opt (keys %$settings) {
1754 next if $opt !~ m/^net(\d+)$/;
1755 my $net = parse_net
($settings->{$opt});
1757 $settings->{$opt} = print_net
($net);
1761 sub vm_is_volid_owner
{
1762 my ($storecfg, $vmid, $volid) = @_;
1764 if ($volid !~ m
|^/|) {
1766 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1767 if ($owner && ($owner == $vmid)) {
1775 sub split_flagged_list
{
1776 my $text = shift || '';
1777 $text =~ s/[,;]/ /g;
1779 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1782 sub join_flagged_list
{
1783 my ($how, $lst) = @_;
1784 join $how, map { $lst->{$_} . $_ } keys %$lst;
1787 sub vmconfig_delete_pending_option
{
1788 my ($conf, $key, $force) = @_;
1790 delete $conf->{pending
}->{$key};
1791 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1792 $pending_delete_hash->{$key} = $force ?
'!' : '';
1793 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1796 sub vmconfig_undelete_pending_option
{
1797 my ($conf, $key) = @_;
1799 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1800 delete $pending_delete_hash->{$key};
1802 if (%$pending_delete_hash) {
1803 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1805 delete $conf->{pending
}->{delete};
1809 sub vmconfig_register_unused_drive
{
1810 my ($storecfg, $vmid, $conf, $drive) = @_;
1812 if (!drive_is_cdrom
($drive)) {
1813 my $volid = $drive->{file
};
1814 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1815 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1820 sub vmconfig_cleanup_pending
{
1823 # remove pending changes when nothing changed
1825 foreach my $opt (keys %{$conf->{pending
}}) {
1826 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1828 delete $conf->{pending
}->{$opt};
1832 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1833 my $pending_delete_hash = {};
1834 while (my ($opt, $force) = each %$current_delete_hash) {
1835 if (defined($conf->{$opt})) {
1836 $pending_delete_hash->{$opt} = $force;
1842 if (%$pending_delete_hash) {
1843 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1845 delete $conf->{pending
}->{delete};
1851 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1855 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1856 format_description
=> 'UUID',
1857 description
=> "Set SMBIOS1 UUID.",
1863 format_description
=> 'string',
1864 description
=> "Set SMBIOS1 version.",
1870 format_description
=> 'string',
1871 description
=> "Set SMBIOS1 serial number.",
1877 format_description
=> 'string',
1878 description
=> "Set SMBIOS1 manufacturer.",
1884 format_description
=> 'string',
1885 description
=> "Set SMBIOS1 product ID.",
1891 format_description
=> 'string',
1892 description
=> "Set SMBIOS1 SKU string.",
1898 format_description
=> 'string',
1899 description
=> "Set SMBIOS1 family string.",
1907 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1914 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1917 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1919 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1920 sub verify_bootdisk
{
1921 my ($value, $noerr) = @_;
1923 return $value if is_valid_drivename
($value);
1925 return undef if $noerr;
1927 die "invalid boot disk '$value'\n";
1930 sub parse_watchdog
{
1933 return undef if !$value;
1935 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1940 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1941 sub verify_usb_device
{
1942 my ($value, $noerr) = @_;
1944 return $value if parse_usb_device
($value);
1946 return undef if $noerr;
1948 die "unable to parse usb device\n";
1951 # add JSON properties for create and set function
1952 sub json_config_properties
{
1955 foreach my $opt (keys %$confdesc) {
1956 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1957 $prop->{$opt} = $confdesc->{$opt};
1964 my ($key, $value) = @_;
1966 die "unknown setting '$key'\n" if !$confdesc->{$key};
1968 my $type = $confdesc->{$key}->{type
};
1970 if (!defined($value)) {
1971 die "got undefined value\n";
1974 if ($value =~ m/[\n\r]/) {
1975 die "property contains a line feed\n";
1978 if ($type eq 'boolean') {
1979 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1980 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1981 die "type check ('boolean') failed - got '$value'\n";
1982 } elsif ($type eq 'integer') {
1983 return int($1) if $value =~ m/^(\d+)$/;
1984 die "type check ('integer') failed - got '$value'\n";
1985 } elsif ($type eq 'number') {
1986 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1987 die "type check ('number') failed - got '$value'\n";
1988 } elsif ($type eq 'string') {
1989 if (my $fmt = $confdesc->{$key}->{format
}) {
1990 if ($fmt eq 'pve-qm-drive') {
1991 # special case - we need to pass $key to parse_drive()
1992 my $drive = parse_drive
($key, $value);
1993 return $value if $drive;
1994 die "unable to parse drive options\n";
1996 PVE
::JSONSchema
::check_format
($fmt, $value);
1999 $value =~ s/^\"(.*)\"$/$1/;
2002 die "internal error"
2006 sub check_iommu_support
{
2007 #fixme : need to check IOMMU support
2008 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2018 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2019 utime undef, undef, $conf;
2023 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2025 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2027 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2029 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2031 # only remove disks owned by this VM
2032 foreach_drive
($conf, sub {
2033 my ($ds, $drive) = @_;
2035 return if drive_is_cdrom
($drive);
2037 my $volid = $drive->{file
};
2039 return if !$volid || $volid =~ m
|^/|;
2041 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2042 return if !$path || !$owner || ($owner != $vmid);
2044 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2047 if ($keep_empty_config) {
2048 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2053 # also remove unused disk
2055 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2058 PVE
::Storage
::foreach_volid
($dl, sub {
2059 my ($volid, $sid, $volname, $d) = @_;
2060 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2069 sub parse_vm_config
{
2070 my ($filename, $raw) = @_;
2072 return undef if !defined($raw);
2075 digest
=> Digest
::SHA
::sha1_hex
($raw),
2080 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2081 || die "got strange filename '$filename'";
2089 my @lines = split(/\n/, $raw);
2090 foreach my $line (@lines) {
2091 next if $line =~ m/^\s*$/;
2093 if ($line =~ m/^\[PENDING\]\s*$/i) {
2094 $section = 'pending';
2095 if (defined($descr)) {
2097 $conf->{description
} = $descr;
2100 $conf = $res->{$section} = {};
2103 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2105 if (defined($descr)) {
2107 $conf->{description
} = $descr;
2110 $conf = $res->{snapshots
}->{$section} = {};
2114 if ($line =~ m/^\#(.*)\s*$/) {
2115 $descr = '' if !defined($descr);
2116 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2120 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2121 $descr = '' if !defined($descr);
2122 $descr .= PVE
::Tools
::decode_text
($2);
2123 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2124 $conf->{snapstate
} = $1;
2125 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2128 $conf->{$key} = $value;
2129 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2131 if ($section eq 'pending') {
2132 $conf->{delete} = $value; # we parse this later
2134 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2136 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2139 eval { $value = check_type
($key, $value); };
2141 warn "vm $vmid - unable to parse value of '$key' - $@";
2143 my $fmt = $confdesc->{$key}->{format
};
2144 if ($fmt && $fmt eq 'pve-qm-drive') {
2145 my $v = parse_drive
($key, $value);
2146 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2147 $v->{file
} = $volid;
2148 $value = print_drive
($vmid, $v);
2150 warn "vm $vmid - unable to parse value of '$key'\n";
2155 if ($key eq 'cdrom') {
2156 $conf->{ide2
} = $value;
2158 $conf->{$key} = $value;
2164 if (defined($descr)) {
2166 $conf->{description
} = $descr;
2168 delete $res->{snapstate
}; # just to be sure
2173 sub write_vm_config
{
2174 my ($filename, $conf) = @_;
2176 delete $conf->{snapstate
}; # just to be sure
2178 if ($conf->{cdrom
}) {
2179 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2180 $conf->{ide2
} = $conf->{cdrom
};
2181 delete $conf->{cdrom
};
2184 # we do not use 'smp' any longer
2185 if ($conf->{sockets
}) {
2186 delete $conf->{smp
};
2187 } elsif ($conf->{smp
}) {
2188 $conf->{sockets
} = $conf->{smp
};
2189 delete $conf->{cores
};
2190 delete $conf->{smp
};
2193 my $used_volids = {};
2195 my $cleanup_config = sub {
2196 my ($cref, $pending, $snapname) = @_;
2198 foreach my $key (keys %$cref) {
2199 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2200 $key eq 'snapstate' || $key eq 'pending';
2201 my $value = $cref->{$key};
2202 if ($key eq 'delete') {
2203 die "propertry 'delete' is only allowed in [PENDING]\n"
2205 # fixme: check syntax?
2208 eval { $value = check_type
($key, $value); };
2209 die "unable to parse value of '$key' - $@" if $@;
2211 $cref->{$key} = $value;
2213 if (!$snapname && is_valid_drivename
($key)) {
2214 my $drive = parse_drive
($key, $value);
2215 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2220 &$cleanup_config($conf);
2222 &$cleanup_config($conf->{pending
}, 1);
2224 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2225 die "internal error" if $snapname eq 'pending';
2226 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2229 # remove 'unusedX' settings if we re-add a volume
2230 foreach my $key (keys %$conf) {
2231 my $value = $conf->{$key};
2232 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2233 delete $conf->{$key};
2237 my $generate_raw_config = sub {
2238 my ($conf, $pending) = @_;
2242 # add description as comment to top of file
2243 if (defined(my $descr = $conf->{description
})) {
2245 foreach my $cl (split(/\n/, $descr)) {
2246 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2249 $raw .= "#\n" if $pending;
2253 foreach my $key (sort keys %$conf) {
2254 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2255 $raw .= "$key: $conf->{$key}\n";
2260 my $raw = &$generate_raw_config($conf);
2262 if (scalar(keys %{$conf->{pending
}})){
2263 $raw .= "\n[PENDING]\n";
2264 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2267 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2268 $raw .= "\n[$snapname]\n";
2269 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2279 # we use static defaults from our JSON schema configuration
2280 foreach my $key (keys %$confdesc) {
2281 if (defined(my $default = $confdesc->{$key}->{default})) {
2282 $res->{$key} = $default;
2286 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2287 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2293 my $vmlist = PVE
::Cluster
::get_vmlist
();
2295 return $res if !$vmlist || !$vmlist->{ids
};
2296 my $ids = $vmlist->{ids
};
2298 foreach my $vmid (keys %$ids) {
2299 my $d = $ids->{$vmid};
2300 next if !$d->{node
} || $d->{node
} ne $nodename;
2301 next if !$d->{type
} || $d->{type
} ne 'qemu';
2302 $res->{$vmid}->{exists} = 1;
2307 # test if VM uses local resources (to prevent migration)
2308 sub check_local_resources
{
2309 my ($conf, $noerr) = @_;
2313 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2314 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2316 foreach my $k (keys %$conf) {
2317 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2318 # sockets are safe: they will recreated be on the target side post-migrate
2319 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2320 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2323 die "VM uses local resources\n" if $loc_res && !$noerr;
2328 # check if used storages are available on all nodes (use by migrate)
2329 sub check_storage_availability
{
2330 my ($storecfg, $conf, $node) = @_;
2332 foreach_drive
($conf, sub {
2333 my ($ds, $drive) = @_;
2335 my $volid = $drive->{file
};
2338 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2341 # check if storage is available on both nodes
2342 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2343 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2347 # list nodes where all VM images are available (used by has_feature API)
2349 my ($conf, $storecfg) = @_;
2351 my $nodelist = PVE
::Cluster
::get_nodelist
();
2352 my $nodehash = { map { $_ => 1 } @$nodelist };
2353 my $nodename = PVE
::INotify
::nodename
();
2355 foreach_drive
($conf, sub {
2356 my ($ds, $drive) = @_;
2358 my $volid = $drive->{file
};
2361 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2363 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2364 if ($scfg->{disable
}) {
2366 } elsif (my $avail = $scfg->{nodes
}) {
2367 foreach my $node (keys %$nodehash) {
2368 delete $nodehash->{$node} if !$avail->{$node};
2370 } elsif (!$scfg->{shared
}) {
2371 foreach my $node (keys %$nodehash) {
2372 delete $nodehash->{$node} if $node ne $nodename
2382 my ($pidfile, $pid) = @_;
2384 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2388 return undef if !$line;
2389 my @param = split(/\0/, $line);
2391 my $cmd = $param[0];
2392 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2394 for (my $i = 0; $i < scalar (@param); $i++) {
2397 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2398 my $p = $param[$i+1];
2399 return 1 if $p && ($p eq $pidfile);
2408 my ($vmid, $nocheck, $node) = @_;
2410 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2412 die "unable to find configuration file for VM $vmid - no such machine\n"
2413 if !$nocheck && ! -f
$filename;
2415 my $pidfile = pidfile_name
($vmid);
2417 if (my $fd = IO
::File-
>new("<$pidfile")) {
2422 my $mtime = $st->mtime;
2423 if ($mtime > time()) {
2424 warn "file '$filename' modified in future\n";
2427 if ($line =~ m/^(\d+)$/) {
2429 if (check_cmdline
($pidfile, $pid)) {
2430 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2442 my $vzlist = config_list
();
2444 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2446 while (defined(my $de = $fd->read)) {
2447 next if $de !~ m/^(\d+)\.pid$/;
2449 next if !defined($vzlist->{$vmid});
2450 if (my $pid = check_running
($vmid)) {
2451 $vzlist->{$vmid}->{pid
} = $pid;
2459 my ($storecfg, $conf) = @_;
2461 my $bootdisk = $conf->{bootdisk
};
2462 return undef if !$bootdisk;
2463 return undef if !is_valid_drivename
($bootdisk);
2465 return undef if !$conf->{$bootdisk};
2467 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2468 return undef if !defined($drive);
2470 return undef if drive_is_cdrom
($drive);
2472 my $volid = $drive->{file
};
2473 return undef if !$volid;
2475 return $drive->{size
};
2478 my $last_proc_pid_stat;
2480 # get VM status information
2481 # This must be fast and should not block ($full == false)
2482 # We only query KVM using QMP if $full == true (this can be slow)
2484 my ($opt_vmid, $full) = @_;
2488 my $storecfg = PVE
::Storage
::config
();
2490 my $list = vzlist
();
2491 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2493 my $cpucount = $cpuinfo->{cpus
} || 1;
2495 foreach my $vmid (keys %$list) {
2496 next if $opt_vmid && ($vmid ne $opt_vmid);
2498 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2499 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2502 $d->{pid
} = $list->{$vmid}->{pid
};
2504 # fixme: better status?
2505 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2507 my $size = disksize
($storecfg, $conf);
2508 if (defined($size)) {
2509 $d->{disk
} = 0; # no info available
2510 $d->{maxdisk
} = $size;
2516 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2517 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2518 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2520 $d->{name
} = $conf->{name
} || "VM $vmid";
2521 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2523 if ($conf->{balloon
}) {
2524 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2525 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2536 $d->{diskwrite
} = 0;
2538 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2543 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2544 foreach my $dev (keys %$netdev) {
2545 next if $dev !~ m/^tap([1-9]\d*)i/;
2547 my $d = $res->{$vmid};
2550 $d->{netout
} += $netdev->{$dev}->{receive
};
2551 $d->{netin
} += $netdev->{$dev}->{transmit
};
2554 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2555 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2560 my $ctime = gettimeofday
;
2562 foreach my $vmid (keys %$list) {
2564 my $d = $res->{$vmid};
2565 my $pid = $d->{pid
};
2568 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2569 next if !$pstat; # not running
2571 my $used = $pstat->{utime} + $pstat->{stime
};
2573 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2575 if ($pstat->{vsize
}) {
2576 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2579 my $old = $last_proc_pid_stat->{$pid};
2581 $last_proc_pid_stat->{$pid} = {
2589 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2591 if ($dtime > 1000) {
2592 my $dutime = $used - $old->{used
};
2594 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2595 $last_proc_pid_stat->{$pid} = {
2601 $d->{cpu
} = $old->{cpu
};
2605 return $res if !$full;
2607 my $qmpclient = PVE
::QMPClient-
>new();
2609 my $ballooncb = sub {
2610 my ($vmid, $resp) = @_;
2612 my $info = $resp->{'return'};
2613 return if !$info->{max_mem
};
2615 my $d = $res->{$vmid};
2617 # use memory assigned to VM
2618 $d->{maxmem
} = $info->{max_mem
};
2619 $d->{balloon
} = $info->{actual
};
2621 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2622 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2623 $d->{freemem
} = $info->{free_mem
};
2626 $d->{ballooninfo
} = $info;
2629 my $blockstatscb = sub {
2630 my ($vmid, $resp) = @_;
2631 my $data = $resp->{'return'} || [];
2632 my $totalrdbytes = 0;
2633 my $totalwrbytes = 0;
2635 for my $blockstat (@$data) {
2636 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2637 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2639 $blockstat->{device
} =~ s/drive-//;
2640 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2642 $res->{$vmid}->{diskread
} = $totalrdbytes;
2643 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2646 my $statuscb = sub {
2647 my ($vmid, $resp) = @_;
2649 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2650 # this fails if ballon driver is not loaded, so this must be
2651 # the last commnand (following command are aborted if this fails).
2652 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2654 my $status = 'unknown';
2655 if (!defined($status = $resp->{'return'}->{status
})) {
2656 warn "unable to get VM status\n";
2660 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2663 foreach my $vmid (keys %$list) {
2664 next if $opt_vmid && ($vmid ne $opt_vmid);
2665 next if !$res->{$vmid}->{pid
}; # not running
2666 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2669 $qmpclient->queue_execute(undef, 1);
2671 foreach my $vmid (keys %$list) {
2672 next if $opt_vmid && ($vmid ne $opt_vmid);
2673 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2680 my ($conf, $func, @param) = @_;
2682 foreach my $ds (valid_drive_names
()) {
2683 next if !defined($conf->{$ds});
2685 my $drive = parse_drive
($ds, $conf->{$ds});
2688 &$func($ds, $drive, @param);
2693 my ($conf, $func, @param) = @_;
2697 my $test_volid = sub {
2698 my ($volid, $is_cdrom) = @_;
2702 $volhash->{$volid} = $is_cdrom || 0;
2705 foreach_drive
($conf, sub {
2706 my ($ds, $drive) = @_;
2707 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2710 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2711 my $snap = $conf->{snapshots
}->{$snapname};
2712 &$test_volid($snap->{vmstate
}, 0);
2713 foreach_drive
($snap, sub {
2714 my ($ds, $drive) = @_;
2715 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2719 foreach my $volid (keys %$volhash) {
2720 &$func($volid, $volhash->{$volid}, @param);
2724 sub vga_conf_has_spice
{
2727 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2732 sub config_to_command
{
2733 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2736 my $globalFlags = [];
2737 my $machineFlags = [];
2743 my $kvmver = kvm_user_version
();
2744 my $vernum = 0; # unknown
2745 my $ostype = $conf->{ostype
};
2746 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2747 $vernum = $1*1000000+$2*1000;
2748 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2749 $vernum = $1*1000000+$2*1000+$3;
2752 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2754 my $have_ovz = -f
'/proc/vz/vestat';
2756 my $q35 = machine_type_is_q35
($conf);
2757 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2758 my $machine_type = $forcemachine || $conf->{machine
};
2759 my $use_old_bios_files = undef;
2760 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2762 my $cpuunits = defined($conf->{cpuunits
}) ?
2763 $conf->{cpuunits
} : $defaults->{cpuunits
};
2765 push @$cmd, '/usr/bin/kvm';
2767 push @$cmd, '-id', $vmid;
2771 my $qmpsocket = qmp_socket
($vmid);
2772 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2773 push @$cmd, '-mon', "chardev=qmp,mode=control";
2776 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2778 push @$cmd, '-daemonize';
2780 if ($conf->{smbios1
}) {
2781 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2784 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2785 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2786 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2787 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2788 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2789 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2790 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2794 # add usb controllers
2795 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2796 push @$devices, @usbcontrollers if @usbcontrollers;
2797 my $vga = $conf->{vga
};
2799 my $qxlnum = vga_conf_has_spice
($vga);
2800 $vga = 'qxl' if $qxlnum;
2803 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2804 $conf->{ostype
} eq 'win7' ||
2805 $conf->{ostype
} eq 'w2k8')) {
2812 # enable absolute mouse coordinates (needed by vnc)
2814 if (defined($conf->{tablet
})) {
2815 $tablet = $conf->{tablet
};
2817 $tablet = $defaults->{tablet
};
2818 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2819 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2822 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2826 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2827 my $d = parse_hostpci
($conf->{"hostpci$i"});
2830 my $pcie = $d->{pcie
};
2832 die "q35 machine model is not enabled" if !$q35;
2833 $pciaddr = print_pcie_addr
("hostpci$i");
2835 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2838 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2840 if ($d->{'x-vga'}) {
2841 $xvga = ',x-vga=on';
2844 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2845 push @$cpuFlags , 'hv_vendor_id=proxmox';
2847 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2851 my $pcidevices = $d->{pciid
};
2852 my $multifunction = 1 if @$pcidevices > 1;
2855 foreach my $pcidevice (@$pcidevices) {
2857 my $id = "hostpci$i";
2858 $id .= ".$j" if $multifunction;
2859 my $addr = $pciaddr;
2860 $addr .= ".$j" if $multifunction;
2861 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2864 $devicestr .= "$rombar$xvga";
2865 $devicestr .= ",multifunction=on" if $multifunction;
2868 push @$devices, '-device', $devicestr;
2874 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
2875 push @$devices, @usbdevices if @usbdevices;
2877 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2878 if (my $path = $conf->{"serial$i"}) {
2879 if ($path eq 'socket') {
2880 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2881 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2882 push @$devices, '-device', "isa-serial,chardev=serial$i";
2884 die "no such serial device\n" if ! -c
$path;
2885 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2886 push @$devices, '-device', "isa-serial,chardev=serial$i";
2892 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2893 if (my $path = $conf->{"parallel$i"}) {
2894 die "no such parallel device\n" if ! -c
$path;
2895 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2896 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2897 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2901 my $vmname = $conf->{name
} || "vm$vmid";
2903 push @$cmd, '-name', $vmname;
2906 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2907 $sockets = $conf->{sockets
} if $conf->{sockets
};
2909 my $cores = $conf->{cores
} || 1;
2911 my $maxcpus = $sockets * $cores;
2913 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2915 my $allowed_vcpus = $cpuinfo->{cpus
};
2917 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2918 if ($allowed_vcpus < $maxcpus);
2920 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2922 push @$cmd, '-nodefaults';
2924 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2926 my $bootindex_hash = {};
2928 foreach my $o (split(//, $bootorder)) {
2929 $bootindex_hash->{$o} = $i*100;
2933 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2935 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2937 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2939 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2941 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2942 my $socket = vnc_socket
($vmid);
2943 push @$cmd, '-vnc', "unix:$socket,x509,password";
2945 push @$cmd, '-nographic';
2949 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2951 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2952 my $useLocaltime = $conf->{localtime};
2955 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2957 if ($ostype =~ m/^w/) { # windows
2958 $useLocaltime = 1 if !defined($conf->{localtime});
2960 # use time drift fix when acpi is enabled
2961 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2962 $tdf = 1 if !defined($conf->{tdf
});
2966 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2967 $ostype eq 'wvista') {
2968 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2969 push @$cmd, '-no-hpet';
2970 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2971 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2972 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2973 push @$cpuFlags , 'hv_time' if !$nokvm;
2975 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
2976 push @$cpuFlags , 'hv_reset' if !$nokvm;
2977 push @$cpuFlags , 'hv_vpindex' if !$nokvm;
2978 push @$cpuFlags , 'hv_runtime' if !$nokvm;
2982 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2986 if ($ostype eq 'win7' || $ostype eq 'win8') {
2987 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2991 push @$rtcFlags, 'driftfix=slew' if $tdf;
2994 push @$machineFlags, 'accel=tcg';
2996 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2999 if ($machine_type) {
3000 push @$machineFlags, "type=${machine_type}";
3003 if ($conf->{startdate
}) {
3004 push @$rtcFlags, "base=$conf->{startdate}";
3005 } elsif ($useLocaltime) {
3006 push @$rtcFlags, 'base=localtime';
3009 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3010 if (my $cputype = $conf->{cpu
}) {
3011 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3012 or die "Cannot parse cpu description: $cputype\n";
3013 $cpu = $cpuconf->{cputype
};
3014 $kvm_off = 1 if $cpuconf->{hidden
};
3017 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3019 push @$cpuFlags , '-x2apic'
3020 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3022 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3024 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3026 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3028 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3029 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3032 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3034 push @$cpuFlags, 'kvm=off' if $kvm_off;
3036 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3037 die "internal error"; # should not happen
3039 push @$cpuFlags, "vendor=${cpu_vendor}"
3040 if $cpu_vendor ne 'default';
3042 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3044 push @$cmd, '-cpu', $cpu;
3046 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3048 push @$cmd, '-S' if $conf->{freeze
};
3050 # set keyboard layout
3051 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3052 push @$cmd, '-k', $kb if $kb;
3055 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3056 #push @$cmd, '-soundhw', 'es1370';
3057 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3059 if($conf->{agent
}) {
3060 my $qgasocket = qmp_socket
($vmid, 1);
3061 my $pciaddr = print_pci_addr
("qga0", $bridges);
3062 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3063 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3064 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3071 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3072 for(my $i = 1; $i < $qxlnum; $i++){
3073 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3074 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3077 # assume other OS works like Linux
3078 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3079 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3083 my $pciaddr = print_pci_addr
("spice", $bridges);
3085 my $nodename = PVE
::INotify
::nodename
();
3086 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3087 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3089 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3091 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3092 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3093 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3096 # enable balloon by default, unless explicitly disabled
3097 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3098 $pciaddr = print_pci_addr
("balloon0", $bridges);
3099 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3102 if ($conf->{watchdog
}) {
3103 my $wdopts = parse_watchdog
($conf->{watchdog
});
3104 $pciaddr = print_pci_addr
("watchdog", $bridges);
3105 my $watchdog = $wdopts->{model
} || 'i6300esb';
3106 push @$devices, '-device', "$watchdog$pciaddr";
3107 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3111 my $scsicontroller = {};
3112 my $ahcicontroller = {};
3113 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3115 # Add iscsi initiator name if available
3116 if (my $initiator = get_initiator_name
()) {
3117 push @$devices, '-iscsi', "initiator-name=$initiator";
3120 foreach_drive
($conf, sub {
3121 my ($ds, $drive) = @_;
3123 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3124 push @$vollist, $drive->{file
};
3127 $use_virtio = 1 if $ds =~ m/^virtio/;
3129 if (drive_is_cdrom
($drive)) {
3130 if ($bootindex_hash->{d
}) {
3131 $drive->{bootindex
} = $bootindex_hash->{d
};
3132 $bootindex_hash->{d
} += 1;
3135 if ($bootindex_hash->{c
}) {
3136 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3137 $bootindex_hash->{c
} += 1;
3141 if($drive->{interface
} eq 'virtio'){
3142 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3145 if ($drive->{interface
} eq 'scsi') {
3147 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3149 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3150 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3153 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3154 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3155 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3156 } elsif ($drive->{iothread
}) {
3157 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3161 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3162 $queues = ",num_queues=$drive->{queues}";
3165 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3166 $scsicontroller->{$controller}=1;
3169 if ($drive->{interface
} eq 'sata') {
3170 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3171 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3172 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3173 $ahcicontroller->{$controller}=1;
3176 if ($drive->{interface
} eq 'efidisk') {
3177 # this will be added somewhere else
3181 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3182 push @$devices, '-drive',$drive_cmd;
3183 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3186 for (my $i = 0; $i < $MAX_NETS; $i++) {
3187 next if !$conf->{"net$i"};
3188 my $d = parse_net
($conf->{"net$i"});
3191 $use_virtio = 1 if $d->{model
} eq 'virtio';
3193 if ($bootindex_hash->{n
}) {
3194 $d->{bootindex
} = $bootindex_hash->{n
};
3195 $bootindex_hash->{n
} += 1;
3198 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3199 push @$devices, '-netdev', $netdevfull;
3201 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3202 push @$devices, '-device', $netdevicefull;
3207 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3212 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3214 while (my ($k, $v) = each %$bridges) {
3215 $pciaddr = print_pci_addr
("pci.$k");
3216 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3221 if ($conf->{args
}) {
3222 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3226 push @$cmd, @$devices;
3227 push @$cmd, '-rtc', join(',', @$rtcFlags)
3228 if scalar(@$rtcFlags);
3229 push @$cmd, '-machine', join(',', @$machineFlags)
3230 if scalar(@$machineFlags);
3231 push @$cmd, '-global', join(',', @$globalFlags)
3232 if scalar(@$globalFlags);
3234 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3239 return "${var_run_tmpdir}/$vmid.vnc";
3245 my $res = vm_mon_cmd
($vmid, 'query-spice');
3247 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3251 my ($vmid, $qga) = @_;
3252 my $sockettype = $qga ?
'qga' : 'qmp';
3253 return "${var_run_tmpdir}/$vmid.$sockettype";
3258 return "${var_run_tmpdir}/$vmid.pid";
3261 sub vm_devices_list
{
3264 my $res = vm_mon_cmd
($vmid, 'query-pci');
3266 foreach my $pcibus (@$res) {
3267 foreach my $device (@{$pcibus->{devices
}}) {
3268 next if !$device->{'qdev_id'};
3269 if ($device->{'pci_bridge'}) {
3270 $devices->{$device->{'qdev_id'}} = 1;
3271 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3272 next if !$bridge_device->{'qdev_id'};
3273 $devices->{$bridge_device->{'qdev_id'}} = 1;
3274 $devices->{$device->{'qdev_id'}}++;
3277 $devices->{$device->{'qdev_id'}} = 1;
3282 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3283 foreach my $block (@$resblock) {
3284 if($block->{device
} =~ m/^drive-(\S+)/){
3289 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3290 foreach my $mice (@$resmice) {
3291 if ($mice->{name
} eq 'QEMU HID Tablet') {
3292 $devices->{tablet
} = 1;
3297 # for usb devices there is no query-usb
3298 # but we can iterate over the entries in
3299 # qom-list path=/machine/peripheral
3300 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3301 foreach my $per (@$resperipheral) {
3302 if ($per->{name
} =~ m/^usb\d+$/) {
3303 $devices->{$per->{name
}} = 1;
3311 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3313 my $q35 = machine_type_is_q35
($conf);
3315 my $devices_list = vm_devices_list
($vmid);
3316 return 1 if defined($devices_list->{$deviceid});
3318 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3320 if ($deviceid eq 'tablet') {
3322 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3324 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3326 die "usb hotplug currently not reliable\n";
3327 # since we can't reliably hot unplug all added usb devices
3328 # and usb passthrough disables live migration
3329 # we disable usb hotplugging for now
3330 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3332 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3334 qemu_iothread_add
($vmid, $deviceid, $device);
3336 qemu_driveadd
($storecfg, $vmid, $device);
3337 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3339 qemu_deviceadd
($vmid, $devicefull);
3340 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3342 eval { qemu_drivedel
($vmid, $deviceid); };
3347 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3350 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3351 my $pciaddr = print_pci_addr
($deviceid);
3352 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3354 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3356 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3357 qemu_iothread_add
($vmid, $deviceid, $device);
3358 $devicefull .= ",iothread=iothread-$deviceid";
3361 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3362 $devicefull .= ",num_queues=$device->{queues}";
3365 qemu_deviceadd
($vmid, $devicefull);
3366 qemu_deviceaddverify
($vmid, $deviceid);
3368 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3370 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3371 qemu_driveadd
($storecfg, $vmid, $device);
3373 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3374 eval { qemu_deviceadd
($vmid, $devicefull); };
3376 eval { qemu_drivedel
($vmid, $deviceid); };
3381 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3383 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3385 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3386 my $use_old_bios_files = undef;
3387 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3389 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3390 qemu_deviceadd
($vmid, $netdevicefull);
3391 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3393 eval { qemu_netdevdel
($vmid, $deviceid); };
3398 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3401 my $pciaddr = print_pci_addr
($deviceid);
3402 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3404 qemu_deviceadd
($vmid, $devicefull);
3405 qemu_deviceaddverify
($vmid, $deviceid);
3408 die "can't hotplug device '$deviceid'\n";
3414 # fixme: this should raise exceptions on error!
3415 sub vm_deviceunplug
{
3416 my ($vmid, $conf, $deviceid) = @_;
3418 my $devices_list = vm_devices_list
($vmid);
3419 return 1 if !defined($devices_list->{$deviceid});
3421 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3423 if ($deviceid eq 'tablet') {
3425 qemu_devicedel
($vmid, $deviceid);
3427 } elsif ($deviceid =~ m/^usb\d+$/) {
3429 die "usb hotplug currently not reliable\n";
3430 # when unplugging usb devices this way,
3431 # there may be remaining usb controllers/hubs
3432 # so we disable it for now
3433 qemu_devicedel
($vmid, $deviceid);
3434 qemu_devicedelverify
($vmid, $deviceid);
3436 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3438 qemu_devicedel
($vmid, $deviceid);
3439 qemu_devicedelverify
($vmid, $deviceid);
3440 qemu_drivedel
($vmid, $deviceid);
3441 qemu_iothread_del
($conf, $vmid, $deviceid);
3443 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3445 qemu_devicedel
($vmid, $deviceid);
3446 qemu_devicedelverify
($vmid, $deviceid);
3447 qemu_iothread_del
($conf, $vmid, $deviceid);
3449 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3451 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3452 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3453 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3455 qemu_devicedel
($vmid, $deviceid);
3456 qemu_drivedel
($vmid, $deviceid);
3457 qemu_deletescsihw
($conf, $vmid, $deviceid);
3459 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3461 qemu_devicedel
($vmid, $deviceid);
3462 qemu_devicedelverify
($vmid, $deviceid);
3463 qemu_netdevdel
($vmid, $deviceid);
3466 die "can't unplug device '$deviceid'\n";
3472 sub qemu_deviceadd
{
3473 my ($vmid, $devicefull) = @_;
3475 $devicefull = "driver=".$devicefull;
3476 my %options = split(/[=,]/, $devicefull);
3478 vm_mon_cmd
($vmid, "device_add" , %options);
3481 sub qemu_devicedel
{
3482 my ($vmid, $deviceid) = @_;
3484 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3487 sub qemu_iothread_add
{
3488 my($vmid, $deviceid, $device) = @_;
3490 if ($device->{iothread
}) {
3491 my $iothreads = vm_iothreads_list
($vmid);
3492 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3496 sub qemu_iothread_del
{
3497 my($conf, $vmid, $deviceid) = @_;
3499 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3500 if ($device->{iothread
}) {
3501 my $iothreads = vm_iothreads_list
($vmid);
3502 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3506 sub qemu_objectadd
{
3507 my($vmid, $objectid, $qomtype) = @_;
3509 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3514 sub qemu_objectdel
{
3515 my($vmid, $objectid) = @_;
3517 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3523 my ($storecfg, $vmid, $device) = @_;
3525 my $drive = print_drive_full
($storecfg, $vmid, $device);
3526 $drive =~ s/\\/\\\\/g;
3527 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3529 # If the command succeeds qemu prints: "OK
"
3530 return 1 if $ret =~ m/OK/s;
3532 die "adding drive failed
: $ret\n";
3536 my($vmid, $deviceid) = @_;
3538 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3541 return 1 if $ret eq "";
3543 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3544 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3546 die "deleting drive
$deviceid failed
: $ret\n";
3549 sub qemu_deviceaddverify {
3550 my ($vmid, $deviceid) = @_;
3552 for (my $i = 0; $i <= 5; $i++) {
3553 my $devices_list = vm_devices_list($vmid);
3554 return 1 if defined($devices_list->{$deviceid});
3558 die "error on hotplug device
'$deviceid'\n";
3562 sub qemu_devicedelverify {
3563 my ($vmid, $deviceid) = @_;
3565 # need to verify that the device is correctly removed as device_del
3566 # is async and empty return is not reliable
3568 for (my $i = 0; $i <= 5; $i++) {
3569 my $devices_list = vm_devices_list($vmid);
3570 return 1 if !defined($devices_list->{$deviceid});
3574 die "error on hot-unplugging device
'$deviceid'\n";
3577 sub qemu_findorcreatescsihw {
3578 my ($storecfg, $conf, $vmid, $device) = @_;
3580 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3582 my $scsihwid="$controller_prefix$controller";
3583 my $devices_list = vm_devices_list($vmid);
3585 if(!defined($devices_list->{$scsihwid})) {
3586 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3592 sub qemu_deletescsihw {
3593 my ($conf, $vmid, $opt) = @_;
3595 my $device = parse_drive($opt, $conf->{$opt});
3597 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3598 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3602 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3604 my $devices_list = vm_devices_list($vmid);
3605 foreach my $opt (keys %{$devices_list}) {
3606 if (PVE::QemuServer::is_valid_drivename($opt)) {
3607 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3608 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3614 my $scsihwid="scsihw
$controller";
3616 vm_deviceunplug($vmid, $conf, $scsihwid);
3621 sub qemu_add_pci_bridge {
3622 my ($storecfg, $conf, $vmid, $device) = @_;
3628 print_pci_addr($device, $bridges);
3630 while (my ($k, $v) = each %$bridges) {
3633 return 1 if !defined($bridgeid) || $bridgeid < 1;
3635 my $bridge = "pci
.$bridgeid";
3636 my $devices_list = vm_devices_list($vmid);
3638 if (!defined($devices_list->{$bridge})) {
3639 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3645 sub qemu_set_link_status {
3646 my ($vmid, $device, $up) = @_;
3648 vm_mon_cmd($vmid, "set_link
", name => $device,
3649 up => $up ? JSON::true : JSON::false);
3652 sub qemu_netdevadd {
3653 my ($vmid, $conf, $device, $deviceid) = @_;
3655 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3656 my %options = split(/[=,]/, $netdev);
3658 vm_mon_cmd($vmid, "netdev_add
", %options);
3662 sub qemu_netdevdel {
3663 my ($vmid, $deviceid) = @_;
3665 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3668 sub qemu_usb_hotplug {
3669 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3673 # remove the old one first
3674 vm_deviceunplug($vmid, $conf, $deviceid);
3676 # check if xhci controller is necessary and available
3677 if ($device->{usb3}) {
3679 my $devicelist = vm_devices_list($vmid);
3681 if (!$devicelist->{xhci}) {
3682 my $pciaddr = print_pci_addr("xhci
");
3683 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3686 my $d = parse_usb_device($device->{host});
3687 $d->{usb3} = $device->{usb3};
3690 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3693 sub qemu_cpu_hotplug {
3694 my ($vmid, $conf, $vcpus) = @_;
3697 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3698 $sockets = $conf->{sockets} if $conf->{sockets};
3699 my $cores = $conf->{cores} || 1;
3700 my $maxcpus = $sockets * $cores;
3702 $vcpus = $maxcpus if !$vcpus;
3704 die "you can
't add more vcpus than maxcpus\n"
3705 if $vcpus > $maxcpus;
3707 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3708 die "online cpu unplug is not yet possible\n"
3709 if $vcpus < $currentvcpus;
3711 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3712 die "vcpus in running vm is different than configuration\n"
3713 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3715 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3716 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3720 sub qemu_block_set_io_throttle {
3721 my ($vmid, $deviceid,
3722 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3723 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3725 return if !check_running($vmid) ;
3727 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3729 bps_rd => int($bps_rd),
3730 bps_wr => int($bps_wr),
3732 iops_rd => int($iops_rd),
3733 iops_wr => int($iops_wr),
3734 bps_max => int($bps_max),
3735 bps_rd_max => int($bps_rd_max),
3736 bps_wr_max => int($bps_wr_max),
3737 iops_max => int($iops_max),
3738 iops_rd_max => int($iops_rd_max),
3739 iops_wr_max => int($iops_wr_max)
3744 # old code, only used to shutdown old VM after update
3746 my ($fh, $timeout) = @_;
3748 my $sel = new IO::Select;
3755 while (scalar (@ready = $sel->can_read($timeout))) {
3757 if ($count = $fh->sysread($buf, 8192)) {
3758 if ($buf =~ /^(.*)\(qemu\) $/s) {
3765 if (!defined($count)) {
3772 die "monitor read timeout\n" if !scalar(@ready);
3777 # old code, only used to shutdown old VM after update
3778 sub vm_monitor_command {
3779 my ($vmid, $cmdstr, $nocheck) = @_;
3784 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3786 my $sname = "${var_run_tmpdir}/$vmid.mon";
3788 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3789 die "unable to connect to VM $vmid socket - $!\n";
3793 # hack: migrate sometime blocks the monitor (when migrate_downtime
3795 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3796 $timeout = 60*60; # 1 hour
3800 my $data = __read_avail($sock, $timeout);
3802 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3803 die "got unexpected qemu monitor banner\n";
3806 my $sel = new IO::Select;
3809 if (!scalar(my @ready = $sel->can_write($timeout))) {
3810 die "monitor write error - timeout";
3813 my $fullcmd = "$cmdstr\r";
3815 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3818 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3819 die "monitor write error - $!";
3822 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3826 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3827 $timeout = 60*60; # 1 hour
3828 } elsif ($cmdstr =~ m/^(eject|change)/) {
3829 $timeout = 60; # note: cdrom mount command is slow
3831 if ($res = __read_avail($sock, $timeout)) {
3833 my @lines = split("\r?\n", $res);
3835 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3837 $res = join("\n", @lines);
3845 syslog("err", "VM $vmid monitor command failed - $err");
3852 sub qemu_block_resize {
3853 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3855 my $running = check_running($vmid);
3857 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3859 return if !$running;
3861 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3865 sub qemu_volume_snapshot {
3866 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3868 my $running = check_running($vmid);
3870 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3871 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3873 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3877 sub qemu_volume_snapshot_delete {
3878 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3880 my $running = check_running($vmid);
3882 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3884 return if !$running;
3886 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
3889 sub set_migration_caps {
3895 "auto-converge" => 1,
3897 "x-rdma-pin-all" => 0,
3902 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
3904 for my $supported_capability (@$supported_capabilities) {
3906 capability => $supported_capability->{capability},
3907 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3911 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
3914 my $fast_plug_option = {
3924 # hotplug changes in [PENDING]
3925 # $selection hash can be used to only apply specified options, for
3926 # example: { cores => 1 } (only apply changed 'cores
')
3927 # $errors ref is used to return error messages
3928 sub vmconfig_hotplug_pending {
3929 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3931 my $defaults = load_defaults();
3933 # commit values which do not have any impact on running VM first
3934 # Note: those option cannot raise errors, we we do not care about
3935 # $selection and always apply them.
3937 my $add_error = sub {
3938 my ($opt, $msg) = @_;
3939 $errors->{$opt} = "hotplug problem - $msg";
3943 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3944 if ($fast_plug_option->{$opt}) {
3945 $conf->{$opt} = $conf->{pending}->{$opt};
3946 delete $conf->{pending}->{$opt};
3952 PVE::QemuConfig->write_config($vmid, $conf);
3953 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3956 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3958 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3959 while (my ($opt, $force) = each %$pending_delete_hash) {
3960 next if $selection && !$selection->{$opt};
3962 if ($opt eq 'hotplug
') {
3963 die "skip\n" if ($conf->{hotplug} =~ /memory/);
3964 } elsif ($opt eq 'tablet
') {
3965 die "skip\n" if !$hotplug_features->{usb};
3966 if ($defaults->{tablet}) {
3967 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3969 vm_deviceunplug($vmid, $conf, $opt);
3971 } elsif ($opt =~ m/^usb\d+/) {
3973 # since we cannot reliably hot unplug usb devices
3974 # we are disabling it
3975 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
3976 vm_deviceunplug($vmid, $conf, $opt);
3977 } elsif ($opt eq 'vcpus
') {
3978 die "skip\n" if !$hotplug_features->{cpu};
3979 qemu_cpu_hotplug($vmid, $conf, undef);
3980 } elsif ($opt eq 'balloon
') {
3981 # enable balloon device is not hotpluggable
3982 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
3983 } elsif ($fast_plug_option->{$opt}) {
3985 } elsif ($opt =~ m/^net(\d+)$/) {
3986 die "skip\n" if !$hotplug_features->{network};
3987 vm_deviceunplug($vmid, $conf, $opt);
3988 } elsif (is_valid_drivename($opt)) {
3989 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3990 vm_deviceunplug($vmid, $conf, $opt);
3991 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3992 } elsif ($opt =~ m/^memory$/) {
3993 die "skip\n" if !$hotplug_features->{memory};
3994 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3995 } elsif ($opt eq 'cpuunits
') {
3996 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
3997 } elsif ($opt eq 'cpulimit
') {
3998 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4004 &$add_error($opt, $err) if $err ne "skip\n";
4006 # save new config if hotplug was successful
4007 delete $conf->{$opt};
4008 vmconfig_undelete_pending_option($conf, $opt);
4009 PVE::QemuConfig->write_config($vmid, $conf);
4010 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4014 foreach my $opt (keys %{$conf->{pending}}) {
4015 next if $selection && !$selection->{$opt};
4016 my $value = $conf->{pending}->{$opt};
4018 if ($opt eq 'hotplug
') {
4019 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4020 } elsif ($opt eq 'tablet
') {
4021 die "skip\n" if !$hotplug_features->{usb};
4023 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4024 } elsif ($value == 0) {
4025 vm_deviceunplug($vmid, $conf, $opt);
4027 } elsif ($opt =~ m/^usb\d+$/) {
4029 # since we cannot reliably hot unplug usb devices
4030 # we are disabling it
4031 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4032 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4033 die "skip\n" if !$d;
4034 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4035 } elsif ($opt eq 'vcpus
') {
4036 die "skip\n" if !$hotplug_features->{cpu};
4037 qemu_cpu_hotplug($vmid, $conf, $value);
4038 } elsif ($opt eq 'balloon
') {
4039 # enable/disable balloning device is not hotpluggable
4040 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4041 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4042 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4044 # allow manual ballooning if shares is set to zero
4045 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4046 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4047 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4049 } elsif ($opt =~ m/^net(\d+)$/) {
4050 # some changes can be done without hotplug
4051 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4052 $vmid, $opt, $value);
4053 } elsif (is_valid_drivename($opt)) {
4054 # some changes can be done without hotplug
4055 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4056 $vmid, $opt, $value, 1);
4057 } elsif ($opt =~ m/^memory$/) { #dimms
4058 die "skip\n" if !$hotplug_features->{memory};
4059 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4060 } elsif ($opt eq 'cpuunits
') {
4061 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4062 } elsif ($opt eq 'cpulimit
') {
4063 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4064 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4066 die "skip\n"; # skip non-hot-pluggable options
4070 &$add_error($opt, $err) if $err ne "skip\n";
4072 # save new config if hotplug was successful
4073 $conf->{$opt} = $value;
4074 delete $conf->{pending}->{$opt};
4075 PVE::QemuConfig->write_config($vmid, $conf);
4076 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4081 sub try_deallocate_drive {
4082 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4084 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4085 my $volid = $drive->{file};
4086 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4087 my $sid = PVE::Storage::parse_volume_id($volid);
4088 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4090 # check if the disk is really unused
4091 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4092 if is_volume_in_use($storecfg, $conf, $key, $volid);
4093 PVE::Storage::vdisk_free($storecfg, $volid);
4096 # If vm is not owner of this disk remove from config
4104 sub vmconfig_delete_or_detach_drive {
4105 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4107 my $drive = parse_drive($opt, $conf->{$opt});
4109 my $rpcenv = PVE::RPCEnvironment::get();
4110 my $authuser = $rpcenv->get_user();
4113 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4114 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4116 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4120 sub vmconfig_apply_pending {
4121 my ($vmid, $conf, $storecfg) = @_;
4125 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4126 while (my ($opt, $force) = each %$pending_delete_hash) {
4127 die "internal error" if $opt =~ m/^unused/;
4128 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4129 if (!defined($conf->{$opt})) {
4130 vmconfig_undelete_pending_option($conf, $opt);
4131 PVE::QemuConfig->write_config($vmid, $conf);
4132 } elsif (is_valid_drivename($opt)) {
4133 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4134 vmconfig_undelete_pending_option($conf, $opt);
4135 delete $conf->{$opt};
4136 PVE::QemuConfig->write_config($vmid, $conf);
4138 vmconfig_undelete_pending_option($conf, $opt);
4139 delete $conf->{$opt};
4140 PVE::QemuConfig->write_config($vmid, $conf);
4144 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4146 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4147 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4149 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4150 # skip if nothing changed
4151 } elsif (is_valid_drivename($opt)) {
4152 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4153 if defined($conf->{$opt});
4154 $conf->{$opt} = $conf->{pending}->{$opt};
4156 $conf->{$opt} = $conf->{pending}->{$opt};
4159 delete $conf->{pending}->{$opt};
4160 PVE::QemuConfig->write_config($vmid, $conf);
4164 my $safe_num_ne = sub {
4167 return 0 if !defined($a) && !defined($b);
4168 return 1 if !defined($a);
4169 return 1 if !defined($b);
4174 my $safe_string_ne = sub {
4177 return 0 if !defined($a) && !defined($b);
4178 return 1 if !defined($a);
4179 return 1 if !defined($b);
4184 sub vmconfig_update_net {
4185 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4187 my $newnet = parse_net($value);
4189 if ($conf->{$opt}) {
4190 my $oldnet = parse_net($conf->{$opt});
4192 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4193 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4194 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4195 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4197 # for non online change, we try to hot-unplug
4198 die "skip\n" if !$hotplug;
4199 vm_deviceunplug($vmid, $conf, $opt);
4202 die "internal error" if $opt !~ m/net(\d+)/;
4203 my $iface = "tap${vmid}i$1";
4205 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4206 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4207 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4208 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4209 PVE::Network::tap_unplug($iface);
4210 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4211 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4212 # Rate can be applied on its own but any change above needs to
4213 # include the rate in tap_plug since OVS resets everything.
4214 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4217 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4218 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4226 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4232 sub vmconfig_update_disk {
4233 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4235 # fixme: do we need force?
4237 my $drive = parse_drive($opt, $value);
4239 if ($conf->{$opt}) {
4241 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4243 my $media = $drive->{media} || 'disk
';
4244 my $oldmedia = $old_drive->{media} || 'disk
';
4245 die "unable to change media type\n" if $media ne $oldmedia;
4247 if (!drive_is_cdrom($old_drive)) {
4249 if ($drive->{file} ne $old_drive->{file}) {
4251 die "skip\n" if !$hotplug;
4253 # unplug and register as unused
4254 vm_deviceunplug($vmid, $conf, $opt);
4255 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4258 # update existing disk
4260 # skip non hotpluggable value
4261 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4262 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4263 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4264 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4269 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4270 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4271 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4272 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4273 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4274 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4275 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4276 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4277 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4278 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4279 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4280 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4282 qemu_block_set_io_throttle($vmid,"drive-$opt",
4283 ($drive->{mbps} || 0)*1024*1024,
4284 ($drive->{mbps_rd} || 0)*1024*1024,
4285 ($drive->{mbps_wr} || 0)*1024*1024,
4286 $drive->{iops} || 0,
4287 $drive->{iops_rd} || 0,
4288 $drive->{iops_wr} || 0,
4289 ($drive->{mbps_max} || 0)*1024*1024,
4290 ($drive->{mbps_rd_max} || 0)*1024*1024,
4291 ($drive->{mbps_wr_max} || 0)*1024*1024,
4292 $drive->{iops_max} || 0,
4293 $drive->{iops_rd_max} || 0,
4294 $drive->{iops_wr_max} || 0);
4303 if ($drive->{file} eq 'none
') {
4304 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4306 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4307 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4308 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4316 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4318 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4319 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4323 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4324 $forcemachine, $spice_ticket) = @_;
4326 PVE::QemuConfig->lock_config($vmid, sub {
4327 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4329 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4331 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4333 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4335 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4336 vmconfig_apply_pending($vmid, $conf, $storecfg);
4337 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4340 my $defaults = load_defaults();
4342 # set environment variable useful inside network script
4343 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4345 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4347 my $migrate_port = 0;
4350 if ($statefile eq 'tcp
') {
4351 my $localip = "localhost";
4352 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4353 my $nodename = PVE::INotify::nodename();
4354 if ($datacenterconf->{migration_unsecure}) {
4355 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4356 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4358 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4359 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4360 $migrate_uri = "tcp:${localip}:${migrate_port}";
4361 push @$cmd, '-incoming
', $migrate_uri;
4364 } elsif ($statefile eq 'unix
') {
4365 # should be default for secure migrations as a ssh TCP forward
4366 # tunnel is not deterministic reliable ready and fails regurarly
4367 # to set up in time, so use UNIX socket forwards
4368 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4369 unlink $socket_addr;
4371 $migrate_uri = "unix:$socket_addr";
4373 push @$cmd, '-incoming
', $migrate_uri;
4377 push @$cmd, '-loadstate
', $statefile;
4384 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4385 my $d = parse_hostpci($conf->{"hostpci$i"});
4387 my $pcidevices = $d->{pciid};
4388 foreach my $pcidevice (@$pcidevices) {
4389 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4391 my $info = pci_device_info("0000:$pciid");
4392 die "IOMMU not present\n" if !check_iommu_support();
4393 die "no pci device info for device '$pciid'\n" if !$info;
4394 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4395 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4399 PVE::Storage::activate_volumes($storecfg, $vollist);
4401 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4403 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4404 eval { run_command($cmd); };
4407 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4408 : $defaults->{cpuunits};
4410 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4413 Slice => 'qemu
.slice
',
4415 CPUShares => $cpuunits
4418 if (my $cpulimit = $conf->{cpulimit}) {
4419 $properties{CPUQuota} = int($cpulimit * 100);
4421 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4423 if ($conf->{hugepages}) {
4426 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4427 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4429 PVE::QemuServer::Memory::hugepages_mount();
4430 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4433 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4434 run_command($cmd, %run_params);
4438 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4442 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4444 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4448 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4449 run_command($cmd, %run_params);
4454 # deactivate volumes if start fails
4455 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4456 die "start failed: $err";
4459 print "migration listens on $migrate_uri\n" if $migrate_uri;
4461 if ($statefile && $statefile ne 'tcp
') {
4462 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4466 if ($migratedfrom) {
4469 set_migration_caps($vmid);
4474 print "spice listens on port $spice_port\n";
4475 if ($spice_ticket) {
4476 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4477 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4483 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4484 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4485 if $conf->{balloon};
4488 foreach my $opt (keys %$conf) {
4489 next if $opt !~ m/^net\d+$/;
4490 my $nicconf = parse_net($conf->{$opt});
4491 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4495 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4496 path => "machine/peripheral/balloon0",
4497 property => "guest-stats-polling-interval",
4498 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4504 my ($vmid, $execute, %params) = @_;
4506 my $cmd = { execute => $execute, arguments => \%params };
4507 vm_qmp_command($vmid, $cmd);
4510 sub vm_mon_cmd_nocheck {
4511 my ($vmid, $execute, %params) = @_;
4513 my $cmd = { execute => $execute, arguments => \%params };
4514 vm_qmp_command($vmid, $cmd, 1);
4517 sub vm_qmp_command {
4518 my ($vmid, $cmd, $nocheck) = @_;
4523 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4524 $timeout = $cmd->{arguments}->{timeout};
4525 delete $cmd->{arguments}->{timeout};
4529 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4530 my $sname = qmp_socket($vmid);
4531 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4532 my $qmpclient = PVE::QMPClient->new();
4534 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4535 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4536 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4537 if scalar(%{$cmd->{arguments}});
4538 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4540 die "unable to
open monitor
socket\n";
4544 syslog("err
", "VM
$vmid qmp command failed
- $err");
4551 sub vm_human_monitor_command {
4552 my ($vmid, $cmdline) = @_;
4557 execute => 'human-monitor-command',
4558 arguments => { 'command-line' => $cmdline},
4561 return vm_qmp_command($vmid, $cmd);
4564 sub vm_commandline {
4565 my ($storecfg, $vmid) = @_;
4567 my $conf = PVE::QemuConfig->load_config($vmid);
4569 my $defaults = load_defaults();
4571 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4573 return join(' ', @$cmd);
4577 my ($vmid, $skiplock) = @_;
4579 PVE::QemuConfig->lock_config($vmid, sub {
4581 my $conf = PVE::QemuConfig->load_config($vmid);
4583 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4585 vm_mon_cmd($vmid, "system_reset
");
4589 sub get_vm_volumes {
4593 foreach_volid($conf, sub {
4594 my ($volid, $is_cdrom) = @_;
4596 return if $volid =~ m|^/|;
4598 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4601 push @$vollist, $volid;
4607 sub vm_stop_cleanup {
4608 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4613 my $vollist = get_vm_volumes($conf);
4614 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4617 foreach my $ext (qw(mon qmp pid vnc qga)) {
4618 unlink "/var/run/qemu-server/${vmid}.$ext";
4621 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4623 warn $@ if $@; # avoid errors - just warn
4626 # Note: use $nockeck to skip tests if VM configuration file exists.
4627 # We need that when migration VMs to other nodes (files already moved)
4628 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4630 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4632 $force = 1 if !defined($force) && !$shutdown;
4635 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4636 kill 15, $pid if $pid;
4637 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4638 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4642 PVE
::QemuConfig-
>lock_config($vmid, sub {
4644 my $pid = check_running
($vmid, $nocheck);
4649 $conf = PVE
::QemuConfig-
>load_config($vmid);
4650 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4651 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4652 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4653 $timeout = $opts->{down
} if $opts->{down
};
4657 $timeout = 60 if !defined($timeout);
4661 if (defined($conf) && $conf->{agent
}) {
4662 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4664 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4667 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4674 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4679 if ($count >= $timeout) {
4681 warn "VM still running - terminating now with SIGTERM\n";
4684 die "VM quit/powerdown failed - got timeout\n";
4687 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4692 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4695 die "VM quit/powerdown failed\n";
4703 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4708 if ($count >= $timeout) {
4709 warn "VM still running - terminating now with SIGKILL\n";
4714 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4719 my ($vmid, $skiplock) = @_;
4721 PVE
::QemuConfig-
>lock_config($vmid, sub {
4723 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4725 PVE
::QemuConfig-
>check_lock($conf)
4726 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4728 vm_mon_cmd
($vmid, "stop");
4733 my ($vmid, $skiplock, $nocheck) = @_;
4735 PVE
::QemuConfig-
>lock_config($vmid, sub {
4739 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4741 PVE
::QemuConfig-
>check_lock($conf)
4742 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4744 vm_mon_cmd
($vmid, "cont");
4747 vm_mon_cmd_nocheck
($vmid, "cont");
4753 my ($vmid, $skiplock, $key) = @_;
4755 PVE
::QemuConfig-
>lock_config($vmid, sub {
4757 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4759 # there is no qmp command, so we use the human monitor command
4760 vm_human_monitor_command
($vmid, "sendkey $key");
4765 my ($storecfg, $vmid, $skiplock) = @_;
4767 PVE
::QemuConfig-
>lock_config($vmid, sub {
4769 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4771 if (!check_running
($vmid)) {
4772 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4774 die "VM $vmid is running - destroy failed\n";
4782 my ($filename, $buf) = @_;
4784 my $fh = IO
::File-
>new($filename, "w");
4785 return undef if !$fh;
4787 my $res = print $fh $buf;
4794 sub pci_device_info
{
4799 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4800 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4802 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4803 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4805 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4806 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4808 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4809 return undef if !defined($product) || $product !~ s/^0x//;
4814 product
=> $product,
4820 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4829 my $name = $dev->{name
};
4831 my $fn = "$pcisysfs/devices/$name/reset";
4833 return file_write
($fn, "1");
4836 sub pci_dev_bind_to_vfio
{
4839 my $name = $dev->{name
};
4841 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4843 if (!-d
$vfio_basedir) {
4844 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4846 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4848 my $testdir = "$vfio_basedir/$name";
4849 return 1 if -d
$testdir;
4851 my $data = "$dev->{vendor} $dev->{product}";
4852 return undef if !file_write
("$vfio_basedir/new_id", $data);
4854 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4855 if (!file_write
($fn, $name)) {
4856 return undef if -f
$fn;
4859 $fn = "$vfio_basedir/bind";
4860 if (! -d
$testdir) {
4861 return undef if !file_write
($fn, $name);
4867 sub pci_dev_group_bind_to_vfio
{
4870 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4872 if (!-d
$vfio_basedir) {
4873 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4875 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4877 # get IOMMU group devices
4878 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4879 my @devs = grep /^0000:/, readdir($D);
4882 foreach my $pciid (@devs) {
4883 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4885 # pci bridges, switches or root ports are not supported
4886 # they have a pci_bus subdirectory so skip them
4887 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4889 my $info = pci_device_info
($1);
4890 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4896 # vzdump restore implementaion
4898 sub tar_archive_read_firstfile
{
4899 my $archive = shift;
4901 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4903 # try to detect archive type first
4904 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
4905 die "unable to open file '$archive'\n";
4906 my $firstfile = <$fh>;
4910 die "ERROR: archive contaions no data\n" if !$firstfile;
4916 sub tar_restore_cleanup
{
4917 my ($storecfg, $statfile) = @_;
4919 print STDERR
"starting cleanup\n";
4921 if (my $fd = IO
::File-
>new($statfile, "r")) {
4922 while (defined(my $line = <$fd>)) {
4923 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4926 if ($volid =~ m
|^/|) {
4927 unlink $volid || die 'unlink failed\n';
4929 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4931 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4933 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4935 print STDERR
"unable to parse line in statfile - $line";
4942 sub restore_archive
{
4943 my ($archive, $vmid, $user, $opts) = @_;
4945 my $format = $opts->{format
};
4948 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4949 $format = 'tar' if !$format;
4951 } elsif ($archive =~ m/\.tar$/) {
4952 $format = 'tar' if !$format;
4953 } elsif ($archive =~ m/.tar.lzo$/) {
4954 $format = 'tar' if !$format;
4956 } elsif ($archive =~ m/\.vma$/) {
4957 $format = 'vma' if !$format;
4958 } elsif ($archive =~ m/\.vma\.gz$/) {
4959 $format = 'vma' if !$format;
4961 } elsif ($archive =~ m/\.vma\.lzo$/) {
4962 $format = 'vma' if !$format;
4965 $format = 'vma' if !$format; # default
4968 # try to detect archive format
4969 if ($format eq 'tar') {
4970 return restore_tar_archive
($archive, $vmid, $user, $opts);
4972 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4976 sub restore_update_config_line
{
4977 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4979 return if $line =~ m/^\#qmdump\#/;
4980 return if $line =~ m/^\#vzdump\#/;
4981 return if $line =~ m/^lock:/;
4982 return if $line =~ m/^unused\d+:/;
4983 return if $line =~ m/^parent:/;
4984 return if $line =~ m/^template:/; # restored VM is never a template
4986 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
4987 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4988 # try to convert old 1.X settings
4989 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4990 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4991 my ($model, $macaddr) = split(/\=/, $devconfig);
4992 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
4995 bridge
=> "vmbr$ind",
4996 macaddr
=> $macaddr,
4998 my $netstr = print_net
($net);
5000 print $outfd "net$cookie->{netcount}: $netstr\n";
5001 $cookie->{netcount
}++;
5003 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5004 my ($id, $netstr) = ($1, $2);
5005 my $net = parse_net
($netstr);
5006 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5007 $netstr = print_net
($net);
5008 print $outfd "$id: $netstr\n";
5009 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5012 my $di = parse_drive
($virtdev, $value);
5013 if (defined($di->{backup
}) && !$di->{backup
}) {
5014 print $outfd "#$line";
5015 } elsif ($map->{$virtdev}) {
5016 delete $di->{format
}; # format can change on restore
5017 $di->{file
} = $map->{$virtdev};
5018 $value = print_drive
($vmid, $di);
5019 print $outfd "$virtdev: $value\n";
5029 my ($cfg, $vmid) = @_;
5031 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5033 my $volid_hash = {};
5034 foreach my $storeid (keys %$info) {
5035 foreach my $item (@{$info->{$storeid}}) {
5036 next if !($item->{volid
} && $item->{size
});
5037 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5038 $volid_hash->{$item->{volid
}} = $item;
5045 sub is_volume_in_use
{
5046 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5048 my $path = PVE
::Storage
::path
($storecfg, $volid);
5050 my $scan_config = sub {
5051 my ($cref, $snapname) = @_;
5053 foreach my $key (keys %$cref) {
5054 my $value = $cref->{$key};
5055 if (is_valid_drivename
($key)) {
5056 next if $skip_drive && $key eq $skip_drive;
5057 my $drive = parse_drive
($key, $value);
5058 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5059 return 1 if $volid eq $drive->{file
};
5060 if ($drive->{file
} =~ m!^/!) {
5061 return 1 if $drive->{file
} eq $path;
5063 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5065 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5067 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5075 return 1 if &$scan_config($conf);
5079 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5080 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5086 sub update_disksize
{
5087 my ($vmid, $conf, $volid_hash) = @_;
5093 # Note: it is allowed to define multiple storages with same path (alias), so
5094 # we need to check both 'volid' and real 'path' (two different volid can point
5095 # to the same path).
5100 foreach my $opt (keys %$conf) {
5101 if (is_valid_drivename
($opt)) {
5102 my $drive = parse_drive
($opt, $conf->{$opt});
5103 my $volid = $drive->{file
};
5106 $used->{$volid} = 1;
5107 if ($volid_hash->{$volid} &&
5108 (my $path = $volid_hash->{$volid}->{path
})) {
5109 $usedpath->{$path} = 1;
5112 next if drive_is_cdrom
($drive);
5113 next if !$volid_hash->{$volid};
5115 $drive->{size
} = $volid_hash->{$volid}->{size
};
5116 my $new = print_drive
($vmid, $drive);
5117 if ($new ne $conf->{$opt}) {
5119 $conf->{$opt} = $new;
5124 # remove 'unusedX' entry if volume is used
5125 foreach my $opt (keys %$conf) {
5126 next if $opt !~ m/^unused\d+$/;
5127 my $volid = $conf->{$opt};
5128 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5129 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5131 delete $conf->{$opt};
5135 foreach my $volid (sort keys %$volid_hash) {
5136 next if $volid =~ m/vm-$vmid-state-/;
5137 next if $used->{$volid};
5138 my $path = $volid_hash->{$volid}->{path
};
5139 next if !$path; # just to be sure
5140 next if $usedpath->{$path};
5142 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5143 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5150 my ($vmid, $nolock) = @_;
5152 my $cfg = PVE
::Storage
::config
();
5154 my $volid_hash = scan_volids
($cfg, $vmid);
5156 my $updatefn = sub {
5159 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5161 PVE
::QemuConfig-
>check_lock($conf);
5164 foreach my $volid (keys %$volid_hash) {
5165 my $info = $volid_hash->{$volid};
5166 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5169 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5171 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5174 if (defined($vmid)) {
5178 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5181 my $vmlist = config_list
();
5182 foreach my $vmid (keys %$vmlist) {
5186 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5192 sub restore_vma_archive
{
5193 my ($archive, $vmid, $user, $opts, $comp) = @_;
5195 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5196 my $readfrom = $archive;
5201 my $qarchive = PVE
::Tools
::shellquote
($archive);
5202 if ($comp eq 'gzip') {
5203 $uncomp = "zcat $qarchive|";
5204 } elsif ($comp eq 'lzop') {
5205 $uncomp = "lzop -d -c $qarchive|";
5207 die "unknown compression method '$comp'\n";
5212 my $tmpdir = "/var/tmp/vzdumptmp$$";
5215 # disable interrupts (always do cleanups)
5216 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5217 warn "got interrupt - ignored\n";
5220 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5221 POSIX
::mkfifo
($mapfifo, 0600);
5224 my $openfifo = sub {
5225 open($fifofh, '>', $mapfifo) || die $!;
5228 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5235 my $rpcenv = PVE
::RPCEnvironment
::get
();
5237 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5238 my $tmpfn = "$conffile.$$.tmp";
5240 # Note: $oldconf is undef if VM does not exists
5241 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5242 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5244 my $print_devmap = sub {
5245 my $virtdev_hash = {};
5247 my $cfgfn = "$tmpdir/qemu-server.conf";
5249 # we can read the config - that is already extracted
5250 my $fh = IO
::File-
>new($cfgfn, "r") ||
5251 "unable to read qemu-server.conf - $!\n";
5253 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5255 my $pve_firewall_dir = '/etc/pve/firewall';
5256 mkdir $pve_firewall_dir; # make sure the dir exists
5257 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5260 while (defined(my $line = <$fh>)) {
5261 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5262 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5263 die "archive does not contain data for drive '$virtdev'\n"
5264 if !$devinfo->{$devname};
5265 if (defined($opts->{storage
})) {
5266 $storeid = $opts->{storage
} || 'local';
5267 } elsif (!$storeid) {
5270 $format = 'raw' if !$format;
5271 $devinfo->{$devname}->{devname
} = $devname;
5272 $devinfo->{$devname}->{virtdev
} = $virtdev;
5273 $devinfo->{$devname}->{format
} = $format;
5274 $devinfo->{$devname}->{storeid
} = $storeid;
5276 # check permission on storage
5277 my $pool = $opts->{pool
}; # todo: do we need that?
5278 if ($user ne 'root@pam') {
5279 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5282 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5286 foreach my $devname (keys %$devinfo) {
5287 die "found no device mapping information for device '$devname'\n"
5288 if !$devinfo->{$devname}->{virtdev
};
5291 my $cfg = PVE
::Storage
::config
();
5293 # create empty/temp config
5295 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5296 foreach_drive
($oldconf, sub {
5297 my ($ds, $drive) = @_;
5299 return if drive_is_cdrom
($drive);
5301 my $volid = $drive->{file
};
5303 return if !$volid || $volid =~ m
|^/|;
5305 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5306 return if !$path || !$owner || ($owner != $vmid);
5308 # Note: only delete disk we want to restore
5309 # other volumes will become unused
5310 if ($virtdev_hash->{$ds}) {
5311 PVE
::Storage
::vdisk_free
($cfg, $volid);
5315 # delete vmstate files
5316 # since after the restore we have no snapshots anymore
5317 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5318 my $snap = $oldconf->{snapshots
}->{$snapname};
5319 if ($snap->{vmstate
}) {
5320 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5329 foreach my $virtdev (sort keys %$virtdev_hash) {
5330 my $d = $virtdev_hash->{$virtdev};
5331 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5332 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5334 # test if requested format is supported
5335 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5336 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5337 $d->{format
} = $defFormat if !$supported;
5339 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5340 $d->{format
}, undef, $alloc_size);
5341 print STDERR
"new volume ID is '$volid'\n";
5342 $d->{volid
} = $volid;
5343 my $path = PVE
::Storage
::path
($cfg, $volid);
5345 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5347 my $write_zeros = 1;
5348 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5352 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5354 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5355 $map->{$virtdev} = $volid;
5358 $fh->seek(0, 0) || die "seek failed - $!\n";
5360 my $outfd = new IO
::File
($tmpfn, "w") ||
5361 die "unable to write config for VM $vmid\n";
5363 my $cookie = { netcount
=> 0 };
5364 while (defined(my $line = <$fh>)) {
5365 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5374 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5375 die "interrupted by signal\n";
5377 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5379 $oldtimeout = alarm($timeout);
5386 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5387 my ($dev_id, $size, $devname) = ($1, $2, $3);
5388 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5389 } elsif ($line =~ m/^CTIME: /) {
5390 # we correctly received the vma config, so we can disable
5391 # the timeout now for disk allocation (set to 10 minutes, so
5392 # that we always timeout if something goes wrong)
5395 print $fifofh "done\n";
5396 my $tmp = $oldtimeout || 0;
5397 $oldtimeout = undef;
5403 print "restore vma archive: $cmd\n";
5404 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5408 alarm($oldtimeout) if $oldtimeout;
5411 foreach my $devname (keys %$devinfo) {
5412 my $volid = $devinfo->{$devname}->{volid
};
5413 push @$vollist, $volid if $volid;
5416 my $cfg = PVE
::Storage
::config
();
5417 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5425 foreach my $devname (keys %$devinfo) {
5426 my $volid = $devinfo->{$devname}->{volid
};
5429 if ($volid =~ m
|^/|) {
5430 unlink $volid || die 'unlink failed\n';
5432 PVE
::Storage
::vdisk_free
($cfg, $volid);
5434 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5436 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5443 rename($tmpfn, $conffile) ||
5444 die "unable to commit configuration file '$conffile'\n";
5446 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5448 eval { rescan
($vmid, 1); };
5452 sub restore_tar_archive
{
5453 my ($archive, $vmid, $user, $opts) = @_;
5455 if ($archive ne '-') {
5456 my $firstfile = tar_archive_read_firstfile
($archive);
5457 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5458 if $firstfile ne 'qemu-server.conf';
5461 my $storecfg = PVE
::Storage
::config
();
5463 # destroy existing data - keep empty config
5464 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5465 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5467 my $tocmd = "/usr/lib/qemu-server/qmextract";
5469 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5470 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5471 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5472 $tocmd .= ' --info' if $opts->{info
};
5474 # tar option "xf" does not autodetect compression when read from STDIN,
5475 # so we pipe to zcat
5476 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5477 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5479 my $tmpdir = "/var/tmp/vzdumptmp$$";
5482 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5483 local $ENV{VZDUMP_VMID
} = $vmid;
5484 local $ENV{VZDUMP_USER
} = $user;
5486 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5487 my $tmpfn = "$conffile.$$.tmp";
5489 # disable interrupts (always do cleanups)
5490 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5491 print STDERR
"got interrupt - ignored\n";
5496 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5497 die "interrupted by signal\n";
5500 if ($archive eq '-') {
5501 print "extracting archive from STDIN\n";
5502 run_command
($cmd, input
=> "<&STDIN");
5504 print "extracting archive '$archive'\n";
5508 return if $opts->{info
};
5512 my $statfile = "$tmpdir/qmrestore.stat";
5513 if (my $fd = IO
::File-
>new($statfile, "r")) {
5514 while (defined (my $line = <$fd>)) {
5515 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5516 $map->{$1} = $2 if $1;
5518 print STDERR
"unable to parse line in statfile - $line\n";
5524 my $confsrc = "$tmpdir/qemu-server.conf";
5526 my $srcfd = new IO
::File
($confsrc, "r") ||
5527 die "unable to open file '$confsrc'\n";
5529 my $outfd = new IO
::File
($tmpfn, "w") ||
5530 die "unable to write config for VM $vmid\n";
5532 my $cookie = { netcount
=> 0 };
5533 while (defined (my $line = <$srcfd>)) {
5534 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5546 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5553 rename $tmpfn, $conffile ||
5554 die "unable to commit configuration file '$conffile'\n";
5556 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5558 eval { rescan
($vmid, 1); };
5562 sub foreach_writable_storage
{
5563 my ($conf, $func) = @_;
5567 foreach my $ds (keys %$conf) {
5568 next if !is_valid_drivename
($ds);
5570 my $drive = parse_drive
($ds, $conf->{$ds});
5572 next if drive_is_cdrom
($drive);
5574 my $volid = $drive->{file
};
5576 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5577 $sidhash->{$sid} = $sid if $sid;
5580 foreach my $sid (sort keys %$sidhash) {
5585 sub do_snapshots_with_qemu
{
5586 my ($storecfg, $volid) = @_;
5588 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5590 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5591 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5595 if ($volid =~ m/\.(qcow2|qed)$/){
5602 sub qga_check_running
{
5605 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5607 warn "Qemu Guest Agent are not running - $@";
5613 sub template_create
{
5614 my ($vmid, $conf, $disk) = @_;
5616 my $storecfg = PVE
::Storage
::config
();
5618 foreach_drive
($conf, sub {
5619 my ($ds, $drive) = @_;
5621 return if drive_is_cdrom
($drive);
5622 return if $disk && $ds ne $disk;
5624 my $volid = $drive->{file
};
5625 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5627 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5628 $drive->{file
} = $voliddst;
5629 $conf->{$ds} = print_drive
($vmid, $drive);
5630 PVE
::QemuConfig-
>write_config($vmid, $conf);
5634 sub qemu_img_convert
{
5635 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5637 my $storecfg = PVE
::Storage
::config
();
5638 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5639 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5641 if ($src_storeid && $dst_storeid) {
5643 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5645 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5646 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5648 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5649 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5651 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5652 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5655 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5656 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5657 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5658 if ($is_zero_initialized) {
5659 push @$cmd, "zeroinit:$dst_path";
5661 push @$cmd, $dst_path;
5666 if($line =~ m/\((\S+)\/100\
%\)/){
5668 my $transferred = int($size * $percent / 100);
5669 my $remaining = $size - $transferred;
5671 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5676 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5678 die "copy failed: $err" if $err;
5682 sub qemu_img_format
{
5683 my ($scfg, $volname) = @_;
5685 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5692 sub qemu_drive_mirror
{
5693 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5695 my $storecfg = PVE
::Storage
::config
();
5696 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5698 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5700 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5702 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5704 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5706 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5707 $opts->{format
} = $format if $format;
5709 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5711 my $finish_job = sub {
5713 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5714 my $stat = @$stats[0];
5721 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5723 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5724 my $stat = @$stats[0];
5725 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5726 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5728 my $busy = $stat->{busy
};
5729 my $ready = $stat->{ready
};
5731 if (my $total = $stat->{len
}) {
5732 my $transferred = $stat->{offset
} || 0;
5733 my $remaining = $total - $transferred;
5734 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5736 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5740 if ($stat->{ready
} eq 'true') {
5742 last if $vmiddst != $vmid;
5744 # try to switch the disk if source and destination are on the same guest
5745 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5750 die $@ if $@ !~ m/cannot be completed/;
5759 my $cancel_job = sub {
5760 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5765 eval { &$cancel_job(); };
5766 die "mirroring error: $err";
5769 if ($vmiddst != $vmid) {
5770 # if we clone a disk for a new target vm, we don't switch the disk
5771 &$cancel_job(); # so we call block-job-cancel
5776 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5777 $newvmid, $storage, $format, $full, $newvollist) = @_;
5782 print "create linked clone of drive $drivename ($drive->{file})\n";
5783 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5784 push @$newvollist, $newvolid;
5786 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5787 $storeid = $storage if $storage;
5789 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5791 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5792 $format = qemu_img_format
($scfg, $volname);
5795 # test if requested format is supported - else use default
5796 my $supported = grep { $_ eq $format } @$validFormats;
5797 $format = $defFormat if !$supported;
5799 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5801 print "create full clone of drive $drivename ($drive->{file})\n";
5802 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5803 push @$newvollist, $newvolid;
5805 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
5807 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5808 if (!$running || $snapname) {
5809 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5812 die "drive-mirror is not working currently when iothread is enabled" if $drive->{iothread
};
5814 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5818 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5821 $disk->{format
} = undef;
5822 $disk->{file
} = $newvolid;
5823 $disk->{size
} = $size;
5828 # this only works if VM is running
5829 sub get_current_qemu_machine
{
5832 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5833 my $res = vm_qmp_command
($vmid, $cmd);
5835 my ($current, $default);
5836 foreach my $e (@$res) {
5837 $default = $e->{name
} if $e->{'is-default'};
5838 $current = $e->{name
} if $e->{'is-current'};
5841 # fallback to the default machine if current is not supported by qemu
5842 return $current || $default || 'pc';
5845 sub qemu_machine_feature_enabled
{
5846 my ($machine, $kvmver, $version_major, $version_minor) = @_;
5851 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
5853 $current_major = $3;
5854 $current_minor = $4;
5856 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
5858 $current_major = $1;
5859 $current_minor = $2;
5862 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
5867 sub qemu_machine_pxe
{
5868 my ($vmid, $conf, $machine) = @_;
5870 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
5872 foreach my $opt (keys %$conf) {
5873 next if $opt !~ m/^net(\d+)$/;
5874 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
5876 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
5877 return $machine.".pxe" if $romfile =~ m/pxe/;
5884 sub qemu_use_old_bios_files
{
5885 my ($machine_type) = @_;
5887 return if !$machine_type;
5889 my $use_old_bios_files = undef;
5891 if ($machine_type =~ m/^(\S+)\.pxe$/) {
5893 $use_old_bios_files = 1;
5895 my $kvmver = kvm_user_version
();
5896 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
5897 # load new efi bios files on migration. So this hack is required to allow
5898 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
5899 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
5900 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
5903 return ($use_old_bios_files, $machine_type);
5910 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
5911 my (undef, $id, $function) = @_;
5912 my $res = { id
=> $id, function
=> $function};
5913 push @{$devices->{$id}}, $res;
5919 sub vm_iothreads_list
{
5922 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
5925 foreach my $iothread (@$res) {
5926 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
5933 my ($conf, $drive) = @_;
5937 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
5939 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
5945 my $controller = int($drive->{index} / $maxdev);
5946 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
5948 return ($maxdev, $controller, $controller_prefix);
5951 # bash completion helper
5953 sub complete_backup_archives
{
5954 my ($cmdname, $pname, $cvalue) = @_;
5956 my $cfg = PVE
::Storage
::config
();
5960 if ($cvalue =~ m/^([^:]+):/) {
5964 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
5967 foreach my $id (keys %$data) {
5968 foreach my $item (@{$data->{$id}}) {
5969 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
5970 push @$res, $item->{volid
} if defined($item->{volid
});
5977 my $complete_vmid_full = sub {
5980 my $idlist = vmstatus
();
5984 foreach my $id (keys %$idlist) {
5985 my $d = $idlist->{$id};
5986 if (defined($running)) {
5987 next if $d->{template
};
5988 next if $running && $d->{status
} ne 'running';
5989 next if !$running && $d->{status
} eq 'running';
5998 return &$complete_vmid_full();
6001 sub complete_vmid_stopped
{
6002 return &$complete_vmid_full(0);
6005 sub complete_vmid_running
{
6006 return &$complete_vmid_full(1);
6009 sub complete_storage
{
6011 my $cfg = PVE
::Storage
::config
();
6012 my $ids = $cfg->{ids
};
6015 foreach my $sid (keys %$ids) {
6016 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6017 next if !$ids->{$sid}->{content
}->{images
};