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);
907 type
=> 'string', format
=> 'pve-qm-usb-device',
908 format_description
=> 'HOSTUSBDEVICE|spice',
909 description
=> <<EODESCR,
910 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
912 'bus-port(.port)*' (decimal numbers) or
913 'vendor_id:product_id' (hexadeciaml numbers) or
916 You can use the 'lsusb -t' command to list existing usb devices.
918 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
920 The value 'spice' can be used to add a usb redirection devices for spice.
926 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).",
933 type
=> 'string', format
=> $usb_fmt,
934 description
=> "Configure an USB device (n is 0 to 4).",
936 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
938 # NOTE: the match-groups of this regex are used in parse_hostpci
939 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
944 pattern
=> qr/$PCIRE(;$PCIRE)*/,
945 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
946 description
=> <<EODESCR,
947 Host PCI device pass through. The PCI ID of a host's PCI device or a list
948 of PCI virtual functions of the host. HOSTPCIID syntax is:
950 'bus:dev.func' (hexadecimal numbers)
952 You can us the 'lspci' command to list existing PCI devices.
957 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
963 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
969 description
=> "Enable vfio-vga device support.",
974 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
978 type
=> 'string', format
=> 'pve-qm-hostpci',
979 description
=> "Map host PCI devices into guest.",
980 verbose_description
=> <<EODESCR,
981 Map host PCI devices into guest.
983 NOTE: This option allows direct access to host hardware. So it is no longer
984 possible to migrate such machines - use with special care.
986 CAUTION: Experimental! User reported problems with this option.
989 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
994 pattern
=> '(/dev/.+|socket)',
995 description
=> "Create a serial device inside the VM (n is 0 to 3)",
996 verbose_description
=> <<EODESCR,
997 Create a serial device inside the VM (n is 0 to 3), and pass through a
998 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
999 host side (use 'qm terminal' to open a terminal connection).
1001 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1003 CAUTION: Experimental! User reported problems with this option.
1010 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1011 description
=> "Map host parallel devices (n is 0 to 2).",
1012 verbose_description
=> <<EODESCR,
1013 Map host parallel devices (n is 0 to 2).
1015 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1017 CAUTION: Experimental! User reported problems with this option.
1021 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1022 $confdesc->{"parallel$i"} = $paralleldesc;
1025 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1026 $confdesc->{"serial$i"} = $serialdesc;
1029 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1030 $confdesc->{"hostpci$i"} = $hostpcidesc;
1033 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1034 $drivename_hash->{"ide$i"} = 1;
1035 $confdesc->{"ide$i"} = $idedesc;
1038 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1039 $drivename_hash->{"sata$i"} = 1;
1040 $confdesc->{"sata$i"} = $satadesc;
1043 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1044 $drivename_hash->{"scsi$i"} = 1;
1045 $confdesc->{"scsi$i"} = $scsidesc ;
1048 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1049 $drivename_hash->{"virtio$i"} = 1;
1050 $confdesc->{"virtio$i"} = $virtiodesc;
1053 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1054 $confdesc->{"usb$i"} = $usbdesc;
1059 type
=> 'string', format
=> 'pve-volume-id',
1060 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1063 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1064 $confdesc->{"unused$i"} = $unuseddesc;
1067 my $kvm_api_version = 0;
1071 return $kvm_api_version if $kvm_api_version;
1073 my $fh = IO
::File-
>new("</dev/kvm") ||
1076 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1077 $kvm_api_version = $v;
1082 return $kvm_api_version;
1085 my $kvm_user_version;
1087 sub kvm_user_version
{
1089 return $kvm_user_version if $kvm_user_version;
1091 $kvm_user_version = 'unknown';
1095 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1096 $kvm_user_version = $2;
1100 eval { run_command
("kvm -version", outfunc
=> $code); };
1103 return $kvm_user_version;
1107 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1109 sub valid_drive_names
{
1110 # order is important - used to autoselect boot disk
1111 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1112 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1113 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1114 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1117 sub is_valid_drivename
{
1120 return defined($drivename_hash->{$dev});
1125 return defined($confdesc->{$key});
1129 return $nic_model_list;
1132 sub os_list_description
{
1136 wxp
=> 'Windows XP',
1137 w2k
=> 'Windows 2000',
1138 w2k3
=>, 'Windows 2003',
1139 w2k8
=> 'Windows 2008',
1140 wvista
=> 'Windows Vista',
1141 win7
=> 'Windows 7',
1142 win8
=> 'Windows 8/2012',
1150 sub get_cdrom_path
{
1152 return $cdrom_path if $cdrom_path;
1154 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1155 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1156 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1160 my ($storecfg, $vmid, $cdrom) = @_;
1162 if ($cdrom eq 'cdrom') {
1163 return get_cdrom_path
();
1164 } elsif ($cdrom eq 'none') {
1166 } elsif ($cdrom =~ m
|^/|) {
1169 return PVE
::Storage
::path
($storecfg, $cdrom);
1173 # try to convert old style file names to volume IDs
1174 sub filename_to_volume_id
{
1175 my ($vmid, $file, $media) = @_;
1177 if (!($file eq 'none' || $file eq 'cdrom' ||
1178 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1180 return undef if $file =~ m
|/|;
1182 if ($media && $media eq 'cdrom') {
1183 $file = "local:iso/$file";
1185 $file = "local:$vmid/$file";
1192 sub verify_media_type
{
1193 my ($opt, $vtype, $media) = @_;
1198 if ($media eq 'disk') {
1200 } elsif ($media eq 'cdrom') {
1203 die "internal error";
1206 return if ($vtype eq $etype);
1208 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1211 sub cleanup_drive_path
{
1212 my ($opt, $storecfg, $drive) = @_;
1214 # try to convert filesystem paths to volume IDs
1216 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1217 ($drive->{file
} !~ m
|^/dev/.+|) &&
1218 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1219 ($drive->{file
} !~ m/^\d+$/)) {
1220 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1221 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1222 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1223 verify_media_type
($opt, $vtype, $drive->{media
});
1224 $drive->{file
} = $volid;
1227 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1230 sub parse_hotplug_features
{
1235 return $res if $data eq '0';
1237 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1239 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1240 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1243 die "invalid hotplug feature '$feature'\n";
1249 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1250 sub pve_verify_hotplug_features
{
1251 my ($value, $noerr) = @_;
1253 return $value if parse_hotplug_features
($value);
1255 return undef if $noerr;
1257 die "unable to parse hotplug option\n";
1260 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1261 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1262 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1263 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1264 # [,iothread=on][,serial=serial][,model=model]
1267 my ($key, $data) = @_;
1269 my ($interface, $index);
1271 if ($key =~ m/^([^\d]+)(\d+)$/) {
1278 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1279 : $confdesc->{$key}->{format
};
1281 warn "invalid drive key: $key\n";
1284 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1285 return undef if !$res;
1286 $res->{interface
} = $interface;
1287 $res->{index} = $index;
1290 foreach my $opt (qw(bps bps_rd bps_wr)) {
1291 if (my $bps = defined(delete $res->{$opt})) {
1292 if (defined($res->{"m$opt"})) {
1293 warn "both $opt and m$opt specified\n";
1297 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1300 return undef if $error;
1302 return undef if $res->{mbps_rd
} && $res->{mbps
};
1303 return undef if $res->{mbps_wr
} && $res->{mbps
};
1304 return undef if $res->{iops_rd
} && $res->{iops
};
1305 return undef if $res->{iops_wr
} && $res->{iops
};
1307 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1308 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1309 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1310 return undef if $res->{interface
} eq 'virtio';
1313 if (my $size = $res->{size
}) {
1314 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1321 my ($vmid, $drive) = @_;
1322 my $data = { %$drive };
1323 delete $data->{$_} for qw(index interface);
1324 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1328 my($fh, $noerr) = @_;
1331 my $SG_GET_VERSION_NUM = 0x2282;
1333 my $versionbuf = "\x00" x
8;
1334 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1336 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1339 my $version = unpack("I", $versionbuf);
1340 if ($version < 30000) {
1341 die "scsi generic interface too old\n" if !$noerr;
1345 my $buf = "\x00" x
36;
1346 my $sensebuf = "\x00" x
8;
1347 my $cmd = pack("C x3 C x1", 0x12, 36);
1349 # see /usr/include/scsi/sg.h
1350 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";
1352 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1353 length($sensebuf), 0, length($buf), $buf,
1354 $cmd, $sensebuf, 6000);
1356 $ret = ioctl($fh, $SG_IO, $packet);
1358 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1362 my @res = unpack($sg_io_hdr_t, $packet);
1363 if ($res[17] || $res[18]) {
1364 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1369 (my $byte0, my $byte1, $res->{vendor
},
1370 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1372 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1373 $res->{type
} = $byte0 & 31;
1381 my $fh = IO
::File-
>new("+<$path") || return undef;
1382 my $res = scsi_inquiry
($fh, 1);
1388 sub machine_type_is_q35
{
1391 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1394 sub print_tabletdevice_full
{
1397 my $q35 = machine_type_is_q35
($conf);
1399 # we use uhci for old VMs because tablet driver was buggy in older qemu
1400 my $usbbus = $q35 ?
"ehci" : "uhci";
1402 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1405 sub print_drivedevice_full
{
1406 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1411 if ($drive->{interface
} eq 'virtio') {
1412 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1413 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1414 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1415 } elsif ($drive->{interface
} eq 'scsi') {
1417 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1418 my $unit = $drive->{index} % $maxdev;
1419 my $devicetype = 'hd';
1421 if (drive_is_cdrom
($drive)) {
1424 if ($drive->{file
} =~ m
|^/|) {
1425 $path = $drive->{file
};
1426 if (my $info = path_is_scsi
($path)) {
1427 if ($info->{type
} == 0) {
1428 $devicetype = 'block';
1429 } elsif ($info->{type
} == 1) { # tape
1430 $devicetype = 'generic';
1434 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1437 if($path =~ m/^iscsi\:\/\
//){
1438 $devicetype = 'generic';
1442 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1443 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1445 $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}";
1448 } elsif ($drive->{interface
} eq 'ide'){
1450 my $controller = int($drive->{index} / $maxdev);
1451 my $unit = $drive->{index} % $maxdev;
1452 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1454 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1455 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1456 $model = URI
::Escape
::uri_unescape
($model);
1457 $device .= ",model=$model";
1459 } elsif ($drive->{interface
} eq 'sata'){
1460 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1461 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1462 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1463 } elsif ($drive->{interface
} eq 'usb') {
1465 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1467 die "unsupported interface type";
1470 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1475 sub get_initiator_name
{
1478 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1479 while (defined(my $line = <$fh>)) {
1480 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1489 sub print_drive_full
{
1490 my ($storecfg, $vmid, $drive) = @_;
1493 my $volid = $drive->{file
};
1496 if (drive_is_cdrom
($drive)) {
1497 $path = get_iso_path
($storecfg, $vmid, $volid);
1499 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1501 $path = PVE
::Storage
::path
($storecfg, $volid);
1502 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1503 $format = qemu_img_format
($scfg, $volname);
1511 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);
1512 foreach my $o (@qemu_drive_options) {
1513 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1515 if (my $serial = $drive->{serial
}) {
1516 $serial = URI
::Escape
::uri_unescape
($serial);
1517 $opts .= ",serial=$serial";
1520 $opts .= ",format=$format" if $format && !$drive->{format
};
1522 foreach my $o (qw(bps bps_rd bps_wr)) {
1523 my $v = $drive->{"m$o"};
1524 $opts .= ",$o=" . int($v*1024*1024) if $v;
1527 my $cache_direct = 0;
1529 if (my $cache = $drive->{cache
}) {
1530 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1531 } elsif (!drive_is_cdrom
($drive)) {
1532 $opts .= ",cache=none";
1536 # aio native works only with O_DIRECT
1537 if (!$drive->{aio
}) {
1539 $opts .= ",aio=native";
1541 $opts .= ",aio=threads";
1545 if (!drive_is_cdrom
($drive)) {
1547 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1548 $detectzeroes = 'off';
1549 } elsif ($drive->{discard
}) {
1550 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1552 # This used to be our default with discard not being specified:
1553 $detectzeroes = 'on';
1555 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1558 my $pathinfo = $path ?
"file=$path," : '';
1560 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1563 sub print_netdevice_full
{
1564 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1566 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1568 my $device = $net->{model
};
1569 if ($net->{model
} eq 'virtio') {
1570 $device = 'virtio-net-pci';
1573 my $pciaddr = print_pci_addr
("$netid", $bridges);
1574 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1575 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1576 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1577 my $vectors = $net->{queues
} * 2 + 2;
1578 $tmpstr .= ",vectors=$vectors,mq=on";
1580 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1582 if ($use_old_bios_files) {
1584 if ($device eq 'virtio-net-pci') {
1585 $romfile = 'pxe-virtio.rom';
1586 } elsif ($device eq 'e1000') {
1587 $romfile = 'pxe-e1000.rom';
1588 } elsif ($device eq 'ne2k') {
1589 $romfile = 'pxe-ne2k_pci.rom';
1590 } elsif ($device eq 'pcnet') {
1591 $romfile = 'pxe-pcnet.rom';
1592 } elsif ($device eq 'rtl8139') {
1593 $romfile = 'pxe-rtl8139.rom';
1595 $tmpstr .= ",romfile=$romfile" if $romfile;
1601 sub print_netdev_full
{
1602 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1605 if ($netid =~ m/^net(\d+)$/) {
1609 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1611 my $ifname = "tap${vmid}i$i";
1613 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1614 die "interface name '$ifname' is too long (max 15 character)\n"
1615 if length($ifname) >= 16;
1617 my $vhostparam = '';
1618 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1620 my $vmname = $conf->{name
} || "vm$vmid";
1623 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1625 if ($net->{bridge
}) {
1626 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1628 $netdev = "type=user,id=$netid,hostname=$vmname";
1631 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1636 sub drive_is_cdrom
{
1639 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1643 sub parse_number_sets
{
1646 foreach my $part (split(/;/, $set)) {
1647 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1648 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1649 push @$res, [ $1, $2 ];
1651 die "invalid range: $part\n";
1660 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1661 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1662 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1669 return undef if !$value;
1671 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1673 my @idlist = split(/;/, $res->{host
});
1674 delete $res->{host
};
1675 foreach my $id (@idlist) {
1676 if ($id =~ /^$PCIRE$/) {
1677 push @{$res->{pciid
}}, { id
=> $1, function
=> ($2//'0') };
1679 # should have been caught by parse_property_string already
1680 die "failed to parse PCI id: $id\n";
1686 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1690 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1695 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
() if !defined($res->{macaddr
});
1702 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1705 sub add_random_macs
{
1706 my ($settings) = @_;
1708 foreach my $opt (keys %$settings) {
1709 next if $opt !~ m/^net(\d+)$/;
1710 my $net = parse_net
($settings->{$opt});
1712 $settings->{$opt} = print_net
($net);
1716 sub vm_is_volid_owner
{
1717 my ($storecfg, $vmid, $volid) = @_;
1719 if ($volid !~ m
|^/|) {
1721 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1722 if ($owner && ($owner == $vmid)) {
1730 sub split_flagged_list
{
1731 my $text = shift || '';
1732 $text =~ s/[,;]/ /g;
1734 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1737 sub join_flagged_list
{
1738 my ($how, $lst) = @_;
1739 join $how, map { $lst->{$_} . $_ } keys %$lst;
1742 sub vmconfig_delete_pending_option
{
1743 my ($conf, $key, $force) = @_;
1745 delete $conf->{pending
}->{$key};
1746 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1747 $pending_delete_hash->{$key} = $force ?
'!' : '';
1748 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1751 sub vmconfig_undelete_pending_option
{
1752 my ($conf, $key) = @_;
1754 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1755 delete $pending_delete_hash->{$key};
1757 if (%$pending_delete_hash) {
1758 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1760 delete $conf->{pending
}->{delete};
1764 sub vmconfig_register_unused_drive
{
1765 my ($storecfg, $vmid, $conf, $drive) = @_;
1767 if (!drive_is_cdrom
($drive)) {
1768 my $volid = $drive->{file
};
1769 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1770 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1775 sub vmconfig_cleanup_pending
{
1778 # remove pending changes when nothing changed
1780 foreach my $opt (keys %{$conf->{pending
}}) {
1781 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1783 delete $conf->{pending
}->{$opt};
1787 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1788 my $pending_delete_hash = {};
1789 while (my ($opt, $force) = each %$current_delete_hash) {
1790 if (defined($conf->{$opt})) {
1791 $pending_delete_hash->{$opt} = $force;
1797 if (%$pending_delete_hash) {
1798 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1800 delete $conf->{pending
}->{delete};
1806 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1810 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1811 format_description
=> 'UUID',
1812 description
=> "Set SMBIOS1 UUID.",
1818 format_description
=> 'string',
1819 description
=> "Set SMBIOS1 version.",
1825 format_description
=> 'string',
1826 description
=> "Set SMBIOS1 serial number.",
1832 format_description
=> 'string',
1833 description
=> "Set SMBIOS1 manufacturer.",
1839 format_description
=> 'string',
1840 description
=> "Set SMBIOS1 product ID.",
1846 format_description
=> 'string',
1847 description
=> "Set SMBIOS1 SKU string.",
1853 format_description
=> 'string',
1854 description
=> "Set SMBIOS1 family string.",
1862 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1869 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1872 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1874 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1875 sub verify_bootdisk
{
1876 my ($value, $noerr) = @_;
1878 return $value if is_valid_drivename
($value);
1880 return undef if $noerr;
1882 die "invalid boot disk '$value'\n";
1885 sub parse_watchdog
{
1888 return undef if !$value;
1890 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1895 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1896 sub verify_usb_device
{
1897 my ($value, $noerr) = @_;
1899 return $value if parse_usb_device
($value);
1901 return undef if $noerr;
1903 die "unable to parse usb device\n";
1906 # add JSON properties for create and set function
1907 sub json_config_properties
{
1910 foreach my $opt (keys %$confdesc) {
1911 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1912 $prop->{$opt} = $confdesc->{$opt};
1919 my ($key, $value) = @_;
1921 die "unknown setting '$key'\n" if !$confdesc->{$key};
1923 my $type = $confdesc->{$key}->{type
};
1925 if (!defined($value)) {
1926 die "got undefined value\n";
1929 if ($value =~ m/[\n\r]/) {
1930 die "property contains a line feed\n";
1933 if ($type eq 'boolean') {
1934 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1935 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1936 die "type check ('boolean') failed - got '$value'\n";
1937 } elsif ($type eq 'integer') {
1938 return int($1) if $value =~ m/^(\d+)$/;
1939 die "type check ('integer') failed - got '$value'\n";
1940 } elsif ($type eq 'number') {
1941 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1942 die "type check ('number') failed - got '$value'\n";
1943 } elsif ($type eq 'string') {
1944 if (my $fmt = $confdesc->{$key}->{format
}) {
1945 if ($fmt eq 'pve-qm-drive') {
1946 # special case - we need to pass $key to parse_drive()
1947 my $drive = parse_drive
($key, $value);
1948 return $value if $drive;
1949 die "unable to parse drive options\n";
1951 PVE
::JSONSchema
::check_format
($fmt, $value);
1954 $value =~ s/^\"(.*)\"$/$1/;
1957 die "internal error"
1961 sub check_iommu_support
{
1962 #fixme : need to check IOMMU support
1963 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1973 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1974 utime undef, undef, $conf;
1978 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1980 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1982 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1984 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1986 # only remove disks owned by this VM
1987 foreach_drive
($conf, sub {
1988 my ($ds, $drive) = @_;
1990 return if drive_is_cdrom
($drive);
1992 my $volid = $drive->{file
};
1994 return if !$volid || $volid =~ m
|^/|;
1996 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1997 return if !$path || !$owner || ($owner != $vmid);
1999 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2002 if ($keep_empty_config) {
2003 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2008 # also remove unused disk
2010 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2013 PVE
::Storage
::foreach_volid
($dl, sub {
2014 my ($volid, $sid, $volname, $d) = @_;
2015 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2024 sub parse_vm_config
{
2025 my ($filename, $raw) = @_;
2027 return undef if !defined($raw);
2030 digest
=> Digest
::SHA
::sha1_hex
($raw),
2035 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2036 || die "got strange filename '$filename'";
2044 my @lines = split(/\n/, $raw);
2045 foreach my $line (@lines) {
2046 next if $line =~ m/^\s*$/;
2048 if ($line =~ m/^\[PENDING\]\s*$/i) {
2049 $section = 'pending';
2050 if (defined($descr)) {
2052 $conf->{description
} = $descr;
2055 $conf = $res->{$section} = {};
2058 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2060 if (defined($descr)) {
2062 $conf->{description
} = $descr;
2065 $conf = $res->{snapshots
}->{$section} = {};
2069 if ($line =~ m/^\#(.*)\s*$/) {
2070 $descr = '' if !defined($descr);
2071 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2075 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2076 $descr = '' if !defined($descr);
2077 $descr .= PVE
::Tools
::decode_text
($2);
2078 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2079 $conf->{snapstate
} = $1;
2080 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2083 $conf->{$key} = $value;
2084 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2086 if ($section eq 'pending') {
2087 $conf->{delete} = $value; # we parse this later
2089 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2091 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2094 eval { $value = check_type
($key, $value); };
2096 warn "vm $vmid - unable to parse value of '$key' - $@";
2098 my $fmt = $confdesc->{$key}->{format
};
2099 if ($fmt && $fmt eq 'pve-qm-drive') {
2100 my $v = parse_drive
($key, $value);
2101 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2102 $v->{file
} = $volid;
2103 $value = print_drive
($vmid, $v);
2105 warn "vm $vmid - unable to parse value of '$key'\n";
2110 if ($key eq 'cdrom') {
2111 $conf->{ide2
} = $value;
2113 $conf->{$key} = $value;
2119 if (defined($descr)) {
2121 $conf->{description
} = $descr;
2123 delete $res->{snapstate
}; # just to be sure
2128 sub write_vm_config
{
2129 my ($filename, $conf) = @_;
2131 delete $conf->{snapstate
}; # just to be sure
2133 if ($conf->{cdrom
}) {
2134 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2135 $conf->{ide2
} = $conf->{cdrom
};
2136 delete $conf->{cdrom
};
2139 # we do not use 'smp' any longer
2140 if ($conf->{sockets
}) {
2141 delete $conf->{smp
};
2142 } elsif ($conf->{smp
}) {
2143 $conf->{sockets
} = $conf->{smp
};
2144 delete $conf->{cores
};
2145 delete $conf->{smp
};
2148 my $used_volids = {};
2150 my $cleanup_config = sub {
2151 my ($cref, $pending, $snapname) = @_;
2153 foreach my $key (keys %$cref) {
2154 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2155 $key eq 'snapstate' || $key eq 'pending';
2156 my $value = $cref->{$key};
2157 if ($key eq 'delete') {
2158 die "propertry 'delete' is only allowed in [PENDING]\n"
2160 # fixme: check syntax?
2163 eval { $value = check_type
($key, $value); };
2164 die "unable to parse value of '$key' - $@" if $@;
2166 $cref->{$key} = $value;
2168 if (!$snapname && is_valid_drivename
($key)) {
2169 my $drive = parse_drive
($key, $value);
2170 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2175 &$cleanup_config($conf);
2177 &$cleanup_config($conf->{pending
}, 1);
2179 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2180 die "internal error" if $snapname eq 'pending';
2181 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2184 # remove 'unusedX' settings if we re-add a volume
2185 foreach my $key (keys %$conf) {
2186 my $value = $conf->{$key};
2187 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2188 delete $conf->{$key};
2192 my $generate_raw_config = sub {
2193 my ($conf, $pending) = @_;
2197 # add description as comment to top of file
2198 if (defined(my $descr = $conf->{description
})) {
2200 foreach my $cl (split(/\n/, $descr)) {
2201 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2204 $raw .= "#\n" if $pending;
2208 foreach my $key (sort keys %$conf) {
2209 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2210 $raw .= "$key: $conf->{$key}\n";
2215 my $raw = &$generate_raw_config($conf);
2217 if (scalar(keys %{$conf->{pending
}})){
2218 $raw .= "\n[PENDING]\n";
2219 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2222 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2223 $raw .= "\n[$snapname]\n";
2224 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2234 # we use static defaults from our JSON schema configuration
2235 foreach my $key (keys %$confdesc) {
2236 if (defined(my $default = $confdesc->{$key}->{default})) {
2237 $res->{$key} = $default;
2241 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2242 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2248 my $vmlist = PVE
::Cluster
::get_vmlist
();
2250 return $res if !$vmlist || !$vmlist->{ids
};
2251 my $ids = $vmlist->{ids
};
2253 foreach my $vmid (keys %$ids) {
2254 my $d = $ids->{$vmid};
2255 next if !$d->{node
} || $d->{node
} ne $nodename;
2256 next if !$d->{type
} || $d->{type
} ne 'qemu';
2257 $res->{$vmid}->{exists} = 1;
2262 # test if VM uses local resources (to prevent migration)
2263 sub check_local_resources
{
2264 my ($conf, $noerr) = @_;
2268 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2269 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2271 foreach my $k (keys %$conf) {
2272 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2273 # sockets are safe: they will recreated be on the target side post-migrate
2274 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2275 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2278 die "VM uses local resources\n" if $loc_res && !$noerr;
2283 # check if used storages are available on all nodes (use by migrate)
2284 sub check_storage_availability
{
2285 my ($storecfg, $conf, $node) = @_;
2287 foreach_drive
($conf, sub {
2288 my ($ds, $drive) = @_;
2290 my $volid = $drive->{file
};
2293 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2296 # check if storage is available on both nodes
2297 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2298 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2302 # list nodes where all VM images are available (used by has_feature API)
2304 my ($conf, $storecfg) = @_;
2306 my $nodelist = PVE
::Cluster
::get_nodelist
();
2307 my $nodehash = { map { $_ => 1 } @$nodelist };
2308 my $nodename = PVE
::INotify
::nodename
();
2310 foreach_drive
($conf, sub {
2311 my ($ds, $drive) = @_;
2313 my $volid = $drive->{file
};
2316 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2318 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2319 if ($scfg->{disable
}) {
2321 } elsif (my $avail = $scfg->{nodes
}) {
2322 foreach my $node (keys %$nodehash) {
2323 delete $nodehash->{$node} if !$avail->{$node};
2325 } elsif (!$scfg->{shared
}) {
2326 foreach my $node (keys %$nodehash) {
2327 delete $nodehash->{$node} if $node ne $nodename
2337 my ($pidfile, $pid) = @_;
2339 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2343 return undef if !$line;
2344 my @param = split(/\0/, $line);
2346 my $cmd = $param[0];
2347 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2349 for (my $i = 0; $i < scalar (@param); $i++) {
2352 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2353 my $p = $param[$i+1];
2354 return 1 if $p && ($p eq $pidfile);
2363 my ($vmid, $nocheck, $node) = @_;
2365 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2367 die "unable to find configuration file for VM $vmid - no such machine\n"
2368 if !$nocheck && ! -f
$filename;
2370 my $pidfile = pidfile_name
($vmid);
2372 if (my $fd = IO
::File-
>new("<$pidfile")) {
2377 my $mtime = $st->mtime;
2378 if ($mtime > time()) {
2379 warn "file '$filename' modified in future\n";
2382 if ($line =~ m/^(\d+)$/) {
2384 if (check_cmdline
($pidfile, $pid)) {
2385 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2397 my $vzlist = config_list
();
2399 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2401 while (defined(my $de = $fd->read)) {
2402 next if $de !~ m/^(\d+)\.pid$/;
2404 next if !defined($vzlist->{$vmid});
2405 if (my $pid = check_running
($vmid)) {
2406 $vzlist->{$vmid}->{pid
} = $pid;
2414 my ($storecfg, $conf) = @_;
2416 my $bootdisk = $conf->{bootdisk
};
2417 return undef if !$bootdisk;
2418 return undef if !is_valid_drivename
($bootdisk);
2420 return undef if !$conf->{$bootdisk};
2422 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2423 return undef if !defined($drive);
2425 return undef if drive_is_cdrom
($drive);
2427 my $volid = $drive->{file
};
2428 return undef if !$volid;
2430 return $drive->{size
};
2433 my $last_proc_pid_stat;
2435 # get VM status information
2436 # This must be fast and should not block ($full == false)
2437 # We only query KVM using QMP if $full == true (this can be slow)
2439 my ($opt_vmid, $full) = @_;
2443 my $storecfg = PVE
::Storage
::config
();
2445 my $list = vzlist
();
2446 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2448 my $cpucount = $cpuinfo->{cpus
} || 1;
2450 foreach my $vmid (keys %$list) {
2451 next if $opt_vmid && ($vmid ne $opt_vmid);
2453 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2454 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2457 $d->{pid
} = $list->{$vmid}->{pid
};
2459 # fixme: better status?
2460 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2462 my $size = disksize
($storecfg, $conf);
2463 if (defined($size)) {
2464 $d->{disk
} = 0; # no info available
2465 $d->{maxdisk
} = $size;
2471 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2472 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2473 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2475 $d->{name
} = $conf->{name
} || "VM $vmid";
2476 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2478 if ($conf->{balloon
}) {
2479 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2480 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2491 $d->{diskwrite
} = 0;
2493 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2498 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2499 foreach my $dev (keys %$netdev) {
2500 next if $dev !~ m/^tap([1-9]\d*)i/;
2502 my $d = $res->{$vmid};
2505 $d->{netout
} += $netdev->{$dev}->{receive
};
2506 $d->{netin
} += $netdev->{$dev}->{transmit
};
2509 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2510 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2515 my $ctime = gettimeofday
;
2517 foreach my $vmid (keys %$list) {
2519 my $d = $res->{$vmid};
2520 my $pid = $d->{pid
};
2523 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2524 next if !$pstat; # not running
2526 my $used = $pstat->{utime} + $pstat->{stime
};
2528 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2530 if ($pstat->{vsize
}) {
2531 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2534 my $old = $last_proc_pid_stat->{$pid};
2536 $last_proc_pid_stat->{$pid} = {
2544 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2546 if ($dtime > 1000) {
2547 my $dutime = $used - $old->{used
};
2549 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2550 $last_proc_pid_stat->{$pid} = {
2556 $d->{cpu
} = $old->{cpu
};
2560 return $res if !$full;
2562 my $qmpclient = PVE
::QMPClient-
>new();
2564 my $ballooncb = sub {
2565 my ($vmid, $resp) = @_;
2567 my $info = $resp->{'return'};
2568 return if !$info->{max_mem
};
2570 my $d = $res->{$vmid};
2572 # use memory assigned to VM
2573 $d->{maxmem
} = $info->{max_mem
};
2574 $d->{balloon
} = $info->{actual
};
2576 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2577 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2578 $d->{freemem
} = $info->{free_mem
};
2581 $d->{ballooninfo
} = $info;
2584 my $blockstatscb = sub {
2585 my ($vmid, $resp) = @_;
2586 my $data = $resp->{'return'} || [];
2587 my $totalrdbytes = 0;
2588 my $totalwrbytes = 0;
2590 for my $blockstat (@$data) {
2591 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2592 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2594 $blockstat->{device
} =~ s/drive-//;
2595 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2597 $res->{$vmid}->{diskread
} = $totalrdbytes;
2598 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2601 my $statuscb = sub {
2602 my ($vmid, $resp) = @_;
2604 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2605 # this fails if ballon driver is not loaded, so this must be
2606 # the last commnand (following command are aborted if this fails).
2607 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2609 my $status = 'unknown';
2610 if (!defined($status = $resp->{'return'}->{status
})) {
2611 warn "unable to get VM status\n";
2615 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2618 foreach my $vmid (keys %$list) {
2619 next if $opt_vmid && ($vmid ne $opt_vmid);
2620 next if !$res->{$vmid}->{pid
}; # not running
2621 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2624 $qmpclient->queue_execute(undef, 1);
2626 foreach my $vmid (keys %$list) {
2627 next if $opt_vmid && ($vmid ne $opt_vmid);
2628 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2635 my ($conf, $func, @param) = @_;
2637 foreach my $ds (valid_drive_names
()) {
2638 next if !defined($conf->{$ds});
2640 my $drive = parse_drive
($ds, $conf->{$ds});
2643 &$func($ds, $drive, @param);
2648 my ($conf, $func, @param) = @_;
2652 my $test_volid = sub {
2653 my ($volid, $is_cdrom) = @_;
2657 $volhash->{$volid} = $is_cdrom || 0;
2660 foreach_drive
($conf, sub {
2661 my ($ds, $drive) = @_;
2662 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2665 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2666 my $snap = $conf->{snapshots
}->{$snapname};
2667 &$test_volid($snap->{vmstate
}, 0);
2668 foreach_drive
($snap, sub {
2669 my ($ds, $drive) = @_;
2670 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2674 foreach my $volid (keys %$volhash) {
2675 &$func($volid, $volhash->{$volid}, @param);
2679 sub vga_conf_has_spice
{
2682 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2687 sub config_to_command
{
2688 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2691 my $globalFlags = [];
2692 my $machineFlags = [];
2698 my $kvmver = kvm_user_version
();
2699 my $vernum = 0; # unknown
2700 my $ostype = $conf->{ostype
};
2701 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2702 $vernum = $1*1000000+$2*1000;
2703 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2704 $vernum = $1*1000000+$2*1000+$3;
2707 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2709 my $have_ovz = -f
'/proc/vz/vestat';
2711 my $q35 = machine_type_is_q35
($conf);
2712 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2713 my $machine_type = $forcemachine || $conf->{machine
};
2714 my $use_old_bios_files = undef;
2715 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2717 my $cpuunits = defined($conf->{cpuunits
}) ?
2718 $conf->{cpuunits
} : $defaults->{cpuunits
};
2720 push @$cmd, '/usr/bin/kvm';
2722 push @$cmd, '-id', $vmid;
2726 my $qmpsocket = qmp_socket
($vmid);
2727 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2728 push @$cmd, '-mon', "chardev=qmp,mode=control";
2731 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2733 push @$cmd, '-daemonize';
2735 if ($conf->{smbios1
}) {
2736 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2739 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2740 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2741 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2742 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2743 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2744 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2745 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2749 # add usb controllers
2750 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2751 push @$devices, @usbcontrollers if @usbcontrollers;
2752 my $vga = $conf->{vga
};
2754 my $qxlnum = vga_conf_has_spice
($vga);
2755 $vga = 'qxl' if $qxlnum;
2758 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2759 $conf->{ostype
} eq 'win7' ||
2760 $conf->{ostype
} eq 'w2k8')) {
2767 # enable absolute mouse coordinates (needed by vnc)
2769 if (defined($conf->{tablet
})) {
2770 $tablet = $conf->{tablet
};
2772 $tablet = $defaults->{tablet
};
2773 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2774 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2777 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2781 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2782 my $d = parse_hostpci
($conf->{"hostpci$i"});
2785 my $pcie = $d->{pcie
};
2787 die "q35 machine model is not enabled" if !$q35;
2788 $pciaddr = print_pcie_addr
("hostpci$i");
2790 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2793 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2795 if ($d->{'x-vga'}) {
2796 $xvga = ',x-vga=on';
2799 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2800 push @$cpuFlags , 'hv_vendor_id=proxmox';
2802 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2806 my $pcidevices = $d->{pciid
};
2807 my $multifunction = 1 if @$pcidevices > 1;
2810 foreach my $pcidevice (@$pcidevices) {
2812 my $id = "hostpci$i";
2813 $id .= ".$j" if $multifunction;
2814 my $addr = $pciaddr;
2815 $addr .= ".$j" if $multifunction;
2816 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2819 $devicestr .= "$rombar$xvga";
2820 $devicestr .= ",multifunction=on" if $multifunction;
2823 push @$devices, '-device', $devicestr;
2829 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
2830 push @$devices, @usbdevices if @usbdevices;
2832 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2833 if (my $path = $conf->{"serial$i"}) {
2834 if ($path eq 'socket') {
2835 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2836 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2837 push @$devices, '-device', "isa-serial,chardev=serial$i";
2839 die "no such serial device\n" if ! -c
$path;
2840 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2841 push @$devices, '-device', "isa-serial,chardev=serial$i";
2847 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2848 if (my $path = $conf->{"parallel$i"}) {
2849 die "no such parallel device\n" if ! -c
$path;
2850 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2851 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2852 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2856 my $vmname = $conf->{name
} || "vm$vmid";
2858 push @$cmd, '-name', $vmname;
2861 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2862 $sockets = $conf->{sockets
} if $conf->{sockets
};
2864 my $cores = $conf->{cores
} || 1;
2866 my $maxcpus = $sockets * $cores;
2868 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2870 my $allowed_vcpus = $cpuinfo->{cpus
};
2872 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2873 if ($allowed_vcpus < $maxcpus);
2875 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2877 push @$cmd, '-nodefaults';
2879 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2881 my $bootindex_hash = {};
2883 foreach my $o (split(//, $bootorder)) {
2884 $bootindex_hash->{$o} = $i*100;
2888 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2890 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2892 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2894 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2896 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2897 my $socket = vnc_socket
($vmid);
2898 push @$cmd, '-vnc', "unix:$socket,x509,password";
2900 push @$cmd, '-nographic';
2904 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2906 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2907 my $useLocaltime = $conf->{localtime};
2910 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2912 if ($ostype =~ m/^w/) { # windows
2913 $useLocaltime = 1 if !defined($conf->{localtime});
2915 # use time drift fix when acpi is enabled
2916 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2917 $tdf = 1 if !defined($conf->{tdf
});
2921 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2922 $ostype eq 'wvista') {
2923 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2924 push @$cmd, '-no-hpet';
2925 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2926 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2927 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2928 push @$cpuFlags , 'hv_time' if !$nokvm;
2930 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
2931 push @$cpuFlags , 'hv_reset' if !$nokvm;
2932 push @$cpuFlags , 'hv_vpindex' if !$nokvm;
2933 push @$cpuFlags , 'hv_runtime' if !$nokvm;
2937 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2941 if ($ostype eq 'win7' || $ostype eq 'win8') {
2942 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2946 push @$rtcFlags, 'driftfix=slew' if $tdf;
2949 push @$machineFlags, 'accel=tcg';
2951 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2954 if ($machine_type) {
2955 push @$machineFlags, "type=${machine_type}";
2958 if ($conf->{startdate
}) {
2959 push @$rtcFlags, "base=$conf->{startdate}";
2960 } elsif ($useLocaltime) {
2961 push @$rtcFlags, 'base=localtime';
2964 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2965 if (my $cputype = $conf->{cpu
}) {
2966 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
2967 or die "Cannot parse cpu description: $cputype\n";
2968 $cpu = $cpuconf->{cputype
};
2969 $kvm_off = 1 if $cpuconf->{hidden
};
2972 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2974 push @$cpuFlags , '-x2apic'
2975 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2977 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2979 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2981 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2983 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2984 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2987 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2989 push @$cpuFlags, 'kvm=off' if $kvm_off;
2991 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
2992 die "internal error"; # should not happen
2994 push @$cpuFlags, "vendor=${cpu_vendor}"
2995 if $cpu_vendor ne 'default';
2997 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2999 push @$cmd, '-cpu', $cpu;
3001 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3003 push @$cmd, '-S' if $conf->{freeze
};
3005 # set keyboard layout
3006 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3007 push @$cmd, '-k', $kb if $kb;
3010 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3011 #push @$cmd, '-soundhw', 'es1370';
3012 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3014 if($conf->{agent
}) {
3015 my $qgasocket = qmp_socket
($vmid, 1);
3016 my $pciaddr = print_pci_addr
("qga0", $bridges);
3017 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3018 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3019 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3026 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3027 for(my $i = 1; $i < $qxlnum; $i++){
3028 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3029 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3032 # assume other OS works like Linux
3033 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3034 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3038 my $pciaddr = print_pci_addr
("spice", $bridges);
3040 my $nodename = PVE
::INotify
::nodename
();
3041 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3042 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3044 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3046 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3047 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3048 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3051 # enable balloon by default, unless explicitly disabled
3052 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3053 $pciaddr = print_pci_addr
("balloon0", $bridges);
3054 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3057 if ($conf->{watchdog
}) {
3058 my $wdopts = parse_watchdog
($conf->{watchdog
});
3059 $pciaddr = print_pci_addr
("watchdog", $bridges);
3060 my $watchdog = $wdopts->{model
} || 'i6300esb';
3061 push @$devices, '-device', "$watchdog$pciaddr";
3062 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3066 my $scsicontroller = {};
3067 my $ahcicontroller = {};
3068 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3070 # Add iscsi initiator name if available
3071 if (my $initiator = get_initiator_name
()) {
3072 push @$devices, '-iscsi', "initiator-name=$initiator";
3075 foreach_drive
($conf, sub {
3076 my ($ds, $drive) = @_;
3078 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3079 push @$vollist, $drive->{file
};
3082 $use_virtio = 1 if $ds =~ m/^virtio/;
3084 if (drive_is_cdrom
($drive)) {
3085 if ($bootindex_hash->{d
}) {
3086 $drive->{bootindex
} = $bootindex_hash->{d
};
3087 $bootindex_hash->{d
} += 1;
3090 if ($bootindex_hash->{c
}) {
3091 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3092 $bootindex_hash->{c
} += 1;
3096 if($drive->{interface
} eq 'virtio'){
3097 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3100 if ($drive->{interface
} eq 'scsi') {
3102 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3104 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3105 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3108 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3109 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3110 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3111 } elsif ($drive->{iothread
}) {
3112 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3116 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3117 $queues = ",num_queues=$drive->{queues}";
3120 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3121 $scsicontroller->{$controller}=1;
3124 if ($drive->{interface
} eq 'sata') {
3125 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3126 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3127 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3128 $ahcicontroller->{$controller}=1;
3131 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3132 push @$devices, '-drive',$drive_cmd;
3133 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3136 for (my $i = 0; $i < $MAX_NETS; $i++) {
3137 next if !$conf->{"net$i"};
3138 my $d = parse_net
($conf->{"net$i"});
3141 $use_virtio = 1 if $d->{model
} eq 'virtio';
3143 if ($bootindex_hash->{n
}) {
3144 $d->{bootindex
} = $bootindex_hash->{n
};
3145 $bootindex_hash->{n
} += 1;
3148 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3149 push @$devices, '-netdev', $netdevfull;
3151 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3152 push @$devices, '-device', $netdevicefull;
3157 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3162 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3164 while (my ($k, $v) = each %$bridges) {
3165 $pciaddr = print_pci_addr
("pci.$k");
3166 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3171 if ($conf->{args
}) {
3172 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3176 push @$cmd, @$devices;
3177 push @$cmd, '-rtc', join(',', @$rtcFlags)
3178 if scalar(@$rtcFlags);
3179 push @$cmd, '-machine', join(',', @$machineFlags)
3180 if scalar(@$machineFlags);
3181 push @$cmd, '-global', join(',', @$globalFlags)
3182 if scalar(@$globalFlags);
3184 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3189 return "${var_run_tmpdir}/$vmid.vnc";
3195 my $res = vm_mon_cmd
($vmid, 'query-spice');
3197 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3201 my ($vmid, $qga) = @_;
3202 my $sockettype = $qga ?
'qga' : 'qmp';
3203 return "${var_run_tmpdir}/$vmid.$sockettype";
3208 return "${var_run_tmpdir}/$vmid.pid";
3211 sub vm_devices_list
{
3214 my $res = vm_mon_cmd
($vmid, 'query-pci');
3216 foreach my $pcibus (@$res) {
3217 foreach my $device (@{$pcibus->{devices
}}) {
3218 next if !$device->{'qdev_id'};
3219 if ($device->{'pci_bridge'}) {
3220 $devices->{$device->{'qdev_id'}} = 1;
3221 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3222 next if !$bridge_device->{'qdev_id'};
3223 $devices->{$bridge_device->{'qdev_id'}} = 1;
3224 $devices->{$device->{'qdev_id'}}++;
3227 $devices->{$device->{'qdev_id'}} = 1;
3232 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3233 foreach my $block (@$resblock) {
3234 if($block->{device
} =~ m/^drive-(\S+)/){
3239 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3240 foreach my $mice (@$resmice) {
3241 if ($mice->{name
} eq 'QEMU HID Tablet') {
3242 $devices->{tablet
} = 1;
3247 # for usb devices there is no query-usb
3248 # but we can iterate over the entries in
3249 # qom-list path=/machine/peripheral
3250 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3251 foreach my $per (@$resperipheral) {
3252 if ($per->{name
} =~ m/^usb\d+$/) {
3253 $devices->{$per->{name
}} = 1;
3261 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3263 my $q35 = machine_type_is_q35
($conf);
3265 my $devices_list = vm_devices_list
($vmid);
3266 return 1 if defined($devices_list->{$deviceid});
3268 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3270 if ($deviceid eq 'tablet') {
3272 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3274 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3276 qemu_iothread_add
($vmid, $deviceid, $device);
3278 qemu_driveadd
($storecfg, $vmid, $device);
3279 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3281 qemu_deviceadd
($vmid, $devicefull);
3282 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3284 eval { qemu_drivedel
($vmid, $deviceid); };
3289 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3292 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3293 my $pciaddr = print_pci_addr
($deviceid);
3294 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3296 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3298 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3299 qemu_iothread_add
($vmid, $deviceid, $device);
3300 $devicefull .= ",iothread=iothread-$deviceid";
3303 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3304 $devicefull .= ",num_queues=$device->{queues}";
3307 qemu_deviceadd
($vmid, $devicefull);
3308 qemu_deviceaddverify
($vmid, $deviceid);
3310 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3312 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3313 qemu_driveadd
($storecfg, $vmid, $device);
3315 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3316 eval { qemu_deviceadd
($vmid, $devicefull); };
3318 eval { qemu_drivedel
($vmid, $deviceid); };
3323 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3325 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3327 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3328 my $use_old_bios_files = undef;
3329 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3331 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3332 qemu_deviceadd
($vmid, $netdevicefull);
3333 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3335 eval { qemu_netdevdel
($vmid, $deviceid); };
3340 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3343 my $pciaddr = print_pci_addr
($deviceid);
3344 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3346 qemu_deviceadd
($vmid, $devicefull);
3347 qemu_deviceaddverify
($vmid, $deviceid);
3350 die "can't hotplug device '$deviceid'\n";
3356 # fixme: this should raise exceptions on error!
3357 sub vm_deviceunplug
{
3358 my ($vmid, $conf, $deviceid) = @_;
3360 my $devices_list = vm_devices_list
($vmid);
3361 return 1 if !defined($devices_list->{$deviceid});
3363 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3365 if ($deviceid eq 'tablet') {
3367 qemu_devicedel
($vmid, $deviceid);
3369 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3371 qemu_devicedel
($vmid, $deviceid);
3372 qemu_devicedelverify
($vmid, $deviceid);
3373 qemu_drivedel
($vmid, $deviceid);
3374 qemu_iothread_del
($conf, $vmid, $deviceid);
3376 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3378 qemu_devicedel
($vmid, $deviceid);
3379 qemu_devicedelverify
($vmid, $deviceid);
3380 qemu_iothread_del
($conf, $vmid, $deviceid);
3382 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3384 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3385 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3386 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3388 qemu_devicedel
($vmid, $deviceid);
3389 qemu_drivedel
($vmid, $deviceid);
3390 qemu_deletescsihw
($conf, $vmid, $deviceid);
3392 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3394 qemu_devicedel
($vmid, $deviceid);
3395 qemu_devicedelverify
($vmid, $deviceid);
3396 qemu_netdevdel
($vmid, $deviceid);
3399 die "can't unplug device '$deviceid'\n";
3405 sub qemu_deviceadd
{
3406 my ($vmid, $devicefull) = @_;
3408 $devicefull = "driver=".$devicefull;
3409 my %options = split(/[=,]/, $devicefull);
3411 vm_mon_cmd
($vmid, "device_add" , %options);
3414 sub qemu_devicedel
{
3415 my ($vmid, $deviceid) = @_;
3417 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3420 sub qemu_iothread_add
{
3421 my($vmid, $deviceid, $device) = @_;
3423 if ($device->{iothread
}) {
3424 my $iothreads = vm_iothreads_list
($vmid);
3425 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3429 sub qemu_iothread_del
{
3430 my($conf, $vmid, $deviceid) = @_;
3432 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3433 if ($device->{iothread
}) {
3434 my $iothreads = vm_iothreads_list
($vmid);
3435 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3439 sub qemu_objectadd
{
3440 my($vmid, $objectid, $qomtype) = @_;
3442 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3447 sub qemu_objectdel
{
3448 my($vmid, $objectid) = @_;
3450 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3456 my ($storecfg, $vmid, $device) = @_;
3458 my $drive = print_drive_full
($storecfg, $vmid, $device);
3459 $drive =~ s/\\/\\\\/g;
3460 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3462 # If the command succeeds qemu prints: "OK
"
3463 return 1 if $ret =~ m/OK/s;
3465 die "adding drive failed
: $ret\n";
3469 my($vmid, $deviceid) = @_;
3471 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3474 return 1 if $ret eq "";
3476 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3477 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3479 die "deleting drive
$deviceid failed
: $ret\n";
3482 sub qemu_deviceaddverify {
3483 my ($vmid, $deviceid) = @_;
3485 for (my $i = 0; $i <= 5; $i++) {
3486 my $devices_list = vm_devices_list($vmid);
3487 return 1 if defined($devices_list->{$deviceid});
3491 die "error on hotplug device
'$deviceid'\n";
3495 sub qemu_devicedelverify {
3496 my ($vmid, $deviceid) = @_;
3498 # need to verify that the device is correctly removed as device_del
3499 # is async and empty return is not reliable
3501 for (my $i = 0; $i <= 5; $i++) {
3502 my $devices_list = vm_devices_list($vmid);
3503 return 1 if !defined($devices_list->{$deviceid});
3507 die "error on hot-unplugging device
'$deviceid'\n";
3510 sub qemu_findorcreatescsihw {
3511 my ($storecfg, $conf, $vmid, $device) = @_;
3513 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3515 my $scsihwid="$controller_prefix$controller";
3516 my $devices_list = vm_devices_list($vmid);
3518 if(!defined($devices_list->{$scsihwid})) {
3519 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3525 sub qemu_deletescsihw {
3526 my ($conf, $vmid, $opt) = @_;
3528 my $device = parse_drive($opt, $conf->{$opt});
3530 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3531 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3535 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3537 my $devices_list = vm_devices_list($vmid);
3538 foreach my $opt (keys %{$devices_list}) {
3539 if (PVE::QemuServer::is_valid_drivename($opt)) {
3540 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3541 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3547 my $scsihwid="scsihw
$controller";
3549 vm_deviceunplug($vmid, $conf, $scsihwid);
3554 sub qemu_add_pci_bridge {
3555 my ($storecfg, $conf, $vmid, $device) = @_;
3561 print_pci_addr($device, $bridges);
3563 while (my ($k, $v) = each %$bridges) {
3566 return 1 if !defined($bridgeid) || $bridgeid < 1;
3568 my $bridge = "pci
.$bridgeid";
3569 my $devices_list = vm_devices_list($vmid);
3571 if (!defined($devices_list->{$bridge})) {
3572 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3578 sub qemu_set_link_status {
3579 my ($vmid, $device, $up) = @_;
3581 vm_mon_cmd($vmid, "set_link
", name => $device,
3582 up => $up ? JSON::true : JSON::false);
3585 sub qemu_netdevadd {
3586 my ($vmid, $conf, $device, $deviceid) = @_;
3588 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3589 my %options = split(/[=,]/, $netdev);
3591 vm_mon_cmd($vmid, "netdev_add
", %options);
3595 sub qemu_netdevdel {
3596 my ($vmid, $deviceid) = @_;
3598 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3601 sub qemu_usb_hotplug {
3602 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3606 # remove the old one first
3607 vm_deviceunplug($vmid, $conf, $deviceid);
3609 # check if xhci controller is necessary and available
3610 if ($device->{usb3}) {
3612 my $devicelist = vm_devices_list($vmid);
3614 if (!$devicelist->{xhci}) {
3615 my $pciaddr = print_pci_addr("xhci
");
3616 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3619 my $d = parse_usb_device($device->{host});
3620 $d->{usb3} = $device->{usb3};
3623 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3626 sub qemu_cpu_hotplug {
3627 my ($vmid, $conf, $vcpus) = @_;
3630 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3631 $sockets = $conf->{sockets} if $conf->{sockets};
3632 my $cores = $conf->{cores} || 1;
3633 my $maxcpus = $sockets * $cores;
3635 $vcpus = $maxcpus if !$vcpus;
3637 die "you can
't add more vcpus than maxcpus\n"
3638 if $vcpus > $maxcpus;
3640 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3641 die "online cpu unplug is not yet possible\n"
3642 if $vcpus < $currentvcpus;
3644 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3645 die "vcpus in running vm is different than configuration\n"
3646 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3648 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3649 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3653 sub qemu_block_set_io_throttle {
3654 my ($vmid, $deviceid,
3655 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3656 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3658 return if !check_running($vmid) ;
3660 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3662 bps_rd => int($bps_rd),
3663 bps_wr => int($bps_wr),
3665 iops_rd => int($iops_rd),
3666 iops_wr => int($iops_wr),
3667 bps_max => int($bps_max),
3668 bps_rd_max => int($bps_rd_max),
3669 bps_wr_max => int($bps_wr_max),
3670 iops_max => int($iops_max),
3671 iops_rd_max => int($iops_rd_max),
3672 iops_wr_max => int($iops_wr_max)
3677 # old code, only used to shutdown old VM after update
3679 my ($fh, $timeout) = @_;
3681 my $sel = new IO::Select;
3688 while (scalar (@ready = $sel->can_read($timeout))) {
3690 if ($count = $fh->sysread($buf, 8192)) {
3691 if ($buf =~ /^(.*)\(qemu\) $/s) {
3698 if (!defined($count)) {
3705 die "monitor read timeout\n" if !scalar(@ready);
3710 # old code, only used to shutdown old VM after update
3711 sub vm_monitor_command {
3712 my ($vmid, $cmdstr, $nocheck) = @_;
3717 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3719 my $sname = "${var_run_tmpdir}/$vmid.mon";
3721 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3722 die "unable to connect to VM $vmid socket - $!\n";
3726 # hack: migrate sometime blocks the monitor (when migrate_downtime
3728 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3729 $timeout = 60*60; # 1 hour
3733 my $data = __read_avail($sock, $timeout);
3735 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3736 die "got unexpected qemu monitor banner\n";
3739 my $sel = new IO::Select;
3742 if (!scalar(my @ready = $sel->can_write($timeout))) {
3743 die "monitor write error - timeout";
3746 my $fullcmd = "$cmdstr\r";
3748 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3751 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3752 die "monitor write error - $!";
3755 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3759 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3760 $timeout = 60*60; # 1 hour
3761 } elsif ($cmdstr =~ m/^(eject|change)/) {
3762 $timeout = 60; # note: cdrom mount command is slow
3764 if ($res = __read_avail($sock, $timeout)) {
3766 my @lines = split("\r?\n", $res);
3768 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3770 $res = join("\n", @lines);
3778 syslog("err", "VM $vmid monitor command failed - $err");
3785 sub qemu_block_resize {
3786 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3788 my $running = check_running($vmid);
3790 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3792 return if !$running;
3794 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
3798 sub qemu_volume_snapshot {
3799 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3801 my $running = check_running($vmid);
3803 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3804 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
3806 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3810 sub qemu_volume_snapshot_delete {
3811 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3813 my $running = check_running($vmid);
3815 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3817 return if !$running;
3819 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
3822 sub set_migration_caps {
3828 "auto-converge" => 1,
3830 "x-rdma-pin-all" => 0,
3835 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
3837 for my $supported_capability (@$supported_capabilities) {
3839 capability => $supported_capability->{capability},
3840 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3844 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
3847 my $fast_plug_option = {
3856 # hotplug changes in [PENDING]
3857 # $selection hash can be used to only apply specified options, for
3858 # example: { cores => 1 } (only apply changed 'cores
')
3859 # $errors ref is used to return error messages
3860 sub vmconfig_hotplug_pending {
3861 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3863 my $defaults = load_defaults();
3865 # commit values which do not have any impact on running VM first
3866 # Note: those option cannot raise errors, we we do not care about
3867 # $selection and always apply them.
3869 my $add_error = sub {
3870 my ($opt, $msg) = @_;
3871 $errors->{$opt} = "hotplug problem - $msg";
3875 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3876 if ($fast_plug_option->{$opt}) {
3877 $conf->{$opt} = $conf->{pending}->{$opt};
3878 delete $conf->{pending}->{$opt};
3884 PVE::QemuConfig->write_config($vmid, $conf);
3885 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3888 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3890 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
3891 while (my ($opt, $force) = each %$pending_delete_hash) {
3892 next if $selection && !$selection->{$opt};
3894 if ($opt eq 'hotplug
') {
3895 die "skip\n" if ($conf->{hotplug} =~ /memory/);
3896 } elsif ($opt eq 'tablet
') {
3897 die "skip\n" if !$hotplug_features->{usb};
3898 if ($defaults->{tablet}) {
3899 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3901 vm_deviceunplug($vmid, $conf, $opt);
3903 } elsif ($opt eq 'vcpus
') {
3904 die "skip\n" if !$hotplug_features->{cpu};
3905 qemu_cpu_hotplug($vmid, $conf, undef);
3906 } elsif ($opt eq 'balloon
') {
3907 # enable balloon device is not hotpluggable
3908 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
3909 } elsif ($fast_plug_option->{$opt}) {
3911 } elsif ($opt =~ m/^net(\d+)$/) {
3912 die "skip\n" if !$hotplug_features->{network};
3913 vm_deviceunplug($vmid, $conf, $opt);
3914 } elsif (is_valid_drivename($opt)) {
3915 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3916 vm_deviceunplug($vmid, $conf, $opt);
3917 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
3918 } elsif ($opt =~ m/^memory$/) {
3919 die "skip\n" if !$hotplug_features->{memory};
3920 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3921 } elsif ($opt eq 'cpuunits
') {
3922 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
3923 } elsif ($opt eq 'cpulimit
') {
3924 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
3930 &$add_error($opt, $err) if $err ne "skip\n";
3932 # save new config if hotplug was successful
3933 delete $conf->{$opt};
3934 vmconfig_undelete_pending_option($conf, $opt);
3935 PVE::QemuConfig->write_config($vmid, $conf);
3936 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3940 foreach my $opt (keys %{$conf->{pending}}) {
3941 next if $selection && !$selection->{$opt};
3942 my $value = $conf->{pending}->{$opt};
3944 if ($opt eq 'hotplug
') {
3945 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3946 } elsif ($opt eq 'tablet
') {
3947 die "skip\n" if !$hotplug_features->{usb};
3949 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3950 } elsif ($value == 0) {
3951 vm_deviceunplug($vmid, $conf, $opt);
3953 } elsif ($opt eq 'vcpus
') {
3954 die "skip\n" if !$hotplug_features->{cpu};
3955 qemu_cpu_hotplug($vmid, $conf, $value);
3956 } elsif ($opt eq 'balloon
') {
3957 # enable/disable balloning device is not hotpluggable
3958 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3959 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3960 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
3962 # allow manual ballooning if shares is set to zero
3963 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3964 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3965 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
3967 } elsif ($opt =~ m/^net(\d+)$/) {
3968 # some changes can be done without hotplug
3969 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3970 $vmid, $opt, $value);
3971 } elsif (is_valid_drivename($opt)) {
3972 # some changes can be done without hotplug
3973 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
3974 $vmid, $opt, $value, 1);
3975 } elsif ($opt =~ m/^memory$/) { #dimms
3976 die "skip\n" if !$hotplug_features->{memory};
3977 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
3978 } elsif ($opt eq 'cpuunits
') {
3979 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
3980 } elsif ($opt eq 'cpulimit
') {
3981 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
3982 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
3984 die "skip\n"; # skip non-hot-pluggable options
3988 &$add_error($opt, $err) if $err ne "skip\n";
3990 # save new config if hotplug was successful
3991 $conf->{$opt} = $value;
3992 delete $conf->{pending}->{$opt};
3993 PVE::QemuConfig->write_config($vmid, $conf);
3994 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
3999 sub try_deallocate_drive {
4000 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4002 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4003 my $volid = $drive->{file};
4004 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4005 my $sid = PVE::Storage::parse_volume_id($volid);
4006 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4008 # check if the disk is really unused
4009 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4010 if is_volume_in_use($storecfg, $conf, $key, $volid);
4011 PVE::Storage::vdisk_free($storecfg, $volid);
4014 # If vm is not owner of this disk remove from config
4022 sub vmconfig_delete_or_detach_drive {
4023 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4025 my $drive = parse_drive($opt, $conf->{$opt});
4027 my $rpcenv = PVE::RPCEnvironment::get();
4028 my $authuser = $rpcenv->get_user();
4031 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4032 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4034 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4038 sub vmconfig_apply_pending {
4039 my ($vmid, $conf, $storecfg) = @_;
4043 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4044 while (my ($opt, $force) = each %$pending_delete_hash) {
4045 die "internal error" if $opt =~ m/^unused/;
4046 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4047 if (!defined($conf->{$opt})) {
4048 vmconfig_undelete_pending_option($conf, $opt);
4049 PVE::QemuConfig->write_config($vmid, $conf);
4050 } elsif (is_valid_drivename($opt)) {
4051 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4052 vmconfig_undelete_pending_option($conf, $opt);
4053 delete $conf->{$opt};
4054 PVE::QemuConfig->write_config($vmid, $conf);
4056 vmconfig_undelete_pending_option($conf, $opt);
4057 delete $conf->{$opt};
4058 PVE::QemuConfig->write_config($vmid, $conf);
4062 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4064 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4065 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4067 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4068 # skip if nothing changed
4069 } elsif (is_valid_drivename($opt)) {
4070 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4071 if defined($conf->{$opt});
4072 $conf->{$opt} = $conf->{pending}->{$opt};
4074 $conf->{$opt} = $conf->{pending}->{$opt};
4077 delete $conf->{pending}->{$opt};
4078 PVE::QemuConfig->write_config($vmid, $conf);
4082 my $safe_num_ne = sub {
4085 return 0 if !defined($a) && !defined($b);
4086 return 1 if !defined($a);
4087 return 1 if !defined($b);
4092 my $safe_string_ne = sub {
4095 return 0 if !defined($a) && !defined($b);
4096 return 1 if !defined($a);
4097 return 1 if !defined($b);
4102 sub vmconfig_update_net {
4103 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4105 my $newnet = parse_net($value);
4107 if ($conf->{$opt}) {
4108 my $oldnet = parse_net($conf->{$opt});
4110 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4111 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4112 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4113 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4115 # for non online change, we try to hot-unplug
4116 die "skip\n" if !$hotplug;
4117 vm_deviceunplug($vmid, $conf, $opt);
4120 die "internal error" if $opt !~ m/net(\d+)/;
4121 my $iface = "tap${vmid}i$1";
4123 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4124 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4125 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4126 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4127 PVE::Network::tap_unplug($iface);
4128 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4129 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4130 # Rate can be applied on its own but any change above needs to
4131 # include the rate in tap_plug since OVS resets everything.
4132 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4135 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4136 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4144 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4150 sub vmconfig_update_disk {
4151 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4153 # fixme: do we need force?
4155 my $drive = parse_drive($opt, $value);
4157 if ($conf->{$opt}) {
4159 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4161 my $media = $drive->{media} || 'disk
';
4162 my $oldmedia = $old_drive->{media} || 'disk
';
4163 die "unable to change media type\n" if $media ne $oldmedia;
4165 if (!drive_is_cdrom($old_drive)) {
4167 if ($drive->{file} ne $old_drive->{file}) {
4169 die "skip\n" if !$hotplug;
4171 # unplug and register as unused
4172 vm_deviceunplug($vmid, $conf, $opt);
4173 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4176 # update existing disk
4178 # skip non hotpluggable value
4179 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4180 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4181 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4182 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4187 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4188 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4189 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4190 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4191 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4192 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4193 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4194 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4195 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4196 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4197 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4198 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4200 qemu_block_set_io_throttle($vmid,"drive-$opt",
4201 ($drive->{mbps} || 0)*1024*1024,
4202 ($drive->{mbps_rd} || 0)*1024*1024,
4203 ($drive->{mbps_wr} || 0)*1024*1024,
4204 $drive->{iops} || 0,
4205 $drive->{iops_rd} || 0,
4206 $drive->{iops_wr} || 0,
4207 ($drive->{mbps_max} || 0)*1024*1024,
4208 ($drive->{mbps_rd_max} || 0)*1024*1024,
4209 ($drive->{mbps_wr_max} || 0)*1024*1024,
4210 $drive->{iops_max} || 0,
4211 $drive->{iops_rd_max} || 0,
4212 $drive->{iops_wr_max} || 0);
4221 if ($drive->{file} eq 'none
') {
4222 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4224 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4225 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4226 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4234 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4236 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4237 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4241 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4242 $forcemachine, $spice_ticket) = @_;
4244 PVE::QemuConfig->lock_config($vmid, sub {
4245 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4247 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4249 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4251 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4253 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4254 vmconfig_apply_pending($vmid, $conf, $storecfg);
4255 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4258 my $defaults = load_defaults();
4260 # set environment variable useful inside network script
4261 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4263 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4265 my $migrate_port = 0;
4268 if ($statefile eq 'tcp
') {
4269 my $localip = "localhost";
4270 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4271 my $nodename = PVE::INotify::nodename();
4272 if ($datacenterconf->{migration_unsecure}) {
4273 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4274 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4276 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4277 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4278 $migrate_uri = "tcp:${localip}:${migrate_port}";
4279 push @$cmd, '-incoming
', $migrate_uri;
4282 } elsif ($statefile eq 'unix
') {
4283 # should be default for secure migrations as a ssh TCP forward
4284 # tunnel is not deterministic reliable ready and fails regurarly
4285 # to set up in time, so use UNIX socket forwards
4286 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4287 unlink $socket_addr;
4289 $migrate_uri = "unix:$socket_addr";
4291 push @$cmd, '-incoming
', $migrate_uri;
4295 push @$cmd, '-loadstate
', $statefile;
4302 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4303 my $d = parse_hostpci($conf->{"hostpci$i"});
4305 my $pcidevices = $d->{pciid};
4306 foreach my $pcidevice (@$pcidevices) {
4307 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4309 my $info = pci_device_info("0000:$pciid");
4310 die "IOMMU not present\n" if !check_iommu_support();
4311 die "no pci device info for device '$pciid'\n" if !$info;
4312 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4313 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4317 PVE::Storage::activate_volumes($storecfg, $vollist);
4319 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4321 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4322 eval { run_command($cmd); };
4325 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4326 : $defaults->{cpuunits};
4328 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4331 Slice => 'qemu
.slice
',
4333 CPUShares => $cpuunits
4336 if (my $cpulimit = $conf->{cpulimit}) {
4337 $properties{CPUQuota} = int($cpulimit * 100);
4339 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4341 if ($conf->{hugepages}) {
4344 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4345 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4347 PVE::QemuServer::Memory::hugepages_mount();
4348 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4351 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4352 run_command($cmd, %run_params);
4356 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4360 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4362 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4366 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4367 run_command($cmd, %run_params);
4372 # deactivate volumes if start fails
4373 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4374 die "start failed: $err";
4377 print "migration listens on $migrate_uri\n" if $migrate_uri;
4379 if ($statefile && $statefile ne 'tcp
') {
4380 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4384 if ($migratedfrom) {
4387 set_migration_caps($vmid);
4392 print "spice listens on port $spice_port\n";
4393 if ($spice_ticket) {
4394 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4395 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4401 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4402 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4403 if $conf->{balloon};
4406 foreach my $opt (keys %$conf) {
4407 next if $opt !~ m/^net\d+$/;
4408 my $nicconf = parse_net($conf->{$opt});
4409 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4413 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4414 path => "machine/peripheral/balloon0",
4415 property => "guest-stats-polling-interval",
4416 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4422 my ($vmid, $execute, %params) = @_;
4424 my $cmd = { execute => $execute, arguments => \%params };
4425 vm_qmp_command($vmid, $cmd);
4428 sub vm_mon_cmd_nocheck {
4429 my ($vmid, $execute, %params) = @_;
4431 my $cmd = { execute => $execute, arguments => \%params };
4432 vm_qmp_command($vmid, $cmd, 1);
4435 sub vm_qmp_command {
4436 my ($vmid, $cmd, $nocheck) = @_;
4441 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4442 $timeout = $cmd->{arguments}->{timeout};
4443 delete $cmd->{arguments}->{timeout};
4447 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4448 my $sname = qmp_socket($vmid);
4449 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4450 my $qmpclient = PVE::QMPClient->new();
4452 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4453 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4454 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4455 if scalar(%{$cmd->{arguments}});
4456 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4458 die "unable to
open monitor
socket\n";
4462 syslog("err
", "VM
$vmid qmp command failed
- $err");
4469 sub vm_human_monitor_command {
4470 my ($vmid, $cmdline) = @_;
4475 execute => 'human-monitor-command',
4476 arguments => { 'command-line' => $cmdline},
4479 return vm_qmp_command($vmid, $cmd);
4482 sub vm_commandline {
4483 my ($storecfg, $vmid) = @_;
4485 my $conf = PVE::QemuConfig->load_config($vmid);
4487 my $defaults = load_defaults();
4489 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4491 return join(' ', @$cmd);
4495 my ($vmid, $skiplock) = @_;
4497 PVE::QemuConfig->lock_config($vmid, sub {
4499 my $conf = PVE::QemuConfig->load_config($vmid);
4501 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4503 vm_mon_cmd($vmid, "system_reset
");
4507 sub get_vm_volumes {
4511 foreach_volid($conf, sub {
4512 my ($volid, $is_cdrom) = @_;
4514 return if $volid =~ m|^/|;
4516 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4519 push @$vollist, $volid;
4525 sub vm_stop_cleanup {
4526 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4531 my $vollist = get_vm_volumes($conf);
4532 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4535 foreach my $ext (qw(mon qmp pid vnc qga)) {
4536 unlink "/var/run/qemu-server/${vmid}.$ext";
4539 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4541 warn $@ if $@; # avoid errors - just warn
4544 # Note: use $nockeck to skip tests if VM configuration file exists.
4545 # We need that when migration VMs to other nodes (files already moved)
4546 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4548 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4550 $force = 1 if !defined($force) && !$shutdown;
4553 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4554 kill 15, $pid if $pid;
4555 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4556 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4560 PVE
::QemuConfig-
>lock_config($vmid, sub {
4562 my $pid = check_running
($vmid, $nocheck);
4567 $conf = PVE
::QemuConfig-
>load_config($vmid);
4568 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4569 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4570 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4571 $timeout = $opts->{down
} if $opts->{down
};
4575 $timeout = 60 if !defined($timeout);
4579 if (defined($conf) && $conf->{agent
}) {
4580 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4582 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4585 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4592 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4597 if ($count >= $timeout) {
4599 warn "VM still running - terminating now with SIGTERM\n";
4602 die "VM quit/powerdown failed - got timeout\n";
4605 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4610 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4613 die "VM quit/powerdown failed\n";
4621 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4626 if ($count >= $timeout) {
4627 warn "VM still running - terminating now with SIGKILL\n";
4632 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4637 my ($vmid, $skiplock) = @_;
4639 PVE
::QemuConfig-
>lock_config($vmid, sub {
4641 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4643 PVE
::QemuConfig-
>check_lock($conf)
4644 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4646 vm_mon_cmd
($vmid, "stop");
4651 my ($vmid, $skiplock, $nocheck) = @_;
4653 PVE
::QemuConfig-
>lock_config($vmid, sub {
4657 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4659 PVE
::QemuConfig-
>check_lock($conf)
4660 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4662 vm_mon_cmd
($vmid, "cont");
4665 vm_mon_cmd_nocheck
($vmid, "cont");
4671 my ($vmid, $skiplock, $key) = @_;
4673 PVE
::QemuConfig-
>lock_config($vmid, sub {
4675 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4677 # there is no qmp command, so we use the human monitor command
4678 vm_human_monitor_command
($vmid, "sendkey $key");
4683 my ($storecfg, $vmid, $skiplock) = @_;
4685 PVE
::QemuConfig-
>lock_config($vmid, sub {
4687 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4689 if (!check_running
($vmid)) {
4690 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4692 die "VM $vmid is running - destroy failed\n";
4700 my ($filename, $buf) = @_;
4702 my $fh = IO
::File-
>new($filename, "w");
4703 return undef if !$fh;
4705 my $res = print $fh $buf;
4712 sub pci_device_info
{
4717 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4718 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4720 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4721 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4723 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4724 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4726 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4727 return undef if !defined($product) || $product !~ s/^0x//;
4732 product
=> $product,
4738 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4747 my $name = $dev->{name
};
4749 my $fn = "$pcisysfs/devices/$name/reset";
4751 return file_write
($fn, "1");
4754 sub pci_dev_bind_to_vfio
{
4757 my $name = $dev->{name
};
4759 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4761 if (!-d
$vfio_basedir) {
4762 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4764 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4766 my $testdir = "$vfio_basedir/$name";
4767 return 1 if -d
$testdir;
4769 my $data = "$dev->{vendor} $dev->{product}";
4770 return undef if !file_write
("$vfio_basedir/new_id", $data);
4772 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4773 if (!file_write
($fn, $name)) {
4774 return undef if -f
$fn;
4777 $fn = "$vfio_basedir/bind";
4778 if (! -d
$testdir) {
4779 return undef if !file_write
($fn, $name);
4785 sub pci_dev_group_bind_to_vfio
{
4788 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4790 if (!-d
$vfio_basedir) {
4791 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4793 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4795 # get IOMMU group devices
4796 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4797 my @devs = grep /^0000:/, readdir($D);
4800 foreach my $pciid (@devs) {
4801 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4803 # pci bridges, switches or root ports are not supported
4804 # they have a pci_bus subdirectory so skip them
4805 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4807 my $info = pci_device_info
($1);
4808 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4814 # vzdump restore implementaion
4816 sub tar_archive_read_firstfile
{
4817 my $archive = shift;
4819 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4821 # try to detect archive type first
4822 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
4823 die "unable to open file '$archive'\n";
4824 my $firstfile = <$fh>;
4828 die "ERROR: archive contaions no data\n" if !$firstfile;
4834 sub tar_restore_cleanup
{
4835 my ($storecfg, $statfile) = @_;
4837 print STDERR
"starting cleanup\n";
4839 if (my $fd = IO
::File-
>new($statfile, "r")) {
4840 while (defined(my $line = <$fd>)) {
4841 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4844 if ($volid =~ m
|^/|) {
4845 unlink $volid || die 'unlink failed\n';
4847 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4849 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4851 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4853 print STDERR
"unable to parse line in statfile - $line";
4860 sub restore_archive
{
4861 my ($archive, $vmid, $user, $opts) = @_;
4863 my $format = $opts->{format
};
4866 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4867 $format = 'tar' if !$format;
4869 } elsif ($archive =~ m/\.tar$/) {
4870 $format = 'tar' if !$format;
4871 } elsif ($archive =~ m/.tar.lzo$/) {
4872 $format = 'tar' if !$format;
4874 } elsif ($archive =~ m/\.vma$/) {
4875 $format = 'vma' if !$format;
4876 } elsif ($archive =~ m/\.vma\.gz$/) {
4877 $format = 'vma' if !$format;
4879 } elsif ($archive =~ m/\.vma\.lzo$/) {
4880 $format = 'vma' if !$format;
4883 $format = 'vma' if !$format; # default
4886 # try to detect archive format
4887 if ($format eq 'tar') {
4888 return restore_tar_archive
($archive, $vmid, $user, $opts);
4890 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4894 sub restore_update_config_line
{
4895 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4897 return if $line =~ m/^\#qmdump\#/;
4898 return if $line =~ m/^\#vzdump\#/;
4899 return if $line =~ m/^lock:/;
4900 return if $line =~ m/^unused\d+:/;
4901 return if $line =~ m/^parent:/;
4902 return if $line =~ m/^template:/; # restored VM is never a template
4904 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4905 # try to convert old 1.X settings
4906 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4907 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4908 my ($model, $macaddr) = split(/\=/, $devconfig);
4909 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4912 bridge
=> "vmbr$ind",
4913 macaddr
=> $macaddr,
4915 my $netstr = print_net
($net);
4917 print $outfd "net$cookie->{netcount}: $netstr\n";
4918 $cookie->{netcount
}++;
4920 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4921 my ($id, $netstr) = ($1, $2);
4922 my $net = parse_net
($netstr);
4923 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4924 $netstr = print_net
($net);
4925 print $outfd "$id: $netstr\n";
4926 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
4929 my $di = parse_drive
($virtdev, $value);
4930 if (defined($di->{backup
}) && !$di->{backup
}) {
4931 print $outfd "#$line";
4932 } elsif ($map->{$virtdev}) {
4933 delete $di->{format
}; # format can change on restore
4934 $di->{file
} = $map->{$virtdev};
4935 $value = print_drive
($vmid, $di);
4936 print $outfd "$virtdev: $value\n";
4946 my ($cfg, $vmid) = @_;
4948 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
4950 my $volid_hash = {};
4951 foreach my $storeid (keys %$info) {
4952 foreach my $item (@{$info->{$storeid}}) {
4953 next if !($item->{volid
} && $item->{size
});
4954 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
4955 $volid_hash->{$item->{volid
}} = $item;
4962 sub is_volume_in_use
{
4963 my ($storecfg, $conf, $skip_drive, $volid) = @_;
4965 my $path = PVE
::Storage
::path
($storecfg, $volid);
4967 my $scan_config = sub {
4968 my ($cref, $snapname) = @_;
4970 foreach my $key (keys %$cref) {
4971 my $value = $cref->{$key};
4972 if (is_valid_drivename
($key)) {
4973 next if $skip_drive && $key eq $skip_drive;
4974 my $drive = parse_drive
($key, $value);
4975 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
4976 return 1 if $volid eq $drive->{file
};
4977 if ($drive->{file
} =~ m!^/!) {
4978 return 1 if $drive->{file
} eq $path;
4980 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
4982 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
4984 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
4992 return 1 if &$scan_config($conf);
4996 foreach my $snapname (keys %{$conf->{snapshots
}}) {
4997 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5003 sub update_disksize
{
5004 my ($vmid, $conf, $volid_hash) = @_;
5010 # Note: it is allowed to define multiple storages with same path (alias), so
5011 # we need to check both 'volid' and real 'path' (two different volid can point
5012 # to the same path).
5017 foreach my $opt (keys %$conf) {
5018 if (is_valid_drivename
($opt)) {
5019 my $drive = parse_drive
($opt, $conf->{$opt});
5020 my $volid = $drive->{file
};
5023 $used->{$volid} = 1;
5024 if ($volid_hash->{$volid} &&
5025 (my $path = $volid_hash->{$volid}->{path
})) {
5026 $usedpath->{$path} = 1;
5029 next if drive_is_cdrom
($drive);
5030 next if !$volid_hash->{$volid};
5032 $drive->{size
} = $volid_hash->{$volid}->{size
};
5033 my $new = print_drive
($vmid, $drive);
5034 if ($new ne $conf->{$opt}) {
5036 $conf->{$opt} = $new;
5041 # remove 'unusedX' entry if volume is used
5042 foreach my $opt (keys %$conf) {
5043 next if $opt !~ m/^unused\d+$/;
5044 my $volid = $conf->{$opt};
5045 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5046 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5048 delete $conf->{$opt};
5052 foreach my $volid (sort keys %$volid_hash) {
5053 next if $volid =~ m/vm-$vmid-state-/;
5054 next if $used->{$volid};
5055 my $path = $volid_hash->{$volid}->{path
};
5056 next if !$path; # just to be sure
5057 next if $usedpath->{$path};
5059 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5060 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5067 my ($vmid, $nolock) = @_;
5069 my $cfg = PVE
::Storage
::config
();
5071 my $volid_hash = scan_volids
($cfg, $vmid);
5073 my $updatefn = sub {
5076 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5078 PVE
::QemuConfig-
>check_lock($conf);
5081 foreach my $volid (keys %$volid_hash) {
5082 my $info = $volid_hash->{$volid};
5083 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5086 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5088 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5091 if (defined($vmid)) {
5095 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5098 my $vmlist = config_list
();
5099 foreach my $vmid (keys %$vmlist) {
5103 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5109 sub restore_vma_archive
{
5110 my ($archive, $vmid, $user, $opts, $comp) = @_;
5112 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5113 my $readfrom = $archive;
5118 my $qarchive = PVE
::Tools
::shellquote
($archive);
5119 if ($comp eq 'gzip') {
5120 $uncomp = "zcat $qarchive|";
5121 } elsif ($comp eq 'lzop') {
5122 $uncomp = "lzop -d -c $qarchive|";
5124 die "unknown compression method '$comp'\n";
5129 my $tmpdir = "/var/tmp/vzdumptmp$$";
5132 # disable interrupts (always do cleanups)
5133 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5134 warn "got interrupt - ignored\n";
5137 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5138 POSIX
::mkfifo
($mapfifo, 0600);
5141 my $openfifo = sub {
5142 open($fifofh, '>', $mapfifo) || die $!;
5145 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5152 my $rpcenv = PVE
::RPCEnvironment
::get
();
5154 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5155 my $tmpfn = "$conffile.$$.tmp";
5157 # Note: $oldconf is undef if VM does not exists
5158 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5159 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5161 my $print_devmap = sub {
5162 my $virtdev_hash = {};
5164 my $cfgfn = "$tmpdir/qemu-server.conf";
5166 # we can read the config - that is already extracted
5167 my $fh = IO
::File-
>new($cfgfn, "r") ||
5168 "unable to read qemu-server.conf - $!\n";
5170 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5172 my $pve_firewall_dir = '/etc/pve/firewall';
5173 mkdir $pve_firewall_dir; # make sure the dir exists
5174 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5177 while (defined(my $line = <$fh>)) {
5178 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5179 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5180 die "archive does not contain data for drive '$virtdev'\n"
5181 if !$devinfo->{$devname};
5182 if (defined($opts->{storage
})) {
5183 $storeid = $opts->{storage
} || 'local';
5184 } elsif (!$storeid) {
5187 $format = 'raw' if !$format;
5188 $devinfo->{$devname}->{devname
} = $devname;
5189 $devinfo->{$devname}->{virtdev
} = $virtdev;
5190 $devinfo->{$devname}->{format
} = $format;
5191 $devinfo->{$devname}->{storeid
} = $storeid;
5193 # check permission on storage
5194 my $pool = $opts->{pool
}; # todo: do we need that?
5195 if ($user ne 'root@pam') {
5196 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5199 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5203 foreach my $devname (keys %$devinfo) {
5204 die "found no device mapping information for device '$devname'\n"
5205 if !$devinfo->{$devname}->{virtdev
};
5208 my $cfg = PVE
::Storage
::config
();
5210 # create empty/temp config
5212 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5213 foreach_drive
($oldconf, sub {
5214 my ($ds, $drive) = @_;
5216 return if drive_is_cdrom
($drive);
5218 my $volid = $drive->{file
};
5220 return if !$volid || $volid =~ m
|^/|;
5222 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5223 return if !$path || !$owner || ($owner != $vmid);
5225 # Note: only delete disk we want to restore
5226 # other volumes will become unused
5227 if ($virtdev_hash->{$ds}) {
5228 PVE
::Storage
::vdisk_free
($cfg, $volid);
5232 # delete vmstate files
5233 # since after the restore we have no snapshots anymore
5234 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5235 my $snap = $oldconf->{snapshots
}->{$snapname};
5236 if ($snap->{vmstate
}) {
5237 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5246 foreach my $virtdev (sort keys %$virtdev_hash) {
5247 my $d = $virtdev_hash->{$virtdev};
5248 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5249 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5251 # test if requested format is supported
5252 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5253 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5254 $d->{format
} = $defFormat if !$supported;
5256 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5257 $d->{format
}, undef, $alloc_size);
5258 print STDERR
"new volume ID is '$volid'\n";
5259 $d->{volid
} = $volid;
5260 my $path = PVE
::Storage
::path
($cfg, $volid);
5262 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5264 my $write_zeros = 1;
5265 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5269 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5271 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5272 $map->{$virtdev} = $volid;
5275 $fh->seek(0, 0) || die "seek failed - $!\n";
5277 my $outfd = new IO
::File
($tmpfn, "w") ||
5278 die "unable to write config for VM $vmid\n";
5280 my $cookie = { netcount
=> 0 };
5281 while (defined(my $line = <$fh>)) {
5282 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5291 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5292 die "interrupted by signal\n";
5294 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5296 $oldtimeout = alarm($timeout);
5303 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5304 my ($dev_id, $size, $devname) = ($1, $2, $3);
5305 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5306 } elsif ($line =~ m/^CTIME: /) {
5307 # we correctly received the vma config, so we can disable
5308 # the timeout now for disk allocation (set to 10 minutes, so
5309 # that we always timeout if something goes wrong)
5312 print $fifofh "done\n";
5313 my $tmp = $oldtimeout || 0;
5314 $oldtimeout = undef;
5320 print "restore vma archive: $cmd\n";
5321 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5325 alarm($oldtimeout) if $oldtimeout;
5328 foreach my $devname (keys %$devinfo) {
5329 my $volid = $devinfo->{$devname}->{volid
};
5330 push @$vollist, $volid if $volid;
5333 my $cfg = PVE
::Storage
::config
();
5334 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5342 foreach my $devname (keys %$devinfo) {
5343 my $volid = $devinfo->{$devname}->{volid
};
5346 if ($volid =~ m
|^/|) {
5347 unlink $volid || die 'unlink failed\n';
5349 PVE
::Storage
::vdisk_free
($cfg, $volid);
5351 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5353 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5360 rename($tmpfn, $conffile) ||
5361 die "unable to commit configuration file '$conffile'\n";
5363 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5365 eval { rescan
($vmid, 1); };
5369 sub restore_tar_archive
{
5370 my ($archive, $vmid, $user, $opts) = @_;
5372 if ($archive ne '-') {
5373 my $firstfile = tar_archive_read_firstfile
($archive);
5374 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5375 if $firstfile ne 'qemu-server.conf';
5378 my $storecfg = PVE
::Storage
::config
();
5380 # destroy existing data - keep empty config
5381 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5382 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5384 my $tocmd = "/usr/lib/qemu-server/qmextract";
5386 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5387 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5388 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5389 $tocmd .= ' --info' if $opts->{info
};
5391 # tar option "xf" does not autodetect compression when read from STDIN,
5392 # so we pipe to zcat
5393 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5394 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5396 my $tmpdir = "/var/tmp/vzdumptmp$$";
5399 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5400 local $ENV{VZDUMP_VMID
} = $vmid;
5401 local $ENV{VZDUMP_USER
} = $user;
5403 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5404 my $tmpfn = "$conffile.$$.tmp";
5406 # disable interrupts (always do cleanups)
5407 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5408 print STDERR
"got interrupt - ignored\n";
5413 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5414 die "interrupted by signal\n";
5417 if ($archive eq '-') {
5418 print "extracting archive from STDIN\n";
5419 run_command
($cmd, input
=> "<&STDIN");
5421 print "extracting archive '$archive'\n";
5425 return if $opts->{info
};
5429 my $statfile = "$tmpdir/qmrestore.stat";
5430 if (my $fd = IO
::File-
>new($statfile, "r")) {
5431 while (defined (my $line = <$fd>)) {
5432 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5433 $map->{$1} = $2 if $1;
5435 print STDERR
"unable to parse line in statfile - $line\n";
5441 my $confsrc = "$tmpdir/qemu-server.conf";
5443 my $srcfd = new IO
::File
($confsrc, "r") ||
5444 die "unable to open file '$confsrc'\n";
5446 my $outfd = new IO
::File
($tmpfn, "w") ||
5447 die "unable to write config for VM $vmid\n";
5449 my $cookie = { netcount
=> 0 };
5450 while (defined (my $line = <$srcfd>)) {
5451 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5463 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5470 rename $tmpfn, $conffile ||
5471 die "unable to commit configuration file '$conffile'\n";
5473 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5475 eval { rescan
($vmid, 1); };
5479 sub foreach_writable_storage
{
5480 my ($conf, $func) = @_;
5484 foreach my $ds (keys %$conf) {
5485 next if !is_valid_drivename
($ds);
5487 my $drive = parse_drive
($ds, $conf->{$ds});
5489 next if drive_is_cdrom
($drive);
5491 my $volid = $drive->{file
};
5493 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5494 $sidhash->{$sid} = $sid if $sid;
5497 foreach my $sid (sort keys %$sidhash) {
5502 sub do_snapshots_with_qemu
{
5503 my ($storecfg, $volid) = @_;
5505 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5507 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5508 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5512 if ($volid =~ m/\.(qcow2|qed)$/){
5519 sub qga_check_running
{
5522 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5524 warn "Qemu Guest Agent are not running - $@";
5530 sub template_create
{
5531 my ($vmid, $conf, $disk) = @_;
5533 my $storecfg = PVE
::Storage
::config
();
5535 foreach_drive
($conf, sub {
5536 my ($ds, $drive) = @_;
5538 return if drive_is_cdrom
($drive);
5539 return if $disk && $ds ne $disk;
5541 my $volid = $drive->{file
};
5542 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5544 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5545 $drive->{file
} = $voliddst;
5546 $conf->{$ds} = print_drive
($vmid, $drive);
5547 PVE
::QemuConfig-
>write_config($vmid, $conf);
5551 sub qemu_img_convert
{
5552 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5554 my $storecfg = PVE
::Storage
::config
();
5555 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5556 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5558 if ($src_storeid && $dst_storeid) {
5560 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5562 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5563 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5565 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5566 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5568 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5569 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5572 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5573 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5574 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5575 if ($is_zero_initialized) {
5576 push @$cmd, "zeroinit:$dst_path";
5578 push @$cmd, $dst_path;
5583 if($line =~ m/\((\S+)\/100\
%\)/){
5585 my $transferred = int($size * $percent / 100);
5586 my $remaining = $size - $transferred;
5588 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5593 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5595 die "copy failed: $err" if $err;
5599 sub qemu_img_format
{
5600 my ($scfg, $volname) = @_;
5602 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5609 sub qemu_drive_mirror
{
5610 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5612 my $storecfg = PVE
::Storage
::config
();
5613 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5615 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5617 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5619 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5621 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5623 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5624 $opts->{format
} = $format if $format;
5626 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5628 my $finish_job = sub {
5630 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5631 my $stat = @$stats[0];
5638 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5640 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5641 my $stat = @$stats[0];
5642 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5643 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5645 my $busy = $stat->{busy
};
5646 my $ready = $stat->{ready
};
5648 if (my $total = $stat->{len
}) {
5649 my $transferred = $stat->{offset
} || 0;
5650 my $remaining = $total - $transferred;
5651 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5653 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5657 if ($stat->{ready
} eq 'true') {
5659 last if $vmiddst != $vmid;
5661 # try to switch the disk if source and destination are on the same guest
5662 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5667 die $@ if $@ !~ m/cannot be completed/;
5676 my $cancel_job = sub {
5677 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5682 eval { &$cancel_job(); };
5683 die "mirroring error: $err";
5686 if ($vmiddst != $vmid) {
5687 # if we clone a disk for a new target vm, we don't switch the disk
5688 &$cancel_job(); # so we call block-job-cancel
5693 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5694 $newvmid, $storage, $format, $full, $newvollist) = @_;
5699 print "create linked clone of drive $drivename ($drive->{file})\n";
5700 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5701 push @$newvollist, $newvolid;
5703 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5704 $storeid = $storage if $storage;
5706 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5708 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5709 $format = qemu_img_format
($scfg, $volname);
5712 # test if requested format is supported - else use default
5713 my $supported = grep { $_ eq $format } @$validFormats;
5714 $format = $defFormat if !$supported;
5716 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5718 print "create full clone of drive $drivename ($drive->{file})\n";
5719 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5720 push @$newvollist, $newvolid;
5722 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5724 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5725 if (!$running || $snapname) {
5726 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5728 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5732 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5735 $disk->{format
} = undef;
5736 $disk->{file
} = $newvolid;
5737 $disk->{size
} = $size;
5742 # this only works if VM is running
5743 sub get_current_qemu_machine
{
5746 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5747 my $res = vm_qmp_command
($vmid, $cmd);
5749 my ($current, $default);
5750 foreach my $e (@$res) {
5751 $default = $e->{name
} if $e->{'is-default'};
5752 $current = $e->{name
} if $e->{'is-current'};
5755 # fallback to the default machine if current is not supported by qemu
5756 return $current || $default || 'pc';
5759 sub qemu_machine_feature_enabled
{
5760 my ($machine, $kvmver, $version_major, $version_minor) = @_;
5765 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
5767 $current_major = $3;
5768 $current_minor = $4;
5770 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
5772 $current_major = $1;
5773 $current_minor = $2;
5776 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
5781 sub qemu_machine_pxe
{
5782 my ($vmid, $conf, $machine) = @_;
5784 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
5786 foreach my $opt (keys %$conf) {
5787 next if $opt !~ m/^net(\d+)$/;
5788 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
5790 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
5791 return $machine.".pxe" if $romfile =~ m/pxe/;
5798 sub qemu_use_old_bios_files
{
5799 my ($machine_type) = @_;
5801 return if !$machine_type;
5803 my $use_old_bios_files = undef;
5805 if ($machine_type =~ m/^(\S+)\.pxe$/) {
5807 $use_old_bios_files = 1;
5809 my $kvmver = kvm_user_version
();
5810 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
5811 # load new efi bios files on migration. So this hack is required to allow
5812 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
5813 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
5814 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
5817 return ($use_old_bios_files, $machine_type);
5824 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
5825 my (undef, $id, $function) = @_;
5826 my $res = { id
=> $id, function
=> $function};
5827 push @{$devices->{$id}}, $res;
5833 sub vm_iothreads_list
{
5836 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
5839 foreach my $iothread (@$res) {
5840 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
5847 my ($conf, $drive) = @_;
5851 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
5853 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
5859 my $controller = int($drive->{index} / $maxdev);
5860 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
5862 return ($maxdev, $controller, $controller_prefix);
5865 # bash completion helper
5867 sub complete_backup_archives
{
5868 my ($cmdname, $pname, $cvalue) = @_;
5870 my $cfg = PVE
::Storage
::config
();
5874 if ($cvalue =~ m/^([^:]+):/) {
5878 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
5881 foreach my $id (keys %$data) {
5882 foreach my $item (@{$data->{$id}}) {
5883 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
5884 push @$res, $item->{volid
} if defined($item->{volid
});
5891 my $complete_vmid_full = sub {
5894 my $idlist = vmstatus
();
5898 foreach my $id (keys %$idlist) {
5899 my $d = $idlist->{$id};
5900 if (defined($running)) {
5901 next if $d->{template
};
5902 next if $running && $d->{status
} ne 'running';
5903 next if !$running && $d->{status
} eq 'running';
5912 return &$complete_vmid_full();
5915 sub complete_vmid_stopped
{
5916 return &$complete_vmid_full(0);
5919 sub complete_vmid_running
{
5920 return &$complete_vmid_full(1);
5923 sub complete_storage
{
5925 my $cfg = PVE
::Storage
::config
();
5926 my $ids = $cfg->{ids
};
5929 foreach my $sid (keys %$ids) {
5930 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
5931 next if !$ids->{$sid}->{content
}->{images
};