1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
32 use PVE
::RPCEnvironment
;
33 use PVE
::QemuServer
::PCI
qw(print_pci_addr print_pcie_addr);
34 use PVE
::QemuServer
::Memory
;
35 use PVE
::QemuServer
::USB
qw(parse_usb_device);
36 use Time
::HiRes
qw(gettimeofday);
37 use File
::Copy
qw(copy);
40 my $OVMF_CODE = '/usr/share/kvm/OVMF_CODE-pure-efi.fd';
41 my $OVMF_VARS = '/usr/share/kvm/OVMF_VARS-pure-efi.fd';
43 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
45 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
47 # Note about locking: we use flock on the config file protect
48 # against concurent actions.
49 # Aditionaly, we have a 'lock' setting in the config file. This
50 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
51 # allowed when such lock is set. But you can ignore this kind of
52 # lock with the --skiplock flag.
54 cfs_register_file
('/qemu-server/',
58 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
59 description
=> "Some command save/restore state from this location.",
65 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
66 description
=> "The name of the snapshot.",
67 type
=> 'string', format
=> 'pve-configid',
71 PVE
::JSONSchema
::register_standard_option
('pve-qm-image-format', {
73 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
74 description
=> "The drive's backing file's data format.",
78 #no warnings 'redefine';
81 my ($controller, $vmid, $option, $value) = @_;
83 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
84 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
88 my $nodename = PVE
::INotify
::nodename
();
90 mkdir "/etc/pve/nodes/$nodename";
91 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
94 my $var_run_tmpdir = "/var/run/qemu-server";
95 mkdir $var_run_tmpdir;
97 my $lock_dir = "/var/lock/qemu-server";
100 my $pcisysfs = "/sys/bus/pci";
102 my $cpu_vendor_list = {
104 486 => 'GenuineIntel',
105 pentium
=> 'GenuineIntel',
106 pentium2
=> 'GenuineIntel',
107 pentium3
=> 'GenuineIntel',
108 coreduo
=> 'GenuineIntel',
109 core2duo
=> 'GenuineIntel',
110 Conroe
=> 'GenuineIntel',
111 Penryn
=> 'GenuineIntel',
112 Nehalem
=> 'GenuineIntel',
113 'Nehalem-IBRS' => 'GenuineIntel',
114 Westmere
=> 'GenuineIntel',
115 'Westmere-IBRS' => 'GenuineIntel',
116 SandyBridge
=> 'GenuineIntel',
117 'SandyBridge-IBRS' => 'GenuineIntel',
118 IvyBridge
=> 'GenuineIntel',
119 'IvyBridge-IBRS' => 'GenuineIntel',
120 Haswell
=> 'GenuineIntel',
121 'Haswell-IBRS' => 'GenuineIntel',
122 'Haswell-noTSX' => 'GenuineIntel',
123 'Haswell-noTSX-IBRS' => 'GenuineIntel',
124 Broadwell
=> 'GenuineIntel',
125 'Broadwell-IBRS' => 'GenuineIntel',
126 'Broadwell-noTSX' => 'GenuineIntel',
127 'Broadwell-noTSX-IBRS' => 'GenuineIntel',
128 'Skylake-Client' => 'GenuineIntel',
129 'Skylake-Client-IBRS' => 'GenuineIntel',
130 'Skylake-Server' => 'GenuineIntel',
131 'Skylake-Server-IBRS' => 'GenuineIntel',
134 athlon
=> 'AuthenticAMD',
135 phenom
=> 'AuthenticAMD',
136 Opteron_G1
=> 'AuthenticAMD',
137 Opteron_G2
=> 'AuthenticAMD',
138 Opteron_G3
=> 'AuthenticAMD',
139 Opteron_G4
=> 'AuthenticAMD',
140 Opteron_G5
=> 'AuthenticAMD',
142 # generic types, use vendor from host node
151 my $cpu_flag = qr/[+-](pcid|spec-ctrl)/;
155 description
=> "Emulated CPU type.",
157 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
162 description
=> "Do not identify as a KVM virtual machine.",
168 description
=> "List of additional CPU flags separated by ';'."
169 . " Use '+FLAG' to enable, '-FLAG' to disable a flag."
170 . " Currently supported flags: 'pcid', 'spec-ctrl'.",
171 format_description
=> '+FLAG[;-FLAG...]',
173 pattern
=> qr/$cpu_flag(;$cpu_flag)*/,
182 enum
=> [qw(i6300esb ib700)],
183 description
=> "Watchdog type to emulate.",
184 default => 'i6300esb',
189 enum
=> [qw(reset shutdown poweroff pause debug none)],
190 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
194 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
200 description
=> "Specifies whether a VM will be started during system bootup.",
206 description
=> "Automatic restart after crash (currently ignored).",
211 type
=> 'string', format
=> 'pve-hotplug-features',
212 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'.",
213 default => 'network,disk,usb',
218 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
224 description
=> "Lock/unlock the VM.",
225 enum
=> [qw(migrate backup snapshot rollback)],
230 description
=> "Limit of CPU usage.",
231 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.",
239 description
=> "CPU weight for a VM.",
240 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.",
248 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
255 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
261 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",
269 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.".
270 "It should not be necessary to set it.",
271 enum
=> PVE
::Tools
::kvmkeymaplist
(),
276 type
=> 'string', format
=> 'dns-name',
277 description
=> "Set a name for the VM. Only used on the configuration web interface.",
282 description
=> "SCSI controller model",
283 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
289 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
294 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 win10 l24 l26 solaris)],
295 description
=> "Specify guest operating system.",
296 verbose_description
=> <<EODESC,
297 Specify guest operating system. This is used to enable special
298 optimization/features for specific operating systems:
301 other;; unspecified OS
302 wxp;; Microsoft Windows XP
303 w2k;; Microsoft Windows 2000
304 w2k3;; Microsoft Windows 2003
305 w2k8;; Microsoft Windows 2008
306 wvista;; Microsoft Windows Vista
307 win7;; Microsoft Windows 7
308 win8;; Microsoft Windows 8/2012/2012r2
309 win10;; Microsoft Windows 10/2016
310 l24;; Linux 2.4 Kernel
311 l26;; Linux 2.6/3.X Kernel
312 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
318 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
319 pattern
=> '[acdn]{1,4}',
324 type
=> 'string', format
=> 'pve-qm-bootdisk',
325 description
=> "Enable booting from specified disk.",
326 pattern
=> '(ide|sata|scsi|virtio)\d+',
331 description
=> "The number of CPUs. Please use option -sockets instead.",
338 description
=> "The number of CPU sockets.",
345 description
=> "The number of cores per socket.",
352 description
=> "Enable/disable NUMA.",
358 description
=> "Enable/disable hugepages memory.",
359 enum
=> [qw(any 2 1024)],
364 description
=> "Number of hotplugged vcpus.",
371 description
=> "Enable/disable ACPI.",
377 description
=> "Enable/disable Qemu GuestAgent.",
383 description
=> "Enable/disable KVM hardware virtualization.",
389 description
=> "Enable/disable time drift fix.",
395 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
400 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
405 description
=> "Select the VGA type.",
406 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
407 " modes (>= 1280x1024x16) then you should use the options " .
408 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
409 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
410 "display sever. For win* OS you can select how many independent " .
411 "displays you want, Linux guests can add displays them self. " .
412 "You can also run without any graphic card, using a serial device" .
414 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
418 type
=> 'string', format
=> 'pve-qm-watchdog',
419 description
=> "Create a virtual hardware watchdog device.",
420 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
421 " (by a guest action), the watchdog must be periodically polled " .
422 "by an agent inside the guest or else the watchdog will reset " .
423 "the guest (or execute the respective action specified)",
428 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
429 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'.",
430 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
433 startup
=> get_standard_option
('pve-startup-order'),
437 description
=> "Enable/disable Template.",
443 description
=> "Arbitrary arguments passed to kvm.",
444 verbose_description
=> <<EODESCR,
445 Arbitrary arguments passed to kvm, for example:
447 args: -no-reboot -no-hpet
449 NOTE: this option is for experts only.
456 description
=> "Enable/disable the USB tablet device.",
457 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
458 "usually needed to allow absolute mouse positioning with VNC. " .
459 "Else the mouse runs out of sync with normal VNC clients. " .
460 "If you're running lots of console-only guests on one host, " .
461 "you may consider disabling this to save some context switches. " .
462 "This is turned off by default if you use spice (-vga=qxl).",
467 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
471 migrate_downtime
=> {
474 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
480 type
=> 'string', format
=> 'pve-qm-ide',
481 typetext
=> '<volume>',
482 description
=> "This is an alias for option -ide2",
486 description
=> "Emulated CPU type.",
490 parent
=> get_standard_option
('pve-snapshot-name', {
492 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
496 description
=> "Timestamp for snapshots.",
502 type
=> 'string', format
=> 'pve-volume-id',
503 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
505 vmstatestorage
=> get_standard_option
('pve-storage-id', {
506 description
=> "Default storage for VM state volumes/files.",
510 description
=> "Specific the Qemu machine type.",
512 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
517 description
=> "Specify SMBIOS type 1 fields.",
518 type
=> 'string', format
=> 'pve-qm-smbios1',
525 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
531 enum
=> [ qw(seabios ovmf) ],
532 description
=> "Select BIOS implementation.",
533 default => 'seabios',
537 # what about other qemu settings ?
539 #machine => 'string',
552 ##soundhw => 'string',
554 while (my ($k, $v) = each %$confdesc) {
555 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
558 my $MAX_IDE_DISKS = 4;
559 my $MAX_SCSI_DISKS = 14;
560 my $MAX_VIRTIO_DISKS = 16;
561 my $MAX_SATA_DISKS = 6;
562 my $MAX_USB_DEVICES = 5;
564 my $MAX_UNUSED_DISKS = 8;
565 my $MAX_HOSTPCI_DEVICES = 4;
566 my $MAX_SERIAL_PORTS = 4;
567 my $MAX_PARALLEL_PORTS = 3;
573 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
574 description
=> "CPUs accessing this NUMA node.",
575 format_description
=> "id[-id];...",
579 description
=> "Amount of memory this NUMA node provides.",
584 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
585 description
=> "Host NUMA nodes to use.",
586 format_description
=> "id[-id];...",
591 enum
=> [qw(preferred bind interleave)],
592 description
=> "NUMA allocation policy.",
596 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
599 type
=> 'string', format
=> $numa_fmt,
600 description
=> "NUMA topology.",
602 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
604 for (my $i = 0; $i < $MAX_NUMA; $i++) {
605 $confdesc->{"numa$i"} = $numadesc;
608 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
609 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
610 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
611 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
613 my $net_fmt_bridge_descr = <<__EOD__;
614 Bridge to attach the network device to. The Proxmox VE standard bridge
617 If you do not specify a bridge, we create a kvm user (NATed) network
618 device, which provides DHCP and DNS services. The following addresses
625 The DHCP server assign addresses to the guest starting from 10.0.2.15.
631 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
632 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
633 format_description
=> "XX:XX:XX:XX:XX:XX",
638 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'.",
639 enum
=> $nic_model_list,
642 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
645 description
=> $net_fmt_bridge_descr,
646 format_description
=> 'bridge',
651 minimum
=> 0, maximum
=> 16,
652 description
=> 'Number of packet queues to be used on the device.',
658 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
663 minimum
=> 1, maximum
=> 4094,
664 description
=> 'VLAN tag to apply to packets on this interface.',
669 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
670 description
=> 'VLAN trunks to pass through this interface.',
671 format_description
=> 'vlanid[;vlanid...]',
676 description
=> 'Whether this interface should be protected by the firewall.',
681 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
688 type
=> 'string', format
=> $net_fmt,
689 description
=> "Specify network devices.",
692 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
694 for (my $i = 0; $i < $MAX_NETS; $i++) {
695 $confdesc->{"net$i"} = $netdesc;
698 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
699 sub verify_volume_id_or_qm_path
{
700 my ($volid, $noerr) = @_;
702 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
706 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
707 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
709 return undef if $noerr;
717 my %drivedesc_base = (
718 volume
=> { alias
=> 'file' },
721 format
=> 'pve-volume-id-or-qm-path',
723 format_description
=> 'volume',
724 description
=> "The drive's backing volume.",
728 enum
=> [qw(cdrom disk)],
729 description
=> "The drive's media type.",
735 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
740 description
=> "Force the drive's physical geometry to have a specific head count.",
745 description
=> "Force the drive's physical geometry to have a specific sector count.",
750 enum
=> [qw(none lba auto)],
751 description
=> "Force disk geometry bios translation mode.",
756 description
=> "Controls qemu's snapshot mode feature."
757 . " If activated, changes made to the disk are temporary and will"
758 . " be discarded when the VM is shutdown.",
763 enum
=> [qw(none writethrough writeback unsafe directsync)],
764 description
=> "The drive's cache mode",
767 format
=> get_standard_option
('pve-qm-image-format'),
770 format
=> 'disk-size',
771 format_description
=> 'DiskSize',
772 description
=> "Disk size. This is purely informational and has no effect.",
777 description
=> "Whether the drive should be included when making backups.",
782 description
=> 'Whether the drive should considered for replication jobs.',
788 enum
=> [qw(ignore report stop)],
789 description
=> 'Read error action.',
794 enum
=> [qw(enospc ignore report stop)],
795 description
=> 'Write error action.',
800 enum
=> [qw(native threads)],
801 description
=> 'AIO type to use.',
806 enum
=> [qw(ignore on)],
807 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
812 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
817 format
=> 'urlencoded',
818 format_description
=> 'serial',
819 maxLength
=> 20*3, # *3 since it's %xx url enoded
820 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
825 my %iothread_fmt = ( iothread
=> {
827 description
=> "Whether to use iothreads for this drive",
834 format
=> 'urlencoded',
835 format_description
=> 'model',
836 maxLength
=> 40*3, # *3 since it's %xx url enoded
837 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
845 description
=> "Number of queues.",
851 my %scsiblock_fmt = (
854 description
=> "whether to use scsi-block for full passthrough of host block device\n\nWARNING: can lead to I/O errors in combination with low memory or high memory fragmentation on host",
860 my $add_throttle_desc = sub {
861 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
864 format_description
=> $unit,
865 description
=> "Maximum $what in $longunit.",
868 $d->{minimum
} = $minimum if defined($minimum);
869 $drivedesc_base{$key} = $d;
871 # throughput: (leaky bucket)
872 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
873 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
874 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
875 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
876 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
877 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
878 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
879 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
880 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
882 # pools: (pool of IO before throttling starts taking effect)
883 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
884 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
885 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
886 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
887 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
888 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
891 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
892 $add_throttle_desc->('bps_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
893 $add_throttle_desc->('bps_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
894 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
895 $add_throttle_desc->('iops_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
896 $add_throttle_desc->('iops_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
899 $drivedesc_base{'bps_rd_length'} = { alias
=> 'bps_rd_max_length' };
900 $drivedesc_base{'bps_wr_length'} = { alias
=> 'bps_wr_max_length' };
901 $drivedesc_base{'iops_rd_length'} = { alias
=> 'iops_rd_max_length' };
902 $drivedesc_base{'iops_wr_length'} = { alias
=> 'iops_wr_max_length' };
908 PVE
::JSONSchema
::register_format
("pve-qm-ide", $ide_fmt);
912 type
=> 'string', format
=> $ide_fmt,
913 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
915 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
925 type
=> 'string', format
=> $scsi_fmt,
926 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
928 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
935 type
=> 'string', format
=> $sata_fmt,
936 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
938 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
946 type
=> 'string', format
=> $virtio_fmt,
947 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
949 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
960 volume
=> { alias
=> 'file' },
963 format
=> 'pve-volume-id-or-qm-path',
965 format_description
=> 'volume',
966 description
=> "The drive's backing volume.",
968 format
=> get_standard_option
('pve-qm-image-format'),
971 format
=> 'disk-size',
972 format_description
=> 'DiskSize',
973 description
=> "Disk size. This is purely informational and has no effect.",
980 type
=> 'string', format
=> $efidisk_fmt,
981 description
=> "Configure a Disk for storing EFI vars",
984 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
989 type
=> 'string', format
=> 'pve-qm-usb-device',
990 format_description
=> 'HOSTUSBDEVICE|spice',
991 description
=> <<EODESCR,
992 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
994 'bus-port(.port)*' (decimal numbers) or
995 'vendor_id:product_id' (hexadeciaml numbers) or
998 You can use the 'lsusb -t' command to list existing usb devices.
1000 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1002 The value 'spice' can be used to add a usb redirection devices for spice.
1008 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).",
1015 type
=> 'string', format
=> $usb_fmt,
1016 description
=> "Configure an USB device (n is 0 to 4).",
1018 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
1020 # NOTE: the match-groups of this regex are used in parse_hostpci
1021 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
1026 pattern
=> qr/$PCIRE(;$PCIRE)*/,
1027 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
1028 description
=> <<EODESCR,
1029 Host PCI device pass through. The PCI ID of a host's PCI device or a list
1030 of PCI virtual functions of the host. HOSTPCIID syntax is:
1032 'bus:dev.func' (hexadecimal numbers)
1034 You can us the 'lspci' command to list existing PCI devices.
1039 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1045 pattern
=> '[^,;]+',
1046 format_description
=> 'string',
1047 description
=> "Custom pci device rom filename (must be located in /usr/share/kvm/).",
1052 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1058 description
=> "Enable vfio-vga device support.",
1063 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1067 type
=> 'string', format
=> 'pve-qm-hostpci',
1068 description
=> "Map host PCI devices into guest.",
1069 verbose_description
=> <<EODESCR,
1070 Map host PCI devices into guest.
1072 NOTE: This option allows direct access to host hardware. So it is no longer
1073 possible to migrate such machines - use with special care.
1075 CAUTION: Experimental! User reported problems with this option.
1078 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1083 pattern
=> '(/dev/.+|socket)',
1084 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1085 verbose_description
=> <<EODESCR,
1086 Create a serial device inside the VM (n is 0 to 3), and pass through a
1087 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1088 host side (use 'qm terminal' to open a terminal connection).
1090 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1092 CAUTION: Experimental! User reported problems with this option.
1099 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1100 description
=> "Map host parallel devices (n is 0 to 2).",
1101 verbose_description
=> <<EODESCR,
1102 Map host parallel devices (n is 0 to 2).
1104 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1106 CAUTION: Experimental! User reported problems with this option.
1110 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1111 $confdesc->{"parallel$i"} = $paralleldesc;
1114 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1115 $confdesc->{"serial$i"} = $serialdesc;
1118 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1119 $confdesc->{"hostpci$i"} = $hostpcidesc;
1122 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1123 $drivename_hash->{"ide$i"} = 1;
1124 $confdesc->{"ide$i"} = $idedesc;
1127 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1128 $drivename_hash->{"sata$i"} = 1;
1129 $confdesc->{"sata$i"} = $satadesc;
1132 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1133 $drivename_hash->{"scsi$i"} = 1;
1134 $confdesc->{"scsi$i"} = $scsidesc ;
1137 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1138 $drivename_hash->{"virtio$i"} = 1;
1139 $confdesc->{"virtio$i"} = $virtiodesc;
1142 $drivename_hash->{efidisk0
} = 1;
1143 $confdesc->{efidisk0
} = $efidisk_desc;
1145 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1146 $confdesc->{"usb$i"} = $usbdesc;
1151 type
=> 'string', format
=> 'pve-volume-id',
1152 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1155 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1156 $confdesc->{"unused$i"} = $unuseddesc;
1159 my $kvm_api_version = 0;
1163 return $kvm_api_version if $kvm_api_version;
1165 my $fh = IO
::File-
>new("</dev/kvm") ||
1168 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1169 $kvm_api_version = $v;
1174 return $kvm_api_version;
1177 my $kvm_user_version;
1179 sub kvm_user_version
{
1181 return $kvm_user_version if $kvm_user_version;
1183 $kvm_user_version = 'unknown';
1187 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1188 $kvm_user_version = $2;
1192 eval { run_command
("kvm -version", outfunc
=> $code); };
1195 return $kvm_user_version;
1199 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1201 sub valid_drive_names
{
1202 # order is important - used to autoselect boot disk
1203 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1204 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1205 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1206 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1210 sub is_valid_drivename
{
1213 return defined($drivename_hash->{$dev});
1218 return defined($confdesc->{$key});
1222 return $nic_model_list;
1225 sub os_list_description
{
1229 wxp
=> 'Windows XP',
1230 w2k
=> 'Windows 2000',
1231 w2k3
=>, 'Windows 2003',
1232 w2k8
=> 'Windows 2008',
1233 wvista
=> 'Windows Vista',
1234 win7
=> 'Windows 7',
1235 win8
=> 'Windows 8/2012',
1236 win10
=> 'Windows 10/2016',
1244 sub get_cdrom_path
{
1246 return $cdrom_path if $cdrom_path;
1248 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1249 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1250 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1254 my ($storecfg, $vmid, $cdrom) = @_;
1256 if ($cdrom eq 'cdrom') {
1257 return get_cdrom_path
();
1258 } elsif ($cdrom eq 'none') {
1260 } elsif ($cdrom =~ m
|^/|) {
1263 return PVE
::Storage
::path
($storecfg, $cdrom);
1267 # try to convert old style file names to volume IDs
1268 sub filename_to_volume_id
{
1269 my ($vmid, $file, $media) = @_;
1271 if (!($file eq 'none' || $file eq 'cdrom' ||
1272 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1274 return undef if $file =~ m
|/|;
1276 if ($media && $media eq 'cdrom') {
1277 $file = "local:iso/$file";
1279 $file = "local:$vmid/$file";
1286 sub verify_media_type
{
1287 my ($opt, $vtype, $media) = @_;
1292 if ($media eq 'disk') {
1294 } elsif ($media eq 'cdrom') {
1297 die "internal error";
1300 return if ($vtype eq $etype);
1302 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1305 sub cleanup_drive_path
{
1306 my ($opt, $storecfg, $drive) = @_;
1308 # try to convert filesystem paths to volume IDs
1310 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1311 ($drive->{file
} !~ m
|^/dev/.+|) &&
1312 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1313 ($drive->{file
} !~ m/^\d+$/)) {
1314 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1315 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1316 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1317 verify_media_type
($opt, $vtype, $drive->{media
});
1318 $drive->{file
} = $volid;
1321 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1324 sub parse_hotplug_features
{
1329 return $res if $data eq '0';
1331 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1333 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1334 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1337 die "invalid hotplug feature '$feature'\n";
1343 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1344 sub pve_verify_hotplug_features
{
1345 my ($value, $noerr) = @_;
1347 return $value if parse_hotplug_features
($value);
1349 return undef if $noerr;
1351 die "unable to parse hotplug option\n";
1354 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1355 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1356 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1357 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1358 # [,iothread=on][,serial=serial][,model=model]
1361 my ($key, $data) = @_;
1363 my ($interface, $index);
1365 if ($key =~ m/^([^\d]+)(\d+)$/) {
1372 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1373 : $confdesc->{$key}->{format
};
1375 warn "invalid drive key: $key\n";
1378 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1379 return undef if !$res;
1380 $res->{interface
} = $interface;
1381 $res->{index} = $index;
1384 foreach my $opt (qw(bps bps_rd bps_wr)) {
1385 if (my $bps = defined(delete $res->{$opt})) {
1386 if (defined($res->{"m$opt"})) {
1387 warn "both $opt and m$opt specified\n";
1391 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1395 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1396 for my $requirement (
1397 [mbps_max
=> 'mbps'],
1398 [mbps_rd_max
=> 'mbps_rd'],
1399 [mbps_wr_max
=> 'mbps_wr'],
1400 [miops_max
=> 'miops'],
1401 [miops_rd_max
=> 'miops_rd'],
1402 [miops_wr_max
=> 'miops_wr'],
1403 [bps_max_length
=> 'mbps_max'],
1404 [bps_rd_max_length
=> 'mbps_rd_max'],
1405 [bps_wr_max_length
=> 'mbps_wr_max'],
1406 [iops_max_length
=> 'iops_max'],
1407 [iops_rd_max_length
=> 'iops_rd_max'],
1408 [iops_wr_max_length
=> 'iops_wr_max']) {
1409 my ($option, $requires) = @$requirement;
1410 if ($res->{$option} && !$res->{$requires}) {
1411 warn "$option requires $requires\n";
1416 return undef if $error;
1418 return undef if $res->{mbps_rd
} && $res->{mbps
};
1419 return undef if $res->{mbps_wr
} && $res->{mbps
};
1420 return undef if $res->{iops_rd
} && $res->{iops
};
1421 return undef if $res->{iops_wr
} && $res->{iops
};
1423 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1424 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1425 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1426 return undef if $res->{interface
} eq 'virtio';
1429 if (my $size = $res->{size
}) {
1430 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1437 my ($vmid, $drive) = @_;
1438 my $data = { %$drive };
1439 delete $data->{$_} for qw(index interface);
1440 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1444 my($fh, $noerr) = @_;
1447 my $SG_GET_VERSION_NUM = 0x2282;
1449 my $versionbuf = "\x00" x
8;
1450 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1452 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1455 my $version = unpack("I", $versionbuf);
1456 if ($version < 30000) {
1457 die "scsi generic interface too old\n" if !$noerr;
1461 my $buf = "\x00" x
36;
1462 my $sensebuf = "\x00" x
8;
1463 my $cmd = pack("C x3 C x1", 0x12, 36);
1465 # see /usr/include/scsi/sg.h
1466 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";
1468 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1469 length($sensebuf), 0, length($buf), $buf,
1470 $cmd, $sensebuf, 6000);
1472 $ret = ioctl($fh, $SG_IO, $packet);
1474 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1478 my @res = unpack($sg_io_hdr_t, $packet);
1479 if ($res[17] || $res[18]) {
1480 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1485 (my $byte0, my $byte1, $res->{vendor
},
1486 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1488 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1489 $res->{type
} = $byte0 & 31;
1497 my $fh = IO
::File-
>new("+<$path") || return undef;
1498 my $res = scsi_inquiry
($fh, 1);
1504 sub machine_type_is_q35
{
1507 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1510 sub print_tabletdevice_full
{
1513 my $q35 = machine_type_is_q35
($conf);
1515 # we use uhci for old VMs because tablet driver was buggy in older qemu
1516 my $usbbus = $q35 ?
"ehci" : "uhci";
1518 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1521 sub print_drivedevice_full
{
1522 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1527 if ($drive->{interface
} eq 'virtio') {
1528 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1529 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1530 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1531 } elsif ($drive->{interface
} eq 'scsi') {
1533 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1534 my $unit = $drive->{index} % $maxdev;
1535 my $devicetype = 'hd';
1537 if (drive_is_cdrom
($drive)) {
1540 if ($drive->{file
} =~ m
|^/|) {
1541 $path = $drive->{file
};
1542 if (my $info = path_is_scsi
($path)) {
1543 if ($info->{type
} == 0 && $drive->{scsiblock
}) {
1544 $devicetype = 'block';
1545 } elsif ($info->{type
} == 1) { # tape
1546 $devicetype = 'generic';
1550 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1553 if($path =~ m/^iscsi\:\/\
//){
1554 $devicetype = 'generic';
1558 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1559 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1561 $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}";
1564 } elsif ($drive->{interface
} eq 'ide'){
1566 my $controller = int($drive->{index} / $maxdev);
1567 my $unit = $drive->{index} % $maxdev;
1568 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1570 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1571 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1572 $model = URI
::Escape
::uri_unescape
($model);
1573 $device .= ",model=$model";
1575 } elsif ($drive->{interface
} eq 'sata'){
1576 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1577 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1578 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1579 } elsif ($drive->{interface
} eq 'usb') {
1581 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1583 die "unsupported interface type";
1586 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1591 sub get_initiator_name
{
1594 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1595 while (defined(my $line = <$fh>)) {
1596 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1605 sub print_drive_full
{
1606 my ($storecfg, $vmid, $drive) = @_;
1609 my $volid = $drive->{file
};
1612 if (drive_is_cdrom
($drive)) {
1613 $path = get_iso_path
($storecfg, $vmid, $volid);
1615 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1617 $path = PVE
::Storage
::path
($storecfg, $volid);
1618 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1619 $format = qemu_img_format
($scfg, $volname);
1627 my @qemu_drive_options = qw(heads secs cyls trans media format cache rerror werror aio discard);
1628 foreach my $o (@qemu_drive_options) {
1629 $opts .= ",$o=$drive->{$o}" if defined($drive->{$o});
1632 # snapshot only accepts on|off
1633 if (defined($drive->{snapshot
})) {
1634 my $v = $drive->{snapshot
} ?
'on' : 'off';
1635 $opts .= ",snapshot=$v";
1638 foreach my $type (['', '-total'], [_rd
=> '-read'], [_wr
=> '-write']) {
1639 my ($dir, $qmpname) = @$type;
1640 if (my $v = $drive->{"mbps$dir"}) {
1641 $opts .= ",throttling.bps$qmpname=".int($v*1024*1024);
1643 if (my $v = $drive->{"mbps${dir}_max"}) {
1644 $opts .= ",throttling.bps$qmpname-max=".int($v*1024*1024);
1646 if (my $v = $drive->{"bps${dir}_max_length"}) {
1647 $opts .= ",throttling.bps$qmpname-max-length=$v";
1649 if (my $v = $drive->{"iops${dir}"}) {
1650 $opts .= ",throttling.iops$qmpname=$v";
1652 if (my $v = $drive->{"iops${dir}_max"}) {
1653 $opts .= ",throttling.iops$qmpname-max=$v";
1655 if (my $v = $drive->{"iops${dir}_max_length"}) {
1656 $opts .= ",throttling.iops$qmpname-max-length=$v";
1660 if (my $serial = $drive->{serial
}) {
1661 $serial = URI
::Escape
::uri_unescape
($serial);
1662 $opts .= ",serial=$serial";
1665 $opts .= ",format=$format" if $format && !$drive->{format
};
1667 my $cache_direct = 0;
1669 if (my $cache = $drive->{cache
}) {
1670 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1671 } elsif (!drive_is_cdrom
($drive)) {
1672 $opts .= ",cache=none";
1676 # aio native works only with O_DIRECT
1677 if (!$drive->{aio
}) {
1679 $opts .= ",aio=native";
1681 $opts .= ",aio=threads";
1685 if (!drive_is_cdrom
($drive)) {
1687 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1688 $detectzeroes = 'off';
1689 } elsif ($drive->{discard
}) {
1690 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1692 # This used to be our default with discard not being specified:
1693 $detectzeroes = 'on';
1695 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1698 my $pathinfo = $path ?
"file=$path," : '';
1700 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1703 sub print_netdevice_full
{
1704 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1706 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1708 my $device = $net->{model
};
1709 if ($net->{model
} eq 'virtio') {
1710 $device = 'virtio-net-pci';
1713 my $pciaddr = print_pci_addr
("$netid", $bridges);
1714 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1715 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1716 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1717 my $vectors = $net->{queues
} * 2 + 2;
1718 $tmpstr .= ",vectors=$vectors,mq=on";
1720 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1722 if ($use_old_bios_files) {
1724 if ($device eq 'virtio-net-pci') {
1725 $romfile = 'pxe-virtio.rom';
1726 } elsif ($device eq 'e1000') {
1727 $romfile = 'pxe-e1000.rom';
1728 } elsif ($device eq 'ne2k') {
1729 $romfile = 'pxe-ne2k_pci.rom';
1730 } elsif ($device eq 'pcnet') {
1731 $romfile = 'pxe-pcnet.rom';
1732 } elsif ($device eq 'rtl8139') {
1733 $romfile = 'pxe-rtl8139.rom';
1735 $tmpstr .= ",romfile=$romfile" if $romfile;
1741 sub print_netdev_full
{
1742 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1745 if ($netid =~ m/^net(\d+)$/) {
1749 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1751 my $ifname = "tap${vmid}i$i";
1753 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1754 die "interface name '$ifname' is too long (max 15 character)\n"
1755 if length($ifname) >= 16;
1757 my $vhostparam = '';
1758 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1760 my $vmname = $conf->{name
} || "vm$vmid";
1763 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1765 if ($net->{bridge
}) {
1766 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1768 $netdev = "type=user,id=$netid,hostname=$vmname";
1771 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1777 sub print_cpu_device
{
1778 my ($conf, $id) = @_;
1780 my $kvm = $conf->{kvm
} // 1;
1781 my $cpu = $kvm ?
"kvm64" : "qemu64";
1782 if (my $cputype = $conf->{cpu
}) {
1783 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1784 or die "Cannot parse cpu description: $cputype\n";
1785 $cpu = $cpuconf->{cputype
};
1788 my $cores = $conf->{cores
} || 1;
1790 my $current_core = ($id - 1) % $cores;
1791 my $current_socket = int(($id - 1 - $current_core)/$cores);
1793 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1796 sub drive_is_cdrom
{
1799 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1803 sub parse_number_sets
{
1806 foreach my $part (split(/;/, $set)) {
1807 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1808 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1809 push @$res, [ $1, $2 ];
1811 die "invalid range: $part\n";
1820 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1821 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1822 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1829 return undef if !$value;
1831 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1833 my @idlist = split(/;/, $res->{host
});
1834 delete $res->{host
};
1835 foreach my $id (@idlist) {
1836 if ($id =~ /^$PCIRE$/) {
1838 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1840 my $pcidevices = lspci
($1);
1841 $res->{pciid
} = $pcidevices->{$1};
1844 # should have been caught by parse_property_string already
1845 die "failed to parse PCI id: $id\n";
1851 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1855 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1860 if (!defined($res->{macaddr
})) {
1861 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1862 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1870 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1873 sub add_random_macs
{
1874 my ($settings) = @_;
1876 foreach my $opt (keys %$settings) {
1877 next if $opt !~ m/^net(\d+)$/;
1878 my $net = parse_net
($settings->{$opt});
1880 $settings->{$opt} = print_net
($net);
1884 sub vm_is_volid_owner
{
1885 my ($storecfg, $vmid, $volid) = @_;
1887 if ($volid !~ m
|^/|) {
1889 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1890 if ($owner && ($owner == $vmid)) {
1898 sub split_flagged_list
{
1899 my $text = shift || '';
1900 $text =~ s/[,;]/ /g;
1902 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1905 sub join_flagged_list
{
1906 my ($how, $lst) = @_;
1907 join $how, map { $lst->{$_} . $_ } keys %$lst;
1910 sub vmconfig_delete_pending_option
{
1911 my ($conf, $key, $force) = @_;
1913 delete $conf->{pending
}->{$key};
1914 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1915 $pending_delete_hash->{$key} = $force ?
'!' : '';
1916 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1919 sub vmconfig_undelete_pending_option
{
1920 my ($conf, $key) = @_;
1922 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1923 delete $pending_delete_hash->{$key};
1925 if (%$pending_delete_hash) {
1926 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1928 delete $conf->{pending
}->{delete};
1932 sub vmconfig_register_unused_drive
{
1933 my ($storecfg, $vmid, $conf, $drive) = @_;
1935 if (!drive_is_cdrom
($drive)) {
1936 my $volid = $drive->{file
};
1937 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1938 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1943 sub vmconfig_cleanup_pending
{
1946 # remove pending changes when nothing changed
1948 foreach my $opt (keys %{$conf->{pending
}}) {
1949 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1951 delete $conf->{pending
}->{$opt};
1955 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1956 my $pending_delete_hash = {};
1957 while (my ($opt, $force) = each %$current_delete_hash) {
1958 if (defined($conf->{$opt})) {
1959 $pending_delete_hash->{$opt} = $force;
1965 if (%$pending_delete_hash) {
1966 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1968 delete $conf->{pending
}->{delete};
1974 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1978 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1979 format_description
=> 'UUID',
1980 description
=> "Set SMBIOS1 UUID.",
1986 format_description
=> 'string',
1987 description
=> "Set SMBIOS1 version.",
1993 format_description
=> 'string',
1994 description
=> "Set SMBIOS1 serial number.",
2000 format_description
=> 'string',
2001 description
=> "Set SMBIOS1 manufacturer.",
2007 format_description
=> 'string',
2008 description
=> "Set SMBIOS1 product ID.",
2014 format_description
=> 'string',
2015 description
=> "Set SMBIOS1 SKU string.",
2021 format_description
=> 'string',
2022 description
=> "Set SMBIOS1 family string.",
2030 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
2037 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
2040 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
2042 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
2043 sub verify_bootdisk
{
2044 my ($value, $noerr) = @_;
2046 return $value if is_valid_drivename
($value);
2048 return undef if $noerr;
2050 die "invalid boot disk '$value'\n";
2053 sub parse_watchdog
{
2056 return undef if !$value;
2058 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
2063 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
2064 sub verify_usb_device
{
2065 my ($value, $noerr) = @_;
2067 return $value if parse_usb_device
($value);
2069 return undef if $noerr;
2071 die "unable to parse usb device\n";
2074 # add JSON properties for create and set function
2075 sub json_config_properties
{
2078 foreach my $opt (keys %$confdesc) {
2079 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2080 $prop->{$opt} = $confdesc->{$opt};
2087 my ($key, $value) = @_;
2089 die "unknown setting '$key'\n" if !$confdesc->{$key};
2091 my $type = $confdesc->{$key}->{type
};
2093 if (!defined($value)) {
2094 die "got undefined value\n";
2097 if ($value =~ m/[\n\r]/) {
2098 die "property contains a line feed\n";
2101 if ($type eq 'boolean') {
2102 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2103 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2104 die "type check ('boolean') failed - got '$value'\n";
2105 } elsif ($type eq 'integer') {
2106 return int($1) if $value =~ m/^(\d+)$/;
2107 die "type check ('integer') failed - got '$value'\n";
2108 } elsif ($type eq 'number') {
2109 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2110 die "type check ('number') failed - got '$value'\n";
2111 } elsif ($type eq 'string') {
2112 if (my $fmt = $confdesc->{$key}->{format
}) {
2113 PVE
::JSONSchema
::check_format
($fmt, $value);
2116 $value =~ s/^\"(.*)\"$/$1/;
2119 die "internal error"
2123 sub check_iommu_support
{
2124 #fixme : need to check IOMMU support
2125 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2135 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2136 utime undef, undef, $conf;
2140 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2142 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2144 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2146 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2148 if ($conf->{template
}) {
2149 # check if any base image is still used by a linked clone
2150 foreach_drive
($conf, sub {
2151 my ($ds, $drive) = @_;
2153 return if drive_is_cdrom
($drive);
2155 my $volid = $drive->{file
};
2157 return if !$volid || $volid =~ m
|^/|;
2159 die "base volume '$volid' is still in use by linked cloned\n"
2160 if PVE
::Storage
::volume_is_base_and_used
($storecfg, $volid);
2165 # only remove disks owned by this VM
2166 foreach_drive
($conf, sub {
2167 my ($ds, $drive) = @_;
2169 return if drive_is_cdrom
($drive);
2171 my $volid = $drive->{file
};
2173 return if !$volid || $volid =~ m
|^/|;
2175 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2176 return if !$path || !$owner || ($owner != $vmid);
2179 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2181 warn "Could not remove disk '$volid', check manually: $@" if $@;
2185 if ($keep_empty_config) {
2186 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2191 # also remove unused disk
2193 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2196 PVE
::Storage
::foreach_volid
($dl, sub {
2197 my ($volid, $sid, $volname, $d) = @_;
2198 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2207 sub parse_vm_config
{
2208 my ($filename, $raw) = @_;
2210 return undef if !defined($raw);
2213 digest
=> Digest
::SHA
::sha1_hex
($raw),
2218 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2219 || die "got strange filename '$filename'";
2227 my @lines = split(/\n/, $raw);
2228 foreach my $line (@lines) {
2229 next if $line =~ m/^\s*$/;
2231 if ($line =~ m/^\[PENDING\]\s*$/i) {
2232 $section = 'pending';
2233 if (defined($descr)) {
2235 $conf->{description
} = $descr;
2238 $conf = $res->{$section} = {};
2241 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2243 if (defined($descr)) {
2245 $conf->{description
} = $descr;
2248 $conf = $res->{snapshots
}->{$section} = {};
2252 if ($line =~ m/^\#(.*)\s*$/) {
2253 $descr = '' if !defined($descr);
2254 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2258 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2259 $descr = '' if !defined($descr);
2260 $descr .= PVE
::Tools
::decode_text
($2);
2261 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2262 $conf->{snapstate
} = $1;
2263 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2266 $conf->{$key} = $value;
2267 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2269 if ($section eq 'pending') {
2270 $conf->{delete} = $value; # we parse this later
2272 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2274 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2277 eval { $value = check_type
($key, $value); };
2279 warn "vm $vmid - unable to parse value of '$key' - $@";
2281 $key = 'ide2' if $key eq 'cdrom';
2282 my $fmt = $confdesc->{$key}->{format
};
2283 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2284 my $v = parse_drive
($key, $value);
2285 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2286 $v->{file
} = $volid;
2287 $value = print_drive
($vmid, $v);
2289 warn "vm $vmid - unable to parse value of '$key'\n";
2294 $conf->{$key} = $value;
2299 if (defined($descr)) {
2301 $conf->{description
} = $descr;
2303 delete $res->{snapstate
}; # just to be sure
2308 sub write_vm_config
{
2309 my ($filename, $conf) = @_;
2311 delete $conf->{snapstate
}; # just to be sure
2313 if ($conf->{cdrom
}) {
2314 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2315 $conf->{ide2
} = $conf->{cdrom
};
2316 delete $conf->{cdrom
};
2319 # we do not use 'smp' any longer
2320 if ($conf->{sockets
}) {
2321 delete $conf->{smp
};
2322 } elsif ($conf->{smp
}) {
2323 $conf->{sockets
} = $conf->{smp
};
2324 delete $conf->{cores
};
2325 delete $conf->{smp
};
2328 my $used_volids = {};
2330 my $cleanup_config = sub {
2331 my ($cref, $pending, $snapname) = @_;
2333 foreach my $key (keys %$cref) {
2334 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2335 $key eq 'snapstate' || $key eq 'pending';
2336 my $value = $cref->{$key};
2337 if ($key eq 'delete') {
2338 die "propertry 'delete' is only allowed in [PENDING]\n"
2340 # fixme: check syntax?
2343 eval { $value = check_type
($key, $value); };
2344 die "unable to parse value of '$key' - $@" if $@;
2346 $cref->{$key} = $value;
2348 if (!$snapname && is_valid_drivename
($key)) {
2349 my $drive = parse_drive
($key, $value);
2350 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2355 &$cleanup_config($conf);
2357 &$cleanup_config($conf->{pending
}, 1);
2359 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2360 die "internal error" if $snapname eq 'pending';
2361 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2364 # remove 'unusedX' settings if we re-add a volume
2365 foreach my $key (keys %$conf) {
2366 my $value = $conf->{$key};
2367 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2368 delete $conf->{$key};
2372 my $generate_raw_config = sub {
2373 my ($conf, $pending) = @_;
2377 # add description as comment to top of file
2378 if (defined(my $descr = $conf->{description
})) {
2380 foreach my $cl (split(/\n/, $descr)) {
2381 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2384 $raw .= "#\n" if $pending;
2388 foreach my $key (sort keys %$conf) {
2389 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2390 $raw .= "$key: $conf->{$key}\n";
2395 my $raw = &$generate_raw_config($conf);
2397 if (scalar(keys %{$conf->{pending
}})){
2398 $raw .= "\n[PENDING]\n";
2399 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2402 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2403 $raw .= "\n[$snapname]\n";
2404 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2414 # we use static defaults from our JSON schema configuration
2415 foreach my $key (keys %$confdesc) {
2416 if (defined(my $default = $confdesc->{$key}->{default})) {
2417 $res->{$key} = $default;
2421 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2422 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2428 my $vmlist = PVE
::Cluster
::get_vmlist
();
2430 return $res if !$vmlist || !$vmlist->{ids
};
2431 my $ids = $vmlist->{ids
};
2433 foreach my $vmid (keys %$ids) {
2434 my $d = $ids->{$vmid};
2435 next if !$d->{node
} || $d->{node
} ne $nodename;
2436 next if !$d->{type
} || $d->{type
} ne 'qemu';
2437 $res->{$vmid}->{exists} = 1;
2442 # test if VM uses local resources (to prevent migration)
2443 sub check_local_resources
{
2444 my ($conf, $noerr) = @_;
2448 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2449 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2451 foreach my $k (keys %$conf) {
2452 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2453 # sockets are safe: they will recreated be on the target side post-migrate
2454 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2455 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2458 die "VM uses local resources\n" if $loc_res && !$noerr;
2463 # check if used storages are available on all nodes (use by migrate)
2464 sub check_storage_availability
{
2465 my ($storecfg, $conf, $node) = @_;
2467 foreach_drive
($conf, sub {
2468 my ($ds, $drive) = @_;
2470 my $volid = $drive->{file
};
2473 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2476 # check if storage is available on both nodes
2477 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2478 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2482 # list nodes where all VM images are available (used by has_feature API)
2484 my ($conf, $storecfg) = @_;
2486 my $nodelist = PVE
::Cluster
::get_nodelist
();
2487 my $nodehash = { map { $_ => 1 } @$nodelist };
2488 my $nodename = PVE
::INotify
::nodename
();
2490 foreach_drive
($conf, sub {
2491 my ($ds, $drive) = @_;
2493 my $volid = $drive->{file
};
2496 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2498 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2499 if ($scfg->{disable
}) {
2501 } elsif (my $avail = $scfg->{nodes
}) {
2502 foreach my $node (keys %$nodehash) {
2503 delete $nodehash->{$node} if !$avail->{$node};
2505 } elsif (!$scfg->{shared
}) {
2506 foreach my $node (keys %$nodehash) {
2507 delete $nodehash->{$node} if $node ne $nodename
2517 my ($pidfile, $pid) = @_;
2519 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2523 return undef if !$line;
2524 my @param = split(/\0/, $line);
2526 my $cmd = $param[0];
2527 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2529 for (my $i = 0; $i < scalar (@param); $i++) {
2532 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2533 my $p = $param[$i+1];
2534 return 1 if $p && ($p eq $pidfile);
2543 my ($vmid, $nocheck, $node) = @_;
2545 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2547 die "unable to find configuration file for VM $vmid - no such machine\n"
2548 if !$nocheck && ! -f
$filename;
2550 my $pidfile = pidfile_name
($vmid);
2552 if (my $fd = IO
::File-
>new("<$pidfile")) {
2557 my $mtime = $st->mtime;
2558 if ($mtime > time()) {
2559 warn "file '$filename' modified in future\n";
2562 if ($line =~ m/^(\d+)$/) {
2564 if (check_cmdline
($pidfile, $pid)) {
2565 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2577 my $vzlist = config_list
();
2579 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2581 while (defined(my $de = $fd->read)) {
2582 next if $de !~ m/^(\d+)\.pid$/;
2584 next if !defined($vzlist->{$vmid});
2585 if (my $pid = check_running
($vmid)) {
2586 $vzlist->{$vmid}->{pid
} = $pid;
2594 my ($storecfg, $conf) = @_;
2596 my $bootdisk = $conf->{bootdisk
};
2597 return undef if !$bootdisk;
2598 return undef if !is_valid_drivename
($bootdisk);
2600 return undef if !$conf->{$bootdisk};
2602 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2603 return undef if !defined($drive);
2605 return undef if drive_is_cdrom
($drive);
2607 my $volid = $drive->{file
};
2608 return undef if !$volid;
2610 return $drive->{size
};
2613 my $last_proc_pid_stat;
2615 # get VM status information
2616 # This must be fast and should not block ($full == false)
2617 # We only query KVM using QMP if $full == true (this can be slow)
2619 my ($opt_vmid, $full) = @_;
2623 my $storecfg = PVE
::Storage
::config
();
2625 my $list = vzlist
();
2626 my $defaults = load_defaults
();
2628 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2630 my $cpucount = $cpuinfo->{cpus
} || 1;
2632 foreach my $vmid (keys %$list) {
2633 next if $opt_vmid && ($vmid ne $opt_vmid);
2635 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2636 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2639 $d->{pid
} = $list->{$vmid}->{pid
};
2641 # fixme: better status?
2642 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2644 my $size = disksize
($storecfg, $conf);
2645 if (defined($size)) {
2646 $d->{disk
} = 0; # no info available
2647 $d->{maxdisk
} = $size;
2653 $d->{cpus
} = ($conf->{sockets
} || $defaults->{sockets
})
2654 * ($conf->{cores
} || $defaults->{cores
});
2655 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2656 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2658 $d->{name
} = $conf->{name
} || "VM $vmid";
2659 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024)
2660 : $defaults->{memory
}*(1024*1024);
2662 if ($conf->{balloon
}) {
2663 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2664 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
}
2665 : $defaults->{shares
};
2676 $d->{diskwrite
} = 0;
2678 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2680 $d->{serial
} = 1 if conf_has_serial
($conf);
2685 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2686 foreach my $dev (keys %$netdev) {
2687 next if $dev !~ m/^tap([1-9]\d*)i/;
2689 my $d = $res->{$vmid};
2692 $d->{netout
} += $netdev->{$dev}->{receive
};
2693 $d->{netin
} += $netdev->{$dev}->{transmit
};
2696 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2697 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2702 my $ctime = gettimeofday
;
2704 foreach my $vmid (keys %$list) {
2706 my $d = $res->{$vmid};
2707 my $pid = $d->{pid
};
2710 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2711 next if !$pstat; # not running
2713 my $used = $pstat->{utime} + $pstat->{stime
};
2715 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2717 if ($pstat->{vsize
}) {
2718 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2721 my $old = $last_proc_pid_stat->{$pid};
2723 $last_proc_pid_stat->{$pid} = {
2731 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2733 if ($dtime > 1000) {
2734 my $dutime = $used - $old->{used
};
2736 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2737 $last_proc_pid_stat->{$pid} = {
2743 $d->{cpu
} = $old->{cpu
};
2747 return $res if !$full;
2749 my $qmpclient = PVE
::QMPClient-
>new();
2751 my $ballooncb = sub {
2752 my ($vmid, $resp) = @_;
2754 my $info = $resp->{'return'};
2755 return if !$info->{max_mem
};
2757 my $d = $res->{$vmid};
2759 # use memory assigned to VM
2760 $d->{maxmem
} = $info->{max_mem
};
2761 $d->{balloon
} = $info->{actual
};
2763 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2764 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2765 $d->{freemem
} = $info->{free_mem
};
2768 $d->{ballooninfo
} = $info;
2771 my $blockstatscb = sub {
2772 my ($vmid, $resp) = @_;
2773 my $data = $resp->{'return'} || [];
2774 my $totalrdbytes = 0;
2775 my $totalwrbytes = 0;
2777 for my $blockstat (@$data) {
2778 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2779 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2781 $blockstat->{device
} =~ s/drive-//;
2782 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2784 $res->{$vmid}->{diskread
} = $totalrdbytes;
2785 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2788 my $statuscb = sub {
2789 my ($vmid, $resp) = @_;
2791 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2792 # this fails if ballon driver is not loaded, so this must be
2793 # the last commnand (following command are aborted if this fails).
2794 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2796 my $status = 'unknown';
2797 if (!defined($status = $resp->{'return'}->{status
})) {
2798 warn "unable to get VM status\n";
2802 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2805 foreach my $vmid (keys %$list) {
2806 next if $opt_vmid && ($vmid ne $opt_vmid);
2807 next if !$res->{$vmid}->{pid
}; # not running
2808 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2811 $qmpclient->queue_execute(undef, 2);
2813 foreach my $vmid (keys %$list) {
2814 next if $opt_vmid && ($vmid ne $opt_vmid);
2815 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2822 my ($conf, $func, @param) = @_;
2824 foreach my $ds (valid_drive_names
()) {
2825 next if !defined($conf->{$ds});
2827 my $drive = parse_drive
($ds, $conf->{$ds});
2830 &$func($ds, $drive, @param);
2835 my ($conf, $func, @param) = @_;
2839 my $test_volid = sub {
2840 my ($volid, $is_cdrom, $replicate, $snapname) = @_;
2844 $volhash->{$volid}->{cdrom
} //= 1;
2845 $volhash->{$volid}->{cdrom
} = 0 if !$is_cdrom;
2847 $volhash->{$volid}->{replicate
} //= 0;
2848 $volhash->{$volid}->{replicate
} = 1 if $replicate;
2850 $volhash->{$volid}->{referenced_in_config
} //= 0;
2851 $volhash->{$volid}->{referenced_in_config
} = 1 if !defined($snapname);
2853 $volhash->{$volid}->{referenced_in_snapshot
}->{$snapname} = 1
2854 if defined($snapname);
2857 foreach_drive
($conf, sub {
2858 my ($ds, $drive) = @_;
2859 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, undef);
2862 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2863 my $snap = $conf->{snapshots
}->{$snapname};
2864 $test_volid->($snap->{vmstate
}, 0, 1, $snapname);
2865 foreach_drive
($snap, sub {
2866 my ($ds, $drive) = @_;
2867 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, $snapname);
2871 foreach my $volid (keys %$volhash) {
2872 &$func($volid, $volhash->{$volid}, @param);
2876 sub conf_has_serial
{
2879 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2880 if ($conf->{"serial$i"}) {
2888 sub vga_conf_has_spice
{
2891 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2896 sub config_to_command
{
2897 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2900 my $globalFlags = [];
2901 my $machineFlags = [];
2907 my $kvmver = kvm_user_version
();
2908 my $vernum = 0; # unknown
2909 my $ostype = $conf->{ostype
};
2910 my $winversion = windows_version
($ostype);
2911 my $kvm = $conf->{kvm
} // 1;
2913 die "KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.\n" if (!$cpuinfo->{hvm
} && $kvm);
2915 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2916 $vernum = $1*1000000+$2*1000;
2917 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2918 $vernum = $1*1000000+$2*1000+$3;
2921 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2923 my $have_ovz = -f
'/proc/vz/vestat';
2925 my $q35 = machine_type_is_q35
($conf);
2926 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2927 my $machine_type = $forcemachine || $conf->{machine
};
2928 my $use_old_bios_files = undef;
2929 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2931 my $cpuunits = defined($conf->{cpuunits
}) ?
2932 $conf->{cpuunits
} : $defaults->{cpuunits
};
2934 push @$cmd, '/usr/bin/kvm';
2936 push @$cmd, '-id', $vmid;
2940 my $qmpsocket = qmp_socket
($vmid);
2941 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2942 push @$cmd, '-mon', "chardev=qmp,mode=control";
2945 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2947 push @$cmd, '-daemonize';
2949 if ($conf->{smbios1
}) {
2950 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2953 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2954 die "uefi base image not found\n" if ! -f
$OVMF_CODE;
2958 if (my $efidisk = $conf->{efidisk0
}) {
2959 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $efidisk);
2960 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
2961 $format = $d->{format
};
2963 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
2964 if (!defined($format)) {
2965 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2966 $format = qemu_img_format
($scfg, $volname);
2970 die "efidisk format must be specified\n"
2971 if !defined($format);
2974 warn "no efidisk configured! Using temporary efivars disk.\n";
2975 $path = "/tmp/$vmid-ovmf.fd";
2976 PVE
::Tools
::file_copy
($OVMF_VARS, $path, -s
$OVMF_VARS);
2980 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$OVMF_CODE";
2981 push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0,file=$path";
2985 # add usb controllers
2986 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2987 push @$devices, @usbcontrollers if @usbcontrollers;
2988 my $vga = $conf->{vga
};
2990 my $qxlnum = vga_conf_has_spice
($vga);
2991 $vga = 'qxl' if $qxlnum;
2994 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 9)) {
2995 $vga = (!$winversion || $winversion >= 6) ?
'std' : 'cirrus';
2997 $vga = ($winversion >= 6) ?
'std' : 'cirrus';
3001 # enable absolute mouse coordinates (needed by vnc)
3003 if (defined($conf->{tablet
})) {
3004 $tablet = $conf->{tablet
};
3006 $tablet = $defaults->{tablet
};
3007 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
3008 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
3011 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
3014 my $gpu_passthrough;
3017 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3018 my $d = parse_hostpci
($conf->{"hostpci$i"});
3021 my $pcie = $d->{pcie
};
3023 die "q35 machine model is not enabled" if !$q35;
3024 $pciaddr = print_pcie_addr
("hostpci$i");
3026 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
3029 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
3030 my $romfile = $d->{romfile
};
3033 if ($d->{'x-vga'}) {
3034 $xvga = ',x-vga=on';
3037 $gpu_passthrough = 1;
3039 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
3043 my $pcidevices = $d->{pciid
};
3044 my $multifunction = 1 if @$pcidevices > 1;
3047 foreach my $pcidevice (@$pcidevices) {
3049 my $id = "hostpci$i";
3050 $id .= ".$j" if $multifunction;
3051 my $addr = $pciaddr;
3052 $addr .= ".$j" if $multifunction;
3053 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
3056 $devicestr .= "$rombar$xvga";
3057 $devicestr .= ",multifunction=on" if $multifunction;
3058 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
3061 push @$devices, '-device', $devicestr;
3067 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
3068 push @$devices, @usbdevices if @usbdevices;
3070 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
3071 if (my $path = $conf->{"serial$i"}) {
3072 if ($path eq 'socket') {
3073 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
3074 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
3075 push @$devices, '-device', "isa-serial,chardev=serial$i";
3077 die "no such serial device\n" if ! -c
$path;
3078 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
3079 push @$devices, '-device', "isa-serial,chardev=serial$i";
3085 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
3086 if (my $path = $conf->{"parallel$i"}) {
3087 die "no such parallel device\n" if ! -c
$path;
3088 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
3089 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
3090 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
3094 my $vmname = $conf->{name
} || "vm$vmid";
3096 push @$cmd, '-name', $vmname;
3099 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
3100 $sockets = $conf->{sockets
} if $conf->{sockets
};
3102 my $cores = $conf->{cores
} || 1;
3104 my $maxcpus = $sockets * $cores;
3106 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3108 my $allowed_vcpus = $cpuinfo->{cpus
};
3110 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3111 if ($allowed_vcpus < $maxcpus);
3113 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
3115 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3116 for (my $i = 2; $i <= $vcpus; $i++) {
3117 my $cpustr = print_cpu_device
($conf,$i);
3118 push @$cmd, '-device', $cpustr;
3123 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3125 push @$cmd, '-nodefaults';
3127 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3129 my $bootindex_hash = {};
3131 foreach my $o (split(//, $bootorder)) {
3132 $bootindex_hash->{$o} = $i*100;
3136 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3138 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3140 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3142 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3144 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3145 my $socket = vnc_socket
($vmid);
3146 push @$cmd, '-vnc', "unix:$socket,x509,password";
3148 push @$cmd, '-nographic';
3152 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3154 my $useLocaltime = $conf->{localtime};
3156 if ($winversion >= 5) { # windows
3157 $useLocaltime = 1 if !defined($conf->{localtime});
3159 # use time drift fix when acpi is enabled
3160 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3161 $tdf = 1 if !defined($conf->{tdf
});
3165 if ($winversion >= 6) {
3166 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3167 push @$cmd, '-no-hpet';
3170 push @$rtcFlags, 'driftfix=slew' if $tdf;
3173 push @$machineFlags, 'accel=tcg';
3176 if ($machine_type) {
3177 push @$machineFlags, "type=${machine_type}";
3180 if ($conf->{startdate
}) {
3181 push @$rtcFlags, "base=$conf->{startdate}";
3182 } elsif ($useLocaltime) {
3183 push @$rtcFlags, 'base=localtime';
3186 my $cpu = $kvm ?
"kvm64" : "qemu64";
3187 if (my $cputype = $conf->{cpu
}) {
3188 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3189 or die "Cannot parse cpu description: $cputype\n";
3190 $cpu = $cpuconf->{cputype
};
3191 $kvm_off = 1 if $cpuconf->{hidden
};
3193 if (defined(my $flags = $cpuconf->{flags
})) {
3194 push @$cpuFlags, split(";", $flags);
3198 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3200 push @$cpuFlags , '-x2apic'
3201 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3203 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3205 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3207 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3209 push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
3210 push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
3213 add_hyperv_enlightenments
($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios
}, $gpu_passthrough) if $kvm;
3215 push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm;
3217 push @$cpuFlags, 'kvm=off' if $kvm_off;
3219 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3220 die "internal error"; # should not happen
3222 push @$cpuFlags, "vendor=${cpu_vendor}"
3223 if $cpu_vendor ne 'default';
3225 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3227 push @$cmd, '-cpu', $cpu;
3229 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3231 push @$cmd, '-S' if $conf->{freeze
};
3233 # set keyboard layout
3234 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3235 push @$cmd, '-k', $kb if $kb;
3238 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3239 #push @$cmd, '-soundhw', 'es1370';
3240 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3242 if($conf->{agent
}) {
3243 my $qgasocket = qmp_socket
($vmid, 1);
3244 my $pciaddr = print_pci_addr
("qga0", $bridges);
3245 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3246 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3247 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3255 for(my $i = 1; $i < $qxlnum; $i++){
3256 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3257 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3260 # assume other OS works like Linux
3261 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3262 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3266 my $pciaddr = print_pci_addr
("spice", $bridges);
3268 my $nodename = PVE
::INotify
::nodename
();
3269 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3270 my @nodeaddrs = PVE
::Tools
::getaddrinfo_all
('localhost', family
=> $pfamily);
3271 die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
3272 my $localhost = PVE
::Network
::addr_to_ip
($nodeaddrs[0]->{addr
});
3273 $spice_port = PVE
::Tools
::next_spice_port
($pfamily, $localhost);
3275 push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
3277 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3278 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3279 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3282 # enable balloon by default, unless explicitly disabled
3283 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3284 $pciaddr = print_pci_addr
("balloon0", $bridges);
3285 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3288 if ($conf->{watchdog
}) {
3289 my $wdopts = parse_watchdog
($conf->{watchdog
});
3290 $pciaddr = print_pci_addr
("watchdog", $bridges);
3291 my $watchdog = $wdopts->{model
} || 'i6300esb';
3292 push @$devices, '-device', "$watchdog$pciaddr";
3293 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3297 my $scsicontroller = {};
3298 my $ahcicontroller = {};
3299 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3301 # Add iscsi initiator name if available
3302 if (my $initiator = get_initiator_name
()) {
3303 push @$devices, '-iscsi', "initiator-name=$initiator";
3306 foreach_drive
($conf, sub {
3307 my ($ds, $drive) = @_;
3309 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3310 push @$vollist, $drive->{file
};
3313 # ignore efidisk here, already added in bios/fw handling code above
3314 return if $drive->{interface
} eq 'efidisk';
3316 $use_virtio = 1 if $ds =~ m/^virtio/;
3318 if (drive_is_cdrom
($drive)) {
3319 if ($bootindex_hash->{d
}) {
3320 $drive->{bootindex
} = $bootindex_hash->{d
};
3321 $bootindex_hash->{d
} += 1;
3324 if ($bootindex_hash->{c
}) {
3325 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3326 $bootindex_hash->{c
} += 1;
3330 if($drive->{interface
} eq 'virtio'){
3331 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3334 if ($drive->{interface
} eq 'scsi') {
3336 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3338 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3339 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3342 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3343 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3344 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3345 } elsif ($drive->{iothread
}) {
3346 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3350 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3351 $queues = ",num_queues=$drive->{queues}";
3354 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3355 $scsicontroller->{$controller}=1;
3358 if ($drive->{interface
} eq 'sata') {
3359 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3360 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3361 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3362 $ahcicontroller->{$controller}=1;
3365 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3366 push @$devices, '-drive',$drive_cmd;
3367 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3370 for (my $i = 0; $i < $MAX_NETS; $i++) {
3371 next if !$conf->{"net$i"};
3372 my $d = parse_net
($conf->{"net$i"});
3375 $use_virtio = 1 if $d->{model
} eq 'virtio';
3377 if ($bootindex_hash->{n
}) {
3378 $d->{bootindex
} = $bootindex_hash->{n
};
3379 $bootindex_hash->{n
} += 1;
3382 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3383 push @$devices, '-netdev', $netdevfull;
3385 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3386 push @$devices, '-device', $netdevicefull;
3391 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3396 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3398 while (my ($k, $v) = each %$bridges) {
3399 $pciaddr = print_pci_addr
("pci.$k");
3400 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3405 if ($conf->{args
}) {
3406 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3410 push @$cmd, @$devices;
3411 push @$cmd, '-rtc', join(',', @$rtcFlags)
3412 if scalar(@$rtcFlags);
3413 push @$cmd, '-machine', join(',', @$machineFlags)
3414 if scalar(@$machineFlags);
3415 push @$cmd, '-global', join(',', @$globalFlags)
3416 if scalar(@$globalFlags);
3418 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3423 return "${var_run_tmpdir}/$vmid.vnc";
3429 my $res = vm_mon_cmd
($vmid, 'query-spice');
3431 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3435 my ($vmid, $qga) = @_;
3436 my $sockettype = $qga ?
'qga' : 'qmp';
3437 return "${var_run_tmpdir}/$vmid.$sockettype";
3442 return "${var_run_tmpdir}/$vmid.pid";
3445 sub vm_devices_list
{
3448 my $res = vm_mon_cmd
($vmid, 'query-pci');
3450 foreach my $pcibus (@$res) {
3451 foreach my $device (@{$pcibus->{devices
}}) {
3452 next if !$device->{'qdev_id'};
3453 if ($device->{'pci_bridge'}) {
3454 $devices->{$device->{'qdev_id'}} = 1;
3455 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3456 next if !$bridge_device->{'qdev_id'};
3457 $devices->{$bridge_device->{'qdev_id'}} = 1;
3458 $devices->{$device->{'qdev_id'}}++;
3461 $devices->{$device->{'qdev_id'}} = 1;
3466 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3467 foreach my $block (@$resblock) {
3468 if($block->{device
} =~ m/^drive-(\S+)/){
3473 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3474 foreach my $mice (@$resmice) {
3475 if ($mice->{name
} eq 'QEMU HID Tablet') {
3476 $devices->{tablet
} = 1;
3481 # for usb devices there is no query-usb
3482 # but we can iterate over the entries in
3483 # qom-list path=/machine/peripheral
3484 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3485 foreach my $per (@$resperipheral) {
3486 if ($per->{name
} =~ m/^usb\d+$/) {
3487 $devices->{$per->{name
}} = 1;
3495 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3497 my $q35 = machine_type_is_q35
($conf);
3499 my $devices_list = vm_devices_list
($vmid);
3500 return 1 if defined($devices_list->{$deviceid});
3502 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3504 if ($deviceid eq 'tablet') {
3506 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3508 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3510 die "usb hotplug currently not reliable\n";
3511 # since we can't reliably hot unplug all added usb devices
3512 # and usb passthrough disables live migration
3513 # we disable usb hotplugging for now
3514 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3516 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3518 qemu_iothread_add
($vmid, $deviceid, $device);
3520 qemu_driveadd
($storecfg, $vmid, $device);
3521 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3523 qemu_deviceadd
($vmid, $devicefull);
3524 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3526 eval { qemu_drivedel
($vmid, $deviceid); };
3531 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3534 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3535 my $pciaddr = print_pci_addr
($deviceid);
3536 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3538 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3540 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3541 qemu_iothread_add
($vmid, $deviceid, $device);
3542 $devicefull .= ",iothread=iothread-$deviceid";
3545 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3546 $devicefull .= ",num_queues=$device->{queues}";
3549 qemu_deviceadd
($vmid, $devicefull);
3550 qemu_deviceaddverify
($vmid, $deviceid);
3552 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3554 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3555 qemu_driveadd
($storecfg, $vmid, $device);
3557 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3558 eval { qemu_deviceadd
($vmid, $devicefull); };
3560 eval { qemu_drivedel
($vmid, $deviceid); };
3565 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3567 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3569 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3570 my $use_old_bios_files = undef;
3571 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3573 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3574 qemu_deviceadd
($vmid, $netdevicefull);
3575 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3577 eval { qemu_netdevdel
($vmid, $deviceid); };
3582 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3585 my $pciaddr = print_pci_addr
($deviceid);
3586 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3588 qemu_deviceadd
($vmid, $devicefull);
3589 qemu_deviceaddverify
($vmid, $deviceid);
3592 die "can't hotplug device '$deviceid'\n";
3598 # fixme: this should raise exceptions on error!
3599 sub vm_deviceunplug
{
3600 my ($vmid, $conf, $deviceid) = @_;
3602 my $devices_list = vm_devices_list
($vmid);
3603 return 1 if !defined($devices_list->{$deviceid});
3605 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3607 if ($deviceid eq 'tablet') {
3609 qemu_devicedel
($vmid, $deviceid);
3611 } elsif ($deviceid =~ m/^usb\d+$/) {
3613 die "usb hotplug currently not reliable\n";
3614 # when unplugging usb devices this way,
3615 # there may be remaining usb controllers/hubs
3616 # so we disable it for now
3617 qemu_devicedel
($vmid, $deviceid);
3618 qemu_devicedelverify
($vmid, $deviceid);
3620 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3622 qemu_devicedel
($vmid, $deviceid);
3623 qemu_devicedelverify
($vmid, $deviceid);
3624 qemu_drivedel
($vmid, $deviceid);
3625 qemu_iothread_del
($conf, $vmid, $deviceid);
3627 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3629 qemu_devicedel
($vmid, $deviceid);
3630 qemu_devicedelverify
($vmid, $deviceid);
3631 qemu_iothread_del
($conf, $vmid, $deviceid);
3633 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3635 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3636 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3637 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3639 qemu_devicedel
($vmid, $deviceid);
3640 qemu_drivedel
($vmid, $deviceid);
3641 qemu_deletescsihw
($conf, $vmid, $deviceid);
3643 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3645 qemu_devicedel
($vmid, $deviceid);
3646 qemu_devicedelverify
($vmid, $deviceid);
3647 qemu_netdevdel
($vmid, $deviceid);
3650 die "can't unplug device '$deviceid'\n";
3656 sub qemu_deviceadd
{
3657 my ($vmid, $devicefull) = @_;
3659 $devicefull = "driver=".$devicefull;
3660 my %options = split(/[=,]/, $devicefull);
3662 vm_mon_cmd
($vmid, "device_add" , %options);
3665 sub qemu_devicedel
{
3666 my ($vmid, $deviceid) = @_;
3668 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3671 sub qemu_iothread_add
{
3672 my($vmid, $deviceid, $device) = @_;
3674 if ($device->{iothread
}) {
3675 my $iothreads = vm_iothreads_list
($vmid);
3676 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3680 sub qemu_iothread_del
{
3681 my($conf, $vmid, $deviceid) = @_;
3683 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3684 if ($device->{iothread
}) {
3685 my $iothreads = vm_iothreads_list
($vmid);
3686 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3690 sub qemu_objectadd
{
3691 my($vmid, $objectid, $qomtype) = @_;
3693 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3698 sub qemu_objectdel
{
3699 my($vmid, $objectid) = @_;
3701 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3707 my ($storecfg, $vmid, $device) = @_;
3709 my $drive = print_drive_full
($storecfg, $vmid, $device);
3710 $drive =~ s/\\/\\\\/g;
3711 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3713 # If the command succeeds qemu prints: "OK
"
3714 return 1 if $ret =~ m/OK/s;
3716 die "adding drive failed
: $ret\n";
3720 my($vmid, $deviceid) = @_;
3722 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3725 return 1 if $ret eq "";
3727 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3728 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3730 die "deleting drive
$deviceid failed
: $ret\n";
3733 sub qemu_deviceaddverify {
3734 my ($vmid, $deviceid) = @_;
3736 for (my $i = 0; $i <= 5; $i++) {
3737 my $devices_list = vm_devices_list($vmid);
3738 return 1 if defined($devices_list->{$deviceid});
3742 die "error on hotplug device
'$deviceid'\n";
3746 sub qemu_devicedelverify {
3747 my ($vmid, $deviceid) = @_;
3749 # need to verify that the device is correctly removed as device_del
3750 # is async and empty return is not reliable
3752 for (my $i = 0; $i <= 5; $i++) {
3753 my $devices_list = vm_devices_list($vmid);
3754 return 1 if !defined($devices_list->{$deviceid});
3758 die "error on hot-unplugging device
'$deviceid'\n";
3761 sub qemu_findorcreatescsihw {
3762 my ($storecfg, $conf, $vmid, $device) = @_;
3764 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3766 my $scsihwid="$controller_prefix$controller";
3767 my $devices_list = vm_devices_list($vmid);
3769 if(!defined($devices_list->{$scsihwid})) {
3770 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3776 sub qemu_deletescsihw {
3777 my ($conf, $vmid, $opt) = @_;
3779 my $device = parse_drive($opt, $conf->{$opt});
3781 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3782 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3786 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3788 my $devices_list = vm_devices_list($vmid);
3789 foreach my $opt (keys %{$devices_list}) {
3790 if (PVE::QemuServer::is_valid_drivename($opt)) {
3791 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3792 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3798 my $scsihwid="scsihw
$controller";
3800 vm_deviceunplug($vmid, $conf, $scsihwid);
3805 sub qemu_add_pci_bridge {
3806 my ($storecfg, $conf, $vmid, $device) = @_;
3812 print_pci_addr($device, $bridges);
3814 while (my ($k, $v) = each %$bridges) {
3817 return 1 if !defined($bridgeid) || $bridgeid < 1;
3819 my $bridge = "pci
.$bridgeid";
3820 my $devices_list = vm_devices_list($vmid);
3822 if (!defined($devices_list->{$bridge})) {
3823 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3829 sub qemu_set_link_status {
3830 my ($vmid, $device, $up) = @_;
3832 vm_mon_cmd($vmid, "set_link
", name => $device,
3833 up => $up ? JSON::true : JSON::false);
3836 sub qemu_netdevadd {
3837 my ($vmid, $conf, $device, $deviceid) = @_;
3839 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3840 my %options = split(/[=,]/, $netdev);
3842 vm_mon_cmd($vmid, "netdev_add
", %options);
3846 sub qemu_netdevdel {
3847 my ($vmid, $deviceid) = @_;
3849 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3852 sub qemu_usb_hotplug {
3853 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3857 # remove the old one first
3858 vm_deviceunplug($vmid, $conf, $deviceid);
3860 # check if xhci controller is necessary and available
3861 if ($device->{usb3}) {
3863 my $devicelist = vm_devices_list($vmid);
3865 if (!$devicelist->{xhci}) {
3866 my $pciaddr = print_pci_addr("xhci
");
3867 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3870 my $d = parse_usb_device($device->{host});
3871 $d->{usb3} = $device->{usb3};
3874 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3877 sub qemu_cpu_hotplug {
3878 my ($vmid, $conf, $vcpus) = @_;
3880 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3883 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3884 $sockets = $conf->{sockets} if $conf->{sockets};
3885 my $cores = $conf->{cores} || 1;
3886 my $maxcpus = $sockets * $cores;
3888 $vcpus = $maxcpus if !$vcpus;
3890 die "you can
't add more vcpus than maxcpus\n"
3891 if $vcpus > $maxcpus;
3893 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3895 if ($vcpus < $currentvcpus) {
3897 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3899 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3900 qemu_devicedel($vmid, "cpu$i");
3902 my $currentrunningvcpus = undef;
3904 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3905 last if scalar(@{$currentrunningvcpus}) == $i-1;
3906 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3910 #update conf after each succesfull cpu unplug
3911 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3912 PVE::QemuConfig->write_config($vmid, $conf);
3915 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3921 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3922 die "vcpus in running vm does not match its configuration\n"
3923 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3925 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3927 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3928 my $cpustr = print_cpu_device($conf, $i);
3929 qemu_deviceadd($vmid, $cpustr);
3932 my $currentrunningvcpus = undef;
3934 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3935 last if scalar(@{$currentrunningvcpus}) == $i;
3936 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3940 #update conf after each succesfull cpu hotplug
3941 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3942 PVE::QemuConfig->write_config($vmid, $conf);
3946 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3947 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3952 sub qemu_block_set_io_throttle {
3953 my ($vmid, $deviceid,
3954 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3955 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3956 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3957 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3959 return if !check_running($vmid) ;
3961 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3963 bps_rd => int($bps_rd),
3964 bps_wr => int($bps_wr),
3966 iops_rd => int($iops_rd),
3967 iops_wr => int($iops_wr),
3968 bps_max => int($bps_max),
3969 bps_rd_max => int($bps_rd_max),
3970 bps_wr_max => int($bps_wr_max),
3971 iops_max => int($iops_max),
3972 iops_rd_max => int($iops_rd_max),
3973 iops_wr_max => int($iops_wr_max),
3974 bps_max_length => int($bps_max_length),
3975 bps_rd_max_length => int($bps_rd_max_length),
3976 bps_wr_max_length => int($bps_wr_max_length),
3977 iops_max_length => int($iops_max_length),
3978 iops_rd_max_length => int($iops_rd_max_length),
3979 iops_wr_max_length => int($iops_wr_max_length),
3984 # old code, only used to shutdown old VM after update
3986 my ($fh, $timeout) = @_;
3988 my $sel = new IO::Select;
3995 while (scalar (@ready = $sel->can_read($timeout))) {
3997 if ($count = $fh->sysread($buf, 8192)) {
3998 if ($buf =~ /^(.*)\(qemu\) $/s) {
4005 if (!defined($count)) {
4012 die "monitor read timeout\n" if !scalar(@ready);
4017 # old code, only used to shutdown old VM after update
4018 sub vm_monitor_command {
4019 my ($vmid, $cmdstr, $nocheck) = @_;
4024 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4026 my $sname = "${var_run_tmpdir}/$vmid.mon";
4028 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
4029 die "unable to connect to VM $vmid socket - $!\n";
4033 # hack: migrate sometime blocks the monitor (when migrate_downtime
4035 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4036 $timeout = 60*60; # 1 hour
4040 my $data = __read_avail($sock, $timeout);
4042 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
4043 die "got unexpected qemu monitor banner\n";
4046 my $sel = new IO::Select;
4049 if (!scalar(my @ready = $sel->can_write($timeout))) {
4050 die "monitor write error - timeout";
4053 my $fullcmd = "$cmdstr\r";
4055 # syslog('info
', "VM $vmid monitor command: $cmdstr");
4058 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4059 die "monitor write error - $!";
4062 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
4066 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4067 $timeout = 60*60; # 1 hour
4068 } elsif ($cmdstr =~ m/^(eject|change)/) {
4069 $timeout = 60; # note: cdrom mount command is slow
4071 if ($res = __read_avail($sock, $timeout)) {
4073 my @lines = split("\r?\n", $res);
4075 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4077 $res = join("\n", @lines);
4085 syslog("err", "VM $vmid monitor command failed - $err");
4092 sub qemu_block_resize {
4093 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4095 my $running = check_running($vmid);
4097 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4099 return if !$running;
4101 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4105 sub qemu_volume_snapshot {
4106 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4108 my $running = check_running($vmid);
4110 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4111 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4113 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4117 sub qemu_volume_snapshot_delete {
4118 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4120 my $running = check_running($vmid);
4122 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4123 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4125 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4129 sub set_migration_caps {
4135 "auto-converge" => 1,
4137 "x-rdma-pin-all" => 0,
4142 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4144 for my $supported_capability (@$supported_capabilities) {
4146 capability => $supported_capability->{capability},
4147 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4151 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4154 my $fast_plug_option = {
4162 'vmstatestorage
' => 1,
4165 # hotplug changes in [PENDING]
4166 # $selection hash can be used to only apply specified options, for
4167 # example: { cores => 1 } (only apply changed 'cores
')
4168 # $errors ref is used to return error messages
4169 sub vmconfig_hotplug_pending {
4170 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4172 my $defaults = load_defaults();
4174 # commit values which do not have any impact on running VM first
4175 # Note: those option cannot raise errors, we we do not care about
4176 # $selection and always apply them.
4178 my $add_error = sub {
4179 my ($opt, $msg) = @_;
4180 $errors->{$opt} = "hotplug problem - $msg";
4184 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4185 if ($fast_plug_option->{$opt}) {
4186 $conf->{$opt} = $conf->{pending}->{$opt};
4187 delete $conf->{pending}->{$opt};
4193 PVE::QemuConfig->write_config($vmid, $conf);
4194 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4197 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4199 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4200 while (my ($opt, $force) = each %$pending_delete_hash) {
4201 next if $selection && !$selection->{$opt};
4203 if ($opt eq 'hotplug
') {
4204 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4205 } elsif ($opt eq 'tablet
') {
4206 die "skip\n" if !$hotplug_features->{usb};
4207 if ($defaults->{tablet}) {
4208 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4210 vm_deviceunplug($vmid, $conf, $opt);
4212 } elsif ($opt =~ m/^usb\d+/) {
4214 # since we cannot reliably hot unplug usb devices
4215 # we are disabling it
4216 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4217 vm_deviceunplug($vmid, $conf, $opt);
4218 } elsif ($opt eq 'vcpus
') {
4219 die "skip\n" if !$hotplug_features->{cpu};
4220 qemu_cpu_hotplug($vmid, $conf, undef);
4221 } elsif ($opt eq 'balloon
') {
4222 # enable balloon device is not hotpluggable
4223 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4224 } elsif ($fast_plug_option->{$opt}) {
4226 } elsif ($opt =~ m/^net(\d+)$/) {
4227 die "skip\n" if !$hotplug_features->{network};
4228 vm_deviceunplug($vmid, $conf, $opt);
4229 } elsif (is_valid_drivename($opt)) {
4230 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4231 vm_deviceunplug($vmid, $conf, $opt);
4232 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4233 } elsif ($opt =~ m/^memory$/) {
4234 die "skip\n" if !$hotplug_features->{memory};
4235 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4236 } elsif ($opt eq 'cpuunits
') {
4237 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4238 } elsif ($opt eq 'cpulimit
') {
4239 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4245 &$add_error($opt, $err) if $err ne "skip\n";
4247 # save new config if hotplug was successful
4248 delete $conf->{$opt};
4249 vmconfig_undelete_pending_option($conf, $opt);
4250 PVE::QemuConfig->write_config($vmid, $conf);
4251 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4255 foreach my $opt (keys %{$conf->{pending}}) {
4256 next if $selection && !$selection->{$opt};
4257 my $value = $conf->{pending}->{$opt};
4259 if ($opt eq 'hotplug
') {
4260 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4261 } elsif ($opt eq 'tablet
') {
4262 die "skip\n" if !$hotplug_features->{usb};
4264 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4265 } elsif ($value == 0) {
4266 vm_deviceunplug($vmid, $conf, $opt);
4268 } elsif ($opt =~ m/^usb\d+$/) {
4270 # since we cannot reliably hot unplug usb devices
4271 # we are disabling it
4272 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4273 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4274 die "skip\n" if !$d;
4275 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4276 } elsif ($opt eq 'vcpus
') {
4277 die "skip\n" if !$hotplug_features->{cpu};
4278 qemu_cpu_hotplug($vmid, $conf, $value);
4279 } elsif ($opt eq 'balloon
') {
4280 # enable/disable balloning device is not hotpluggable
4281 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4282 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4283 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4285 # allow manual ballooning if shares is set to zero
4286 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4287 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4288 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4290 } elsif ($opt =~ m/^net(\d+)$/) {
4291 # some changes can be done without hotplug
4292 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4293 $vmid, $opt, $value);
4294 } elsif (is_valid_drivename($opt)) {
4295 # some changes can be done without hotplug
4296 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4297 $vmid, $opt, $value, 1);
4298 } elsif ($opt =~ m/^memory$/) { #dimms
4299 die "skip\n" if !$hotplug_features->{memory};
4300 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4301 } elsif ($opt eq 'cpuunits
') {
4302 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4303 } elsif ($opt eq 'cpulimit
') {
4304 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4305 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4307 die "skip\n"; # skip non-hot-pluggable options
4311 &$add_error($opt, $err) if $err ne "skip\n";
4313 # save new config if hotplug was successful
4314 $conf->{$opt} = $value;
4315 delete $conf->{pending}->{$opt};
4316 PVE::QemuConfig->write_config($vmid, $conf);
4317 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4322 sub try_deallocate_drive {
4323 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4325 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4326 my $volid = $drive->{file};
4327 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4328 my $sid = PVE::Storage::parse_volume_id($volid);
4329 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4331 # check if the disk is really unused
4332 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4333 if is_volume_in_use($storecfg, $conf, $key, $volid);
4334 PVE::Storage::vdisk_free($storecfg, $volid);
4337 # If vm is not owner of this disk remove from config
4345 sub vmconfig_delete_or_detach_drive {
4346 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4348 my $drive = parse_drive($opt, $conf->{$opt});
4350 my $rpcenv = PVE::RPCEnvironment::get();
4351 my $authuser = $rpcenv->get_user();
4354 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4355 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4357 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4361 sub vmconfig_apply_pending {
4362 my ($vmid, $conf, $storecfg) = @_;
4366 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4367 while (my ($opt, $force) = each %$pending_delete_hash) {
4368 die "internal error" if $opt =~ m/^unused/;
4369 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4370 if (!defined($conf->{$opt})) {
4371 vmconfig_undelete_pending_option($conf, $opt);
4372 PVE::QemuConfig->write_config($vmid, $conf);
4373 } elsif (is_valid_drivename($opt)) {
4374 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4375 vmconfig_undelete_pending_option($conf, $opt);
4376 delete $conf->{$opt};
4377 PVE::QemuConfig->write_config($vmid, $conf);
4379 vmconfig_undelete_pending_option($conf, $opt);
4380 delete $conf->{$opt};
4381 PVE::QemuConfig->write_config($vmid, $conf);
4385 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4387 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4388 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4390 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4391 # skip if nothing changed
4392 } elsif (is_valid_drivename($opt)) {
4393 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4394 if defined($conf->{$opt});
4395 $conf->{$opt} = $conf->{pending}->{$opt};
4397 $conf->{$opt} = $conf->{pending}->{$opt};
4400 delete $conf->{pending}->{$opt};
4401 PVE::QemuConfig->write_config($vmid, $conf);
4405 my $safe_num_ne = sub {
4408 return 0 if !defined($a) && !defined($b);
4409 return 1 if !defined($a);
4410 return 1 if !defined($b);
4415 my $safe_string_ne = sub {
4418 return 0 if !defined($a) && !defined($b);
4419 return 1 if !defined($a);
4420 return 1 if !defined($b);
4425 sub vmconfig_update_net {
4426 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4428 my $newnet = parse_net($value);
4430 if ($conf->{$opt}) {
4431 my $oldnet = parse_net($conf->{$opt});
4433 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4434 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4435 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4436 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4438 # for non online change, we try to hot-unplug
4439 die "skip\n" if !$hotplug;
4440 vm_deviceunplug($vmid, $conf, $opt);
4443 die "internal error" if $opt !~ m/net(\d+)/;
4444 my $iface = "tap${vmid}i$1";
4446 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4447 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4448 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4449 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4450 PVE::Network::tap_unplug($iface);
4451 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4452 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4453 # Rate can be applied on its own but any change above needs to
4454 # include the rate in tap_plug since OVS resets everything.
4455 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4458 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4459 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4467 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4473 sub vmconfig_update_disk {
4474 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4476 # fixme: do we need force?
4478 my $drive = parse_drive($opt, $value);
4480 if ($conf->{$opt}) {
4482 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4484 my $media = $drive->{media} || 'disk
';
4485 my $oldmedia = $old_drive->{media} || 'disk
';
4486 die "unable to change media type\n" if $media ne $oldmedia;
4488 if (!drive_is_cdrom($old_drive)) {
4490 if ($drive->{file} ne $old_drive->{file}) {
4492 die "skip\n" if !$hotplug;
4494 # unplug and register as unused
4495 vm_deviceunplug($vmid, $conf, $opt);
4496 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4499 # update existing disk
4501 # skip non hotpluggable value
4502 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4503 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4504 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4505 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4510 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4511 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4512 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4513 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4514 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4515 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4516 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4517 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4518 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4519 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4520 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4521 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4522 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4523 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4524 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4525 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4526 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4527 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4529 qemu_block_set_io_throttle($vmid,"drive-$opt",
4530 ($drive->{mbps} || 0)*1024*1024,
4531 ($drive->{mbps_rd} || 0)*1024*1024,
4532 ($drive->{mbps_wr} || 0)*1024*1024,
4533 $drive->{iops} || 0,
4534 $drive->{iops_rd} || 0,
4535 $drive->{iops_wr} || 0,
4536 ($drive->{mbps_max} || 0)*1024*1024,
4537 ($drive->{mbps_rd_max} || 0)*1024*1024,
4538 ($drive->{mbps_wr_max} || 0)*1024*1024,
4539 $drive->{iops_max} || 0,
4540 $drive->{iops_rd_max} || 0,
4541 $drive->{iops_wr_max} || 0,
4542 $drive->{bps_max_length} || 1,
4543 $drive->{bps_rd_max_length} || 1,
4544 $drive->{bps_wr_max_length} || 1,
4545 $drive->{iops_max_length} || 1,
4546 $drive->{iops_rd_max_length} || 1,
4547 $drive->{iops_wr_max_length} || 1);
4556 if ($drive->{file} eq 'none
') {
4557 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4559 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4560 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4561 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4569 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4571 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4572 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4576 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4577 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
4579 PVE::QemuConfig->lock_config($vmid, sub {
4580 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4582 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4584 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4586 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4588 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4589 vmconfig_apply_pending($vmid, $conf, $storecfg);
4590 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4593 my $defaults = load_defaults();
4595 # set environment variable useful inside network script
4596 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4598 my $local_volumes = {};
4600 if ($targetstorage) {
4601 foreach_drive($conf, sub {
4602 my ($ds, $drive) = @_;
4604 return if drive_is_cdrom($drive);
4606 my $volid = $drive->{file};
4610 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
4612 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4613 return if $scfg->{shared};
4614 $local_volumes->{$ds} = [$volid, $storeid, $volname];
4619 foreach my $opt (sort keys %$local_volumes) {
4621 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
4622 my $drive = parse_drive($opt, $conf->{$opt});
4624 #if remote storage is specified, use default format
4625 if ($targetstorage && $targetstorage ne "1") {
4626 $storeid = $targetstorage;
4627 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4628 $format = $defFormat;
4630 #else we use same format than original
4631 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4632 $format = qemu_img_format($scfg, $volid);
4635 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
4636 my $newdrive = $drive;
4637 $newdrive->{format} = $format;
4638 $newdrive->{file} = $newvolid;
4639 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
4640 $local_volumes->{$opt} = $drivestr;
4641 #pass drive to conf for command line
4642 $conf->{$opt} = $drivestr;
4646 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4648 my $migrate_port = 0;
4651 if ($statefile eq 'tcp
') {
4652 my $localip = "localhost";
4653 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4654 my $nodename = PVE::INotify::nodename();
4656 if (!defined($migration_type)) {
4657 if (defined($datacenterconf->{migration}->{type})) {
4658 $migration_type = $datacenterconf->{migration}->{type};
4660 $migration_type = 'secure
';
4664 if ($migration_type eq 'insecure
') {
4665 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4666 if ($migrate_network_addr) {
4667 $localip = $migrate_network_addr;
4669 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4672 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4675 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4676 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4677 $migrate_uri = "tcp:${localip}:${migrate_port}";
4678 push @$cmd, '-incoming
', $migrate_uri;
4681 } elsif ($statefile eq 'unix
') {
4682 # should be default for secure migrations as a ssh TCP forward
4683 # tunnel is not deterministic reliable ready and fails regurarly
4684 # to set up in time, so use UNIX socket forwards
4685 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4686 unlink $socket_addr;
4688 $migrate_uri = "unix:$socket_addr";
4690 push @$cmd, '-incoming
', $migrate_uri;
4694 push @$cmd, '-loadstate
', $statefile;
4701 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4702 my $d = parse_hostpci($conf->{"hostpci$i"});
4704 my $pcidevices = $d->{pciid};
4705 foreach my $pcidevice (@$pcidevices) {
4706 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4708 my $info = pci_device_info("0000:$pciid");
4709 die "IOMMU not present\n" if !check_iommu_support();
4710 die "no pci device info for device '$pciid'\n" if !$info;
4711 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4712 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4716 PVE::Storage::activate_volumes($storecfg, $vollist);
4718 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4720 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4721 eval { run_command($cmd); };
4724 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4725 : $defaults->{cpuunits};
4727 my $start_timeout = $conf->{hugepages} ? 300 : 30;
4728 my %run_params = (timeout => $statefile ? undef : $start_timeout, umask => 0077);
4731 Slice => 'qemu
.slice
',
4733 CPUShares => $cpuunits
4736 if (my $cpulimit = $conf->{cpulimit}) {
4737 $properties{CPUQuota} = int($cpulimit * 100);
4739 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4741 if ($conf->{hugepages}) {
4744 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4745 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4747 PVE::QemuServer::Memory::hugepages_mount();
4748 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4751 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4752 run_command($cmd, %run_params);
4756 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4760 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4762 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4766 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4767 run_command($cmd, %run_params);
4772 # deactivate volumes if start fails
4773 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4774 die "start failed: $err";
4777 print "migration listens on $migrate_uri\n" if $migrate_uri;
4779 if ($statefile && $statefile ne 'tcp
' && $statefile ne 'unix
') {
4780 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4784 #start nbd server for storage migration
4785 if ($targetstorage) {
4786 my $nodename = PVE::INotify::nodename();
4787 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4788 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
4789 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4790 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4792 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet
', data => { host => "${localip}", port => "${migrate_port}" } } );
4794 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4796 foreach my $opt (sort keys %$local_volumes) {
4797 my $volid = $local_volumes->{$opt};
4798 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
4799 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
4800 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
4804 if ($migratedfrom) {
4806 set_migration_caps($vmid);
4811 print "spice listens on port $spice_port\n";
4812 if ($spice_ticket) {
4813 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4814 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4819 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4820 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4821 if $conf->{balloon};
4824 foreach my $opt (keys %$conf) {
4825 next if $opt !~ m/^net\d+$/;
4826 my $nicconf = parse_net($conf->{$opt});
4827 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4831 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4832 path => "machine/peripheral/balloon0",
4833 property => "guest-stats-polling-interval",
4834 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4840 my ($vmid, $execute, %params) = @_;
4842 my $cmd = { execute => $execute, arguments => \%params };
4843 vm_qmp_command($vmid, $cmd);
4846 sub vm_mon_cmd_nocheck {
4847 my ($vmid, $execute, %params) = @_;
4849 my $cmd = { execute => $execute, arguments => \%params };
4850 vm_qmp_command($vmid, $cmd, 1);
4853 sub vm_qmp_command {
4854 my ($vmid, $cmd, $nocheck) = @_;
4859 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4860 $timeout = $cmd->{arguments}->{timeout};
4861 delete $cmd->{arguments}->{timeout};
4865 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4866 my $sname = qmp_socket($vmid);
4867 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4868 my $qmpclient = PVE::QMPClient->new();
4870 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4871 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4872 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4873 if scalar(%{$cmd->{arguments}});
4874 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4876 die "unable to
open monitor
socket\n";
4880 syslog("err
", "VM
$vmid qmp command failed
- $err");
4887 sub vm_human_monitor_command {
4888 my ($vmid, $cmdline) = @_;
4893 execute => 'human-monitor-command',
4894 arguments => { 'command-line' => $cmdline},
4897 return vm_qmp_command($vmid, $cmd);
4900 sub vm_commandline {
4901 my ($storecfg, $vmid) = @_;
4903 my $conf = PVE::QemuConfig->load_config($vmid);
4905 my $defaults = load_defaults();
4907 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4909 return PVE::Tools::cmd2string($cmd);
4913 my ($vmid, $skiplock) = @_;
4915 PVE::QemuConfig->lock_config($vmid, sub {
4917 my $conf = PVE::QemuConfig->load_config($vmid);
4919 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4921 vm_mon_cmd($vmid, "system_reset
");
4925 sub get_vm_volumes {
4929 foreach_volid($conf, sub {
4930 my ($volid, $attr) = @_;
4932 return if $volid =~ m|^/|;
4934 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4937 push @$vollist, $volid;
4943 sub vm_stop_cleanup {
4944 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4949 my $vollist = get_vm_volumes($conf);
4950 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4953 foreach my $ext (qw(mon qmp pid vnc qga)) {
4954 unlink "/var/run/qemu-server/${vmid}.$ext";
4957 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4959 warn $@ if $@; # avoid errors - just warn
4962 # Note: use $nockeck to skip tests if VM configuration file exists.
4963 # We need that when migration VMs to other nodes (files already moved)
4964 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4966 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4968 $force = 1 if !defined($force) && !$shutdown;
4971 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4972 kill 15, $pid if $pid;
4973 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4974 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4978 PVE
::QemuConfig-
>lock_config($vmid, sub {
4980 my $pid = check_running
($vmid, $nocheck);
4985 $conf = PVE
::QemuConfig-
>load_config($vmid);
4986 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4987 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4988 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4989 $timeout = $opts->{down
} if $opts->{down
};
4993 $timeout = 60 if !defined($timeout);
4997 if (defined($conf) && $conf->{agent
}) {
4998 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
5000 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
5003 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
5010 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
5015 if ($count >= $timeout) {
5017 warn "VM still running - terminating now with SIGTERM\n";
5020 die "VM quit/powerdown failed - got timeout\n";
5023 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
5028 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
5031 die "VM quit/powerdown failed\n";
5039 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
5044 if ($count >= $timeout) {
5045 warn "VM still running - terminating now with SIGKILL\n";
5050 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
5055 my ($vmid, $skiplock) = @_;
5057 PVE
::QemuConfig-
>lock_config($vmid, sub {
5059 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5061 PVE
::QemuConfig-
>check_lock($conf)
5062 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5064 vm_mon_cmd
($vmid, "stop");
5069 my ($vmid, $skiplock, $nocheck) = @_;
5071 PVE
::QemuConfig-
>lock_config($vmid, sub {
5075 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5077 PVE
::QemuConfig-
>check_lock($conf)
5078 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5080 vm_mon_cmd
($vmid, "cont");
5083 vm_mon_cmd_nocheck
($vmid, "cont");
5089 my ($vmid, $skiplock, $key) = @_;
5091 PVE
::QemuConfig-
>lock_config($vmid, sub {
5093 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5095 # there is no qmp command, so we use the human monitor command
5096 vm_human_monitor_command
($vmid, "sendkey $key");
5101 my ($storecfg, $vmid, $skiplock) = @_;
5103 PVE
::QemuConfig-
>lock_config($vmid, sub {
5105 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5107 if (!check_running
($vmid)) {
5108 destroy_vm
($storecfg, $vmid, undef, $skiplock);
5110 die "VM $vmid is running - destroy failed\n";
5118 my ($filename, $buf) = @_;
5120 my $fh = IO
::File-
>new($filename, "w");
5121 return undef if !$fh;
5123 my $res = print $fh $buf;
5130 sub pci_device_info
{
5135 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
5136 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
5138 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
5139 return undef if !defined($irq) || $irq !~ m/^\d+$/;
5141 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
5142 return undef if !defined($vendor) || $vendor !~ s/^0x//;
5144 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
5145 return undef if !defined($product) || $product !~ s/^0x//;
5150 product
=> $product,
5156 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
5165 my $name = $dev->{name
};
5167 my $fn = "$pcisysfs/devices/$name/reset";
5169 return file_write
($fn, "1");
5172 sub pci_dev_bind_to_vfio
{
5175 my $name = $dev->{name
};
5177 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5179 if (!-d
$vfio_basedir) {
5180 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5182 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5184 my $testdir = "$vfio_basedir/$name";
5185 return 1 if -d
$testdir;
5187 my $data = "$dev->{vendor} $dev->{product}";
5188 return undef if !file_write
("$vfio_basedir/new_id", $data);
5190 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5191 if (!file_write
($fn, $name)) {
5192 return undef if -f
$fn;
5195 $fn = "$vfio_basedir/bind";
5196 if (! -d
$testdir) {
5197 return undef if !file_write
($fn, $name);
5203 sub pci_dev_group_bind_to_vfio
{
5206 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5208 if (!-d
$vfio_basedir) {
5209 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5211 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5213 # get IOMMU group devices
5214 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5215 my @devs = grep /^0000:/, readdir($D);
5218 foreach my $pciid (@devs) {
5219 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5221 # pci bridges, switches or root ports are not supported
5222 # they have a pci_bus subdirectory so skip them
5223 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5225 my $info = pci_device_info
($1);
5226 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5232 # vzdump restore implementaion
5234 sub tar_archive_read_firstfile
{
5235 my $archive = shift;
5237 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5239 # try to detect archive type first
5240 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5241 die "unable to open file '$archive'\n";
5242 my $firstfile = <$fh>;
5246 die "ERROR: archive contaions no data\n" if !$firstfile;
5252 sub tar_restore_cleanup
{
5253 my ($storecfg, $statfile) = @_;
5255 print STDERR
"starting cleanup\n";
5257 if (my $fd = IO
::File-
>new($statfile, "r")) {
5258 while (defined(my $line = <$fd>)) {
5259 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5262 if ($volid =~ m
|^/|) {
5263 unlink $volid || die 'unlink failed\n';
5265 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5267 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5269 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5271 print STDERR
"unable to parse line in statfile - $line";
5278 sub restore_archive
{
5279 my ($archive, $vmid, $user, $opts) = @_;
5281 my $format = $opts->{format
};
5284 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5285 $format = 'tar' if !$format;
5287 } elsif ($archive =~ m/\.tar$/) {
5288 $format = 'tar' if !$format;
5289 } elsif ($archive =~ m/.tar.lzo$/) {
5290 $format = 'tar' if !$format;
5292 } elsif ($archive =~ m/\.vma$/) {
5293 $format = 'vma' if !$format;
5294 } elsif ($archive =~ m/\.vma\.gz$/) {
5295 $format = 'vma' if !$format;
5297 } elsif ($archive =~ m/\.vma\.lzo$/) {
5298 $format = 'vma' if !$format;
5301 $format = 'vma' if !$format; # default
5304 # try to detect archive format
5305 if ($format eq 'tar') {
5306 return restore_tar_archive
($archive, $vmid, $user, $opts);
5308 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5312 sub restore_update_config_line
{
5313 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5315 return if $line =~ m/^\#qmdump\#/;
5316 return if $line =~ m/^\#vzdump\#/;
5317 return if $line =~ m/^lock:/;
5318 return if $line =~ m/^unused\d+:/;
5319 return if $line =~ m/^parent:/;
5320 return if $line =~ m/^template:/; # restored VM is never a template
5322 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5323 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5324 # try to convert old 1.X settings
5325 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5326 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5327 my ($model, $macaddr) = split(/\=/, $devconfig);
5328 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5331 bridge
=> "vmbr$ind",
5332 macaddr
=> $macaddr,
5334 my $netstr = print_net
($net);
5336 print $outfd "net$cookie->{netcount}: $netstr\n";
5337 $cookie->{netcount
}++;
5339 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5340 my ($id, $netstr) = ($1, $2);
5341 my $net = parse_net
($netstr);
5342 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5343 $netstr = print_net
($net);
5344 print $outfd "$id: $netstr\n";
5345 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5348 my $di = parse_drive
($virtdev, $value);
5349 if (defined($di->{backup
}) && !$di->{backup
}) {
5350 print $outfd "#$line";
5351 } elsif ($map->{$virtdev}) {
5352 delete $di->{format
}; # format can change on restore
5353 $di->{file
} = $map->{$virtdev};
5354 $value = print_drive
($vmid, $di);
5355 print $outfd "$virtdev: $value\n";
5359 } elsif (($line =~ m/^(smbios1: )(.*)/) && $unique) {
5360 my ($uuid, $uuid_str);
5361 UUID
::generate
($uuid);
5362 UUID
::unparse
($uuid, $uuid_str);
5363 my $smbios1 = parse_smbios1
($2);
5364 $smbios1->{uuid
} = $uuid_str;
5365 print $outfd $1.print_smbios1
($smbios1)."\n";
5372 my ($cfg, $vmid) = @_;
5374 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5376 my $volid_hash = {};
5377 foreach my $storeid (keys %$info) {
5378 foreach my $item (@{$info->{$storeid}}) {
5379 next if !($item->{volid
} && $item->{size
});
5380 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5381 $volid_hash->{$item->{volid
}} = $item;
5388 sub is_volume_in_use
{
5389 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5391 my $path = PVE
::Storage
::path
($storecfg, $volid);
5393 my $scan_config = sub {
5394 my ($cref, $snapname) = @_;
5396 foreach my $key (keys %$cref) {
5397 my $value = $cref->{$key};
5398 if (is_valid_drivename
($key)) {
5399 next if $skip_drive && $key eq $skip_drive;
5400 my $drive = parse_drive
($key, $value);
5401 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5402 return 1 if $volid eq $drive->{file
};
5403 if ($drive->{file
} =~ m!^/!) {
5404 return 1 if $drive->{file
} eq $path;
5406 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5408 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5410 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5418 return 1 if &$scan_config($conf);
5422 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5423 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5429 sub update_disksize
{
5430 my ($vmid, $conf, $volid_hash) = @_;
5434 # used and unused disks
5435 my $referenced = {};
5437 # Note: it is allowed to define multiple storages with same path (alias), so
5438 # we need to check both 'volid' and real 'path' (two different volid can point
5439 # to the same path).
5441 my $referencedpath = {};
5444 foreach my $opt (keys %$conf) {
5445 if (is_valid_drivename
($opt)) {
5446 my $drive = parse_drive
($opt, $conf->{$opt});
5447 my $volid = $drive->{file
};
5450 $referenced->{$volid} = 1;
5451 if ($volid_hash->{$volid} &&
5452 (my $path = $volid_hash->{$volid}->{path
})) {
5453 $referencedpath->{$path} = 1;
5456 next if drive_is_cdrom
($drive);
5457 next if !$volid_hash->{$volid};
5459 $drive->{size
} = $volid_hash->{$volid}->{size
};
5460 my $new = print_drive
($vmid, $drive);
5461 if ($new ne $conf->{$opt}) {
5463 $conf->{$opt} = $new;
5468 # remove 'unusedX' entry if volume is used
5469 foreach my $opt (keys %$conf) {
5470 next if $opt !~ m/^unused\d+$/;
5471 my $volid = $conf->{$opt};
5472 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5473 if ($referenced->{$volid} || ($path && $referencedpath->{$path})) {
5475 delete $conf->{$opt};
5478 $referenced->{$volid} = 1;
5479 $referencedpath->{$path} = 1 if $path;
5482 foreach my $volid (sort keys %$volid_hash) {
5483 next if $volid =~ m/vm-$vmid-state-/;
5484 next if $referenced->{$volid};
5485 my $path = $volid_hash->{$volid}->{path
};
5486 next if !$path; # just to be sure
5487 next if $referencedpath->{$path};
5489 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5490 $referencedpath->{$path} = 1; # avoid to add more than once (aliases)
5497 my ($vmid, $nolock) = @_;
5499 my $cfg = PVE
::Storage
::config
();
5501 my $volid_hash = scan_volids
($cfg, $vmid);
5503 my $updatefn = sub {
5506 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5508 PVE
::QemuConfig-
>check_lock($conf);
5511 foreach my $volid (keys %$volid_hash) {
5512 my $info = $volid_hash->{$volid};
5513 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5516 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5518 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5521 if (defined($vmid)) {
5525 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5528 my $vmlist = config_list
();
5529 foreach my $vmid (keys %$vmlist) {
5533 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5539 sub restore_vma_archive
{
5540 my ($archive, $vmid, $user, $opts, $comp) = @_;
5542 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5543 my $readfrom = $archive;
5548 my $qarchive = PVE
::Tools
::shellquote
($archive);
5549 if ($comp eq 'gzip') {
5550 $uncomp = "zcat $qarchive|";
5551 } elsif ($comp eq 'lzop') {
5552 $uncomp = "lzop -d -c $qarchive|";
5554 die "unknown compression method '$comp'\n";
5559 my $tmpdir = "/var/tmp/vzdumptmp$$";
5562 # disable interrupts (always do cleanups)
5566 local $SIG{HUP
} = sub { warn "got interrupt - ignored\n"; };
5568 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5569 POSIX
::mkfifo
($mapfifo, 0600);
5572 my $openfifo = sub {
5573 open($fifofh, '>', $mapfifo) || die $!;
5576 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5583 my $rpcenv = PVE
::RPCEnvironment
::get
();
5585 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5586 my $tmpfn = "$conffile.$$.tmp";
5588 # Note: $oldconf is undef if VM does not exists
5589 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5590 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5592 my $print_devmap = sub {
5593 my $virtdev_hash = {};
5595 my $cfgfn = "$tmpdir/qemu-server.conf";
5597 # we can read the config - that is already extracted
5598 my $fh = IO
::File-
>new($cfgfn, "r") ||
5599 "unable to read qemu-server.conf - $!\n";
5601 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5603 my $pve_firewall_dir = '/etc/pve/firewall';
5604 mkdir $pve_firewall_dir; # make sure the dir exists
5605 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5608 while (defined(my $line = <$fh>)) {
5609 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5610 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5611 die "archive does not contain data for drive '$virtdev'\n"
5612 if !$devinfo->{$devname};
5613 if (defined($opts->{storage
})) {
5614 $storeid = $opts->{storage
} || 'local';
5615 } elsif (!$storeid) {
5618 $format = 'raw' if !$format;
5619 $devinfo->{$devname}->{devname
} = $devname;
5620 $devinfo->{$devname}->{virtdev
} = $virtdev;
5621 $devinfo->{$devname}->{format
} = $format;
5622 $devinfo->{$devname}->{storeid
} = $storeid;
5624 # check permission on storage
5625 my $pool = $opts->{pool
}; # todo: do we need that?
5626 if ($user ne 'root@pam') {
5627 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5630 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5634 foreach my $devname (keys %$devinfo) {
5635 die "found no device mapping information for device '$devname'\n"
5636 if !$devinfo->{$devname}->{virtdev
};
5639 my $cfg = PVE
::Storage
::config
();
5641 # create empty/temp config
5643 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5644 foreach_drive
($oldconf, sub {
5645 my ($ds, $drive) = @_;
5647 return if drive_is_cdrom
($drive);
5649 my $volid = $drive->{file
};
5651 return if !$volid || $volid =~ m
|^/|;
5653 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5654 return if !$path || !$owner || ($owner != $vmid);
5656 # Note: only delete disk we want to restore
5657 # other volumes will become unused
5658 if ($virtdev_hash->{$ds}) {
5659 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5666 # delete vmstate files
5667 # since after the restore we have no snapshots anymore
5668 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5669 my $snap = $oldconf->{snapshots
}->{$snapname};
5670 if ($snap->{vmstate
}) {
5671 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5680 foreach my $virtdev (sort keys %$virtdev_hash) {
5681 my $d = $virtdev_hash->{$virtdev};
5682 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5683 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5685 # test if requested format is supported
5686 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5687 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5688 $d->{format
} = $defFormat if !$supported;
5690 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5691 $d->{format
}, undef, $alloc_size);
5692 print STDERR
"new volume ID is '$volid'\n";
5693 $d->{volid
} = $volid;
5694 my $path = PVE
::Storage
::path
($cfg, $volid);
5696 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5698 my $write_zeros = 1;
5699 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5703 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5705 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5706 $map->{$virtdev} = $volid;
5709 $fh->seek(0, 0) || die "seek failed - $!\n";
5711 my $outfd = new IO
::File
($tmpfn, "w") ||
5712 die "unable to write config for VM $vmid\n";
5714 my $cookie = { netcount
=> 0 };
5715 while (defined(my $line = <$fh>)) {
5716 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5729 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5730 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5732 $oldtimeout = alarm($timeout);
5739 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5740 my ($dev_id, $size, $devname) = ($1, $2, $3);
5741 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5742 } elsif ($line =~ m/^CTIME: /) {
5743 # we correctly received the vma config, so we can disable
5744 # the timeout now for disk allocation (set to 10 minutes, so
5745 # that we always timeout if something goes wrong)
5748 print $fifofh "done\n";
5749 my $tmp = $oldtimeout || 0;
5750 $oldtimeout = undef;
5756 print "restore vma archive: $cmd\n";
5757 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5761 alarm($oldtimeout) if $oldtimeout;
5764 foreach my $devname (keys %$devinfo) {
5765 my $volid = $devinfo->{$devname}->{volid
};
5766 push @$vollist, $volid if $volid;
5769 my $cfg = PVE
::Storage
::config
();
5770 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5778 foreach my $devname (keys %$devinfo) {
5779 my $volid = $devinfo->{$devname}->{volid
};
5782 if ($volid =~ m
|^/|) {
5783 unlink $volid || die 'unlink failed\n';
5785 PVE
::Storage
::vdisk_free
($cfg, $volid);
5787 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5789 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5796 rename($tmpfn, $conffile) ||
5797 die "unable to commit configuration file '$conffile'\n";
5799 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5801 eval { rescan
($vmid, 1); };
5805 sub restore_tar_archive
{
5806 my ($archive, $vmid, $user, $opts) = @_;
5808 if ($archive ne '-') {
5809 my $firstfile = tar_archive_read_firstfile
($archive);
5810 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5811 if $firstfile ne 'qemu-server.conf';
5814 my $storecfg = PVE
::Storage
::config
();
5816 # destroy existing data - keep empty config
5817 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5818 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5820 my $tocmd = "/usr/lib/qemu-server/qmextract";
5822 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5823 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5824 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5825 $tocmd .= ' --info' if $opts->{info
};
5827 # tar option "xf" does not autodetect compression when read from STDIN,
5828 # so we pipe to zcat
5829 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5830 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5832 my $tmpdir = "/var/tmp/vzdumptmp$$";
5835 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5836 local $ENV{VZDUMP_VMID
} = $vmid;
5837 local $ENV{VZDUMP_USER
} = $user;
5839 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5840 my $tmpfn = "$conffile.$$.tmp";
5842 # disable interrupts (always do cleanups)
5846 local $SIG{HUP
} = sub { print STDERR
"got interrupt - ignored\n"; };
5854 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5856 if ($archive eq '-') {
5857 print "extracting archive from STDIN\n";
5858 run_command
($cmd, input
=> "<&STDIN");
5860 print "extracting archive '$archive'\n";
5864 return if $opts->{info
};
5868 my $statfile = "$tmpdir/qmrestore.stat";
5869 if (my $fd = IO
::File-
>new($statfile, "r")) {
5870 while (defined (my $line = <$fd>)) {
5871 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5872 $map->{$1} = $2 if $1;
5874 print STDERR
"unable to parse line in statfile - $line\n";
5880 my $confsrc = "$tmpdir/qemu-server.conf";
5882 my $srcfd = new IO
::File
($confsrc, "r") ||
5883 die "unable to open file '$confsrc'\n";
5885 my $outfd = new IO
::File
($tmpfn, "w") ||
5886 die "unable to write config for VM $vmid\n";
5888 my $cookie = { netcount
=> 0 };
5889 while (defined (my $line = <$srcfd>)) {
5890 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5902 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5909 rename $tmpfn, $conffile ||
5910 die "unable to commit configuration file '$conffile'\n";
5912 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5914 eval { rescan
($vmid, 1); };
5918 sub foreach_storage_used_by_vm
{
5919 my ($conf, $func) = @_;
5923 foreach_drive
($conf, sub {
5924 my ($ds, $drive) = @_;
5925 return if drive_is_cdrom
($drive);
5927 my $volid = $drive->{file
};
5929 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5930 $sidhash->{$sid} = $sid if $sid;
5933 foreach my $sid (sort keys %$sidhash) {
5938 sub do_snapshots_with_qemu
{
5939 my ($storecfg, $volid) = @_;
5941 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5943 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5944 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5948 if ($volid =~ m/\.(qcow2|qed)$/){
5955 sub qga_check_running
{
5958 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5960 warn "Qemu Guest Agent is not running - $@";
5966 sub template_create
{
5967 my ($vmid, $conf, $disk) = @_;
5969 my $storecfg = PVE
::Storage
::config
();
5971 foreach_drive
($conf, sub {
5972 my ($ds, $drive) = @_;
5974 return if drive_is_cdrom
($drive);
5975 return if $disk && $ds ne $disk;
5977 my $volid = $drive->{file
};
5978 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5980 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5981 $drive->{file
} = $voliddst;
5982 $conf->{$ds} = print_drive
($vmid, $drive);
5983 PVE
::QemuConfig-
>write_config($vmid, $conf);
5987 sub qemu_img_convert
{
5988 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5990 my $storecfg = PVE
::Storage
::config
();
5991 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5992 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5994 if ($src_storeid && $dst_storeid) {
5996 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5998 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5999 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6001 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6002 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6004 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6005 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6008 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
6009 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6010 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
6011 if ($is_zero_initialized) {
6012 push @$cmd, "zeroinit:$dst_path";
6014 push @$cmd, $dst_path;
6019 if($line =~ m/\((\S+)\/100\
%\)/){
6021 my $transferred = int($size * $percent / 100);
6022 my $remaining = $size - $transferred;
6024 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6029 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6031 die "copy failed: $err" if $err;
6035 sub qemu_img_format
{
6036 my ($scfg, $volname) = @_;
6038 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6045 sub qemu_drive_mirror
{
6046 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
6048 $jobs = {} if !$jobs;
6052 $jobs->{"drive-$drive"} = {};
6054 if ($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+):exportname=(\S+)/) {
6057 my $exportname = $3;
6060 my $unixsocket = "/run/qemu-server/$vmid.mirror-drive-$drive";
6061 $qemu_target = "nbd+unix:///$exportname?socket=$unixsocket";
6062 my $cmd = ['socat', '-T30', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=5"];
6065 if (!defined($pid)) {
6066 die "forking socat tunnel failed\n";
6067 } elsif ($pid == 0) {
6069 warn "exec failed: $!\n";
6072 $jobs->{"drive-$drive"}->{pid
} = $pid;
6075 while (!-S
$unixsocket) {
6076 die "nbd connection helper timed out\n"
6081 my $storecfg = PVE
::Storage
::config
();
6082 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6084 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6086 $format = qemu_img_format
($dst_scfg, $dst_volname);
6088 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6090 $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
6093 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
6094 $opts->{format
} = $format if $format;
6096 print "drive mirror is starting for drive-$drive\n";
6098 eval { vm_mon_cmd
($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
6101 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6102 die "mirroring error: $err";
6105 qemu_drive_mirror_monitor
($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
6108 sub qemu_drive_mirror_monitor
{
6109 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
6112 my $err_complete = 0;
6115 die "storage migration timed out\n" if $err_complete > 300;
6117 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6119 my $running_mirror_jobs = {};
6120 foreach my $stat (@$stats) {
6121 next if $stat->{type
} ne 'mirror';
6122 $running_mirror_jobs->{$stat->{device
}} = $stat;
6125 my $readycounter = 0;
6127 foreach my $job (keys %$jobs) {
6129 if(defined($jobs->{$job}->{complete
}) && !defined($running_mirror_jobs->{$job})) {
6130 print "$job : finished\n";
6131 delete $jobs->{$job};
6135 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
6137 my $busy = $running_mirror_jobs->{$job}->{busy
};
6138 my $ready = $running_mirror_jobs->{$job}->{ready
};
6139 if (my $total = $running_mirror_jobs->{$job}->{len
}) {
6140 my $transferred = $running_mirror_jobs->{$job}->{offset
} || 0;
6141 my $remaining = $total - $transferred;
6142 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6144 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6147 $readycounter++ if $running_mirror_jobs->{$job}->{ready
};
6150 last if scalar(keys %$jobs) == 0;
6152 if ($readycounter == scalar(keys %$jobs)) {
6153 print "all mirroring jobs are ready \n";
6154 last if $skipcomplete; #do the complete later
6156 if ($vmiddst && $vmiddst != $vmid) {
6157 my $agent_running = $qga && qga_check_running
($vmid);
6158 if ($agent_running) {
6159 print "freeze filesystem\n";
6160 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6162 print "suspend vm\n";
6163 eval { PVE
::QemuServer
::vm_suspend
($vmid, 1); };
6166 # if we clone a disk for a new target vm, we don't switch the disk
6167 PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs);
6169 if ($agent_running) {
6170 print "unfreeze filesystem\n";
6171 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6173 print "resume vm\n";
6174 eval { PVE
::QemuServer
::vm_resume
($vmid, 1, 1); };
6180 foreach my $job (keys %$jobs) {
6181 # try to switch the disk if source and destination are on the same guest
6182 print "$job: Completing block job...\n";
6184 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> $job) };
6185 if ($@ =~ m/cannot be completed/) {
6186 print "$job: Block job cannot be completed, try again.\n";
6189 print "$job: Completed successfully.\n";
6190 $jobs->{$job}->{complete
} = 1;
6191 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6202 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6203 die "mirroring error: $err";
6208 sub qemu_blockjobs_cancel
{
6209 my ($vmid, $jobs) = @_;
6211 foreach my $job (keys %$jobs) {
6212 print "$job: Cancelling block job\n";
6213 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> $job); };
6214 $jobs->{$job}->{cancel
} = 1;
6218 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6220 my $running_jobs = {};
6221 foreach my $stat (@$stats) {
6222 $running_jobs->{$stat->{device
}} = $stat;
6225 foreach my $job (keys %$jobs) {
6227 if (defined($jobs->{$job}->{cancel
}) && !defined($running_jobs->{$job})) {
6228 print "$job: Done.\n";
6229 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6230 delete $jobs->{$job};
6234 last if scalar(keys %$jobs) == 0;
6240 sub qemu_blockjobs_finish_tunnel
{
6241 my ($vmid, $job, $cpid) = @_;
6245 for (my $i = 1; $i < 20; $i++) {
6246 my $waitpid = waitpid($cpid, WNOHANG
);
6247 last if (defined($waitpid) && ($waitpid == $cpid));
6251 } elsif ($i >= 15) {
6256 unlink "/run/qemu-server/$vmid.mirror-$job";
6260 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6261 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
6266 print "create linked clone of drive $drivename ($drive->{file})\n";
6267 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6268 push @$newvollist, $newvolid;
6271 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6272 $storeid = $storage if $storage;
6274 my $dst_format = resolve_dst_disk_format
($storecfg, $storeid, $volname, $format);
6275 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6277 print "create full clone of drive $drivename ($drive->{file})\n";
6278 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $dst_format, undef, ($size/1024));
6279 push @$newvollist, $newvolid;
6281 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
6283 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6284 if (!$running || $snapname) {
6285 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6288 my $kvmver = get_running_qemu_version
($vmid);
6289 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
6290 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6291 if $drive->{iothread
};
6294 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
6298 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6301 $disk->{format
} = undef;
6302 $disk->{file
} = $newvolid;
6303 $disk->{size
} = $size;
6308 # this only works if VM is running
6309 sub get_current_qemu_machine
{
6312 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6313 my $res = vm_qmp_command
($vmid, $cmd);
6315 my ($current, $default);
6316 foreach my $e (@$res) {
6317 $default = $e->{name
} if $e->{'is-default'};
6318 $current = $e->{name
} if $e->{'is-current'};
6321 # fallback to the default machine if current is not supported by qemu
6322 return $current || $default || 'pc';
6325 sub get_running_qemu_version
{
6327 my $cmd = { execute
=> 'query-version', arguments
=> {} };
6328 my $res = vm_qmp_command
($vmid, $cmd);
6329 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6332 sub qemu_machine_feature_enabled
{
6333 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6338 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6340 $current_major = $3;
6341 $current_minor = $4;
6343 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6345 $current_major = $1;
6346 $current_minor = $2;
6349 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6354 sub qemu_machine_pxe
{
6355 my ($vmid, $conf, $machine) = @_;
6357 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6359 foreach my $opt (keys %$conf) {
6360 next if $opt !~ m/^net(\d+)$/;
6361 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6363 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6364 return $machine.".pxe" if $romfile =~ m/pxe/;
6371 sub qemu_use_old_bios_files
{
6372 my ($machine_type) = @_;
6374 return if !$machine_type;
6376 my $use_old_bios_files = undef;
6378 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6380 $use_old_bios_files = 1;
6382 my $kvmver = kvm_user_version
();
6383 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6384 # load new efi bios files on migration. So this hack is required to allow
6385 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6386 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6387 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6390 return ($use_old_bios_files, $machine_type);
6393 sub create_efidisk
{
6394 my ($storecfg, $storeid, $vmid, $fmt) = @_;
6396 die "EFI vars default image not found\n" if ! -f
$OVMF_VARS;
6398 my $vars_size = PVE
::Tools
::convert_size
(-s
$OVMF_VARS, 'b' => 'kb');
6399 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
6400 PVE
::Storage
::activate_volumes
($storecfg, [$volid]);
6402 my $path = PVE
::Storage
::path
($storecfg, $volid);
6404 run_command
(['/usr/bin/qemu-img', 'convert', '-n', '-f', 'raw', '-O', $fmt, $OVMF_VARS, $path]);
6406 die "Copying EFI vars image failed: $@" if $@;
6408 return ($volid, $vars_size);
6415 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6416 my (undef, $id, $function) = @_;
6417 my $res = { id
=> $id, function
=> $function};
6418 push @{$devices->{$id}}, $res;
6421 # Entries should be sorted by functions.
6422 foreach my $id (keys %$devices) {
6423 my $dev = $devices->{$id};
6424 $devices->{$id} = [ sort { $a->{function
} <=> $b->{function
} } @$dev ];
6430 sub vm_iothreads_list
{
6433 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6436 foreach my $iothread (@$res) {
6437 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6444 my ($conf, $drive) = @_;
6448 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)) {
6450 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6456 my $controller = int($drive->{index} / $maxdev);
6457 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6459 return ($maxdev, $controller, $controller_prefix);
6462 sub add_hyperv_enlightenments
{
6463 my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough) = @_;
6465 return if $winversion < 6;
6466 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6468 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6470 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
6471 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6472 push @$cpuFlags , 'hv_vapic';
6473 push @$cpuFlags , 'hv_time';
6475 push @$cpuFlags , 'hv_spinlocks=0xffff';
6478 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
6479 push @$cpuFlags , 'hv_reset';
6480 push @$cpuFlags , 'hv_vpindex';
6481 push @$cpuFlags , 'hv_runtime';
6484 if ($winversion >= 7) {
6485 push @$cpuFlags , 'hv_relaxed';
6489 sub windows_version
{
6492 return 0 if !$ostype;
6496 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6498 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6500 } elsif ($ostype =~ m/^win(\d+)$/) {
6507 sub resolve_dst_disk_format
{
6508 my ($storecfg, $storeid, $src_volname, $format) = @_;
6509 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6512 # if no target format is specified, use the source disk format as hint
6514 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6515 $format = qemu_img_format
($scfg, $src_volname);
6521 # test if requested format is supported - else use default
6522 my $supported = grep { $_ eq $format } @$validFormats;
6523 $format = $defFormat if !$supported;
6527 sub resolve_first_disk
{
6529 my @disks = PVE
::QemuServer
::valid_drive_names
();
6531 foreach my $ds (reverse @disks) {
6532 next if !$conf->{$ds};
6533 my $disk = PVE
::QemuServer
::parse_drive
($ds, $conf->{$ds});
6534 next if PVE
::QemuServer
::drive_is_cdrom
($disk);
6540 sub generate_smbios1_uuid
{
6541 my ($uuid, $uuid_str);
6542 UUID
::generate
($uuid);
6543 UUID
::unparse
($uuid, $uuid_str);
6544 return "uuid=$uuid_str";
6547 # bash completion helper
6549 sub complete_backup_archives
{
6550 my ($cmdname, $pname, $cvalue) = @_;
6552 my $cfg = PVE
::Storage
::config
();
6556 if ($cvalue =~ m/^([^:]+):/) {
6560 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6563 foreach my $id (keys %$data) {
6564 foreach my $item (@{$data->{$id}}) {
6565 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6566 push @$res, $item->{volid
} if defined($item->{volid
});
6573 my $complete_vmid_full = sub {
6576 my $idlist = vmstatus
();
6580 foreach my $id (keys %$idlist) {
6581 my $d = $idlist->{$id};
6582 if (defined($running)) {
6583 next if $d->{template
};
6584 next if $running && $d->{status
} ne 'running';
6585 next if !$running && $d->{status
} eq 'running';
6594 return &$complete_vmid_full();
6597 sub complete_vmid_stopped
{
6598 return &$complete_vmid_full(0);
6601 sub complete_vmid_running
{
6602 return &$complete_vmid_full(1);
6605 sub complete_storage
{
6607 my $cfg = PVE
::Storage
::config
();
6608 my $ids = $cfg->{ids
};
6611 foreach my $sid (keys %$ids) {
6612 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6613 next if !$ids->{$sid}->{content
}->{images
};
6623 vm_mon_cmd
($vmid, 'nbd-server-stop');