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
=> "Whether the drive should be included when making snapshots.",
761 enum
=> [qw(none writethrough writeback unsafe directsync)],
762 description
=> "The drive's cache mode",
765 format
=> get_standard_option
('pve-qm-image-format'),
768 format
=> 'disk-size',
769 format_description
=> 'DiskSize',
770 description
=> "Disk size. This is purely informational and has no effect.",
775 description
=> "Whether the drive should be included when making backups.",
780 description
=> 'Whether the drive should considered for replication jobs.',
786 enum
=> [qw(ignore report stop)],
787 description
=> 'Read error action.',
792 enum
=> [qw(enospc ignore report stop)],
793 description
=> 'Write error action.',
798 enum
=> [qw(native threads)],
799 description
=> 'AIO type to use.',
804 enum
=> [qw(ignore on)],
805 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
810 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
815 format
=> 'urlencoded',
816 format_description
=> 'serial',
817 maxLength
=> 20*3, # *3 since it's %xx url enoded
818 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
823 my %iothread_fmt = ( iothread
=> {
825 description
=> "Whether to use iothreads for this drive",
832 format
=> 'urlencoded',
833 format_description
=> 'model',
834 maxLength
=> 40*3, # *3 since it's %xx url enoded
835 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
843 description
=> "Number of queues.",
849 my %scsiblock_fmt = (
852 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",
858 my $add_throttle_desc = sub {
859 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
862 format_description
=> $unit,
863 description
=> "Maximum $what in $longunit.",
866 $d->{minimum
} = $minimum if defined($minimum);
867 $drivedesc_base{$key} = $d;
869 # throughput: (leaky bucket)
870 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
871 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
872 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
873 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
874 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
875 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
876 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
877 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
878 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
880 # pools: (pool of IO before throttling starts taking effect)
881 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
882 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
883 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
884 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
885 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
886 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
889 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
890 $add_throttle_desc->('bps_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
891 $add_throttle_desc->('bps_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
892 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
893 $add_throttle_desc->('iops_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
894 $add_throttle_desc->('iops_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
897 $drivedesc_base{'bps_rd_length'} = { alias
=> 'bps_rd_max_length' };
898 $drivedesc_base{'bps_wr_length'} = { alias
=> 'bps_wr_max_length' };
899 $drivedesc_base{'iops_rd_length'} = { alias
=> 'iops_rd_max_length' };
900 $drivedesc_base{'iops_wr_length'} = { alias
=> 'iops_wr_max_length' };
906 PVE
::JSONSchema
::register_format
("pve-qm-ide", $ide_fmt);
910 type
=> 'string', format
=> $ide_fmt,
911 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
913 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
923 type
=> 'string', format
=> $scsi_fmt,
924 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
926 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
933 type
=> 'string', format
=> $sata_fmt,
934 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
936 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
944 type
=> 'string', format
=> $virtio_fmt,
945 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
947 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
958 volume
=> { alias
=> 'file' },
961 format
=> 'pve-volume-id-or-qm-path',
963 format_description
=> 'volume',
964 description
=> "The drive's backing volume.",
966 format
=> get_standard_option
('pve-qm-image-format'),
969 format
=> 'disk-size',
970 format_description
=> 'DiskSize',
971 description
=> "Disk size. This is purely informational and has no effect.",
978 type
=> 'string', format
=> $efidisk_fmt,
979 description
=> "Configure a Disk for storing EFI vars",
982 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
987 type
=> 'string', format
=> 'pve-qm-usb-device',
988 format_description
=> 'HOSTUSBDEVICE|spice',
989 description
=> <<EODESCR,
990 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
992 'bus-port(.port)*' (decimal numbers) or
993 'vendor_id:product_id' (hexadeciaml numbers) or
996 You can use the 'lsusb -t' command to list existing usb devices.
998 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1000 The value 'spice' can be used to add a usb redirection devices for spice.
1006 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).",
1013 type
=> 'string', format
=> $usb_fmt,
1014 description
=> "Configure an USB device (n is 0 to 4).",
1016 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
1018 # NOTE: the match-groups of this regex are used in parse_hostpci
1019 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
1024 pattern
=> qr/$PCIRE(;$PCIRE)*/,
1025 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
1026 description
=> <<EODESCR,
1027 Host PCI device pass through. The PCI ID of a host's PCI device or a list
1028 of PCI virtual functions of the host. HOSTPCIID syntax is:
1030 'bus:dev.func' (hexadecimal numbers)
1032 You can us the 'lspci' command to list existing PCI devices.
1037 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1043 pattern
=> '[^,;]+',
1044 format_description
=> 'string',
1045 description
=> "Custom pci device rom filename (must be located in /usr/share/kvm/).",
1050 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1056 description
=> "Enable vfio-vga device support.",
1061 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1065 type
=> 'string', format
=> 'pve-qm-hostpci',
1066 description
=> "Map host PCI devices into guest.",
1067 verbose_description
=> <<EODESCR,
1068 Map host PCI devices into guest.
1070 NOTE: This option allows direct access to host hardware. So it is no longer
1071 possible to migrate such machines - use with special care.
1073 CAUTION: Experimental! User reported problems with this option.
1076 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1081 pattern
=> '(/dev/.+|socket)',
1082 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1083 verbose_description
=> <<EODESCR,
1084 Create a serial device inside the VM (n is 0 to 3), and pass through a
1085 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1086 host side (use 'qm terminal' to open a terminal connection).
1088 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1090 CAUTION: Experimental! User reported problems with this option.
1097 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1098 description
=> "Map host parallel devices (n is 0 to 2).",
1099 verbose_description
=> <<EODESCR,
1100 Map host parallel devices (n is 0 to 2).
1102 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1104 CAUTION: Experimental! User reported problems with this option.
1108 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1109 $confdesc->{"parallel$i"} = $paralleldesc;
1112 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1113 $confdesc->{"serial$i"} = $serialdesc;
1116 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1117 $confdesc->{"hostpci$i"} = $hostpcidesc;
1120 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1121 $drivename_hash->{"ide$i"} = 1;
1122 $confdesc->{"ide$i"} = $idedesc;
1125 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1126 $drivename_hash->{"sata$i"} = 1;
1127 $confdesc->{"sata$i"} = $satadesc;
1130 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1131 $drivename_hash->{"scsi$i"} = 1;
1132 $confdesc->{"scsi$i"} = $scsidesc ;
1135 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1136 $drivename_hash->{"virtio$i"} = 1;
1137 $confdesc->{"virtio$i"} = $virtiodesc;
1140 $drivename_hash->{efidisk0
} = 1;
1141 $confdesc->{efidisk0
} = $efidisk_desc;
1143 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1144 $confdesc->{"usb$i"} = $usbdesc;
1149 type
=> 'string', format
=> 'pve-volume-id',
1150 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1153 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1154 $confdesc->{"unused$i"} = $unuseddesc;
1157 my $kvm_api_version = 0;
1161 return $kvm_api_version if $kvm_api_version;
1163 my $fh = IO
::File-
>new("</dev/kvm") ||
1166 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1167 $kvm_api_version = $v;
1172 return $kvm_api_version;
1175 my $kvm_user_version;
1177 sub kvm_user_version
{
1179 return $kvm_user_version if $kvm_user_version;
1181 $kvm_user_version = 'unknown';
1185 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1186 $kvm_user_version = $2;
1190 eval { run_command
("kvm -version", outfunc
=> $code); };
1193 return $kvm_user_version;
1197 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1199 sub valid_drive_names
{
1200 # order is important - used to autoselect boot disk
1201 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1202 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1203 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1204 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1208 sub is_valid_drivename
{
1211 return defined($drivename_hash->{$dev});
1216 return defined($confdesc->{$key});
1220 return $nic_model_list;
1223 sub os_list_description
{
1227 wxp
=> 'Windows XP',
1228 w2k
=> 'Windows 2000',
1229 w2k3
=>, 'Windows 2003',
1230 w2k8
=> 'Windows 2008',
1231 wvista
=> 'Windows Vista',
1232 win7
=> 'Windows 7',
1233 win8
=> 'Windows 8/2012',
1234 win10
=> 'Windows 10/2016',
1242 sub get_cdrom_path
{
1244 return $cdrom_path if $cdrom_path;
1246 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1247 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1248 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1252 my ($storecfg, $vmid, $cdrom) = @_;
1254 if ($cdrom eq 'cdrom') {
1255 return get_cdrom_path
();
1256 } elsif ($cdrom eq 'none') {
1258 } elsif ($cdrom =~ m
|^/|) {
1261 return PVE
::Storage
::path
($storecfg, $cdrom);
1265 # try to convert old style file names to volume IDs
1266 sub filename_to_volume_id
{
1267 my ($vmid, $file, $media) = @_;
1269 if (!($file eq 'none' || $file eq 'cdrom' ||
1270 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1272 return undef if $file =~ m
|/|;
1274 if ($media && $media eq 'cdrom') {
1275 $file = "local:iso/$file";
1277 $file = "local:$vmid/$file";
1284 sub verify_media_type
{
1285 my ($opt, $vtype, $media) = @_;
1290 if ($media eq 'disk') {
1292 } elsif ($media eq 'cdrom') {
1295 die "internal error";
1298 return if ($vtype eq $etype);
1300 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1303 sub cleanup_drive_path
{
1304 my ($opt, $storecfg, $drive) = @_;
1306 # try to convert filesystem paths to volume IDs
1308 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1309 ($drive->{file
} !~ m
|^/dev/.+|) &&
1310 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1311 ($drive->{file
} !~ m/^\d+$/)) {
1312 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1313 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1314 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1315 verify_media_type
($opt, $vtype, $drive->{media
});
1316 $drive->{file
} = $volid;
1319 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1322 sub parse_hotplug_features
{
1327 return $res if $data eq '0';
1329 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1331 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1332 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1335 die "invalid hotplug feature '$feature'\n";
1341 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1342 sub pve_verify_hotplug_features
{
1343 my ($value, $noerr) = @_;
1345 return $value if parse_hotplug_features
($value);
1347 return undef if $noerr;
1349 die "unable to parse hotplug option\n";
1352 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1353 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1354 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1355 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1356 # [,iothread=on][,serial=serial][,model=model]
1359 my ($key, $data) = @_;
1361 my ($interface, $index);
1363 if ($key =~ m/^([^\d]+)(\d+)$/) {
1370 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1371 : $confdesc->{$key}->{format
};
1373 warn "invalid drive key: $key\n";
1376 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1377 return undef if !$res;
1378 $res->{interface
} = $interface;
1379 $res->{index} = $index;
1382 foreach my $opt (qw(bps bps_rd bps_wr)) {
1383 if (my $bps = defined(delete $res->{$opt})) {
1384 if (defined($res->{"m$opt"})) {
1385 warn "both $opt and m$opt specified\n";
1389 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1393 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1394 for my $requirement (
1395 [mbps_max
=> 'mbps'],
1396 [mbps_rd_max
=> 'mbps_rd'],
1397 [mbps_wr_max
=> 'mbps_wr'],
1398 [miops_max
=> 'miops'],
1399 [miops_rd_max
=> 'miops_rd'],
1400 [miops_wr_max
=> 'miops_wr'],
1401 [bps_max_length
=> 'mbps_max'],
1402 [bps_rd_max_length
=> 'mbps_rd_max'],
1403 [bps_wr_max_length
=> 'mbps_wr_max'],
1404 [iops_max_length
=> 'iops_max'],
1405 [iops_rd_max_length
=> 'iops_rd_max'],
1406 [iops_wr_max_length
=> 'iops_wr_max']) {
1407 my ($option, $requires) = @$requirement;
1408 if ($res->{$option} && !$res->{$requires}) {
1409 warn "$option requires $requires\n";
1414 return undef if $error;
1416 return undef if $res->{mbps_rd
} && $res->{mbps
};
1417 return undef if $res->{mbps_wr
} && $res->{mbps
};
1418 return undef if $res->{iops_rd
} && $res->{iops
};
1419 return undef if $res->{iops_wr
} && $res->{iops
};
1421 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1422 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1423 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1424 return undef if $res->{interface
} eq 'virtio';
1427 if (my $size = $res->{size
}) {
1428 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1435 my ($vmid, $drive) = @_;
1436 my $data = { %$drive };
1437 delete $data->{$_} for qw(index interface);
1438 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1442 my($fh, $noerr) = @_;
1445 my $SG_GET_VERSION_NUM = 0x2282;
1447 my $versionbuf = "\x00" x
8;
1448 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1450 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1453 my $version = unpack("I", $versionbuf);
1454 if ($version < 30000) {
1455 die "scsi generic interface too old\n" if !$noerr;
1459 my $buf = "\x00" x
36;
1460 my $sensebuf = "\x00" x
8;
1461 my $cmd = pack("C x3 C x1", 0x12, 36);
1463 # see /usr/include/scsi/sg.h
1464 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";
1466 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1467 length($sensebuf), 0, length($buf), $buf,
1468 $cmd, $sensebuf, 6000);
1470 $ret = ioctl($fh, $SG_IO, $packet);
1472 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1476 my @res = unpack($sg_io_hdr_t, $packet);
1477 if ($res[17] || $res[18]) {
1478 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1483 (my $byte0, my $byte1, $res->{vendor
},
1484 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1486 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1487 $res->{type
} = $byte0 & 31;
1495 my $fh = IO
::File-
>new("+<$path") || return undef;
1496 my $res = scsi_inquiry
($fh, 1);
1502 sub machine_type_is_q35
{
1505 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1508 sub print_tabletdevice_full
{
1511 my $q35 = machine_type_is_q35
($conf);
1513 # we use uhci for old VMs because tablet driver was buggy in older qemu
1514 my $usbbus = $q35 ?
"ehci" : "uhci";
1516 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1519 sub print_drivedevice_full
{
1520 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1525 if ($drive->{interface
} eq 'virtio') {
1526 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1527 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1528 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1529 } elsif ($drive->{interface
} eq 'scsi') {
1531 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1532 my $unit = $drive->{index} % $maxdev;
1533 my $devicetype = 'hd';
1535 if (drive_is_cdrom
($drive)) {
1538 if ($drive->{file
} =~ m
|^/|) {
1539 $path = $drive->{file
};
1540 if (my $info = path_is_scsi
($path)) {
1541 if ($info->{type
} == 0 && $drive->{scsiblock
}) {
1542 $devicetype = 'block';
1543 } elsif ($info->{type
} == 1) { # tape
1544 $devicetype = 'generic';
1548 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1551 if($path =~ m/^iscsi\:\/\
//){
1552 $devicetype = 'generic';
1556 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1557 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1559 $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}";
1562 } elsif ($drive->{interface
} eq 'ide'){
1564 my $controller = int($drive->{index} / $maxdev);
1565 my $unit = $drive->{index} % $maxdev;
1566 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1568 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1569 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1570 $model = URI
::Escape
::uri_unescape
($model);
1571 $device .= ",model=$model";
1573 } elsif ($drive->{interface
} eq 'sata'){
1574 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1575 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1576 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1577 } elsif ($drive->{interface
} eq 'usb') {
1579 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1581 die "unsupported interface type";
1584 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1589 sub get_initiator_name
{
1592 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1593 while (defined(my $line = <$fh>)) {
1594 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1603 sub print_drive_full
{
1604 my ($storecfg, $vmid, $drive) = @_;
1607 my $volid = $drive->{file
};
1610 if (drive_is_cdrom
($drive)) {
1611 $path = get_iso_path
($storecfg, $vmid, $volid);
1613 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1615 $path = PVE
::Storage
::path
($storecfg, $volid);
1616 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1617 $format = qemu_img_format
($scfg, $volname);
1625 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard);
1626 foreach my $o (@qemu_drive_options) {
1627 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1629 foreach my $type (['', '-total'], [_rd
=> '-read'], [_wr
=> '-write']) {
1630 my ($dir, $qmpname) = @$type;
1631 if (my $v = $drive->{"mbps$dir"}) {
1632 $opts .= ",throttling.bps$qmpname=".int($v*1024*1024);
1634 if (my $v = $drive->{"mbps${dir}_max"}) {
1635 $opts .= ",throttling.bps$qmpname-max=".int($v*1024*1024);
1637 if (my $v = $drive->{"bps${dir}_max_length"}) {
1638 $opts .= ",throttling.bps$qmpname-max-length=$v";
1640 if (my $v = $drive->{"iops${dir}"}) {
1641 $opts .= ",throttling.iops$qmpname=$v";
1643 if (my $v = $drive->{"iops${dir}_max"}) {
1644 $opts .= ",throttling.iops$qmpname-max=$v";
1646 if (my $v = $drive->{"iops${dir}_max_length"}) {
1647 $opts .= ",throttling.iops$qmpname-max-length=$v";
1651 if (my $serial = $drive->{serial
}) {
1652 $serial = URI
::Escape
::uri_unescape
($serial);
1653 $opts .= ",serial=$serial";
1656 $opts .= ",format=$format" if $format && !$drive->{format
};
1658 my $cache_direct = 0;
1660 if (my $cache = $drive->{cache
}) {
1661 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1662 } elsif (!drive_is_cdrom
($drive)) {
1663 $opts .= ",cache=none";
1667 # aio native works only with O_DIRECT
1668 if (!$drive->{aio
}) {
1670 $opts .= ",aio=native";
1672 $opts .= ",aio=threads";
1676 if (!drive_is_cdrom
($drive)) {
1678 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1679 $detectzeroes = 'off';
1680 } elsif ($drive->{discard
}) {
1681 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1683 # This used to be our default with discard not being specified:
1684 $detectzeroes = 'on';
1686 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1689 my $pathinfo = $path ?
"file=$path," : '';
1691 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1694 sub print_netdevice_full
{
1695 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1697 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1699 my $device = $net->{model
};
1700 if ($net->{model
} eq 'virtio') {
1701 $device = 'virtio-net-pci';
1704 my $pciaddr = print_pci_addr
("$netid", $bridges);
1705 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1706 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1707 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1708 my $vectors = $net->{queues
} * 2 + 2;
1709 $tmpstr .= ",vectors=$vectors,mq=on";
1711 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1713 if ($use_old_bios_files) {
1715 if ($device eq 'virtio-net-pci') {
1716 $romfile = 'pxe-virtio.rom';
1717 } elsif ($device eq 'e1000') {
1718 $romfile = 'pxe-e1000.rom';
1719 } elsif ($device eq 'ne2k') {
1720 $romfile = 'pxe-ne2k_pci.rom';
1721 } elsif ($device eq 'pcnet') {
1722 $romfile = 'pxe-pcnet.rom';
1723 } elsif ($device eq 'rtl8139') {
1724 $romfile = 'pxe-rtl8139.rom';
1726 $tmpstr .= ",romfile=$romfile" if $romfile;
1732 sub print_netdev_full
{
1733 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1736 if ($netid =~ m/^net(\d+)$/) {
1740 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1742 my $ifname = "tap${vmid}i$i";
1744 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1745 die "interface name '$ifname' is too long (max 15 character)\n"
1746 if length($ifname) >= 16;
1748 my $vhostparam = '';
1749 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1751 my $vmname = $conf->{name
} || "vm$vmid";
1754 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1756 if ($net->{bridge
}) {
1757 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1759 $netdev = "type=user,id=$netid,hostname=$vmname";
1762 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1768 sub print_cpu_device
{
1769 my ($conf, $id) = @_;
1771 my $kvm = $conf->{kvm
} // 1;
1772 my $cpu = $kvm ?
"kvm64" : "qemu64";
1773 if (my $cputype = $conf->{cpu
}) {
1774 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1775 or die "Cannot parse cpu description: $cputype\n";
1776 $cpu = $cpuconf->{cputype
};
1779 my $cores = $conf->{cores
} || 1;
1781 my $current_core = ($id - 1) % $cores;
1782 my $current_socket = int(($id - 1 - $current_core)/$cores);
1784 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1787 sub drive_is_cdrom
{
1790 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1794 sub parse_number_sets
{
1797 foreach my $part (split(/;/, $set)) {
1798 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1799 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1800 push @$res, [ $1, $2 ];
1802 die "invalid range: $part\n";
1811 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1812 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1813 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1820 return undef if !$value;
1822 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1824 my @idlist = split(/;/, $res->{host
});
1825 delete $res->{host
};
1826 foreach my $id (@idlist) {
1827 if ($id =~ /^$PCIRE$/) {
1829 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1831 my $pcidevices = lspci
($1);
1832 $res->{pciid
} = $pcidevices->{$1};
1835 # should have been caught by parse_property_string already
1836 die "failed to parse PCI id: $id\n";
1842 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1846 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1851 if (!defined($res->{macaddr
})) {
1852 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1853 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1861 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1864 sub add_random_macs
{
1865 my ($settings) = @_;
1867 foreach my $opt (keys %$settings) {
1868 next if $opt !~ m/^net(\d+)$/;
1869 my $net = parse_net
($settings->{$opt});
1871 $settings->{$opt} = print_net
($net);
1875 sub vm_is_volid_owner
{
1876 my ($storecfg, $vmid, $volid) = @_;
1878 if ($volid !~ m
|^/|) {
1880 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1881 if ($owner && ($owner == $vmid)) {
1889 sub split_flagged_list
{
1890 my $text = shift || '';
1891 $text =~ s/[,;]/ /g;
1893 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1896 sub join_flagged_list
{
1897 my ($how, $lst) = @_;
1898 join $how, map { $lst->{$_} . $_ } keys %$lst;
1901 sub vmconfig_delete_pending_option
{
1902 my ($conf, $key, $force) = @_;
1904 delete $conf->{pending
}->{$key};
1905 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1906 $pending_delete_hash->{$key} = $force ?
'!' : '';
1907 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1910 sub vmconfig_undelete_pending_option
{
1911 my ($conf, $key) = @_;
1913 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1914 delete $pending_delete_hash->{$key};
1916 if (%$pending_delete_hash) {
1917 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1919 delete $conf->{pending
}->{delete};
1923 sub vmconfig_register_unused_drive
{
1924 my ($storecfg, $vmid, $conf, $drive) = @_;
1926 if (!drive_is_cdrom
($drive)) {
1927 my $volid = $drive->{file
};
1928 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1929 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1934 sub vmconfig_cleanup_pending
{
1937 # remove pending changes when nothing changed
1939 foreach my $opt (keys %{$conf->{pending
}}) {
1940 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1942 delete $conf->{pending
}->{$opt};
1946 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1947 my $pending_delete_hash = {};
1948 while (my ($opt, $force) = each %$current_delete_hash) {
1949 if (defined($conf->{$opt})) {
1950 $pending_delete_hash->{$opt} = $force;
1956 if (%$pending_delete_hash) {
1957 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1959 delete $conf->{pending
}->{delete};
1965 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1969 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1970 format_description
=> 'UUID',
1971 description
=> "Set SMBIOS1 UUID.",
1977 format_description
=> 'string',
1978 description
=> "Set SMBIOS1 version.",
1984 format_description
=> 'string',
1985 description
=> "Set SMBIOS1 serial number.",
1991 format_description
=> 'string',
1992 description
=> "Set SMBIOS1 manufacturer.",
1998 format_description
=> 'string',
1999 description
=> "Set SMBIOS1 product ID.",
2005 format_description
=> 'string',
2006 description
=> "Set SMBIOS1 SKU string.",
2012 format_description
=> 'string',
2013 description
=> "Set SMBIOS1 family string.",
2021 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
2028 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
2031 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
2033 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
2034 sub verify_bootdisk
{
2035 my ($value, $noerr) = @_;
2037 return $value if is_valid_drivename
($value);
2039 return undef if $noerr;
2041 die "invalid boot disk '$value'\n";
2044 sub parse_watchdog
{
2047 return undef if !$value;
2049 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
2054 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
2055 sub verify_usb_device
{
2056 my ($value, $noerr) = @_;
2058 return $value if parse_usb_device
($value);
2060 return undef if $noerr;
2062 die "unable to parse usb device\n";
2065 # add JSON properties for create and set function
2066 sub json_config_properties
{
2069 foreach my $opt (keys %$confdesc) {
2070 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2071 $prop->{$opt} = $confdesc->{$opt};
2078 my ($key, $value) = @_;
2080 die "unknown setting '$key'\n" if !$confdesc->{$key};
2082 my $type = $confdesc->{$key}->{type
};
2084 if (!defined($value)) {
2085 die "got undefined value\n";
2088 if ($value =~ m/[\n\r]/) {
2089 die "property contains a line feed\n";
2092 if ($type eq 'boolean') {
2093 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2094 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2095 die "type check ('boolean') failed - got '$value'\n";
2096 } elsif ($type eq 'integer') {
2097 return int($1) if $value =~ m/^(\d+)$/;
2098 die "type check ('integer') failed - got '$value'\n";
2099 } elsif ($type eq 'number') {
2100 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2101 die "type check ('number') failed - got '$value'\n";
2102 } elsif ($type eq 'string') {
2103 if (my $fmt = $confdesc->{$key}->{format
}) {
2104 PVE
::JSONSchema
::check_format
($fmt, $value);
2107 $value =~ s/^\"(.*)\"$/$1/;
2110 die "internal error"
2114 sub check_iommu_support
{
2115 #fixme : need to check IOMMU support
2116 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2126 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2127 utime undef, undef, $conf;
2131 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2133 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2135 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2137 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2139 if ($conf->{template
}) {
2140 # check if any base image is still used by a linked clone
2141 foreach_drive
($conf, sub {
2142 my ($ds, $drive) = @_;
2144 return if drive_is_cdrom
($drive);
2146 my $volid = $drive->{file
};
2148 return if !$volid || $volid =~ m
|^/|;
2150 die "base volume '$volid' is still in use by linked cloned\n"
2151 if PVE
::Storage
::volume_is_base_and_used
($storecfg, $volid);
2156 # only remove disks owned by this VM
2157 foreach_drive
($conf, sub {
2158 my ($ds, $drive) = @_;
2160 return if drive_is_cdrom
($drive);
2162 my $volid = $drive->{file
};
2164 return if !$volid || $volid =~ m
|^/|;
2166 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2167 return if !$path || !$owner || ($owner != $vmid);
2170 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2172 warn "Could not remove disk '$volid', check manually: $@" if $@;
2176 if ($keep_empty_config) {
2177 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2182 # also remove unused disk
2184 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2187 PVE
::Storage
::foreach_volid
($dl, sub {
2188 my ($volid, $sid, $volname, $d) = @_;
2189 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2198 sub parse_vm_config
{
2199 my ($filename, $raw) = @_;
2201 return undef if !defined($raw);
2204 digest
=> Digest
::SHA
::sha1_hex
($raw),
2209 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2210 || die "got strange filename '$filename'";
2218 my @lines = split(/\n/, $raw);
2219 foreach my $line (@lines) {
2220 next if $line =~ m/^\s*$/;
2222 if ($line =~ m/^\[PENDING\]\s*$/i) {
2223 $section = 'pending';
2224 if (defined($descr)) {
2226 $conf->{description
} = $descr;
2229 $conf = $res->{$section} = {};
2232 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2234 if (defined($descr)) {
2236 $conf->{description
} = $descr;
2239 $conf = $res->{snapshots
}->{$section} = {};
2243 if ($line =~ m/^\#(.*)\s*$/) {
2244 $descr = '' if !defined($descr);
2245 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2249 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2250 $descr = '' if !defined($descr);
2251 $descr .= PVE
::Tools
::decode_text
($2);
2252 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2253 $conf->{snapstate
} = $1;
2254 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2257 $conf->{$key} = $value;
2258 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2260 if ($section eq 'pending') {
2261 $conf->{delete} = $value; # we parse this later
2263 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2265 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2268 eval { $value = check_type
($key, $value); };
2270 warn "vm $vmid - unable to parse value of '$key' - $@";
2272 $key = 'ide2' if $key eq 'cdrom';
2273 my $fmt = $confdesc->{$key}->{format
};
2274 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2275 my $v = parse_drive
($key, $value);
2276 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2277 $v->{file
} = $volid;
2278 $value = print_drive
($vmid, $v);
2280 warn "vm $vmid - unable to parse value of '$key'\n";
2285 $conf->{$key} = $value;
2290 if (defined($descr)) {
2292 $conf->{description
} = $descr;
2294 delete $res->{snapstate
}; # just to be sure
2299 sub write_vm_config
{
2300 my ($filename, $conf) = @_;
2302 delete $conf->{snapstate
}; # just to be sure
2304 if ($conf->{cdrom
}) {
2305 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2306 $conf->{ide2
} = $conf->{cdrom
};
2307 delete $conf->{cdrom
};
2310 # we do not use 'smp' any longer
2311 if ($conf->{sockets
}) {
2312 delete $conf->{smp
};
2313 } elsif ($conf->{smp
}) {
2314 $conf->{sockets
} = $conf->{smp
};
2315 delete $conf->{cores
};
2316 delete $conf->{smp
};
2319 my $used_volids = {};
2321 my $cleanup_config = sub {
2322 my ($cref, $pending, $snapname) = @_;
2324 foreach my $key (keys %$cref) {
2325 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2326 $key eq 'snapstate' || $key eq 'pending';
2327 my $value = $cref->{$key};
2328 if ($key eq 'delete') {
2329 die "propertry 'delete' is only allowed in [PENDING]\n"
2331 # fixme: check syntax?
2334 eval { $value = check_type
($key, $value); };
2335 die "unable to parse value of '$key' - $@" if $@;
2337 $cref->{$key} = $value;
2339 if (!$snapname && is_valid_drivename
($key)) {
2340 my $drive = parse_drive
($key, $value);
2341 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2346 &$cleanup_config($conf);
2348 &$cleanup_config($conf->{pending
}, 1);
2350 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2351 die "internal error" if $snapname eq 'pending';
2352 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2355 # remove 'unusedX' settings if we re-add a volume
2356 foreach my $key (keys %$conf) {
2357 my $value = $conf->{$key};
2358 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2359 delete $conf->{$key};
2363 my $generate_raw_config = sub {
2364 my ($conf, $pending) = @_;
2368 # add description as comment to top of file
2369 if (defined(my $descr = $conf->{description
})) {
2371 foreach my $cl (split(/\n/, $descr)) {
2372 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2375 $raw .= "#\n" if $pending;
2379 foreach my $key (sort keys %$conf) {
2380 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2381 $raw .= "$key: $conf->{$key}\n";
2386 my $raw = &$generate_raw_config($conf);
2388 if (scalar(keys %{$conf->{pending
}})){
2389 $raw .= "\n[PENDING]\n";
2390 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2393 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2394 $raw .= "\n[$snapname]\n";
2395 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2405 # we use static defaults from our JSON schema configuration
2406 foreach my $key (keys %$confdesc) {
2407 if (defined(my $default = $confdesc->{$key}->{default})) {
2408 $res->{$key} = $default;
2412 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2413 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2419 my $vmlist = PVE
::Cluster
::get_vmlist
();
2421 return $res if !$vmlist || !$vmlist->{ids
};
2422 my $ids = $vmlist->{ids
};
2424 foreach my $vmid (keys %$ids) {
2425 my $d = $ids->{$vmid};
2426 next if !$d->{node
} || $d->{node
} ne $nodename;
2427 next if !$d->{type
} || $d->{type
} ne 'qemu';
2428 $res->{$vmid}->{exists} = 1;
2433 # test if VM uses local resources (to prevent migration)
2434 sub check_local_resources
{
2435 my ($conf, $noerr) = @_;
2439 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2440 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2442 foreach my $k (keys %$conf) {
2443 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2444 # sockets are safe: they will recreated be on the target side post-migrate
2445 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2446 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2449 die "VM uses local resources\n" if $loc_res && !$noerr;
2454 # check if used storages are available on all nodes (use by migrate)
2455 sub check_storage_availability
{
2456 my ($storecfg, $conf, $node) = @_;
2458 foreach_drive
($conf, sub {
2459 my ($ds, $drive) = @_;
2461 my $volid = $drive->{file
};
2464 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2467 # check if storage is available on both nodes
2468 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2469 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2473 # list nodes where all VM images are available (used by has_feature API)
2475 my ($conf, $storecfg) = @_;
2477 my $nodelist = PVE
::Cluster
::get_nodelist
();
2478 my $nodehash = { map { $_ => 1 } @$nodelist };
2479 my $nodename = PVE
::INotify
::nodename
();
2481 foreach_drive
($conf, sub {
2482 my ($ds, $drive) = @_;
2484 my $volid = $drive->{file
};
2487 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2489 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2490 if ($scfg->{disable
}) {
2492 } elsif (my $avail = $scfg->{nodes
}) {
2493 foreach my $node (keys %$nodehash) {
2494 delete $nodehash->{$node} if !$avail->{$node};
2496 } elsif (!$scfg->{shared
}) {
2497 foreach my $node (keys %$nodehash) {
2498 delete $nodehash->{$node} if $node ne $nodename
2508 my ($pidfile, $pid) = @_;
2510 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2514 return undef if !$line;
2515 my @param = split(/\0/, $line);
2517 my $cmd = $param[0];
2518 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2520 for (my $i = 0; $i < scalar (@param); $i++) {
2523 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2524 my $p = $param[$i+1];
2525 return 1 if $p && ($p eq $pidfile);
2534 my ($vmid, $nocheck, $node) = @_;
2536 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2538 die "unable to find configuration file for VM $vmid - no such machine\n"
2539 if !$nocheck && ! -f
$filename;
2541 my $pidfile = pidfile_name
($vmid);
2543 if (my $fd = IO
::File-
>new("<$pidfile")) {
2548 my $mtime = $st->mtime;
2549 if ($mtime > time()) {
2550 warn "file '$filename' modified in future\n";
2553 if ($line =~ m/^(\d+)$/) {
2555 if (check_cmdline
($pidfile, $pid)) {
2556 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2568 my $vzlist = config_list
();
2570 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2572 while (defined(my $de = $fd->read)) {
2573 next if $de !~ m/^(\d+)\.pid$/;
2575 next if !defined($vzlist->{$vmid});
2576 if (my $pid = check_running
($vmid)) {
2577 $vzlist->{$vmid}->{pid
} = $pid;
2585 my ($storecfg, $conf) = @_;
2587 my $bootdisk = $conf->{bootdisk
};
2588 return undef if !$bootdisk;
2589 return undef if !is_valid_drivename
($bootdisk);
2591 return undef if !$conf->{$bootdisk};
2593 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2594 return undef if !defined($drive);
2596 return undef if drive_is_cdrom
($drive);
2598 my $volid = $drive->{file
};
2599 return undef if !$volid;
2601 return $drive->{size
};
2604 my $last_proc_pid_stat;
2606 # get VM status information
2607 # This must be fast and should not block ($full == false)
2608 # We only query KVM using QMP if $full == true (this can be slow)
2610 my ($opt_vmid, $full) = @_;
2614 my $storecfg = PVE
::Storage
::config
();
2616 my $list = vzlist
();
2617 my $defaults = load_defaults
();
2619 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2621 my $cpucount = $cpuinfo->{cpus
} || 1;
2623 foreach my $vmid (keys %$list) {
2624 next if $opt_vmid && ($vmid ne $opt_vmid);
2626 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2627 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2630 $d->{pid
} = $list->{$vmid}->{pid
};
2632 # fixme: better status?
2633 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2635 my $size = disksize
($storecfg, $conf);
2636 if (defined($size)) {
2637 $d->{disk
} = 0; # no info available
2638 $d->{maxdisk
} = $size;
2644 $d->{cpus
} = ($conf->{sockets
} || $defaults->{sockets
})
2645 * ($conf->{cores
} || $defaults->{cores
});
2646 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2647 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2649 $d->{name
} = $conf->{name
} || "VM $vmid";
2650 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024)
2651 : $defaults->{memory
}*(1024*1024);
2653 if ($conf->{balloon
}) {
2654 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2655 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
}
2656 : $defaults->{shares
};
2667 $d->{diskwrite
} = 0;
2669 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2674 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2675 foreach my $dev (keys %$netdev) {
2676 next if $dev !~ m/^tap([1-9]\d*)i/;
2678 my $d = $res->{$vmid};
2681 $d->{netout
} += $netdev->{$dev}->{receive
};
2682 $d->{netin
} += $netdev->{$dev}->{transmit
};
2685 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2686 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2691 my $ctime = gettimeofday
;
2693 foreach my $vmid (keys %$list) {
2695 my $d = $res->{$vmid};
2696 my $pid = $d->{pid
};
2699 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2700 next if !$pstat; # not running
2702 my $used = $pstat->{utime} + $pstat->{stime
};
2704 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2706 if ($pstat->{vsize
}) {
2707 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2710 my $old = $last_proc_pid_stat->{$pid};
2712 $last_proc_pid_stat->{$pid} = {
2720 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2722 if ($dtime > 1000) {
2723 my $dutime = $used - $old->{used
};
2725 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2726 $last_proc_pid_stat->{$pid} = {
2732 $d->{cpu
} = $old->{cpu
};
2736 return $res if !$full;
2738 my $qmpclient = PVE
::QMPClient-
>new();
2740 my $ballooncb = sub {
2741 my ($vmid, $resp) = @_;
2743 my $info = $resp->{'return'};
2744 return if !$info->{max_mem
};
2746 my $d = $res->{$vmid};
2748 # use memory assigned to VM
2749 $d->{maxmem
} = $info->{max_mem
};
2750 $d->{balloon
} = $info->{actual
};
2752 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2753 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2754 $d->{freemem
} = $info->{free_mem
};
2757 $d->{ballooninfo
} = $info;
2760 my $blockstatscb = sub {
2761 my ($vmid, $resp) = @_;
2762 my $data = $resp->{'return'} || [];
2763 my $totalrdbytes = 0;
2764 my $totalwrbytes = 0;
2766 for my $blockstat (@$data) {
2767 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2768 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2770 $blockstat->{device
} =~ s/drive-//;
2771 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2773 $res->{$vmid}->{diskread
} = $totalrdbytes;
2774 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2777 my $statuscb = sub {
2778 my ($vmid, $resp) = @_;
2780 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2781 # this fails if ballon driver is not loaded, so this must be
2782 # the last commnand (following command are aborted if this fails).
2783 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2785 my $status = 'unknown';
2786 if (!defined($status = $resp->{'return'}->{status
})) {
2787 warn "unable to get VM status\n";
2791 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2794 foreach my $vmid (keys %$list) {
2795 next if $opt_vmid && ($vmid ne $opt_vmid);
2796 next if !$res->{$vmid}->{pid
}; # not running
2797 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2800 $qmpclient->queue_execute(undef, 2);
2802 foreach my $vmid (keys %$list) {
2803 next if $opt_vmid && ($vmid ne $opt_vmid);
2804 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2811 my ($conf, $func, @param) = @_;
2813 foreach my $ds (valid_drive_names
()) {
2814 next if !defined($conf->{$ds});
2816 my $drive = parse_drive
($ds, $conf->{$ds});
2819 &$func($ds, $drive, @param);
2824 my ($conf, $func, @param) = @_;
2828 my $test_volid = sub {
2829 my ($volid, $is_cdrom, $replicate, $snapname) = @_;
2833 $volhash->{$volid}->{cdrom
} //= 1;
2834 $volhash->{$volid}->{cdrom
} = 0 if !$is_cdrom;
2836 $volhash->{$volid}->{replicate
} //= 0;
2837 $volhash->{$volid}->{replicate
} = 1 if $replicate;
2839 $volhash->{$volid}->{referenced_in_config
} //= 0;
2840 $volhash->{$volid}->{referenced_in_config
} = 1 if !defined($snapname);
2842 $volhash->{$volid}->{referenced_in_snapshot
}->{$snapname} = 1
2843 if defined($snapname);
2846 foreach_drive
($conf, sub {
2847 my ($ds, $drive) = @_;
2848 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, undef);
2851 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2852 my $snap = $conf->{snapshots
}->{$snapname};
2853 $test_volid->($snap->{vmstate
}, 0, 1, $snapname);
2854 foreach_drive
($snap, sub {
2855 my ($ds, $drive) = @_;
2856 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, $snapname);
2860 foreach my $volid (keys %$volhash) {
2861 &$func($volid, $volhash->{$volid}, @param);
2865 sub vga_conf_has_spice
{
2868 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2873 sub config_to_command
{
2874 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2877 my $globalFlags = [];
2878 my $machineFlags = [];
2884 my $kvmver = kvm_user_version
();
2885 my $vernum = 0; # unknown
2886 my $ostype = $conf->{ostype
};
2887 my $winversion = windows_version
($ostype);
2888 my $kvm = $conf->{kvm
} // 1;
2890 die "KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.\n" if (!$cpuinfo->{hvm
} && $kvm);
2892 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2893 $vernum = $1*1000000+$2*1000;
2894 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2895 $vernum = $1*1000000+$2*1000+$3;
2898 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2900 my $have_ovz = -f
'/proc/vz/vestat';
2902 my $q35 = machine_type_is_q35
($conf);
2903 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2904 my $machine_type = $forcemachine || $conf->{machine
};
2905 my $use_old_bios_files = undef;
2906 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2908 my $cpuunits = defined($conf->{cpuunits
}) ?
2909 $conf->{cpuunits
} : $defaults->{cpuunits
};
2911 push @$cmd, '/usr/bin/kvm';
2913 push @$cmd, '-id', $vmid;
2917 my $qmpsocket = qmp_socket
($vmid);
2918 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2919 push @$cmd, '-mon', "chardev=qmp,mode=control";
2922 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2924 push @$cmd, '-daemonize';
2926 if ($conf->{smbios1
}) {
2927 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2930 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2931 die "uefi base image not found\n" if ! -f
$OVMF_CODE;
2935 if (my $efidisk = $conf->{efidisk0
}) {
2936 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $efidisk);
2937 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
2938 $format = $d->{format
};
2940 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
2941 if (!defined($format)) {
2942 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2943 $format = qemu_img_format
($scfg, $volname);
2947 die "efidisk format must be specified\n"
2948 if !defined($format);
2951 warn "no efidisk configured! Using temporary efivars disk.\n";
2952 $path = "/tmp/$vmid-ovmf.fd";
2953 PVE
::Tools
::file_copy
($OVMF_VARS, $path, -s
$OVMF_VARS);
2957 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$OVMF_CODE";
2958 push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0,file=$path";
2962 # add usb controllers
2963 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2964 push @$devices, @usbcontrollers if @usbcontrollers;
2965 my $vga = $conf->{vga
};
2967 my $qxlnum = vga_conf_has_spice
($vga);
2968 $vga = 'qxl' if $qxlnum;
2971 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 9)) {
2972 $vga = (!$winversion || $winversion >= 6) ?
'std' : 'cirrus';
2974 $vga = ($winversion >= 6) ?
'std' : 'cirrus';
2978 # enable absolute mouse coordinates (needed by vnc)
2980 if (defined($conf->{tablet
})) {
2981 $tablet = $conf->{tablet
};
2983 $tablet = $defaults->{tablet
};
2984 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2985 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2988 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2991 my $gpu_passthrough;
2994 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2995 my $d = parse_hostpci
($conf->{"hostpci$i"});
2998 my $pcie = $d->{pcie
};
3000 die "q35 machine model is not enabled" if !$q35;
3001 $pciaddr = print_pcie_addr
("hostpci$i");
3003 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
3006 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
3007 my $romfile = $d->{romfile
};
3010 if ($d->{'x-vga'}) {
3011 $xvga = ',x-vga=on';
3014 $gpu_passthrough = 1;
3016 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
3020 my $pcidevices = $d->{pciid
};
3021 my $multifunction = 1 if @$pcidevices > 1;
3024 foreach my $pcidevice (@$pcidevices) {
3026 my $id = "hostpci$i";
3027 $id .= ".$j" if $multifunction;
3028 my $addr = $pciaddr;
3029 $addr .= ".$j" if $multifunction;
3030 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
3033 $devicestr .= "$rombar$xvga";
3034 $devicestr .= ",multifunction=on" if $multifunction;
3035 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
3038 push @$devices, '-device', $devicestr;
3044 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
3045 push @$devices, @usbdevices if @usbdevices;
3047 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
3048 if (my $path = $conf->{"serial$i"}) {
3049 if ($path eq 'socket') {
3050 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
3051 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
3052 push @$devices, '-device', "isa-serial,chardev=serial$i";
3054 die "no such serial device\n" if ! -c
$path;
3055 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
3056 push @$devices, '-device', "isa-serial,chardev=serial$i";
3062 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
3063 if (my $path = $conf->{"parallel$i"}) {
3064 die "no such parallel device\n" if ! -c
$path;
3065 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
3066 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
3067 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
3071 my $vmname = $conf->{name
} || "vm$vmid";
3073 push @$cmd, '-name', $vmname;
3076 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
3077 $sockets = $conf->{sockets
} if $conf->{sockets
};
3079 my $cores = $conf->{cores
} || 1;
3081 my $maxcpus = $sockets * $cores;
3083 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3085 my $allowed_vcpus = $cpuinfo->{cpus
};
3087 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3088 if ($allowed_vcpus < $maxcpus);
3090 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
3092 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3093 for (my $i = 2; $i <= $vcpus; $i++) {
3094 my $cpustr = print_cpu_device
($conf,$i);
3095 push @$cmd, '-device', $cpustr;
3100 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3102 push @$cmd, '-nodefaults';
3104 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3106 my $bootindex_hash = {};
3108 foreach my $o (split(//, $bootorder)) {
3109 $bootindex_hash->{$o} = $i*100;
3113 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3115 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3117 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3119 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3121 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3122 my $socket = vnc_socket
($vmid);
3123 push @$cmd, '-vnc', "unix:$socket,x509,password";
3125 push @$cmd, '-nographic';
3129 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3131 my $useLocaltime = $conf->{localtime};
3133 if ($winversion >= 5) { # windows
3134 $useLocaltime = 1 if !defined($conf->{localtime});
3136 # use time drift fix when acpi is enabled
3137 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3138 $tdf = 1 if !defined($conf->{tdf
});
3142 if ($winversion >= 6) {
3143 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3144 push @$cmd, '-no-hpet';
3147 push @$rtcFlags, 'driftfix=slew' if $tdf;
3150 push @$machineFlags, 'accel=tcg';
3153 if ($machine_type) {
3154 push @$machineFlags, "type=${machine_type}";
3157 if ($conf->{startdate
}) {
3158 push @$rtcFlags, "base=$conf->{startdate}";
3159 } elsif ($useLocaltime) {
3160 push @$rtcFlags, 'base=localtime';
3163 my $cpu = $kvm ?
"kvm64" : "qemu64";
3164 if (my $cputype = $conf->{cpu
}) {
3165 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3166 or die "Cannot parse cpu description: $cputype\n";
3167 $cpu = $cpuconf->{cputype
};
3168 $kvm_off = 1 if $cpuconf->{hidden
};
3170 if (defined(my $flags = $cpuconf->{flags
})) {
3171 push @$cpuFlags, split(";", $flags);
3175 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3177 push @$cpuFlags , '-x2apic'
3178 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3180 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3182 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3184 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3186 push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
3187 push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
3190 add_hyperv_enlightenments
($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios
}, $gpu_passthrough) if $kvm;
3192 push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm;
3194 push @$cpuFlags, 'kvm=off' if $kvm_off;
3196 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3197 die "internal error"; # should not happen
3199 push @$cpuFlags, "vendor=${cpu_vendor}"
3200 if $cpu_vendor ne 'default';
3202 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3204 push @$cmd, '-cpu', $cpu;
3206 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3208 push @$cmd, '-S' if $conf->{freeze
};
3210 # set keyboard layout
3211 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3212 push @$cmd, '-k', $kb if $kb;
3215 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3216 #push @$cmd, '-soundhw', 'es1370';
3217 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3219 if($conf->{agent
}) {
3220 my $qgasocket = qmp_socket
($vmid, 1);
3221 my $pciaddr = print_pci_addr
("qga0", $bridges);
3222 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3223 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3224 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3232 for(my $i = 1; $i < $qxlnum; $i++){
3233 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3234 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3237 # assume other OS works like Linux
3238 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3239 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3243 my $pciaddr = print_pci_addr
("spice", $bridges);
3245 my $nodename = PVE
::INotify
::nodename
();
3246 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3247 my @nodeaddrs = PVE
::Tools
::getaddrinfo_all
('localhost', family
=> $pfamily);
3248 die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
3249 my $localhost = PVE
::Network
::addr_to_ip
($nodeaddrs[0]->{addr
});
3250 $spice_port = PVE
::Tools
::next_spice_port
($pfamily, $localhost);
3252 push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
3254 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3255 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3256 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3259 # enable balloon by default, unless explicitly disabled
3260 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3261 $pciaddr = print_pci_addr
("balloon0", $bridges);
3262 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3265 if ($conf->{watchdog
}) {
3266 my $wdopts = parse_watchdog
($conf->{watchdog
});
3267 $pciaddr = print_pci_addr
("watchdog", $bridges);
3268 my $watchdog = $wdopts->{model
} || 'i6300esb';
3269 push @$devices, '-device', "$watchdog$pciaddr";
3270 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3274 my $scsicontroller = {};
3275 my $ahcicontroller = {};
3276 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3278 # Add iscsi initiator name if available
3279 if (my $initiator = get_initiator_name
()) {
3280 push @$devices, '-iscsi', "initiator-name=$initiator";
3283 foreach_drive
($conf, sub {
3284 my ($ds, $drive) = @_;
3286 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3287 push @$vollist, $drive->{file
};
3290 # ignore efidisk here, already added in bios/fw handling code above
3291 return if $drive->{interface
} eq 'efidisk';
3293 $use_virtio = 1 if $ds =~ m/^virtio/;
3295 if (drive_is_cdrom
($drive)) {
3296 if ($bootindex_hash->{d
}) {
3297 $drive->{bootindex
} = $bootindex_hash->{d
};
3298 $bootindex_hash->{d
} += 1;
3301 if ($bootindex_hash->{c
}) {
3302 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3303 $bootindex_hash->{c
} += 1;
3307 if($drive->{interface
} eq 'virtio'){
3308 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3311 if ($drive->{interface
} eq 'scsi') {
3313 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3315 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3316 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3319 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3320 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3321 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3322 } elsif ($drive->{iothread
}) {
3323 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3327 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3328 $queues = ",num_queues=$drive->{queues}";
3331 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3332 $scsicontroller->{$controller}=1;
3335 if ($drive->{interface
} eq 'sata') {
3336 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3337 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3338 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3339 $ahcicontroller->{$controller}=1;
3342 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3343 push @$devices, '-drive',$drive_cmd;
3344 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3347 for (my $i = 0; $i < $MAX_NETS; $i++) {
3348 next if !$conf->{"net$i"};
3349 my $d = parse_net
($conf->{"net$i"});
3352 $use_virtio = 1 if $d->{model
} eq 'virtio';
3354 if ($bootindex_hash->{n
}) {
3355 $d->{bootindex
} = $bootindex_hash->{n
};
3356 $bootindex_hash->{n
} += 1;
3359 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3360 push @$devices, '-netdev', $netdevfull;
3362 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3363 push @$devices, '-device', $netdevicefull;
3368 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3373 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3375 while (my ($k, $v) = each %$bridges) {
3376 $pciaddr = print_pci_addr
("pci.$k");
3377 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3382 if ($conf->{args
}) {
3383 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3387 push @$cmd, @$devices;
3388 push @$cmd, '-rtc', join(',', @$rtcFlags)
3389 if scalar(@$rtcFlags);
3390 push @$cmd, '-machine', join(',', @$machineFlags)
3391 if scalar(@$machineFlags);
3392 push @$cmd, '-global', join(',', @$globalFlags)
3393 if scalar(@$globalFlags);
3395 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3400 return "${var_run_tmpdir}/$vmid.vnc";
3406 my $res = vm_mon_cmd
($vmid, 'query-spice');
3408 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3412 my ($vmid, $qga) = @_;
3413 my $sockettype = $qga ?
'qga' : 'qmp';
3414 return "${var_run_tmpdir}/$vmid.$sockettype";
3419 return "${var_run_tmpdir}/$vmid.pid";
3422 sub vm_devices_list
{
3425 my $res = vm_mon_cmd
($vmid, 'query-pci');
3427 foreach my $pcibus (@$res) {
3428 foreach my $device (@{$pcibus->{devices
}}) {
3429 next if !$device->{'qdev_id'};
3430 if ($device->{'pci_bridge'}) {
3431 $devices->{$device->{'qdev_id'}} = 1;
3432 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3433 next if !$bridge_device->{'qdev_id'};
3434 $devices->{$bridge_device->{'qdev_id'}} = 1;
3435 $devices->{$device->{'qdev_id'}}++;
3438 $devices->{$device->{'qdev_id'}} = 1;
3443 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3444 foreach my $block (@$resblock) {
3445 if($block->{device
} =~ m/^drive-(\S+)/){
3450 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3451 foreach my $mice (@$resmice) {
3452 if ($mice->{name
} eq 'QEMU HID Tablet') {
3453 $devices->{tablet
} = 1;
3458 # for usb devices there is no query-usb
3459 # but we can iterate over the entries in
3460 # qom-list path=/machine/peripheral
3461 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3462 foreach my $per (@$resperipheral) {
3463 if ($per->{name
} =~ m/^usb\d+$/) {
3464 $devices->{$per->{name
}} = 1;
3472 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3474 my $q35 = machine_type_is_q35
($conf);
3476 my $devices_list = vm_devices_list
($vmid);
3477 return 1 if defined($devices_list->{$deviceid});
3479 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3481 if ($deviceid eq 'tablet') {
3483 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3485 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3487 die "usb hotplug currently not reliable\n";
3488 # since we can't reliably hot unplug all added usb devices
3489 # and usb passthrough disables live migration
3490 # we disable usb hotplugging for now
3491 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3493 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3495 qemu_iothread_add
($vmid, $deviceid, $device);
3497 qemu_driveadd
($storecfg, $vmid, $device);
3498 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3500 qemu_deviceadd
($vmid, $devicefull);
3501 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3503 eval { qemu_drivedel
($vmid, $deviceid); };
3508 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3511 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3512 my $pciaddr = print_pci_addr
($deviceid);
3513 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3515 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3517 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3518 qemu_iothread_add
($vmid, $deviceid, $device);
3519 $devicefull .= ",iothread=iothread-$deviceid";
3522 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3523 $devicefull .= ",num_queues=$device->{queues}";
3526 qemu_deviceadd
($vmid, $devicefull);
3527 qemu_deviceaddverify
($vmid, $deviceid);
3529 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3531 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3532 qemu_driveadd
($storecfg, $vmid, $device);
3534 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3535 eval { qemu_deviceadd
($vmid, $devicefull); };
3537 eval { qemu_drivedel
($vmid, $deviceid); };
3542 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3544 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3546 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3547 my $use_old_bios_files = undef;
3548 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3550 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3551 qemu_deviceadd
($vmid, $netdevicefull);
3552 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3554 eval { qemu_netdevdel
($vmid, $deviceid); };
3559 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3562 my $pciaddr = print_pci_addr
($deviceid);
3563 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3565 qemu_deviceadd
($vmid, $devicefull);
3566 qemu_deviceaddverify
($vmid, $deviceid);
3569 die "can't hotplug device '$deviceid'\n";
3575 # fixme: this should raise exceptions on error!
3576 sub vm_deviceunplug
{
3577 my ($vmid, $conf, $deviceid) = @_;
3579 my $devices_list = vm_devices_list
($vmid);
3580 return 1 if !defined($devices_list->{$deviceid});
3582 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3584 if ($deviceid eq 'tablet') {
3586 qemu_devicedel
($vmid, $deviceid);
3588 } elsif ($deviceid =~ m/^usb\d+$/) {
3590 die "usb hotplug currently not reliable\n";
3591 # when unplugging usb devices this way,
3592 # there may be remaining usb controllers/hubs
3593 # so we disable it for now
3594 qemu_devicedel
($vmid, $deviceid);
3595 qemu_devicedelverify
($vmid, $deviceid);
3597 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3599 qemu_devicedel
($vmid, $deviceid);
3600 qemu_devicedelverify
($vmid, $deviceid);
3601 qemu_drivedel
($vmid, $deviceid);
3602 qemu_iothread_del
($conf, $vmid, $deviceid);
3604 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3606 qemu_devicedel
($vmid, $deviceid);
3607 qemu_devicedelverify
($vmid, $deviceid);
3608 qemu_iothread_del
($conf, $vmid, $deviceid);
3610 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3612 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3613 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3614 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3616 qemu_devicedel
($vmid, $deviceid);
3617 qemu_drivedel
($vmid, $deviceid);
3618 qemu_deletescsihw
($conf, $vmid, $deviceid);
3620 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3622 qemu_devicedel
($vmid, $deviceid);
3623 qemu_devicedelverify
($vmid, $deviceid);
3624 qemu_netdevdel
($vmid, $deviceid);
3627 die "can't unplug device '$deviceid'\n";
3633 sub qemu_deviceadd
{
3634 my ($vmid, $devicefull) = @_;
3636 $devicefull = "driver=".$devicefull;
3637 my %options = split(/[=,]/, $devicefull);
3639 vm_mon_cmd
($vmid, "device_add" , %options);
3642 sub qemu_devicedel
{
3643 my ($vmid, $deviceid) = @_;
3645 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3648 sub qemu_iothread_add
{
3649 my($vmid, $deviceid, $device) = @_;
3651 if ($device->{iothread
}) {
3652 my $iothreads = vm_iothreads_list
($vmid);
3653 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3657 sub qemu_iothread_del
{
3658 my($conf, $vmid, $deviceid) = @_;
3660 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3661 if ($device->{iothread
}) {
3662 my $iothreads = vm_iothreads_list
($vmid);
3663 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3667 sub qemu_objectadd
{
3668 my($vmid, $objectid, $qomtype) = @_;
3670 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3675 sub qemu_objectdel
{
3676 my($vmid, $objectid) = @_;
3678 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3684 my ($storecfg, $vmid, $device) = @_;
3686 my $drive = print_drive_full
($storecfg, $vmid, $device);
3687 $drive =~ s/\\/\\\\/g;
3688 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3690 # If the command succeeds qemu prints: "OK
"
3691 return 1 if $ret =~ m/OK/s;
3693 die "adding drive failed
: $ret\n";
3697 my($vmid, $deviceid) = @_;
3699 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3702 return 1 if $ret eq "";
3704 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3705 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3707 die "deleting drive
$deviceid failed
: $ret\n";
3710 sub qemu_deviceaddverify {
3711 my ($vmid, $deviceid) = @_;
3713 for (my $i = 0; $i <= 5; $i++) {
3714 my $devices_list = vm_devices_list($vmid);
3715 return 1 if defined($devices_list->{$deviceid});
3719 die "error on hotplug device
'$deviceid'\n";
3723 sub qemu_devicedelverify {
3724 my ($vmid, $deviceid) = @_;
3726 # need to verify that the device is correctly removed as device_del
3727 # is async and empty return is not reliable
3729 for (my $i = 0; $i <= 5; $i++) {
3730 my $devices_list = vm_devices_list($vmid);
3731 return 1 if !defined($devices_list->{$deviceid});
3735 die "error on hot-unplugging device
'$deviceid'\n";
3738 sub qemu_findorcreatescsihw {
3739 my ($storecfg, $conf, $vmid, $device) = @_;
3741 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3743 my $scsihwid="$controller_prefix$controller";
3744 my $devices_list = vm_devices_list($vmid);
3746 if(!defined($devices_list->{$scsihwid})) {
3747 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3753 sub qemu_deletescsihw {
3754 my ($conf, $vmid, $opt) = @_;
3756 my $device = parse_drive($opt, $conf->{$opt});
3758 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3759 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3763 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3765 my $devices_list = vm_devices_list($vmid);
3766 foreach my $opt (keys %{$devices_list}) {
3767 if (PVE::QemuServer::is_valid_drivename($opt)) {
3768 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3769 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3775 my $scsihwid="scsihw
$controller";
3777 vm_deviceunplug($vmid, $conf, $scsihwid);
3782 sub qemu_add_pci_bridge {
3783 my ($storecfg, $conf, $vmid, $device) = @_;
3789 print_pci_addr($device, $bridges);
3791 while (my ($k, $v) = each %$bridges) {
3794 return 1 if !defined($bridgeid) || $bridgeid < 1;
3796 my $bridge = "pci
.$bridgeid";
3797 my $devices_list = vm_devices_list($vmid);
3799 if (!defined($devices_list->{$bridge})) {
3800 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3806 sub qemu_set_link_status {
3807 my ($vmid, $device, $up) = @_;
3809 vm_mon_cmd($vmid, "set_link
", name => $device,
3810 up => $up ? JSON::true : JSON::false);
3813 sub qemu_netdevadd {
3814 my ($vmid, $conf, $device, $deviceid) = @_;
3816 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3817 my %options = split(/[=,]/, $netdev);
3819 vm_mon_cmd($vmid, "netdev_add
", %options);
3823 sub qemu_netdevdel {
3824 my ($vmid, $deviceid) = @_;
3826 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3829 sub qemu_usb_hotplug {
3830 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3834 # remove the old one first
3835 vm_deviceunplug($vmid, $conf, $deviceid);
3837 # check if xhci controller is necessary and available
3838 if ($device->{usb3}) {
3840 my $devicelist = vm_devices_list($vmid);
3842 if (!$devicelist->{xhci}) {
3843 my $pciaddr = print_pci_addr("xhci
");
3844 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3847 my $d = parse_usb_device($device->{host});
3848 $d->{usb3} = $device->{usb3};
3851 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3854 sub qemu_cpu_hotplug {
3855 my ($vmid, $conf, $vcpus) = @_;
3857 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3860 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3861 $sockets = $conf->{sockets} if $conf->{sockets};
3862 my $cores = $conf->{cores} || 1;
3863 my $maxcpus = $sockets * $cores;
3865 $vcpus = $maxcpus if !$vcpus;
3867 die "you can
't add more vcpus than maxcpus\n"
3868 if $vcpus > $maxcpus;
3870 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3872 if ($vcpus < $currentvcpus) {
3874 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3876 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3877 qemu_devicedel($vmid, "cpu$i");
3879 my $currentrunningvcpus = undef;
3881 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3882 last if scalar(@{$currentrunningvcpus}) == $i-1;
3883 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3887 #update conf after each succesfull cpu unplug
3888 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3889 PVE::QemuConfig->write_config($vmid, $conf);
3892 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3898 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3899 die "vcpus in running vm does not match its configuration\n"
3900 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3902 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3904 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3905 my $cpustr = print_cpu_device($conf, $i);
3906 qemu_deviceadd($vmid, $cpustr);
3909 my $currentrunningvcpus = undef;
3911 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3912 last if scalar(@{$currentrunningvcpus}) == $i;
3913 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3917 #update conf after each succesfull cpu hotplug
3918 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3919 PVE::QemuConfig->write_config($vmid, $conf);
3923 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3924 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3929 sub qemu_block_set_io_throttle {
3930 my ($vmid, $deviceid,
3931 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3932 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3933 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3934 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3936 return if !check_running($vmid) ;
3938 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3940 bps_rd => int($bps_rd),
3941 bps_wr => int($bps_wr),
3943 iops_rd => int($iops_rd),
3944 iops_wr => int($iops_wr),
3945 bps_max => int($bps_max),
3946 bps_rd_max => int($bps_rd_max),
3947 bps_wr_max => int($bps_wr_max),
3948 iops_max => int($iops_max),
3949 iops_rd_max => int($iops_rd_max),
3950 iops_wr_max => int($iops_wr_max),
3951 bps_max_length => int($bps_max_length),
3952 bps_rd_max_length => int($bps_rd_max_length),
3953 bps_wr_max_length => int($bps_wr_max_length),
3954 iops_max_length => int($iops_max_length),
3955 iops_rd_max_length => int($iops_rd_max_length),
3956 iops_wr_max_length => int($iops_wr_max_length),
3961 # old code, only used to shutdown old VM after update
3963 my ($fh, $timeout) = @_;
3965 my $sel = new IO::Select;
3972 while (scalar (@ready = $sel->can_read($timeout))) {
3974 if ($count = $fh->sysread($buf, 8192)) {
3975 if ($buf =~ /^(.*)\(qemu\) $/s) {
3982 if (!defined($count)) {
3989 die "monitor read timeout\n" if !scalar(@ready);
3994 # old code, only used to shutdown old VM after update
3995 sub vm_monitor_command {
3996 my ($vmid, $cmdstr, $nocheck) = @_;
4001 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4003 my $sname = "${var_run_tmpdir}/$vmid.mon";
4005 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
4006 die "unable to connect to VM $vmid socket - $!\n";
4010 # hack: migrate sometime blocks the monitor (when migrate_downtime
4012 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4013 $timeout = 60*60; # 1 hour
4017 my $data = __read_avail($sock, $timeout);
4019 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
4020 die "got unexpected qemu monitor banner\n";
4023 my $sel = new IO::Select;
4026 if (!scalar(my @ready = $sel->can_write($timeout))) {
4027 die "monitor write error - timeout";
4030 my $fullcmd = "$cmdstr\r";
4032 # syslog('info
', "VM $vmid monitor command: $cmdstr");
4035 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4036 die "monitor write error - $!";
4039 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
4043 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4044 $timeout = 60*60; # 1 hour
4045 } elsif ($cmdstr =~ m/^(eject|change)/) {
4046 $timeout = 60; # note: cdrom mount command is slow
4048 if ($res = __read_avail($sock, $timeout)) {
4050 my @lines = split("\r?\n", $res);
4052 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4054 $res = join("\n", @lines);
4062 syslog("err", "VM $vmid monitor command failed - $err");
4069 sub qemu_block_resize {
4070 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4072 my $running = check_running($vmid);
4074 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4076 return if !$running;
4078 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4082 sub qemu_volume_snapshot {
4083 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4085 my $running = check_running($vmid);
4087 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4088 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4090 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4094 sub qemu_volume_snapshot_delete {
4095 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4097 my $running = check_running($vmid);
4099 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4100 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4102 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4106 sub set_migration_caps {
4112 "auto-converge" => 1,
4114 "x-rdma-pin-all" => 0,
4119 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4121 for my $supported_capability (@$supported_capabilities) {
4123 capability => $supported_capability->{capability},
4124 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4128 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4131 my $fast_plug_option = {
4139 'vmstatestorage
' => 1,
4142 # hotplug changes in [PENDING]
4143 # $selection hash can be used to only apply specified options, for
4144 # example: { cores => 1 } (only apply changed 'cores
')
4145 # $errors ref is used to return error messages
4146 sub vmconfig_hotplug_pending {
4147 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4149 my $defaults = load_defaults();
4151 # commit values which do not have any impact on running VM first
4152 # Note: those option cannot raise errors, we we do not care about
4153 # $selection and always apply them.
4155 my $add_error = sub {
4156 my ($opt, $msg) = @_;
4157 $errors->{$opt} = "hotplug problem - $msg";
4161 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4162 if ($fast_plug_option->{$opt}) {
4163 $conf->{$opt} = $conf->{pending}->{$opt};
4164 delete $conf->{pending}->{$opt};
4170 PVE::QemuConfig->write_config($vmid, $conf);
4171 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4174 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4176 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4177 while (my ($opt, $force) = each %$pending_delete_hash) {
4178 next if $selection && !$selection->{$opt};
4180 if ($opt eq 'hotplug
') {
4181 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4182 } elsif ($opt eq 'tablet
') {
4183 die "skip\n" if !$hotplug_features->{usb};
4184 if ($defaults->{tablet}) {
4185 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4187 vm_deviceunplug($vmid, $conf, $opt);
4189 } elsif ($opt =~ m/^usb\d+/) {
4191 # since we cannot reliably hot unplug usb devices
4192 # we are disabling it
4193 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4194 vm_deviceunplug($vmid, $conf, $opt);
4195 } elsif ($opt eq 'vcpus
') {
4196 die "skip\n" if !$hotplug_features->{cpu};
4197 qemu_cpu_hotplug($vmid, $conf, undef);
4198 } elsif ($opt eq 'balloon
') {
4199 # enable balloon device is not hotpluggable
4200 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4201 } elsif ($fast_plug_option->{$opt}) {
4203 } elsif ($opt =~ m/^net(\d+)$/) {
4204 die "skip\n" if !$hotplug_features->{network};
4205 vm_deviceunplug($vmid, $conf, $opt);
4206 } elsif (is_valid_drivename($opt)) {
4207 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4208 vm_deviceunplug($vmid, $conf, $opt);
4209 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4210 } elsif ($opt =~ m/^memory$/) {
4211 die "skip\n" if !$hotplug_features->{memory};
4212 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4213 } elsif ($opt eq 'cpuunits
') {
4214 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4215 } elsif ($opt eq 'cpulimit
') {
4216 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4222 &$add_error($opt, $err) if $err ne "skip\n";
4224 # save new config if hotplug was successful
4225 delete $conf->{$opt};
4226 vmconfig_undelete_pending_option($conf, $opt);
4227 PVE::QemuConfig->write_config($vmid, $conf);
4228 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4232 foreach my $opt (keys %{$conf->{pending}}) {
4233 next if $selection && !$selection->{$opt};
4234 my $value = $conf->{pending}->{$opt};
4236 if ($opt eq 'hotplug
') {
4237 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4238 } elsif ($opt eq 'tablet
') {
4239 die "skip\n" if !$hotplug_features->{usb};
4241 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4242 } elsif ($value == 0) {
4243 vm_deviceunplug($vmid, $conf, $opt);
4245 } elsif ($opt =~ m/^usb\d+$/) {
4247 # since we cannot reliably hot unplug usb devices
4248 # we are disabling it
4249 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4250 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4251 die "skip\n" if !$d;
4252 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4253 } elsif ($opt eq 'vcpus
') {
4254 die "skip\n" if !$hotplug_features->{cpu};
4255 qemu_cpu_hotplug($vmid, $conf, $value);
4256 } elsif ($opt eq 'balloon
') {
4257 # enable/disable balloning device is not hotpluggable
4258 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4259 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4260 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4262 # allow manual ballooning if shares is set to zero
4263 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4264 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4265 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4267 } elsif ($opt =~ m/^net(\d+)$/) {
4268 # some changes can be done without hotplug
4269 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4270 $vmid, $opt, $value);
4271 } elsif (is_valid_drivename($opt)) {
4272 # some changes can be done without hotplug
4273 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4274 $vmid, $opt, $value, 1);
4275 } elsif ($opt =~ m/^memory$/) { #dimms
4276 die "skip\n" if !$hotplug_features->{memory};
4277 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4278 } elsif ($opt eq 'cpuunits
') {
4279 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4280 } elsif ($opt eq 'cpulimit
') {
4281 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4282 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4284 die "skip\n"; # skip non-hot-pluggable options
4288 &$add_error($opt, $err) if $err ne "skip\n";
4290 # save new config if hotplug was successful
4291 $conf->{$opt} = $value;
4292 delete $conf->{pending}->{$opt};
4293 PVE::QemuConfig->write_config($vmid, $conf);
4294 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4299 sub try_deallocate_drive {
4300 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4302 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4303 my $volid = $drive->{file};
4304 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4305 my $sid = PVE::Storage::parse_volume_id($volid);
4306 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4308 # check if the disk is really unused
4309 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4310 if is_volume_in_use($storecfg, $conf, $key, $volid);
4311 PVE::Storage::vdisk_free($storecfg, $volid);
4314 # If vm is not owner of this disk remove from config
4322 sub vmconfig_delete_or_detach_drive {
4323 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4325 my $drive = parse_drive($opt, $conf->{$opt});
4327 my $rpcenv = PVE::RPCEnvironment::get();
4328 my $authuser = $rpcenv->get_user();
4331 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4332 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4334 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4338 sub vmconfig_apply_pending {
4339 my ($vmid, $conf, $storecfg) = @_;
4343 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4344 while (my ($opt, $force) = each %$pending_delete_hash) {
4345 die "internal error" if $opt =~ m/^unused/;
4346 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4347 if (!defined($conf->{$opt})) {
4348 vmconfig_undelete_pending_option($conf, $opt);
4349 PVE::QemuConfig->write_config($vmid, $conf);
4350 } elsif (is_valid_drivename($opt)) {
4351 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4352 vmconfig_undelete_pending_option($conf, $opt);
4353 delete $conf->{$opt};
4354 PVE::QemuConfig->write_config($vmid, $conf);
4356 vmconfig_undelete_pending_option($conf, $opt);
4357 delete $conf->{$opt};
4358 PVE::QemuConfig->write_config($vmid, $conf);
4362 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4364 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4365 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4367 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4368 # skip if nothing changed
4369 } elsif (is_valid_drivename($opt)) {
4370 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4371 if defined($conf->{$opt});
4372 $conf->{$opt} = $conf->{pending}->{$opt};
4374 $conf->{$opt} = $conf->{pending}->{$opt};
4377 delete $conf->{pending}->{$opt};
4378 PVE::QemuConfig->write_config($vmid, $conf);
4382 my $safe_num_ne = sub {
4385 return 0 if !defined($a) && !defined($b);
4386 return 1 if !defined($a);
4387 return 1 if !defined($b);
4392 my $safe_string_ne = sub {
4395 return 0 if !defined($a) && !defined($b);
4396 return 1 if !defined($a);
4397 return 1 if !defined($b);
4402 sub vmconfig_update_net {
4403 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4405 my $newnet = parse_net($value);
4407 if ($conf->{$opt}) {
4408 my $oldnet = parse_net($conf->{$opt});
4410 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4411 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4412 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4413 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4415 # for non online change, we try to hot-unplug
4416 die "skip\n" if !$hotplug;
4417 vm_deviceunplug($vmid, $conf, $opt);
4420 die "internal error" if $opt !~ m/net(\d+)/;
4421 my $iface = "tap${vmid}i$1";
4423 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4424 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4425 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4426 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4427 PVE::Network::tap_unplug($iface);
4428 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4429 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4430 # Rate can be applied on its own but any change above needs to
4431 # include the rate in tap_plug since OVS resets everything.
4432 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4435 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4436 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4444 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4450 sub vmconfig_update_disk {
4451 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4453 # fixme: do we need force?
4455 my $drive = parse_drive($opt, $value);
4457 if ($conf->{$opt}) {
4459 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4461 my $media = $drive->{media} || 'disk
';
4462 my $oldmedia = $old_drive->{media} || 'disk
';
4463 die "unable to change media type\n" if $media ne $oldmedia;
4465 if (!drive_is_cdrom($old_drive)) {
4467 if ($drive->{file} ne $old_drive->{file}) {
4469 die "skip\n" if !$hotplug;
4471 # unplug and register as unused
4472 vm_deviceunplug($vmid, $conf, $opt);
4473 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4476 # update existing disk
4478 # skip non hotpluggable value
4479 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4480 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4481 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4482 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4487 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4488 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4489 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4490 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4491 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4492 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4493 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4494 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4495 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4496 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4497 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4498 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4499 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4500 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4501 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4502 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4503 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4504 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4506 qemu_block_set_io_throttle($vmid,"drive-$opt",
4507 ($drive->{mbps} || 0)*1024*1024,
4508 ($drive->{mbps_rd} || 0)*1024*1024,
4509 ($drive->{mbps_wr} || 0)*1024*1024,
4510 $drive->{iops} || 0,
4511 $drive->{iops_rd} || 0,
4512 $drive->{iops_wr} || 0,
4513 ($drive->{mbps_max} || 0)*1024*1024,
4514 ($drive->{mbps_rd_max} || 0)*1024*1024,
4515 ($drive->{mbps_wr_max} || 0)*1024*1024,
4516 $drive->{iops_max} || 0,
4517 $drive->{iops_rd_max} || 0,
4518 $drive->{iops_wr_max} || 0,
4519 $drive->{bps_max_length} || 1,
4520 $drive->{bps_rd_max_length} || 1,
4521 $drive->{bps_wr_max_length} || 1,
4522 $drive->{iops_max_length} || 1,
4523 $drive->{iops_rd_max_length} || 1,
4524 $drive->{iops_wr_max_length} || 1);
4533 if ($drive->{file} eq 'none
') {
4534 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4536 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4537 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4538 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4546 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4548 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4549 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4553 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4554 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
4556 PVE::QemuConfig->lock_config($vmid, sub {
4557 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4559 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4561 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4563 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4565 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4566 vmconfig_apply_pending($vmid, $conf, $storecfg);
4567 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4570 my $defaults = load_defaults();
4572 # set environment variable useful inside network script
4573 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4575 my $local_volumes = {};
4577 if ($targetstorage) {
4578 foreach_drive($conf, sub {
4579 my ($ds, $drive) = @_;
4581 return if drive_is_cdrom($drive);
4583 my $volid = $drive->{file};
4587 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
4589 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4590 return if $scfg->{shared};
4591 $local_volumes->{$ds} = [$volid, $storeid, $volname];
4596 foreach my $opt (sort keys %$local_volumes) {
4598 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
4599 my $drive = parse_drive($opt, $conf->{$opt});
4601 #if remote storage is specified, use default format
4602 if ($targetstorage && $targetstorage ne "1") {
4603 $storeid = $targetstorage;
4604 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4605 $format = $defFormat;
4607 #else we use same format than original
4608 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4609 $format = qemu_img_format($scfg, $volid);
4612 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
4613 my $newdrive = $drive;
4614 $newdrive->{format} = $format;
4615 $newdrive->{file} = $newvolid;
4616 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
4617 $local_volumes->{$opt} = $drivestr;
4618 #pass drive to conf for command line
4619 $conf->{$opt} = $drivestr;
4623 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4625 my $migrate_port = 0;
4628 if ($statefile eq 'tcp
') {
4629 my $localip = "localhost";
4630 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4631 my $nodename = PVE::INotify::nodename();
4633 if (!defined($migration_type)) {
4634 if (defined($datacenterconf->{migration}->{type})) {
4635 $migration_type = $datacenterconf->{migration}->{type};
4637 $migration_type = 'secure
';
4641 if ($migration_type eq 'insecure
') {
4642 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4643 if ($migrate_network_addr) {
4644 $localip = $migrate_network_addr;
4646 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4649 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4652 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4653 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4654 $migrate_uri = "tcp:${localip}:${migrate_port}";
4655 push @$cmd, '-incoming
', $migrate_uri;
4658 } elsif ($statefile eq 'unix
') {
4659 # should be default for secure migrations as a ssh TCP forward
4660 # tunnel is not deterministic reliable ready and fails regurarly
4661 # to set up in time, so use UNIX socket forwards
4662 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4663 unlink $socket_addr;
4665 $migrate_uri = "unix:$socket_addr";
4667 push @$cmd, '-incoming
', $migrate_uri;
4671 push @$cmd, '-loadstate
', $statefile;
4678 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4679 my $d = parse_hostpci($conf->{"hostpci$i"});
4681 my $pcidevices = $d->{pciid};
4682 foreach my $pcidevice (@$pcidevices) {
4683 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4685 my $info = pci_device_info("0000:$pciid");
4686 die "IOMMU not present\n" if !check_iommu_support();
4687 die "no pci device info for device '$pciid'\n" if !$info;
4688 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4689 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4693 PVE::Storage::activate_volumes($storecfg, $vollist);
4695 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4697 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4698 eval { run_command($cmd); };
4701 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4702 : $defaults->{cpuunits};
4704 my $start_timeout = $conf->{hugepages} ? 300 : 30;
4705 my %run_params = (timeout => $statefile ? undef : $start_timeout, umask => 0077);
4708 Slice => 'qemu
.slice
',
4710 CPUShares => $cpuunits
4713 if (my $cpulimit = $conf->{cpulimit}) {
4714 $properties{CPUQuota} = int($cpulimit * 100);
4716 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4718 if ($conf->{hugepages}) {
4721 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4722 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4724 PVE::QemuServer::Memory::hugepages_mount();
4725 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4728 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4729 run_command($cmd, %run_params);
4733 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4737 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4739 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4743 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4744 run_command($cmd, %run_params);
4749 # deactivate volumes if start fails
4750 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4751 die "start failed: $err";
4754 print "migration listens on $migrate_uri\n" if $migrate_uri;
4756 if ($statefile && $statefile ne 'tcp
' && $statefile ne 'unix
') {
4757 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4761 #start nbd server for storage migration
4762 if ($targetstorage) {
4763 my $nodename = PVE::INotify::nodename();
4764 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4765 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
4766 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4767 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4769 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet
', data => { host => "${localip}", port => "${migrate_port}" } } );
4771 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4773 foreach my $opt (sort keys %$local_volumes) {
4774 my $volid = $local_volumes->{$opt};
4775 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
4776 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
4777 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
4781 if ($migratedfrom) {
4783 set_migration_caps($vmid);
4788 print "spice listens on port $spice_port\n";
4789 if ($spice_ticket) {
4790 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4791 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4796 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4797 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4798 if $conf->{balloon};
4801 foreach my $opt (keys %$conf) {
4802 next if $opt !~ m/^net\d+$/;
4803 my $nicconf = parse_net($conf->{$opt});
4804 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4808 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4809 path => "machine/peripheral/balloon0",
4810 property => "guest-stats-polling-interval",
4811 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4817 my ($vmid, $execute, %params) = @_;
4819 my $cmd = { execute => $execute, arguments => \%params };
4820 vm_qmp_command($vmid, $cmd);
4823 sub vm_mon_cmd_nocheck {
4824 my ($vmid, $execute, %params) = @_;
4826 my $cmd = { execute => $execute, arguments => \%params };
4827 vm_qmp_command($vmid, $cmd, 1);
4830 sub vm_qmp_command {
4831 my ($vmid, $cmd, $nocheck) = @_;
4836 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4837 $timeout = $cmd->{arguments}->{timeout};
4838 delete $cmd->{arguments}->{timeout};
4842 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4843 my $sname = qmp_socket($vmid);
4844 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4845 my $qmpclient = PVE::QMPClient->new();
4847 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4848 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4849 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4850 if scalar(%{$cmd->{arguments}});
4851 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4853 die "unable to
open monitor
socket\n";
4857 syslog("err
", "VM
$vmid qmp command failed
- $err");
4864 sub vm_human_monitor_command {
4865 my ($vmid, $cmdline) = @_;
4870 execute => 'human-monitor-command',
4871 arguments => { 'command-line' => $cmdline},
4874 return vm_qmp_command($vmid, $cmd);
4877 sub vm_commandline {
4878 my ($storecfg, $vmid) = @_;
4880 my $conf = PVE::QemuConfig->load_config($vmid);
4882 my $defaults = load_defaults();
4884 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4886 return PVE::Tools::cmd2string($cmd);
4890 my ($vmid, $skiplock) = @_;
4892 PVE::QemuConfig->lock_config($vmid, sub {
4894 my $conf = PVE::QemuConfig->load_config($vmid);
4896 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4898 vm_mon_cmd($vmid, "system_reset
");
4902 sub get_vm_volumes {
4906 foreach_volid($conf, sub {
4907 my ($volid, $attr) = @_;
4909 return if $volid =~ m|^/|;
4911 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4914 push @$vollist, $volid;
4920 sub vm_stop_cleanup {
4921 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4926 my $vollist = get_vm_volumes($conf);
4927 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4930 foreach my $ext (qw(mon qmp pid vnc qga)) {
4931 unlink "/var/run/qemu-server/${vmid}.$ext";
4934 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4936 warn $@ if $@; # avoid errors - just warn
4939 # Note: use $nockeck to skip tests if VM configuration file exists.
4940 # We need that when migration VMs to other nodes (files already moved)
4941 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4943 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4945 $force = 1 if !defined($force) && !$shutdown;
4948 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4949 kill 15, $pid if $pid;
4950 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4951 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4955 PVE
::QemuConfig-
>lock_config($vmid, sub {
4957 my $pid = check_running
($vmid, $nocheck);
4962 $conf = PVE
::QemuConfig-
>load_config($vmid);
4963 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4964 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4965 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4966 $timeout = $opts->{down
} if $opts->{down
};
4970 $timeout = 60 if !defined($timeout);
4974 if (defined($conf) && $conf->{agent
}) {
4975 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4977 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4980 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4987 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4992 if ($count >= $timeout) {
4994 warn "VM still running - terminating now with SIGTERM\n";
4997 die "VM quit/powerdown failed - got timeout\n";
5000 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
5005 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
5008 die "VM quit/powerdown failed\n";
5016 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
5021 if ($count >= $timeout) {
5022 warn "VM still running - terminating now with SIGKILL\n";
5027 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
5032 my ($vmid, $skiplock) = @_;
5034 PVE
::QemuConfig-
>lock_config($vmid, sub {
5036 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5038 PVE
::QemuConfig-
>check_lock($conf)
5039 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5041 vm_mon_cmd
($vmid, "stop");
5046 my ($vmid, $skiplock, $nocheck) = @_;
5048 PVE
::QemuConfig-
>lock_config($vmid, sub {
5052 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5054 PVE
::QemuConfig-
>check_lock($conf)
5055 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5057 vm_mon_cmd
($vmid, "cont");
5060 vm_mon_cmd_nocheck
($vmid, "cont");
5066 my ($vmid, $skiplock, $key) = @_;
5068 PVE
::QemuConfig-
>lock_config($vmid, sub {
5070 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5072 # there is no qmp command, so we use the human monitor command
5073 vm_human_monitor_command
($vmid, "sendkey $key");
5078 my ($storecfg, $vmid, $skiplock) = @_;
5080 PVE
::QemuConfig-
>lock_config($vmid, sub {
5082 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5084 if (!check_running
($vmid)) {
5085 destroy_vm
($storecfg, $vmid, undef, $skiplock);
5087 die "VM $vmid is running - destroy failed\n";
5095 my ($filename, $buf) = @_;
5097 my $fh = IO
::File-
>new($filename, "w");
5098 return undef if !$fh;
5100 my $res = print $fh $buf;
5107 sub pci_device_info
{
5112 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
5113 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
5115 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
5116 return undef if !defined($irq) || $irq !~ m/^\d+$/;
5118 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
5119 return undef if !defined($vendor) || $vendor !~ s/^0x//;
5121 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
5122 return undef if !defined($product) || $product !~ s/^0x//;
5127 product
=> $product,
5133 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
5142 my $name = $dev->{name
};
5144 my $fn = "$pcisysfs/devices/$name/reset";
5146 return file_write
($fn, "1");
5149 sub pci_dev_bind_to_vfio
{
5152 my $name = $dev->{name
};
5154 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5156 if (!-d
$vfio_basedir) {
5157 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5159 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5161 my $testdir = "$vfio_basedir/$name";
5162 return 1 if -d
$testdir;
5164 my $data = "$dev->{vendor} $dev->{product}";
5165 return undef if !file_write
("$vfio_basedir/new_id", $data);
5167 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5168 if (!file_write
($fn, $name)) {
5169 return undef if -f
$fn;
5172 $fn = "$vfio_basedir/bind";
5173 if (! -d
$testdir) {
5174 return undef if !file_write
($fn, $name);
5180 sub pci_dev_group_bind_to_vfio
{
5183 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5185 if (!-d
$vfio_basedir) {
5186 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5188 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5190 # get IOMMU group devices
5191 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5192 my @devs = grep /^0000:/, readdir($D);
5195 foreach my $pciid (@devs) {
5196 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5198 # pci bridges, switches or root ports are not supported
5199 # they have a pci_bus subdirectory so skip them
5200 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5202 my $info = pci_device_info
($1);
5203 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5209 # vzdump restore implementaion
5211 sub tar_archive_read_firstfile
{
5212 my $archive = shift;
5214 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5216 # try to detect archive type first
5217 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5218 die "unable to open file '$archive'\n";
5219 my $firstfile = <$fh>;
5223 die "ERROR: archive contaions no data\n" if !$firstfile;
5229 sub tar_restore_cleanup
{
5230 my ($storecfg, $statfile) = @_;
5232 print STDERR
"starting cleanup\n";
5234 if (my $fd = IO
::File-
>new($statfile, "r")) {
5235 while (defined(my $line = <$fd>)) {
5236 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5239 if ($volid =~ m
|^/|) {
5240 unlink $volid || die 'unlink failed\n';
5242 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5244 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5246 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5248 print STDERR
"unable to parse line in statfile - $line";
5255 sub restore_archive
{
5256 my ($archive, $vmid, $user, $opts) = @_;
5258 my $format = $opts->{format
};
5261 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5262 $format = 'tar' if !$format;
5264 } elsif ($archive =~ m/\.tar$/) {
5265 $format = 'tar' if !$format;
5266 } elsif ($archive =~ m/.tar.lzo$/) {
5267 $format = 'tar' if !$format;
5269 } elsif ($archive =~ m/\.vma$/) {
5270 $format = 'vma' if !$format;
5271 } elsif ($archive =~ m/\.vma\.gz$/) {
5272 $format = 'vma' if !$format;
5274 } elsif ($archive =~ m/\.vma\.lzo$/) {
5275 $format = 'vma' if !$format;
5278 $format = 'vma' if !$format; # default
5281 # try to detect archive format
5282 if ($format eq 'tar') {
5283 return restore_tar_archive
($archive, $vmid, $user, $opts);
5285 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5289 sub restore_update_config_line
{
5290 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5292 return if $line =~ m/^\#qmdump\#/;
5293 return if $line =~ m/^\#vzdump\#/;
5294 return if $line =~ m/^lock:/;
5295 return if $line =~ m/^unused\d+:/;
5296 return if $line =~ m/^parent:/;
5297 return if $line =~ m/^template:/; # restored VM is never a template
5299 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5300 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5301 # try to convert old 1.X settings
5302 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5303 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5304 my ($model, $macaddr) = split(/\=/, $devconfig);
5305 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5308 bridge
=> "vmbr$ind",
5309 macaddr
=> $macaddr,
5311 my $netstr = print_net
($net);
5313 print $outfd "net$cookie->{netcount}: $netstr\n";
5314 $cookie->{netcount
}++;
5316 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5317 my ($id, $netstr) = ($1, $2);
5318 my $net = parse_net
($netstr);
5319 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5320 $netstr = print_net
($net);
5321 print $outfd "$id: $netstr\n";
5322 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5325 my $di = parse_drive
($virtdev, $value);
5326 if (defined($di->{backup
}) && !$di->{backup
}) {
5327 print $outfd "#$line";
5328 } elsif ($map->{$virtdev}) {
5329 delete $di->{format
}; # format can change on restore
5330 $di->{file
} = $map->{$virtdev};
5331 $value = print_drive
($vmid, $di);
5332 print $outfd "$virtdev: $value\n";
5342 my ($cfg, $vmid) = @_;
5344 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5346 my $volid_hash = {};
5347 foreach my $storeid (keys %$info) {
5348 foreach my $item (@{$info->{$storeid}}) {
5349 next if !($item->{volid
} && $item->{size
});
5350 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5351 $volid_hash->{$item->{volid
}} = $item;
5358 sub is_volume_in_use
{
5359 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5361 my $path = PVE
::Storage
::path
($storecfg, $volid);
5363 my $scan_config = sub {
5364 my ($cref, $snapname) = @_;
5366 foreach my $key (keys %$cref) {
5367 my $value = $cref->{$key};
5368 if (is_valid_drivename
($key)) {
5369 next if $skip_drive && $key eq $skip_drive;
5370 my $drive = parse_drive
($key, $value);
5371 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5372 return 1 if $volid eq $drive->{file
};
5373 if ($drive->{file
} =~ m!^/!) {
5374 return 1 if $drive->{file
} eq $path;
5376 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5378 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5380 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5388 return 1 if &$scan_config($conf);
5392 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5393 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5399 sub update_disksize
{
5400 my ($vmid, $conf, $volid_hash) = @_;
5404 # used and unused disks
5405 my $referenced = {};
5407 # Note: it is allowed to define multiple storages with same path (alias), so
5408 # we need to check both 'volid' and real 'path' (two different volid can point
5409 # to the same path).
5411 my $referencedpath = {};
5414 foreach my $opt (keys %$conf) {
5415 if (is_valid_drivename
($opt)) {
5416 my $drive = parse_drive
($opt, $conf->{$opt});
5417 my $volid = $drive->{file
};
5420 $referenced->{$volid} = 1;
5421 if ($volid_hash->{$volid} &&
5422 (my $path = $volid_hash->{$volid}->{path
})) {
5423 $referencedpath->{$path} = 1;
5426 next if drive_is_cdrom
($drive);
5427 next if !$volid_hash->{$volid};
5429 $drive->{size
} = $volid_hash->{$volid}->{size
};
5430 my $new = print_drive
($vmid, $drive);
5431 if ($new ne $conf->{$opt}) {
5433 $conf->{$opt} = $new;
5438 # remove 'unusedX' entry if volume is used
5439 foreach my $opt (keys %$conf) {
5440 next if $opt !~ m/^unused\d+$/;
5441 my $volid = $conf->{$opt};
5442 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5443 if ($referenced->{$volid} || ($path && $referencedpath->{$path})) {
5445 delete $conf->{$opt};
5448 $referenced->{$volid} = 1;
5449 $referencedpath->{$path} = 1 if $path;
5452 foreach my $volid (sort keys %$volid_hash) {
5453 next if $volid =~ m/vm-$vmid-state-/;
5454 next if $referenced->{$volid};
5455 my $path = $volid_hash->{$volid}->{path
};
5456 next if !$path; # just to be sure
5457 next if $referencedpath->{$path};
5459 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5460 $referencedpath->{$path} = 1; # avoid to add more than once (aliases)
5467 my ($vmid, $nolock) = @_;
5469 my $cfg = PVE
::Storage
::config
();
5471 my $volid_hash = scan_volids
($cfg, $vmid);
5473 my $updatefn = sub {
5476 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5478 PVE
::QemuConfig-
>check_lock($conf);
5481 foreach my $volid (keys %$volid_hash) {
5482 my $info = $volid_hash->{$volid};
5483 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5486 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5488 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5491 if (defined($vmid)) {
5495 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5498 my $vmlist = config_list
();
5499 foreach my $vmid (keys %$vmlist) {
5503 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5509 sub restore_vma_archive
{
5510 my ($archive, $vmid, $user, $opts, $comp) = @_;
5512 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5513 my $readfrom = $archive;
5518 my $qarchive = PVE
::Tools
::shellquote
($archive);
5519 if ($comp eq 'gzip') {
5520 $uncomp = "zcat $qarchive|";
5521 } elsif ($comp eq 'lzop') {
5522 $uncomp = "lzop -d -c $qarchive|";
5524 die "unknown compression method '$comp'\n";
5529 my $tmpdir = "/var/tmp/vzdumptmp$$";
5532 # disable interrupts (always do cleanups)
5536 local $SIG{HUP
} = sub { warn "got interrupt - ignored\n"; };
5538 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5539 POSIX
::mkfifo
($mapfifo, 0600);
5542 my $openfifo = sub {
5543 open($fifofh, '>', $mapfifo) || die $!;
5546 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5553 my $rpcenv = PVE
::RPCEnvironment
::get
();
5555 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5556 my $tmpfn = "$conffile.$$.tmp";
5558 # Note: $oldconf is undef if VM does not exists
5559 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5560 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5562 my $print_devmap = sub {
5563 my $virtdev_hash = {};
5565 my $cfgfn = "$tmpdir/qemu-server.conf";
5567 # we can read the config - that is already extracted
5568 my $fh = IO
::File-
>new($cfgfn, "r") ||
5569 "unable to read qemu-server.conf - $!\n";
5571 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5573 my $pve_firewall_dir = '/etc/pve/firewall';
5574 mkdir $pve_firewall_dir; # make sure the dir exists
5575 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5578 while (defined(my $line = <$fh>)) {
5579 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5580 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5581 die "archive does not contain data for drive '$virtdev'\n"
5582 if !$devinfo->{$devname};
5583 if (defined($opts->{storage
})) {
5584 $storeid = $opts->{storage
} || 'local';
5585 } elsif (!$storeid) {
5588 $format = 'raw' if !$format;
5589 $devinfo->{$devname}->{devname
} = $devname;
5590 $devinfo->{$devname}->{virtdev
} = $virtdev;
5591 $devinfo->{$devname}->{format
} = $format;
5592 $devinfo->{$devname}->{storeid
} = $storeid;
5594 # check permission on storage
5595 my $pool = $opts->{pool
}; # todo: do we need that?
5596 if ($user ne 'root@pam') {
5597 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5600 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5604 foreach my $devname (keys %$devinfo) {
5605 die "found no device mapping information for device '$devname'\n"
5606 if !$devinfo->{$devname}->{virtdev
};
5609 my $cfg = PVE
::Storage
::config
();
5611 # create empty/temp config
5613 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5614 foreach_drive
($oldconf, sub {
5615 my ($ds, $drive) = @_;
5617 return if drive_is_cdrom
($drive);
5619 my $volid = $drive->{file
};
5621 return if !$volid || $volid =~ m
|^/|;
5623 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5624 return if !$path || !$owner || ($owner != $vmid);
5626 # Note: only delete disk we want to restore
5627 # other volumes will become unused
5628 if ($virtdev_hash->{$ds}) {
5629 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5636 # delete vmstate files
5637 # since after the restore we have no snapshots anymore
5638 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5639 my $snap = $oldconf->{snapshots
}->{$snapname};
5640 if ($snap->{vmstate
}) {
5641 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5650 foreach my $virtdev (sort keys %$virtdev_hash) {
5651 my $d = $virtdev_hash->{$virtdev};
5652 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5653 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5655 # test if requested format is supported
5656 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5657 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5658 $d->{format
} = $defFormat if !$supported;
5660 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5661 $d->{format
}, undef, $alloc_size);
5662 print STDERR
"new volume ID is '$volid'\n";
5663 $d->{volid
} = $volid;
5664 my $path = PVE
::Storage
::path
($cfg, $volid);
5666 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5668 my $write_zeros = 1;
5669 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5673 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5675 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5676 $map->{$virtdev} = $volid;
5679 $fh->seek(0, 0) || die "seek failed - $!\n";
5681 my $outfd = new IO
::File
($tmpfn, "w") ||
5682 die "unable to write config for VM $vmid\n";
5684 my $cookie = { netcount
=> 0 };
5685 while (defined(my $line = <$fh>)) {
5686 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5699 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5700 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5702 $oldtimeout = alarm($timeout);
5709 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5710 my ($dev_id, $size, $devname) = ($1, $2, $3);
5711 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5712 } elsif ($line =~ m/^CTIME: /) {
5713 # we correctly received the vma config, so we can disable
5714 # the timeout now for disk allocation (set to 10 minutes, so
5715 # that we always timeout if something goes wrong)
5718 print $fifofh "done\n";
5719 my $tmp = $oldtimeout || 0;
5720 $oldtimeout = undef;
5726 print "restore vma archive: $cmd\n";
5727 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5731 alarm($oldtimeout) if $oldtimeout;
5734 foreach my $devname (keys %$devinfo) {
5735 my $volid = $devinfo->{$devname}->{volid
};
5736 push @$vollist, $volid if $volid;
5739 my $cfg = PVE
::Storage
::config
();
5740 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5748 foreach my $devname (keys %$devinfo) {
5749 my $volid = $devinfo->{$devname}->{volid
};
5752 if ($volid =~ m
|^/|) {
5753 unlink $volid || die 'unlink failed\n';
5755 PVE
::Storage
::vdisk_free
($cfg, $volid);
5757 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5759 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5766 rename($tmpfn, $conffile) ||
5767 die "unable to commit configuration file '$conffile'\n";
5769 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5771 eval { rescan
($vmid, 1); };
5775 sub restore_tar_archive
{
5776 my ($archive, $vmid, $user, $opts) = @_;
5778 if ($archive ne '-') {
5779 my $firstfile = tar_archive_read_firstfile
($archive);
5780 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5781 if $firstfile ne 'qemu-server.conf';
5784 my $storecfg = PVE
::Storage
::config
();
5786 # destroy existing data - keep empty config
5787 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5788 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5790 my $tocmd = "/usr/lib/qemu-server/qmextract";
5792 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5793 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5794 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5795 $tocmd .= ' --info' if $opts->{info
};
5797 # tar option "xf" does not autodetect compression when read from STDIN,
5798 # so we pipe to zcat
5799 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5800 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5802 my $tmpdir = "/var/tmp/vzdumptmp$$";
5805 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5806 local $ENV{VZDUMP_VMID
} = $vmid;
5807 local $ENV{VZDUMP_USER
} = $user;
5809 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5810 my $tmpfn = "$conffile.$$.tmp";
5812 # disable interrupts (always do cleanups)
5816 local $SIG{HUP
} = sub { print STDERR
"got interrupt - ignored\n"; };
5824 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5826 if ($archive eq '-') {
5827 print "extracting archive from STDIN\n";
5828 run_command
($cmd, input
=> "<&STDIN");
5830 print "extracting archive '$archive'\n";
5834 return if $opts->{info
};
5838 my $statfile = "$tmpdir/qmrestore.stat";
5839 if (my $fd = IO
::File-
>new($statfile, "r")) {
5840 while (defined (my $line = <$fd>)) {
5841 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5842 $map->{$1} = $2 if $1;
5844 print STDERR
"unable to parse line in statfile - $line\n";
5850 my $confsrc = "$tmpdir/qemu-server.conf";
5852 my $srcfd = new IO
::File
($confsrc, "r") ||
5853 die "unable to open file '$confsrc'\n";
5855 my $outfd = new IO
::File
($tmpfn, "w") ||
5856 die "unable to write config for VM $vmid\n";
5858 my $cookie = { netcount
=> 0 };
5859 while (defined (my $line = <$srcfd>)) {
5860 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5872 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5879 rename $tmpfn, $conffile ||
5880 die "unable to commit configuration file '$conffile'\n";
5882 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5884 eval { rescan
($vmid, 1); };
5888 sub foreach_storage_used_by_vm
{
5889 my ($conf, $func) = @_;
5893 foreach_drive
($conf, sub {
5894 my ($ds, $drive) = @_;
5895 return if drive_is_cdrom
($drive);
5897 my $volid = $drive->{file
};
5899 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5900 $sidhash->{$sid} = $sid if $sid;
5903 foreach my $sid (sort keys %$sidhash) {
5908 sub do_snapshots_with_qemu
{
5909 my ($storecfg, $volid) = @_;
5911 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5913 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5914 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5918 if ($volid =~ m/\.(qcow2|qed)$/){
5925 sub qga_check_running
{
5928 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5930 warn "Qemu Guest Agent is not running - $@";
5936 sub template_create
{
5937 my ($vmid, $conf, $disk) = @_;
5939 my $storecfg = PVE
::Storage
::config
();
5941 foreach_drive
($conf, sub {
5942 my ($ds, $drive) = @_;
5944 return if drive_is_cdrom
($drive);
5945 return if $disk && $ds ne $disk;
5947 my $volid = $drive->{file
};
5948 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5950 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5951 $drive->{file
} = $voliddst;
5952 $conf->{$ds} = print_drive
($vmid, $drive);
5953 PVE
::QemuConfig-
>write_config($vmid, $conf);
5957 sub qemu_img_convert
{
5958 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5960 my $storecfg = PVE
::Storage
::config
();
5961 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5962 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5964 if ($src_storeid && $dst_storeid) {
5966 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5968 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5969 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5971 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5972 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5974 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5975 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5978 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5979 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5980 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5981 if ($is_zero_initialized) {
5982 push @$cmd, "zeroinit:$dst_path";
5984 push @$cmd, $dst_path;
5989 if($line =~ m/\((\S+)\/100\
%\)/){
5991 my $transferred = int($size * $percent / 100);
5992 my $remaining = $size - $transferred;
5994 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5999 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6001 die "copy failed: $err" if $err;
6005 sub qemu_img_format
{
6006 my ($scfg, $volname) = @_;
6008 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6015 sub qemu_drive_mirror
{
6016 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
6018 $jobs = {} if !$jobs;
6022 $jobs->{"drive-$drive"} = {};
6024 if ($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+):exportname=(\S+)/) {
6027 my $exportname = $3;
6030 my $unixsocket = "/run/qemu-server/$vmid.mirror-drive-$drive";
6031 $qemu_target = "nbd+unix:///$exportname?socket=$unixsocket";
6032 my $cmd = ['socat', '-T30', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=5"];
6035 if (!defined($pid)) {
6036 die "forking socat tunnel failed\n";
6037 } elsif ($pid == 0) {
6039 warn "exec failed: $!\n";
6042 $jobs->{"drive-$drive"}->{pid
} = $pid;
6045 while (!-S
$unixsocket) {
6046 die "nbd connection helper timed out\n"
6051 my $storecfg = PVE
::Storage
::config
();
6052 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6054 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6056 $format = qemu_img_format
($dst_scfg, $dst_volname);
6058 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6060 $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
6063 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
6064 $opts->{format
} = $format if $format;
6066 print "drive mirror is starting for drive-$drive\n";
6068 eval { vm_mon_cmd
($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
6071 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6072 die "mirroring error: $err";
6075 qemu_drive_mirror_monitor
($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
6078 sub qemu_drive_mirror_monitor
{
6079 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
6082 my $err_complete = 0;
6085 die "storage migration timed out\n" if $err_complete > 300;
6087 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6089 my $running_mirror_jobs = {};
6090 foreach my $stat (@$stats) {
6091 next if $stat->{type
} ne 'mirror';
6092 $running_mirror_jobs->{$stat->{device
}} = $stat;
6095 my $readycounter = 0;
6097 foreach my $job (keys %$jobs) {
6099 if(defined($jobs->{$job}->{complete
}) && !defined($running_mirror_jobs->{$job})) {
6100 print "$job : finished\n";
6101 delete $jobs->{$job};
6105 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
6107 my $busy = $running_mirror_jobs->{$job}->{busy
};
6108 my $ready = $running_mirror_jobs->{$job}->{ready
};
6109 if (my $total = $running_mirror_jobs->{$job}->{len
}) {
6110 my $transferred = $running_mirror_jobs->{$job}->{offset
} || 0;
6111 my $remaining = $total - $transferred;
6112 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6114 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6117 $readycounter++ if $running_mirror_jobs->{$job}->{ready
};
6120 last if scalar(keys %$jobs) == 0;
6122 if ($readycounter == scalar(keys %$jobs)) {
6123 print "all mirroring jobs are ready \n";
6124 last if $skipcomplete; #do the complete later
6126 if ($vmiddst && $vmiddst != $vmid) {
6127 my $agent_running = $qga && qga_check_running
($vmid);
6128 if ($agent_running) {
6129 print "freeze filesystem\n";
6130 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6132 print "suspend vm\n";
6133 eval { PVE
::QemuServer
::vm_suspend
($vmid, 1); };
6136 # if we clone a disk for a new target vm, we don't switch the disk
6137 PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs);
6139 if ($agent_running) {
6140 print "unfreeze filesystem\n";
6141 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6143 print "resume vm\n";
6144 eval { PVE
::QemuServer
::vm_resume
($vmid, 1, 1); };
6150 foreach my $job (keys %$jobs) {
6151 # try to switch the disk if source and destination are on the same guest
6152 print "$job: Completing block job...\n";
6154 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> $job) };
6155 if ($@ =~ m/cannot be completed/) {
6156 print "$job: Block job cannot be completed, try again.\n";
6159 print "$job: Completed successfully.\n";
6160 $jobs->{$job}->{complete
} = 1;
6161 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6172 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6173 die "mirroring error: $err";
6178 sub qemu_blockjobs_cancel
{
6179 my ($vmid, $jobs) = @_;
6181 foreach my $job (keys %$jobs) {
6182 print "$job: Cancelling block job\n";
6183 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> $job); };
6184 $jobs->{$job}->{cancel
} = 1;
6188 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6190 my $running_jobs = {};
6191 foreach my $stat (@$stats) {
6192 $running_jobs->{$stat->{device
}} = $stat;
6195 foreach my $job (keys %$jobs) {
6197 if (defined($jobs->{$job}->{cancel
}) && !defined($running_jobs->{$job})) {
6198 print "$job: Done.\n";
6199 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6200 delete $jobs->{$job};
6204 last if scalar(keys %$jobs) == 0;
6210 sub qemu_blockjobs_finish_tunnel
{
6211 my ($vmid, $job, $cpid) = @_;
6215 for (my $i = 1; $i < 20; $i++) {
6216 my $waitpid = waitpid($cpid, WNOHANG
);
6217 last if (defined($waitpid) && ($waitpid == $cpid));
6221 } elsif ($i >= 15) {
6226 unlink "/run/qemu-server/$vmid.mirror-$job";
6230 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6231 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
6236 print "create linked clone of drive $drivename ($drive->{file})\n";
6237 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6238 push @$newvollist, $newvolid;
6241 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6242 $storeid = $storage if $storage;
6244 my $dst_format = resolve_dst_disk_format
($storecfg, $storeid, $volname, $format);
6245 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6247 print "create full clone of drive $drivename ($drive->{file})\n";
6248 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $dst_format, undef, ($size/1024));
6249 push @$newvollist, $newvolid;
6251 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
6253 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6254 if (!$running || $snapname) {
6255 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6258 my $kvmver = get_running_qemu_version
($vmid);
6259 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
6260 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6261 if $drive->{iothread
};
6264 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
6268 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6271 $disk->{format
} = undef;
6272 $disk->{file
} = $newvolid;
6273 $disk->{size
} = $size;
6278 # this only works if VM is running
6279 sub get_current_qemu_machine
{
6282 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6283 my $res = vm_qmp_command
($vmid, $cmd);
6285 my ($current, $default);
6286 foreach my $e (@$res) {
6287 $default = $e->{name
} if $e->{'is-default'};
6288 $current = $e->{name
} if $e->{'is-current'};
6291 # fallback to the default machine if current is not supported by qemu
6292 return $current || $default || 'pc';
6295 sub get_running_qemu_version
{
6297 my $cmd = { execute
=> 'query-version', arguments
=> {} };
6298 my $res = vm_qmp_command
($vmid, $cmd);
6299 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6302 sub qemu_machine_feature_enabled
{
6303 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6308 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6310 $current_major = $3;
6311 $current_minor = $4;
6313 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6315 $current_major = $1;
6316 $current_minor = $2;
6319 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6324 sub qemu_machine_pxe
{
6325 my ($vmid, $conf, $machine) = @_;
6327 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6329 foreach my $opt (keys %$conf) {
6330 next if $opt !~ m/^net(\d+)$/;
6331 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6333 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6334 return $machine.".pxe" if $romfile =~ m/pxe/;
6341 sub qemu_use_old_bios_files
{
6342 my ($machine_type) = @_;
6344 return if !$machine_type;
6346 my $use_old_bios_files = undef;
6348 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6350 $use_old_bios_files = 1;
6352 my $kvmver = kvm_user_version
();
6353 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6354 # load new efi bios files on migration. So this hack is required to allow
6355 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6356 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6357 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6360 return ($use_old_bios_files, $machine_type);
6363 sub create_efidisk
{
6364 my ($storecfg, $storeid, $vmid, $fmt) = @_;
6366 die "EFI vars default image not found\n" if ! -f
$OVMF_VARS;
6368 my $vars_size = PVE
::Tools
::convert_size
(-s
$OVMF_VARS, 'b' => 'kb');
6369 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
6370 PVE
::Storage
::activate_volumes
($storecfg, [$volid]);
6372 my $path = PVE
::Storage
::path
($storecfg, $volid);
6374 run_command
(['/usr/bin/qemu-img', 'convert', '-n', '-f', 'raw', '-O', $fmt, $OVMF_VARS, $path]);
6376 die "Copying EFI vars image failed: $@" if $@;
6378 return ($volid, $vars_size);
6385 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6386 my (undef, $id, $function) = @_;
6387 my $res = { id
=> $id, function
=> $function};
6388 push @{$devices->{$id}}, $res;
6391 # Entries should be sorted by functions.
6392 foreach my $id (keys %$devices) {
6393 my $dev = $devices->{$id};
6394 $devices->{$id} = [ sort { $a->{function
} <=> $b->{function
} } @$dev ];
6400 sub vm_iothreads_list
{
6403 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6406 foreach my $iothread (@$res) {
6407 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6414 my ($conf, $drive) = @_;
6418 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)) {
6420 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6426 my $controller = int($drive->{index} / $maxdev);
6427 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6429 return ($maxdev, $controller, $controller_prefix);
6432 sub add_hyperv_enlightenments
{
6433 my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough) = @_;
6435 return if $winversion < 6;
6436 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6438 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6440 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
6441 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6442 push @$cpuFlags , 'hv_vapic';
6443 push @$cpuFlags , 'hv_time';
6445 push @$cpuFlags , 'hv_spinlocks=0xffff';
6448 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
6449 push @$cpuFlags , 'hv_reset';
6450 push @$cpuFlags , 'hv_vpindex';
6451 push @$cpuFlags , 'hv_runtime';
6454 if ($winversion >= 7) {
6455 push @$cpuFlags , 'hv_relaxed';
6459 sub windows_version
{
6462 return 0 if !$ostype;
6466 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6468 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6470 } elsif ($ostype =~ m/^win(\d+)$/) {
6477 sub resolve_dst_disk_format
{
6478 my ($storecfg, $storeid, $src_volname, $format) = @_;
6479 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6482 # if no target format is specified, use the source disk format as hint
6484 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6485 $format = qemu_img_format
($scfg, $src_volname);
6491 # test if requested format is supported - else use default
6492 my $supported = grep { $_ eq $format } @$validFormats;
6493 $format = $defFormat if !$supported;
6497 sub resolve_first_disk
{
6499 my @disks = PVE
::QemuServer
::valid_drive_names
();
6501 foreach my $ds (reverse @disks) {
6502 next if !$conf->{$ds};
6503 my $disk = PVE
::QemuServer
::parse_drive
($ds, $conf->{$ds});
6504 next if PVE
::QemuServer
::drive_is_cdrom
($disk);
6510 sub generate_smbios1_uuid
{
6511 my ($uuid, $uuid_str);
6512 UUID
::generate
($uuid);
6513 UUID
::unparse
($uuid, $uuid_str);
6514 return "uuid=$uuid_str";
6517 # bash completion helper
6519 sub complete_backup_archives
{
6520 my ($cmdname, $pname, $cvalue) = @_;
6522 my $cfg = PVE
::Storage
::config
();
6526 if ($cvalue =~ m/^([^:]+):/) {
6530 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6533 foreach my $id (keys %$data) {
6534 foreach my $item (@{$data->{$id}}) {
6535 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6536 push @$res, $item->{volid
} if defined($item->{volid
});
6543 my $complete_vmid_full = sub {
6546 my $idlist = vmstatus
();
6550 foreach my $id (keys %$idlist) {
6551 my $d = $idlist->{$id};
6552 if (defined($running)) {
6553 next if $d->{template
};
6554 next if $running && $d->{status
} ne 'running';
6555 next if !$running && $d->{status
} eq 'running';
6564 return &$complete_vmid_full();
6567 sub complete_vmid_stopped
{
6568 return &$complete_vmid_full(0);
6571 sub complete_vmid_running
{
6572 return &$complete_vmid_full(1);
6575 sub complete_storage
{
6577 my $cfg = PVE
::Storage
::config
();
6578 my $ids = $cfg->{ids
};
6581 foreach my $sid (keys %$ids) {
6582 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6583 next if !$ids->{$sid}->{content
}->{images
};
6593 vm_mon_cmd
($vmid, 'nbd-server-stop');