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
153 description
=> "Emulated CPU type.",
155 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
160 description
=> "Do not identify as a KVM virtual machine.",
166 description
=> "Override CPU flags. Currently only the 'pcid' flag is supported."
167 . " Use '+pcid' or '-pcid' to enable or disable."
168 . " This takes precedence over flags coming from the cpu type or changed implicitly via the OS type.",
169 format_description
=> 'flaglist',
171 pattern
=> '[+-]pcid',
181 enum
=> [qw(i6300esb ib700)],
182 description
=> "Watchdog type to emulate.",
183 default => 'i6300esb',
188 enum
=> [qw(reset shutdown poweroff pause debug none)],
189 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
193 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
199 description
=> "Specifies whether a VM will be started during system bootup.",
205 description
=> "Automatic restart after crash (currently ignored).",
210 type
=> 'string', format
=> 'pve-hotplug-features',
211 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'.",
212 default => 'network,disk,usb',
217 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
223 description
=> "Lock/unlock the VM.",
224 enum
=> [qw(migrate backup snapshot rollback)],
229 description
=> "Limit of CPU usage.",
230 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.",
238 description
=> "CPU weight for a VM.",
239 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.",
247 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
254 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
260 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",
268 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.".
269 "It should not be necessary to set it.",
270 enum
=> PVE
::Tools
::kvmkeymaplist
(),
275 type
=> 'string', format
=> 'dns-name',
276 description
=> "Set a name for the VM. Only used on the configuration web interface.",
281 description
=> "SCSI controller model",
282 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
288 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
293 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 win10 l24 l26 solaris)],
294 description
=> "Specify guest operating system.",
295 verbose_description
=> <<EODESC,
296 Specify guest operating system. This is used to enable special
297 optimization/features for specific operating systems:
300 other;; unspecified OS
301 wxp;; Microsoft Windows XP
302 w2k;; Microsoft Windows 2000
303 w2k3;; Microsoft Windows 2003
304 w2k8;; Microsoft Windows 2008
305 wvista;; Microsoft Windows Vista
306 win7;; Microsoft Windows 7
307 win8;; Microsoft Windows 8/2012/2012r2
308 win10;; Microsoft Windows 10/2016
309 l24;; Linux 2.4 Kernel
310 l26;; Linux 2.6/3.X Kernel
311 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
317 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
318 pattern
=> '[acdn]{1,4}',
323 type
=> 'string', format
=> 'pve-qm-bootdisk',
324 description
=> "Enable booting from specified disk.",
325 pattern
=> '(ide|sata|scsi|virtio)\d+',
330 description
=> "The number of CPUs. Please use option -sockets instead.",
337 description
=> "The number of CPU sockets.",
344 description
=> "The number of cores per socket.",
351 description
=> "Enable/disable NUMA.",
357 description
=> "Enable/disable hugepages memory.",
358 enum
=> [qw(any 2 1024)],
363 description
=> "Number of hotplugged vcpus.",
370 description
=> "Enable/disable ACPI.",
376 description
=> "Enable/disable Qemu GuestAgent.",
382 description
=> "Enable/disable KVM hardware virtualization.",
388 description
=> "Enable/disable time drift fix.",
394 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
399 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
404 description
=> "Select the VGA type.",
405 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
406 " modes (>= 1280x1024x16) then you should use the options " .
407 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
408 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
409 "display sever. For win* OS you can select how many independent " .
410 "displays you want, Linux guests can add displays them self. " .
411 "You can also run without any graphic card, using a serial device" .
413 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
417 type
=> 'string', format
=> 'pve-qm-watchdog',
418 description
=> "Create a virtual hardware watchdog device.",
419 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
420 " (by a guest action), the watchdog must be periodically polled " .
421 "by an agent inside the guest or else the watchdog will reset " .
422 "the guest (or execute the respective action specified)",
427 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
428 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'.",
429 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
432 startup
=> get_standard_option
('pve-startup-order'),
436 description
=> "Enable/disable Template.",
442 description
=> "Arbitrary arguments passed to kvm.",
443 verbose_description
=> <<EODESCR,
444 Arbitrary arguments passed to kvm, for example:
446 args: -no-reboot -no-hpet
448 NOTE: this option is for experts only.
455 description
=> "Enable/disable the USB tablet device.",
456 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
457 "usually needed to allow absolute mouse positioning with VNC. " .
458 "Else the mouse runs out of sync with normal VNC clients. " .
459 "If you're running lots of console-only guests on one host, " .
460 "you may consider disabling this to save some context switches. " .
461 "This is turned off by default if you use spice (-vga=qxl).",
466 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
470 migrate_downtime
=> {
473 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
479 type
=> 'string', format
=> 'pve-qm-ide',
480 typetext
=> '<volume>',
481 description
=> "This is an alias for option -ide2",
485 description
=> "Emulated CPU type.",
489 parent
=> get_standard_option
('pve-snapshot-name', {
491 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
495 description
=> "Timestamp for snapshots.",
501 type
=> 'string', format
=> 'pve-volume-id',
502 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
504 vmstatestorage
=> get_standard_option
('pve-storage-id', {
505 description
=> "Default storage for VM state volumes/files.",
509 description
=> "Specific the Qemu machine type.",
511 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
516 description
=> "Specify SMBIOS type 1 fields.",
517 type
=> 'string', format
=> 'pve-qm-smbios1',
524 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
530 enum
=> [ qw(seabios ovmf) ],
531 description
=> "Select BIOS implementation.",
532 default => 'seabios',
536 # what about other qemu settings ?
538 #machine => 'string',
551 ##soundhw => 'string',
553 while (my ($k, $v) = each %$confdesc) {
554 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
557 my $MAX_IDE_DISKS = 4;
558 my $MAX_SCSI_DISKS = 14;
559 my $MAX_VIRTIO_DISKS = 16;
560 my $MAX_SATA_DISKS = 6;
561 my $MAX_USB_DEVICES = 5;
563 my $MAX_UNUSED_DISKS = 8;
564 my $MAX_HOSTPCI_DEVICES = 4;
565 my $MAX_SERIAL_PORTS = 4;
566 my $MAX_PARALLEL_PORTS = 3;
572 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
573 description
=> "CPUs accessing this NUMA node.",
574 format_description
=> "id[-id];...",
578 description
=> "Amount of memory this NUMA node provides.",
583 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
584 description
=> "Host NUMA nodes to use.",
585 format_description
=> "id[-id];...",
590 enum
=> [qw(preferred bind interleave)],
591 description
=> "NUMA allocation policy.",
595 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
598 type
=> 'string', format
=> $numa_fmt,
599 description
=> "NUMA topology.",
601 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
603 for (my $i = 0; $i < $MAX_NUMA; $i++) {
604 $confdesc->{"numa$i"} = $numadesc;
607 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
608 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
609 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
610 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
612 my $net_fmt_bridge_descr = <<__EOD__;
613 Bridge to attach the network device to. The Proxmox VE standard bridge
616 If you do not specify a bridge, we create a kvm user (NATed) network
617 device, which provides DHCP and DNS services. The following addresses
624 The DHCP server assign addresses to the guest starting from 10.0.2.15.
630 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
631 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
632 format_description
=> "XX:XX:XX:XX:XX:XX",
637 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'.",
638 enum
=> $nic_model_list,
641 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
644 description
=> $net_fmt_bridge_descr,
645 format_description
=> 'bridge',
650 minimum
=> 0, maximum
=> 16,
651 description
=> 'Number of packet queues to be used on the device.',
657 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
662 minimum
=> 1, maximum
=> 4094,
663 description
=> 'VLAN tag to apply to packets on this interface.',
668 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
669 description
=> 'VLAN trunks to pass through this interface.',
670 format_description
=> 'vlanid[;vlanid...]',
675 description
=> 'Whether this interface should be protected by the firewall.',
680 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
687 type
=> 'string', format
=> $net_fmt,
688 description
=> "Specify network devices.",
691 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
693 for (my $i = 0; $i < $MAX_NETS; $i++) {
694 $confdesc->{"net$i"} = $netdesc;
697 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
698 sub verify_volume_id_or_qm_path
{
699 my ($volid, $noerr) = @_;
701 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
705 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
706 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
708 return undef if $noerr;
716 my %drivedesc_base = (
717 volume
=> { alias
=> 'file' },
720 format
=> 'pve-volume-id-or-qm-path',
722 format_description
=> 'volume',
723 description
=> "The drive's backing volume.",
727 enum
=> [qw(cdrom disk)],
728 description
=> "The drive's media type.",
734 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
739 description
=> "Force the drive's physical geometry to have a specific head count.",
744 description
=> "Force the drive's physical geometry to have a specific sector count.",
749 enum
=> [qw(none lba auto)],
750 description
=> "Force disk geometry bios translation mode.",
755 description
=> "Whether the drive should be included when making snapshots.",
760 enum
=> [qw(none writethrough writeback unsafe directsync)],
761 description
=> "The drive's cache mode",
764 format
=> get_standard_option
('pve-qm-image-format'),
767 format
=> 'disk-size',
768 format_description
=> 'DiskSize',
769 description
=> "Disk size. This is purely informational and has no effect.",
774 description
=> "Whether the drive should be included when making backups.",
779 description
=> 'Whether the drive should considered for replication jobs.',
785 enum
=> [qw(ignore report stop)],
786 description
=> 'Read error action.',
791 enum
=> [qw(enospc ignore report stop)],
792 description
=> 'Write error action.',
797 enum
=> [qw(native threads)],
798 description
=> 'AIO type to use.',
803 enum
=> [qw(ignore on)],
804 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
809 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
814 format
=> 'urlencoded',
815 format_description
=> 'serial',
816 maxLength
=> 20*3, # *3 since it's %xx url enoded
817 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
822 my %iothread_fmt = ( iothread
=> {
824 description
=> "Whether to use iothreads for this drive",
831 format
=> 'urlencoded',
832 format_description
=> 'model',
833 maxLength
=> 40*3, # *3 since it's %xx url enoded
834 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
842 description
=> "Number of queues.",
848 my %scsiblock_fmt = (
851 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",
857 my $add_throttle_desc = sub {
858 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
861 format_description
=> $unit,
862 description
=> "Maximum $what in $longunit.",
865 $d->{minimum
} = $minimum if defined($minimum);
866 $drivedesc_base{$key} = $d;
868 # throughput: (leaky bucket)
869 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
870 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
871 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
872 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
873 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
874 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
875 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
876 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
877 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
879 # pools: (pool of IO before throttling starts taking effect)
880 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
881 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
882 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
883 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
884 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
885 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
888 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
889 $add_throttle_desc->('bps_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
890 $add_throttle_desc->('bps_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
891 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
892 $add_throttle_desc->('iops_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
893 $add_throttle_desc->('iops_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
896 $drivedesc_base{'bps_rd_length'} = { alias
=> 'bps_rd_max_length' };
897 $drivedesc_base{'bps_wr_length'} = { alias
=> 'bps_wr_max_length' };
898 $drivedesc_base{'iops_rd_length'} = { alias
=> 'iops_rd_max_length' };
899 $drivedesc_base{'iops_wr_length'} = { alias
=> 'iops_wr_max_length' };
905 PVE
::JSONSchema
::register_format
("pve-qm-ide", $ide_fmt);
909 type
=> 'string', format
=> $ide_fmt,
910 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
912 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
922 type
=> 'string', format
=> $scsi_fmt,
923 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
925 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
932 type
=> 'string', format
=> $sata_fmt,
933 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
935 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
943 type
=> 'string', format
=> $virtio_fmt,
944 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
946 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
957 volume
=> { alias
=> 'file' },
960 format
=> 'pve-volume-id-or-qm-path',
962 format_description
=> 'volume',
963 description
=> "The drive's backing volume.",
965 format
=> get_standard_option
('pve-qm-image-format'),
968 format
=> 'disk-size',
969 format_description
=> 'DiskSize',
970 description
=> "Disk size. This is purely informational and has no effect.",
977 type
=> 'string', format
=> $efidisk_fmt,
978 description
=> "Configure a Disk for storing EFI vars",
981 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
986 type
=> 'string', format
=> 'pve-qm-usb-device',
987 format_description
=> 'HOSTUSBDEVICE|spice',
988 description
=> <<EODESCR,
989 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
991 'bus-port(.port)*' (decimal numbers) or
992 'vendor_id:product_id' (hexadeciaml numbers) or
995 You can use the 'lsusb -t' command to list existing usb devices.
997 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
999 The value 'spice' can be used to add a usb redirection devices for spice.
1005 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).",
1012 type
=> 'string', format
=> $usb_fmt,
1013 description
=> "Configure an USB device (n is 0 to 4).",
1015 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
1017 # NOTE: the match-groups of this regex are used in parse_hostpci
1018 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
1023 pattern
=> qr/$PCIRE(;$PCIRE)*/,
1024 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
1025 description
=> <<EODESCR,
1026 Host PCI device pass through. The PCI ID of a host's PCI device or a list
1027 of PCI virtual functions of the host. HOSTPCIID syntax is:
1029 'bus:dev.func' (hexadecimal numbers)
1031 You can us the 'lspci' command to list existing PCI devices.
1036 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1042 pattern
=> '[^,;]+',
1043 format_description
=> 'string',
1044 description
=> "Custom pci device rom filename (must be located in /usr/share/kvm/).",
1049 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1055 description
=> "Enable vfio-vga device support.",
1060 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1064 type
=> 'string', format
=> 'pve-qm-hostpci',
1065 description
=> "Map host PCI devices into guest.",
1066 verbose_description
=> <<EODESCR,
1067 Map host PCI devices into guest.
1069 NOTE: This option allows direct access to host hardware. So it is no longer
1070 possible to migrate such machines - use with special care.
1072 CAUTION: Experimental! User reported problems with this option.
1075 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1080 pattern
=> '(/dev/.+|socket)',
1081 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1082 verbose_description
=> <<EODESCR,
1083 Create a serial device inside the VM (n is 0 to 3), and pass through a
1084 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1085 host side (use 'qm terminal' to open a terminal connection).
1087 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1089 CAUTION: Experimental! User reported problems with this option.
1096 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1097 description
=> "Map host parallel devices (n is 0 to 2).",
1098 verbose_description
=> <<EODESCR,
1099 Map host parallel devices (n is 0 to 2).
1101 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1103 CAUTION: Experimental! User reported problems with this option.
1107 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1108 $confdesc->{"parallel$i"} = $paralleldesc;
1111 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1112 $confdesc->{"serial$i"} = $serialdesc;
1115 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1116 $confdesc->{"hostpci$i"} = $hostpcidesc;
1119 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1120 $drivename_hash->{"ide$i"} = 1;
1121 $confdesc->{"ide$i"} = $idedesc;
1124 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1125 $drivename_hash->{"sata$i"} = 1;
1126 $confdesc->{"sata$i"} = $satadesc;
1129 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1130 $drivename_hash->{"scsi$i"} = 1;
1131 $confdesc->{"scsi$i"} = $scsidesc ;
1134 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1135 $drivename_hash->{"virtio$i"} = 1;
1136 $confdesc->{"virtio$i"} = $virtiodesc;
1139 $drivename_hash->{efidisk0
} = 1;
1140 $confdesc->{efidisk0
} = $efidisk_desc;
1142 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1143 $confdesc->{"usb$i"} = $usbdesc;
1148 type
=> 'string', format
=> 'pve-volume-id',
1149 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1152 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1153 $confdesc->{"unused$i"} = $unuseddesc;
1156 my $kvm_api_version = 0;
1160 return $kvm_api_version if $kvm_api_version;
1162 my $fh = IO
::File-
>new("</dev/kvm") ||
1165 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1166 $kvm_api_version = $v;
1171 return $kvm_api_version;
1174 my $kvm_user_version;
1176 sub kvm_user_version
{
1178 return $kvm_user_version if $kvm_user_version;
1180 $kvm_user_version = 'unknown';
1184 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1185 $kvm_user_version = $2;
1189 eval { run_command
("kvm -version", outfunc
=> $code); };
1192 return $kvm_user_version;
1196 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1198 sub valid_drive_names
{
1199 # order is important - used to autoselect boot disk
1200 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1201 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1202 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1203 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1207 sub is_valid_drivename
{
1210 return defined($drivename_hash->{$dev});
1215 return defined($confdesc->{$key});
1219 return $nic_model_list;
1222 sub os_list_description
{
1226 wxp
=> 'Windows XP',
1227 w2k
=> 'Windows 2000',
1228 w2k3
=>, 'Windows 2003',
1229 w2k8
=> 'Windows 2008',
1230 wvista
=> 'Windows Vista',
1231 win7
=> 'Windows 7',
1232 win8
=> 'Windows 8/2012',
1233 win10
=> 'Windows 10/2016',
1241 sub get_cdrom_path
{
1243 return $cdrom_path if $cdrom_path;
1245 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1246 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1247 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1251 my ($storecfg, $vmid, $cdrom) = @_;
1253 if ($cdrom eq 'cdrom') {
1254 return get_cdrom_path
();
1255 } elsif ($cdrom eq 'none') {
1257 } elsif ($cdrom =~ m
|^/|) {
1260 return PVE
::Storage
::path
($storecfg, $cdrom);
1264 # try to convert old style file names to volume IDs
1265 sub filename_to_volume_id
{
1266 my ($vmid, $file, $media) = @_;
1268 if (!($file eq 'none' || $file eq 'cdrom' ||
1269 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1271 return undef if $file =~ m
|/|;
1273 if ($media && $media eq 'cdrom') {
1274 $file = "local:iso/$file";
1276 $file = "local:$vmid/$file";
1283 sub verify_media_type
{
1284 my ($opt, $vtype, $media) = @_;
1289 if ($media eq 'disk') {
1291 } elsif ($media eq 'cdrom') {
1294 die "internal error";
1297 return if ($vtype eq $etype);
1299 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1302 sub cleanup_drive_path
{
1303 my ($opt, $storecfg, $drive) = @_;
1305 # try to convert filesystem paths to volume IDs
1307 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1308 ($drive->{file
} !~ m
|^/dev/.+|) &&
1309 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1310 ($drive->{file
} !~ m/^\d+$/)) {
1311 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1312 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1313 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1314 verify_media_type
($opt, $vtype, $drive->{media
});
1315 $drive->{file
} = $volid;
1318 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1321 sub parse_hotplug_features
{
1326 return $res if $data eq '0';
1328 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1330 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1331 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1334 die "invalid hotplug feature '$feature'\n";
1340 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1341 sub pve_verify_hotplug_features
{
1342 my ($value, $noerr) = @_;
1344 return $value if parse_hotplug_features
($value);
1346 return undef if $noerr;
1348 die "unable to parse hotplug option\n";
1351 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1352 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1353 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1354 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1355 # [,iothread=on][,serial=serial][,model=model]
1358 my ($key, $data) = @_;
1360 my ($interface, $index);
1362 if ($key =~ m/^([^\d]+)(\d+)$/) {
1369 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1370 : $confdesc->{$key}->{format
};
1372 warn "invalid drive key: $key\n";
1375 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1376 return undef if !$res;
1377 $res->{interface
} = $interface;
1378 $res->{index} = $index;
1381 foreach my $opt (qw(bps bps_rd bps_wr)) {
1382 if (my $bps = defined(delete $res->{$opt})) {
1383 if (defined($res->{"m$opt"})) {
1384 warn "both $opt and m$opt specified\n";
1388 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1392 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1393 for my $requirement (
1394 [mbps_max
=> 'mbps'],
1395 [mbps_rd_max
=> 'mbps_rd'],
1396 [mbps_wr_max
=> 'mbps_wr'],
1397 [miops_max
=> 'miops'],
1398 [miops_rd_max
=> 'miops_rd'],
1399 [miops_wr_max
=> 'miops_wr'],
1400 [bps_max_length
=> 'mbps_max'],
1401 [bps_rd_max_length
=> 'mbps_rd_max'],
1402 [bps_wr_max_length
=> 'mbps_wr_max'],
1403 [iops_max_length
=> 'iops_max'],
1404 [iops_rd_max_length
=> 'iops_rd_max'],
1405 [iops_wr_max_length
=> 'iops_wr_max']) {
1406 my ($option, $requires) = @$requirement;
1407 if ($res->{$option} && !$res->{$requires}) {
1408 warn "$option requires $requires\n";
1413 return undef if $error;
1415 return undef if $res->{mbps_rd
} && $res->{mbps
};
1416 return undef if $res->{mbps_wr
} && $res->{mbps
};
1417 return undef if $res->{iops_rd
} && $res->{iops
};
1418 return undef if $res->{iops_wr
} && $res->{iops
};
1420 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1421 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1422 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1423 return undef if $res->{interface
} eq 'virtio';
1426 if (my $size = $res->{size
}) {
1427 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1434 my ($vmid, $drive) = @_;
1435 my $data = { %$drive };
1436 delete $data->{$_} for qw(index interface);
1437 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1441 my($fh, $noerr) = @_;
1444 my $SG_GET_VERSION_NUM = 0x2282;
1446 my $versionbuf = "\x00" x
8;
1447 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1449 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1452 my $version = unpack("I", $versionbuf);
1453 if ($version < 30000) {
1454 die "scsi generic interface too old\n" if !$noerr;
1458 my $buf = "\x00" x
36;
1459 my $sensebuf = "\x00" x
8;
1460 my $cmd = pack("C x3 C x1", 0x12, 36);
1462 # see /usr/include/scsi/sg.h
1463 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";
1465 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1466 length($sensebuf), 0, length($buf), $buf,
1467 $cmd, $sensebuf, 6000);
1469 $ret = ioctl($fh, $SG_IO, $packet);
1471 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1475 my @res = unpack($sg_io_hdr_t, $packet);
1476 if ($res[17] || $res[18]) {
1477 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1482 (my $byte0, my $byte1, $res->{vendor
},
1483 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1485 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1486 $res->{type
} = $byte0 & 31;
1494 my $fh = IO
::File-
>new("+<$path") || return undef;
1495 my $res = scsi_inquiry
($fh, 1);
1501 sub machine_type_is_q35
{
1504 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1507 sub print_tabletdevice_full
{
1510 my $q35 = machine_type_is_q35
($conf);
1512 # we use uhci for old VMs because tablet driver was buggy in older qemu
1513 my $usbbus = $q35 ?
"ehci" : "uhci";
1515 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1518 sub print_drivedevice_full
{
1519 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1524 if ($drive->{interface
} eq 'virtio') {
1525 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1526 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1527 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1528 } elsif ($drive->{interface
} eq 'scsi') {
1530 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1531 my $unit = $drive->{index} % $maxdev;
1532 my $devicetype = 'hd';
1534 if (drive_is_cdrom
($drive)) {
1537 if ($drive->{file
} =~ m
|^/|) {
1538 $path = $drive->{file
};
1539 if (my $info = path_is_scsi
($path)) {
1540 if ($info->{type
} == 0 && $drive->{scsiblock
}) {
1541 $devicetype = 'block';
1542 } elsif ($info->{type
} == 1) { # tape
1543 $devicetype = 'generic';
1547 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1550 if($path =~ m/^iscsi\:\/\
//){
1551 $devicetype = 'generic';
1555 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1556 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1558 $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}";
1561 } elsif ($drive->{interface
} eq 'ide'){
1563 my $controller = int($drive->{index} / $maxdev);
1564 my $unit = $drive->{index} % $maxdev;
1565 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1567 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1568 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1569 $model = URI
::Escape
::uri_unescape
($model);
1570 $device .= ",model=$model";
1572 } elsif ($drive->{interface
} eq 'sata'){
1573 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1574 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1575 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1576 } elsif ($drive->{interface
} eq 'usb') {
1578 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1580 die "unsupported interface type";
1583 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1588 sub get_initiator_name
{
1591 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1592 while (defined(my $line = <$fh>)) {
1593 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1602 sub print_drive_full
{
1603 my ($storecfg, $vmid, $drive) = @_;
1606 my $volid = $drive->{file
};
1609 if (drive_is_cdrom
($drive)) {
1610 $path = get_iso_path
($storecfg, $vmid, $volid);
1612 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1614 $path = PVE
::Storage
::path
($storecfg, $volid);
1615 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1616 $format = qemu_img_format
($scfg, $volname);
1624 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard);
1625 foreach my $o (@qemu_drive_options) {
1626 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1628 foreach my $type (['', '-total'], [_rd
=> '-read'], [_wr
=> '-write']) {
1629 my ($dir, $qmpname) = @$type;
1630 if (my $v = $drive->{"mbps$dir"}) {
1631 $opts .= ",throttling.bps$qmpname=".int($v*1024*1024);
1633 if (my $v = $drive->{"mbps${dir}_max"}) {
1634 $opts .= ",throttling.bps$qmpname-max=".int($v*1024*1024);
1636 if (my $v = $drive->{"bps${dir}_max_length"}) {
1637 $opts .= ",throttling.bps$qmpname-max-length=$v";
1639 if (my $v = $drive->{"iops${dir}"}) {
1640 $opts .= ",throttling.iops$qmpname=$v";
1642 if (my $v = $drive->{"iops${dir}_max"}) {
1643 $opts .= ",throttling.iops$qmpname-max=$v";
1645 if (my $v = $drive->{"iops${dir}_max_length"}) {
1646 $opts .= ",throttling.iops$qmpname-max-length=$v";
1650 if (my $serial = $drive->{serial
}) {
1651 $serial = URI
::Escape
::uri_unescape
($serial);
1652 $opts .= ",serial=$serial";
1655 $opts .= ",format=$format" if $format && !$drive->{format
};
1657 my $cache_direct = 0;
1659 if (my $cache = $drive->{cache
}) {
1660 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1661 } elsif (!drive_is_cdrom
($drive)) {
1662 $opts .= ",cache=none";
1666 # aio native works only with O_DIRECT
1667 if (!$drive->{aio
}) {
1669 $opts .= ",aio=native";
1671 $opts .= ",aio=threads";
1675 if (!drive_is_cdrom
($drive)) {
1677 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1678 $detectzeroes = 'off';
1679 } elsif ($drive->{discard
}) {
1680 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1682 # This used to be our default with discard not being specified:
1683 $detectzeroes = 'on';
1685 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1688 my $pathinfo = $path ?
"file=$path," : '';
1690 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1693 sub print_netdevice_full
{
1694 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1696 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1698 my $device = $net->{model
};
1699 if ($net->{model
} eq 'virtio') {
1700 $device = 'virtio-net-pci';
1703 my $pciaddr = print_pci_addr
("$netid", $bridges);
1704 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1705 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1706 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1707 my $vectors = $net->{queues
} * 2 + 2;
1708 $tmpstr .= ",vectors=$vectors,mq=on";
1710 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1712 if ($use_old_bios_files) {
1714 if ($device eq 'virtio-net-pci') {
1715 $romfile = 'pxe-virtio.rom';
1716 } elsif ($device eq 'e1000') {
1717 $romfile = 'pxe-e1000.rom';
1718 } elsif ($device eq 'ne2k') {
1719 $romfile = 'pxe-ne2k_pci.rom';
1720 } elsif ($device eq 'pcnet') {
1721 $romfile = 'pxe-pcnet.rom';
1722 } elsif ($device eq 'rtl8139') {
1723 $romfile = 'pxe-rtl8139.rom';
1725 $tmpstr .= ",romfile=$romfile" if $romfile;
1731 sub print_netdev_full
{
1732 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1735 if ($netid =~ m/^net(\d+)$/) {
1739 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1741 my $ifname = "tap${vmid}i$i";
1743 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1744 die "interface name '$ifname' is too long (max 15 character)\n"
1745 if length($ifname) >= 16;
1747 my $vhostparam = '';
1748 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1750 my $vmname = $conf->{name
} || "vm$vmid";
1753 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1755 if ($net->{bridge
}) {
1756 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1758 $netdev = "type=user,id=$netid,hostname=$vmname";
1761 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1767 sub print_cpu_device
{
1768 my ($conf, $id) = @_;
1770 my $kvm = $conf->{kvm
} // 1;
1771 my $cpu = $kvm ?
"kvm64" : "qemu64";
1772 if (my $cputype = $conf->{cpu
}) {
1773 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1774 or die "Cannot parse cpu description: $cputype\n";
1775 $cpu = $cpuconf->{cputype
};
1778 my $cores = $conf->{cores
} || 1;
1780 my $current_core = ($id - 1) % $cores;
1781 my $current_socket = int(($id - 1 - $current_core)/$cores);
1783 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1786 sub drive_is_cdrom
{
1789 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1793 sub parse_number_sets
{
1796 foreach my $part (split(/;/, $set)) {
1797 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1798 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1799 push @$res, [ $1, $2 ];
1801 die "invalid range: $part\n";
1810 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1811 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1812 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1819 return undef if !$value;
1821 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1823 my @idlist = split(/;/, $res->{host
});
1824 delete $res->{host
};
1825 foreach my $id (@idlist) {
1826 if ($id =~ /^$PCIRE$/) {
1828 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1830 my $pcidevices = lspci
($1);
1831 $res->{pciid
} = $pcidevices->{$1};
1834 # should have been caught by parse_property_string already
1835 die "failed to parse PCI id: $id\n";
1841 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1845 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1850 if (!defined($res->{macaddr
})) {
1851 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1852 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1860 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1863 sub add_random_macs
{
1864 my ($settings) = @_;
1866 foreach my $opt (keys %$settings) {
1867 next if $opt !~ m/^net(\d+)$/;
1868 my $net = parse_net
($settings->{$opt});
1870 $settings->{$opt} = print_net
($net);
1874 sub vm_is_volid_owner
{
1875 my ($storecfg, $vmid, $volid) = @_;
1877 if ($volid !~ m
|^/|) {
1879 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1880 if ($owner && ($owner == $vmid)) {
1888 sub split_flagged_list
{
1889 my $text = shift || '';
1890 $text =~ s/[,;]/ /g;
1892 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1895 sub join_flagged_list
{
1896 my ($how, $lst) = @_;
1897 join $how, map { $lst->{$_} . $_ } keys %$lst;
1900 sub vmconfig_delete_pending_option
{
1901 my ($conf, $key, $force) = @_;
1903 delete $conf->{pending
}->{$key};
1904 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1905 $pending_delete_hash->{$key} = $force ?
'!' : '';
1906 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1909 sub vmconfig_undelete_pending_option
{
1910 my ($conf, $key) = @_;
1912 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1913 delete $pending_delete_hash->{$key};
1915 if (%$pending_delete_hash) {
1916 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1918 delete $conf->{pending
}->{delete};
1922 sub vmconfig_register_unused_drive
{
1923 my ($storecfg, $vmid, $conf, $drive) = @_;
1925 if (!drive_is_cdrom
($drive)) {
1926 my $volid = $drive->{file
};
1927 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1928 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1933 sub vmconfig_cleanup_pending
{
1936 # remove pending changes when nothing changed
1938 foreach my $opt (keys %{$conf->{pending
}}) {
1939 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1941 delete $conf->{pending
}->{$opt};
1945 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1946 my $pending_delete_hash = {};
1947 while (my ($opt, $force) = each %$current_delete_hash) {
1948 if (defined($conf->{$opt})) {
1949 $pending_delete_hash->{$opt} = $force;
1955 if (%$pending_delete_hash) {
1956 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1958 delete $conf->{pending
}->{delete};
1964 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1968 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1969 format_description
=> 'UUID',
1970 description
=> "Set SMBIOS1 UUID.",
1976 format_description
=> 'string',
1977 description
=> "Set SMBIOS1 version.",
1983 format_description
=> 'string',
1984 description
=> "Set SMBIOS1 serial number.",
1990 format_description
=> 'string',
1991 description
=> "Set SMBIOS1 manufacturer.",
1997 format_description
=> 'string',
1998 description
=> "Set SMBIOS1 product ID.",
2004 format_description
=> 'string',
2005 description
=> "Set SMBIOS1 SKU string.",
2011 format_description
=> 'string',
2012 description
=> "Set SMBIOS1 family string.",
2020 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
2027 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
2030 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
2032 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
2033 sub verify_bootdisk
{
2034 my ($value, $noerr) = @_;
2036 return $value if is_valid_drivename
($value);
2038 return undef if $noerr;
2040 die "invalid boot disk '$value'\n";
2043 sub parse_watchdog
{
2046 return undef if !$value;
2048 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
2053 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
2054 sub verify_usb_device
{
2055 my ($value, $noerr) = @_;
2057 return $value if parse_usb_device
($value);
2059 return undef if $noerr;
2061 die "unable to parse usb device\n";
2064 # add JSON properties for create and set function
2065 sub json_config_properties
{
2068 foreach my $opt (keys %$confdesc) {
2069 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2070 $prop->{$opt} = $confdesc->{$opt};
2077 my ($key, $value) = @_;
2079 die "unknown setting '$key'\n" if !$confdesc->{$key};
2081 my $type = $confdesc->{$key}->{type
};
2083 if (!defined($value)) {
2084 die "got undefined value\n";
2087 if ($value =~ m/[\n\r]/) {
2088 die "property contains a line feed\n";
2091 if ($type eq 'boolean') {
2092 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2093 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2094 die "type check ('boolean') failed - got '$value'\n";
2095 } elsif ($type eq 'integer') {
2096 return int($1) if $value =~ m/^(\d+)$/;
2097 die "type check ('integer') failed - got '$value'\n";
2098 } elsif ($type eq 'number') {
2099 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2100 die "type check ('number') failed - got '$value'\n";
2101 } elsif ($type eq 'string') {
2102 if (my $fmt = $confdesc->{$key}->{format
}) {
2103 PVE
::JSONSchema
::check_format
($fmt, $value);
2106 $value =~ s/^\"(.*)\"$/$1/;
2109 die "internal error"
2113 sub check_iommu_support
{
2114 #fixme : need to check IOMMU support
2115 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2125 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2126 utime undef, undef, $conf;
2130 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2132 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2134 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2136 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2138 if ($conf->{template
}) {
2139 # check if any base image is still used by a linked clone
2140 foreach_drive
($conf, sub {
2141 my ($ds, $drive) = @_;
2143 return if drive_is_cdrom
($drive);
2145 my $volid = $drive->{file
};
2147 return if !$volid || $volid =~ m
|^/|;
2149 die "base volume '$volid' is still in use by linked cloned\n"
2150 if PVE
::Storage
::volume_is_base_and_used
($storecfg, $volid);
2155 # only remove disks owned by this VM
2156 foreach_drive
($conf, sub {
2157 my ($ds, $drive) = @_;
2159 return if drive_is_cdrom
($drive);
2161 my $volid = $drive->{file
};
2163 return if !$volid || $volid =~ m
|^/|;
2165 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2166 return if !$path || !$owner || ($owner != $vmid);
2169 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2171 warn "Could not remove disk '$volid', check manually: $@" if $@;
2175 if ($keep_empty_config) {
2176 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2181 # also remove unused disk
2183 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2186 PVE
::Storage
::foreach_volid
($dl, sub {
2187 my ($volid, $sid, $volname, $d) = @_;
2188 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2197 sub parse_vm_config
{
2198 my ($filename, $raw) = @_;
2200 return undef if !defined($raw);
2203 digest
=> Digest
::SHA
::sha1_hex
($raw),
2208 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2209 || die "got strange filename '$filename'";
2217 my @lines = split(/\n/, $raw);
2218 foreach my $line (@lines) {
2219 next if $line =~ m/^\s*$/;
2221 if ($line =~ m/^\[PENDING\]\s*$/i) {
2222 $section = 'pending';
2223 if (defined($descr)) {
2225 $conf->{description
} = $descr;
2228 $conf = $res->{$section} = {};
2231 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2233 if (defined($descr)) {
2235 $conf->{description
} = $descr;
2238 $conf = $res->{snapshots
}->{$section} = {};
2242 if ($line =~ m/^\#(.*)\s*$/) {
2243 $descr = '' if !defined($descr);
2244 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2248 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2249 $descr = '' if !defined($descr);
2250 $descr .= PVE
::Tools
::decode_text
($2);
2251 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2252 $conf->{snapstate
} = $1;
2253 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2256 $conf->{$key} = $value;
2257 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2259 if ($section eq 'pending') {
2260 $conf->{delete} = $value; # we parse this later
2262 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2264 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2267 eval { $value = check_type
($key, $value); };
2269 warn "vm $vmid - unable to parse value of '$key' - $@";
2271 $key = 'ide2' if $key eq 'cdrom';
2272 my $fmt = $confdesc->{$key}->{format
};
2273 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2274 my $v = parse_drive
($key, $value);
2275 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2276 $v->{file
} = $volid;
2277 $value = print_drive
($vmid, $v);
2279 warn "vm $vmid - unable to parse value of '$key'\n";
2284 $conf->{$key} = $value;
2289 if (defined($descr)) {
2291 $conf->{description
} = $descr;
2293 delete $res->{snapstate
}; # just to be sure
2298 sub write_vm_config
{
2299 my ($filename, $conf) = @_;
2301 delete $conf->{snapstate
}; # just to be sure
2303 if ($conf->{cdrom
}) {
2304 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2305 $conf->{ide2
} = $conf->{cdrom
};
2306 delete $conf->{cdrom
};
2309 # we do not use 'smp' any longer
2310 if ($conf->{sockets
}) {
2311 delete $conf->{smp
};
2312 } elsif ($conf->{smp
}) {
2313 $conf->{sockets
} = $conf->{smp
};
2314 delete $conf->{cores
};
2315 delete $conf->{smp
};
2318 my $used_volids = {};
2320 my $cleanup_config = sub {
2321 my ($cref, $pending, $snapname) = @_;
2323 foreach my $key (keys %$cref) {
2324 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2325 $key eq 'snapstate' || $key eq 'pending';
2326 my $value = $cref->{$key};
2327 if ($key eq 'delete') {
2328 die "propertry 'delete' is only allowed in [PENDING]\n"
2330 # fixme: check syntax?
2333 eval { $value = check_type
($key, $value); };
2334 die "unable to parse value of '$key' - $@" if $@;
2336 $cref->{$key} = $value;
2338 if (!$snapname && is_valid_drivename
($key)) {
2339 my $drive = parse_drive
($key, $value);
2340 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2345 &$cleanup_config($conf);
2347 &$cleanup_config($conf->{pending
}, 1);
2349 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2350 die "internal error" if $snapname eq 'pending';
2351 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2354 # remove 'unusedX' settings if we re-add a volume
2355 foreach my $key (keys %$conf) {
2356 my $value = $conf->{$key};
2357 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2358 delete $conf->{$key};
2362 my $generate_raw_config = sub {
2363 my ($conf, $pending) = @_;
2367 # add description as comment to top of file
2368 if (defined(my $descr = $conf->{description
})) {
2370 foreach my $cl (split(/\n/, $descr)) {
2371 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2374 $raw .= "#\n" if $pending;
2378 foreach my $key (sort keys %$conf) {
2379 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2380 $raw .= "$key: $conf->{$key}\n";
2385 my $raw = &$generate_raw_config($conf);
2387 if (scalar(keys %{$conf->{pending
}})){
2388 $raw .= "\n[PENDING]\n";
2389 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2392 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2393 $raw .= "\n[$snapname]\n";
2394 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2404 # we use static defaults from our JSON schema configuration
2405 foreach my $key (keys %$confdesc) {
2406 if (defined(my $default = $confdesc->{$key}->{default})) {
2407 $res->{$key} = $default;
2411 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2412 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2418 my $vmlist = PVE
::Cluster
::get_vmlist
();
2420 return $res if !$vmlist || !$vmlist->{ids
};
2421 my $ids = $vmlist->{ids
};
2423 foreach my $vmid (keys %$ids) {
2424 my $d = $ids->{$vmid};
2425 next if !$d->{node
} || $d->{node
} ne $nodename;
2426 next if !$d->{type
} || $d->{type
} ne 'qemu';
2427 $res->{$vmid}->{exists} = 1;
2432 # test if VM uses local resources (to prevent migration)
2433 sub check_local_resources
{
2434 my ($conf, $noerr) = @_;
2438 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2439 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2441 foreach my $k (keys %$conf) {
2442 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2443 # sockets are safe: they will recreated be on the target side post-migrate
2444 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2445 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2448 die "VM uses local resources\n" if $loc_res && !$noerr;
2453 # check if used storages are available on all nodes (use by migrate)
2454 sub check_storage_availability
{
2455 my ($storecfg, $conf, $node) = @_;
2457 foreach_drive
($conf, sub {
2458 my ($ds, $drive) = @_;
2460 my $volid = $drive->{file
};
2463 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2466 # check if storage is available on both nodes
2467 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2468 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2472 # list nodes where all VM images are available (used by has_feature API)
2474 my ($conf, $storecfg) = @_;
2476 my $nodelist = PVE
::Cluster
::get_nodelist
();
2477 my $nodehash = { map { $_ => 1 } @$nodelist };
2478 my $nodename = PVE
::INotify
::nodename
();
2480 foreach_drive
($conf, sub {
2481 my ($ds, $drive) = @_;
2483 my $volid = $drive->{file
};
2486 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2488 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2489 if ($scfg->{disable
}) {
2491 } elsif (my $avail = $scfg->{nodes
}) {
2492 foreach my $node (keys %$nodehash) {
2493 delete $nodehash->{$node} if !$avail->{$node};
2495 } elsif (!$scfg->{shared
}) {
2496 foreach my $node (keys %$nodehash) {
2497 delete $nodehash->{$node} if $node ne $nodename
2507 my ($pidfile, $pid) = @_;
2509 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2513 return undef if !$line;
2514 my @param = split(/\0/, $line);
2516 my $cmd = $param[0];
2517 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2519 for (my $i = 0; $i < scalar (@param); $i++) {
2522 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2523 my $p = $param[$i+1];
2524 return 1 if $p && ($p eq $pidfile);
2533 my ($vmid, $nocheck, $node) = @_;
2535 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2537 die "unable to find configuration file for VM $vmid - no such machine\n"
2538 if !$nocheck && ! -f
$filename;
2540 my $pidfile = pidfile_name
($vmid);
2542 if (my $fd = IO
::File-
>new("<$pidfile")) {
2547 my $mtime = $st->mtime;
2548 if ($mtime > time()) {
2549 warn "file '$filename' modified in future\n";
2552 if ($line =~ m/^(\d+)$/) {
2554 if (check_cmdline
($pidfile, $pid)) {
2555 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2567 my $vzlist = config_list
();
2569 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2571 while (defined(my $de = $fd->read)) {
2572 next if $de !~ m/^(\d+)\.pid$/;
2574 next if !defined($vzlist->{$vmid});
2575 if (my $pid = check_running
($vmid)) {
2576 $vzlist->{$vmid}->{pid
} = $pid;
2584 my ($storecfg, $conf) = @_;
2586 my $bootdisk = $conf->{bootdisk
};
2587 return undef if !$bootdisk;
2588 return undef if !is_valid_drivename
($bootdisk);
2590 return undef if !$conf->{$bootdisk};
2592 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2593 return undef if !defined($drive);
2595 return undef if drive_is_cdrom
($drive);
2597 my $volid = $drive->{file
};
2598 return undef if !$volid;
2600 return $drive->{size
};
2603 my $last_proc_pid_stat;
2605 # get VM status information
2606 # This must be fast and should not block ($full == false)
2607 # We only query KVM using QMP if $full == true (this can be slow)
2609 my ($opt_vmid, $full) = @_;
2613 my $storecfg = PVE
::Storage
::config
();
2615 my $list = vzlist
();
2616 my $defaults = load_defaults
();
2618 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2620 my $cpucount = $cpuinfo->{cpus
} || 1;
2622 foreach my $vmid (keys %$list) {
2623 next if $opt_vmid && ($vmid ne $opt_vmid);
2625 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2626 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2629 $d->{pid
} = $list->{$vmid}->{pid
};
2631 # fixme: better status?
2632 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2634 my $size = disksize
($storecfg, $conf);
2635 if (defined($size)) {
2636 $d->{disk
} = 0; # no info available
2637 $d->{maxdisk
} = $size;
2643 $d->{cpus
} = ($conf->{sockets
} || $defaults->{sockets
})
2644 * ($conf->{cores
} || $defaults->{cores
});
2645 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2646 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2648 $d->{name
} = $conf->{name
} || "VM $vmid";
2649 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024)
2650 : $defaults->{memory
}*(1024*1024);
2652 if ($conf->{balloon
}) {
2653 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2654 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
}
2655 : $defaults->{shares
};
2666 $d->{diskwrite
} = 0;
2668 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2673 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2674 foreach my $dev (keys %$netdev) {
2675 next if $dev !~ m/^tap([1-9]\d*)i/;
2677 my $d = $res->{$vmid};
2680 $d->{netout
} += $netdev->{$dev}->{receive
};
2681 $d->{netin
} += $netdev->{$dev}->{transmit
};
2684 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2685 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2690 my $ctime = gettimeofday
;
2692 foreach my $vmid (keys %$list) {
2694 my $d = $res->{$vmid};
2695 my $pid = $d->{pid
};
2698 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2699 next if !$pstat; # not running
2701 my $used = $pstat->{utime} + $pstat->{stime
};
2703 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2705 if ($pstat->{vsize
}) {
2706 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2709 my $old = $last_proc_pid_stat->{$pid};
2711 $last_proc_pid_stat->{$pid} = {
2719 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2721 if ($dtime > 1000) {
2722 my $dutime = $used - $old->{used
};
2724 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2725 $last_proc_pid_stat->{$pid} = {
2731 $d->{cpu
} = $old->{cpu
};
2735 return $res if !$full;
2737 my $qmpclient = PVE
::QMPClient-
>new();
2739 my $ballooncb = sub {
2740 my ($vmid, $resp) = @_;
2742 my $info = $resp->{'return'};
2743 return if !$info->{max_mem
};
2745 my $d = $res->{$vmid};
2747 # use memory assigned to VM
2748 $d->{maxmem
} = $info->{max_mem
};
2749 $d->{balloon
} = $info->{actual
};
2751 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2752 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2753 $d->{freemem
} = $info->{free_mem
};
2756 $d->{ballooninfo
} = $info;
2759 my $blockstatscb = sub {
2760 my ($vmid, $resp) = @_;
2761 my $data = $resp->{'return'} || [];
2762 my $totalrdbytes = 0;
2763 my $totalwrbytes = 0;
2765 for my $blockstat (@$data) {
2766 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2767 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2769 $blockstat->{device
} =~ s/drive-//;
2770 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2772 $res->{$vmid}->{diskread
} = $totalrdbytes;
2773 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2776 my $statuscb = sub {
2777 my ($vmid, $resp) = @_;
2779 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2780 # this fails if ballon driver is not loaded, so this must be
2781 # the last commnand (following command are aborted if this fails).
2782 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2784 my $status = 'unknown';
2785 if (!defined($status = $resp->{'return'}->{status
})) {
2786 warn "unable to get VM status\n";
2790 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2793 foreach my $vmid (keys %$list) {
2794 next if $opt_vmid && ($vmid ne $opt_vmid);
2795 next if !$res->{$vmid}->{pid
}; # not running
2796 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2799 $qmpclient->queue_execute(undef, 2);
2801 foreach my $vmid (keys %$list) {
2802 next if $opt_vmid && ($vmid ne $opt_vmid);
2803 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2810 my ($conf, $func, @param) = @_;
2812 foreach my $ds (valid_drive_names
()) {
2813 next if !defined($conf->{$ds});
2815 my $drive = parse_drive
($ds, $conf->{$ds});
2818 &$func($ds, $drive, @param);
2823 my ($conf, $func, @param) = @_;
2827 my $test_volid = sub {
2828 my ($volid, $is_cdrom, $replicate, $snapname) = @_;
2832 $volhash->{$volid}->{cdrom
} //= 1;
2833 $volhash->{$volid}->{cdrom
} = 0 if !$is_cdrom;
2835 $volhash->{$volid}->{replicate
} //= 0;
2836 $volhash->{$volid}->{replicate
} = 1 if $replicate;
2838 $volhash->{$volid}->{referenced_in_config
} //= 0;
2839 $volhash->{$volid}->{referenced_in_config
} = 1 if !defined($snapname);
2841 $volhash->{$volid}->{referenced_in_snapshot
}->{$snapname} = 1
2842 if defined($snapname);
2845 foreach_drive
($conf, sub {
2846 my ($ds, $drive) = @_;
2847 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, undef);
2850 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2851 my $snap = $conf->{snapshots
}->{$snapname};
2852 $test_volid->($snap->{vmstate
}, 0, 1, $snapname);
2853 foreach_drive
($snap, sub {
2854 my ($ds, $drive) = @_;
2855 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, $snapname);
2859 foreach my $volid (keys %$volhash) {
2860 &$func($volid, $volhash->{$volid}, @param);
2864 sub vga_conf_has_spice
{
2867 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2872 sub config_to_command
{
2873 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2876 my $globalFlags = [];
2877 my $machineFlags = [];
2883 my $kvmver = kvm_user_version
();
2884 my $vernum = 0; # unknown
2885 my $ostype = $conf->{ostype
};
2886 my $winversion = windows_version
($ostype);
2887 my $kvm = $conf->{kvm
} // 1;
2889 die "KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.\n" if (!$cpuinfo->{hvm
} && $kvm);
2891 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2892 $vernum = $1*1000000+$2*1000;
2893 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2894 $vernum = $1*1000000+$2*1000+$3;
2897 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2899 my $have_ovz = -f
'/proc/vz/vestat';
2901 my $q35 = machine_type_is_q35
($conf);
2902 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2903 my $machine_type = $forcemachine || $conf->{machine
};
2904 my $use_old_bios_files = undef;
2905 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2907 my $cpuunits = defined($conf->{cpuunits
}) ?
2908 $conf->{cpuunits
} : $defaults->{cpuunits
};
2910 push @$cmd, '/usr/bin/kvm';
2912 push @$cmd, '-id', $vmid;
2916 my $qmpsocket = qmp_socket
($vmid);
2917 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2918 push @$cmd, '-mon', "chardev=qmp,mode=control";
2921 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2923 push @$cmd, '-daemonize';
2925 if ($conf->{smbios1
}) {
2926 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2929 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2930 die "uefi base image not found\n" if ! -f
$OVMF_CODE;
2934 if (my $efidisk = $conf->{efidisk0
}) {
2935 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $efidisk);
2936 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
2937 $format = $d->{format
};
2939 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
2940 if (!defined($format)) {
2941 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2942 $format = qemu_img_format
($scfg, $volname);
2946 die "efidisk format must be specified\n"
2947 if !defined($format);
2950 warn "no efidisk configured! Using temporary efivars disk.\n";
2951 $path = "/tmp/$vmid-ovmf.fd";
2952 PVE
::Tools
::file_copy
($OVMF_VARS, $path, -s
$OVMF_VARS);
2956 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$OVMF_CODE";
2957 push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0,file=$path";
2961 # add usb controllers
2962 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2963 push @$devices, @usbcontrollers if @usbcontrollers;
2964 my $vga = $conf->{vga
};
2966 my $qxlnum = vga_conf_has_spice
($vga);
2967 $vga = 'qxl' if $qxlnum;
2970 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 9)) {
2971 $vga = (!$winversion || $winversion >= 6) ?
'std' : 'cirrus';
2973 $vga = ($winversion >= 6) ?
'std' : 'cirrus';
2977 # enable absolute mouse coordinates (needed by vnc)
2979 if (defined($conf->{tablet
})) {
2980 $tablet = $conf->{tablet
};
2982 $tablet = $defaults->{tablet
};
2983 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2984 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2987 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2990 my $gpu_passthrough;
2993 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2994 my $d = parse_hostpci
($conf->{"hostpci$i"});
2997 my $pcie = $d->{pcie
};
2999 die "q35 machine model is not enabled" if !$q35;
3000 $pciaddr = print_pcie_addr
("hostpci$i");
3002 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
3005 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
3006 my $romfile = $d->{romfile
};
3009 if ($d->{'x-vga'}) {
3010 $xvga = ',x-vga=on';
3013 $gpu_passthrough = 1;
3015 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
3019 my $pcidevices = $d->{pciid
};
3020 my $multifunction = 1 if @$pcidevices > 1;
3023 foreach my $pcidevice (@$pcidevices) {
3025 my $id = "hostpci$i";
3026 $id .= ".$j" if $multifunction;
3027 my $addr = $pciaddr;
3028 $addr .= ".$j" if $multifunction;
3029 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
3032 $devicestr .= "$rombar$xvga";
3033 $devicestr .= ",multifunction=on" if $multifunction;
3034 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
3037 push @$devices, '-device', $devicestr;
3043 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
3044 push @$devices, @usbdevices if @usbdevices;
3046 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
3047 if (my $path = $conf->{"serial$i"}) {
3048 if ($path eq 'socket') {
3049 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
3050 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
3051 push @$devices, '-device', "isa-serial,chardev=serial$i";
3053 die "no such serial device\n" if ! -c
$path;
3054 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
3055 push @$devices, '-device', "isa-serial,chardev=serial$i";
3061 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
3062 if (my $path = $conf->{"parallel$i"}) {
3063 die "no such parallel device\n" if ! -c
$path;
3064 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
3065 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
3066 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
3070 my $vmname = $conf->{name
} || "vm$vmid";
3072 push @$cmd, '-name', $vmname;
3075 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
3076 $sockets = $conf->{sockets
} if $conf->{sockets
};
3078 my $cores = $conf->{cores
} || 1;
3080 my $maxcpus = $sockets * $cores;
3082 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3084 my $allowed_vcpus = $cpuinfo->{cpus
};
3086 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3087 if ($allowed_vcpus < $maxcpus);
3089 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
3091 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3092 for (my $i = 2; $i <= $vcpus; $i++) {
3093 my $cpustr = print_cpu_device
($conf,$i);
3094 push @$cmd, '-device', $cpustr;
3099 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3101 push @$cmd, '-nodefaults';
3103 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3105 my $bootindex_hash = {};
3107 foreach my $o (split(//, $bootorder)) {
3108 $bootindex_hash->{$o} = $i*100;
3112 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3114 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3116 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3118 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3120 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3121 my $socket = vnc_socket
($vmid);
3122 push @$cmd, '-vnc', "unix:$socket,x509,password";
3124 push @$cmd, '-nographic';
3128 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3130 my $useLocaltime = $conf->{localtime};
3132 if ($winversion >= 5) { # windows
3133 $useLocaltime = 1 if !defined($conf->{localtime});
3135 # use time drift fix when acpi is enabled
3136 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3137 $tdf = 1 if !defined($conf->{tdf
});
3141 if ($winversion >= 6) {
3142 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3143 push @$cmd, '-no-hpet';
3146 push @$rtcFlags, 'driftfix=slew' if $tdf;
3149 push @$machineFlags, 'accel=tcg';
3152 if ($machine_type) {
3153 push @$machineFlags, "type=${machine_type}";
3156 if ($conf->{startdate
}) {
3157 push @$rtcFlags, "base=$conf->{startdate}";
3158 } elsif ($useLocaltime) {
3159 push @$rtcFlags, 'base=localtime';
3162 my $cpu = $kvm ?
"kvm64" : "qemu64";
3163 if (my $cputype = $conf->{cpu
}) {
3164 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3165 or die "Cannot parse cpu description: $cputype\n";
3166 $cpu = $cpuconf->{cputype
};
3167 $kvm_off = 1 if $cpuconf->{hidden
};
3169 if (defined(my $flags = $cpuconf->{flags
})) {
3170 push @$cpuFlags, $flags;
3174 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3176 push @$cpuFlags , '-x2apic'
3177 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3179 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3181 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3183 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3185 push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
3186 push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
3189 add_hyperv_enlightenments
($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios
}, $gpu_passthrough) if $kvm;
3191 push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm;
3193 push @$cpuFlags, 'kvm=off' if $kvm_off;
3195 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3196 die "internal error"; # should not happen
3198 push @$cpuFlags, "vendor=${cpu_vendor}"
3199 if $cpu_vendor ne 'default';
3201 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3203 push @$cmd, '-cpu', $cpu;
3205 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3207 push @$cmd, '-S' if $conf->{freeze
};
3209 # set keyboard layout
3210 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3211 push @$cmd, '-k', $kb if $kb;
3214 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3215 #push @$cmd, '-soundhw', 'es1370';
3216 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3218 if($conf->{agent
}) {
3219 my $qgasocket = qmp_socket
($vmid, 1);
3220 my $pciaddr = print_pci_addr
("qga0", $bridges);
3221 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3222 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3223 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3231 for(my $i = 1; $i < $qxlnum; $i++){
3232 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3233 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3236 # assume other OS works like Linux
3237 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3238 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3242 my $pciaddr = print_pci_addr
("spice", $bridges);
3244 my $nodename = PVE
::INotify
::nodename
();
3245 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3246 my @nodeaddrs = PVE
::Tools
::getaddrinfo_all
('localhost', family
=> $pfamily);
3247 die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
3248 my $localhost = PVE
::Network
::addr_to_ip
($nodeaddrs[0]->{addr
});
3249 $spice_port = PVE
::Tools
::next_spice_port
($pfamily, $localhost);
3251 push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
3253 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3254 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3255 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3258 # enable balloon by default, unless explicitly disabled
3259 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3260 $pciaddr = print_pci_addr
("balloon0", $bridges);
3261 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3264 if ($conf->{watchdog
}) {
3265 my $wdopts = parse_watchdog
($conf->{watchdog
});
3266 $pciaddr = print_pci_addr
("watchdog", $bridges);
3267 my $watchdog = $wdopts->{model
} || 'i6300esb';
3268 push @$devices, '-device', "$watchdog$pciaddr";
3269 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3273 my $scsicontroller = {};
3274 my $ahcicontroller = {};
3275 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3277 # Add iscsi initiator name if available
3278 if (my $initiator = get_initiator_name
()) {
3279 push @$devices, '-iscsi', "initiator-name=$initiator";
3282 foreach_drive
($conf, sub {
3283 my ($ds, $drive) = @_;
3285 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3286 push @$vollist, $drive->{file
};
3289 # ignore efidisk here, already added in bios/fw handling code above
3290 return if $drive->{interface
} eq 'efidisk';
3292 $use_virtio = 1 if $ds =~ m/^virtio/;
3294 if (drive_is_cdrom
($drive)) {
3295 if ($bootindex_hash->{d
}) {
3296 $drive->{bootindex
} = $bootindex_hash->{d
};
3297 $bootindex_hash->{d
} += 1;
3300 if ($bootindex_hash->{c
}) {
3301 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3302 $bootindex_hash->{c
} += 1;
3306 if($drive->{interface
} eq 'virtio'){
3307 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3310 if ($drive->{interface
} eq 'scsi') {
3312 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3314 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3315 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3318 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3319 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3320 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3321 } elsif ($drive->{iothread
}) {
3322 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3326 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3327 $queues = ",num_queues=$drive->{queues}";
3330 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3331 $scsicontroller->{$controller}=1;
3334 if ($drive->{interface
} eq 'sata') {
3335 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3336 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3337 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3338 $ahcicontroller->{$controller}=1;
3341 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3342 push @$devices, '-drive',$drive_cmd;
3343 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3346 for (my $i = 0; $i < $MAX_NETS; $i++) {
3347 next if !$conf->{"net$i"};
3348 my $d = parse_net
($conf->{"net$i"});
3351 $use_virtio = 1 if $d->{model
} eq 'virtio';
3353 if ($bootindex_hash->{n
}) {
3354 $d->{bootindex
} = $bootindex_hash->{n
};
3355 $bootindex_hash->{n
} += 1;
3358 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3359 push @$devices, '-netdev', $netdevfull;
3361 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3362 push @$devices, '-device', $netdevicefull;
3367 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3372 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3374 while (my ($k, $v) = each %$bridges) {
3375 $pciaddr = print_pci_addr
("pci.$k");
3376 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3381 if ($conf->{args
}) {
3382 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3386 push @$cmd, @$devices;
3387 push @$cmd, '-rtc', join(',', @$rtcFlags)
3388 if scalar(@$rtcFlags);
3389 push @$cmd, '-machine', join(',', @$machineFlags)
3390 if scalar(@$machineFlags);
3391 push @$cmd, '-global', join(',', @$globalFlags)
3392 if scalar(@$globalFlags);
3394 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3399 return "${var_run_tmpdir}/$vmid.vnc";
3405 my $res = vm_mon_cmd
($vmid, 'query-spice');
3407 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3411 my ($vmid, $qga) = @_;
3412 my $sockettype = $qga ?
'qga' : 'qmp';
3413 return "${var_run_tmpdir}/$vmid.$sockettype";
3418 return "${var_run_tmpdir}/$vmid.pid";
3421 sub vm_devices_list
{
3424 my $res = vm_mon_cmd
($vmid, 'query-pci');
3426 foreach my $pcibus (@$res) {
3427 foreach my $device (@{$pcibus->{devices
}}) {
3428 next if !$device->{'qdev_id'};
3429 if ($device->{'pci_bridge'}) {
3430 $devices->{$device->{'qdev_id'}} = 1;
3431 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3432 next if !$bridge_device->{'qdev_id'};
3433 $devices->{$bridge_device->{'qdev_id'}} = 1;
3434 $devices->{$device->{'qdev_id'}}++;
3437 $devices->{$device->{'qdev_id'}} = 1;
3442 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3443 foreach my $block (@$resblock) {
3444 if($block->{device
} =~ m/^drive-(\S+)/){
3449 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3450 foreach my $mice (@$resmice) {
3451 if ($mice->{name
} eq 'QEMU HID Tablet') {
3452 $devices->{tablet
} = 1;
3457 # for usb devices there is no query-usb
3458 # but we can iterate over the entries in
3459 # qom-list path=/machine/peripheral
3460 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3461 foreach my $per (@$resperipheral) {
3462 if ($per->{name
} =~ m/^usb\d+$/) {
3463 $devices->{$per->{name
}} = 1;
3471 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3473 my $q35 = machine_type_is_q35
($conf);
3475 my $devices_list = vm_devices_list
($vmid);
3476 return 1 if defined($devices_list->{$deviceid});
3478 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3480 if ($deviceid eq 'tablet') {
3482 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3484 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3486 die "usb hotplug currently not reliable\n";
3487 # since we can't reliably hot unplug all added usb devices
3488 # and usb passthrough disables live migration
3489 # we disable usb hotplugging for now
3490 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3492 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3494 qemu_iothread_add
($vmid, $deviceid, $device);
3496 qemu_driveadd
($storecfg, $vmid, $device);
3497 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3499 qemu_deviceadd
($vmid, $devicefull);
3500 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3502 eval { qemu_drivedel
($vmid, $deviceid); };
3507 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3510 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3511 my $pciaddr = print_pci_addr
($deviceid);
3512 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3514 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3516 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3517 qemu_iothread_add
($vmid, $deviceid, $device);
3518 $devicefull .= ",iothread=iothread-$deviceid";
3521 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3522 $devicefull .= ",num_queues=$device->{queues}";
3525 qemu_deviceadd
($vmid, $devicefull);
3526 qemu_deviceaddverify
($vmid, $deviceid);
3528 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3530 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3531 qemu_driveadd
($storecfg, $vmid, $device);
3533 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3534 eval { qemu_deviceadd
($vmid, $devicefull); };
3536 eval { qemu_drivedel
($vmid, $deviceid); };
3541 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3543 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3545 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3546 my $use_old_bios_files = undef;
3547 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3549 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3550 qemu_deviceadd
($vmid, $netdevicefull);
3551 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3553 eval { qemu_netdevdel
($vmid, $deviceid); };
3558 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3561 my $pciaddr = print_pci_addr
($deviceid);
3562 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3564 qemu_deviceadd
($vmid, $devicefull);
3565 qemu_deviceaddverify
($vmid, $deviceid);
3568 die "can't hotplug device '$deviceid'\n";
3574 # fixme: this should raise exceptions on error!
3575 sub vm_deviceunplug
{
3576 my ($vmid, $conf, $deviceid) = @_;
3578 my $devices_list = vm_devices_list
($vmid);
3579 return 1 if !defined($devices_list->{$deviceid});
3581 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3583 if ($deviceid eq 'tablet') {
3585 qemu_devicedel
($vmid, $deviceid);
3587 } elsif ($deviceid =~ m/^usb\d+$/) {
3589 die "usb hotplug currently not reliable\n";
3590 # when unplugging usb devices this way,
3591 # there may be remaining usb controllers/hubs
3592 # so we disable it for now
3593 qemu_devicedel
($vmid, $deviceid);
3594 qemu_devicedelverify
($vmid, $deviceid);
3596 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3598 qemu_devicedel
($vmid, $deviceid);
3599 qemu_devicedelverify
($vmid, $deviceid);
3600 qemu_drivedel
($vmid, $deviceid);
3601 qemu_iothread_del
($conf, $vmid, $deviceid);
3603 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3605 qemu_devicedel
($vmid, $deviceid);
3606 qemu_devicedelverify
($vmid, $deviceid);
3607 qemu_iothread_del
($conf, $vmid, $deviceid);
3609 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3611 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3612 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3613 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3615 qemu_devicedel
($vmid, $deviceid);
3616 qemu_drivedel
($vmid, $deviceid);
3617 qemu_deletescsihw
($conf, $vmid, $deviceid);
3619 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3621 qemu_devicedel
($vmid, $deviceid);
3622 qemu_devicedelverify
($vmid, $deviceid);
3623 qemu_netdevdel
($vmid, $deviceid);
3626 die "can't unplug device '$deviceid'\n";
3632 sub qemu_deviceadd
{
3633 my ($vmid, $devicefull) = @_;
3635 $devicefull = "driver=".$devicefull;
3636 my %options = split(/[=,]/, $devicefull);
3638 vm_mon_cmd
($vmid, "device_add" , %options);
3641 sub qemu_devicedel
{
3642 my ($vmid, $deviceid) = @_;
3644 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3647 sub qemu_iothread_add
{
3648 my($vmid, $deviceid, $device) = @_;
3650 if ($device->{iothread
}) {
3651 my $iothreads = vm_iothreads_list
($vmid);
3652 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3656 sub qemu_iothread_del
{
3657 my($conf, $vmid, $deviceid) = @_;
3659 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3660 if ($device->{iothread
}) {
3661 my $iothreads = vm_iothreads_list
($vmid);
3662 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3666 sub qemu_objectadd
{
3667 my($vmid, $objectid, $qomtype) = @_;
3669 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3674 sub qemu_objectdel
{
3675 my($vmid, $objectid) = @_;
3677 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3683 my ($storecfg, $vmid, $device) = @_;
3685 my $drive = print_drive_full
($storecfg, $vmid, $device);
3686 $drive =~ s/\\/\\\\/g;
3687 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3689 # If the command succeeds qemu prints: "OK
"
3690 return 1 if $ret =~ m/OK/s;
3692 die "adding drive failed
: $ret\n";
3696 my($vmid, $deviceid) = @_;
3698 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3701 return 1 if $ret eq "";
3703 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3704 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3706 die "deleting drive
$deviceid failed
: $ret\n";
3709 sub qemu_deviceaddverify {
3710 my ($vmid, $deviceid) = @_;
3712 for (my $i = 0; $i <= 5; $i++) {
3713 my $devices_list = vm_devices_list($vmid);
3714 return 1 if defined($devices_list->{$deviceid});
3718 die "error on hotplug device
'$deviceid'\n";
3722 sub qemu_devicedelverify {
3723 my ($vmid, $deviceid) = @_;
3725 # need to verify that the device is correctly removed as device_del
3726 # is async and empty return is not reliable
3728 for (my $i = 0; $i <= 5; $i++) {
3729 my $devices_list = vm_devices_list($vmid);
3730 return 1 if !defined($devices_list->{$deviceid});
3734 die "error on hot-unplugging device
'$deviceid'\n";
3737 sub qemu_findorcreatescsihw {
3738 my ($storecfg, $conf, $vmid, $device) = @_;
3740 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3742 my $scsihwid="$controller_prefix$controller";
3743 my $devices_list = vm_devices_list($vmid);
3745 if(!defined($devices_list->{$scsihwid})) {
3746 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3752 sub qemu_deletescsihw {
3753 my ($conf, $vmid, $opt) = @_;
3755 my $device = parse_drive($opt, $conf->{$opt});
3757 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3758 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3762 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3764 my $devices_list = vm_devices_list($vmid);
3765 foreach my $opt (keys %{$devices_list}) {
3766 if (PVE::QemuServer::is_valid_drivename($opt)) {
3767 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3768 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3774 my $scsihwid="scsihw
$controller";
3776 vm_deviceunplug($vmid, $conf, $scsihwid);
3781 sub qemu_add_pci_bridge {
3782 my ($storecfg, $conf, $vmid, $device) = @_;
3788 print_pci_addr($device, $bridges);
3790 while (my ($k, $v) = each %$bridges) {
3793 return 1 if !defined($bridgeid) || $bridgeid < 1;
3795 my $bridge = "pci
.$bridgeid";
3796 my $devices_list = vm_devices_list($vmid);
3798 if (!defined($devices_list->{$bridge})) {
3799 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3805 sub qemu_set_link_status {
3806 my ($vmid, $device, $up) = @_;
3808 vm_mon_cmd($vmid, "set_link
", name => $device,
3809 up => $up ? JSON::true : JSON::false);
3812 sub qemu_netdevadd {
3813 my ($vmid, $conf, $device, $deviceid) = @_;
3815 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3816 my %options = split(/[=,]/, $netdev);
3818 vm_mon_cmd($vmid, "netdev_add
", %options);
3822 sub qemu_netdevdel {
3823 my ($vmid, $deviceid) = @_;
3825 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3828 sub qemu_usb_hotplug {
3829 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3833 # remove the old one first
3834 vm_deviceunplug($vmid, $conf, $deviceid);
3836 # check if xhci controller is necessary and available
3837 if ($device->{usb3}) {
3839 my $devicelist = vm_devices_list($vmid);
3841 if (!$devicelist->{xhci}) {
3842 my $pciaddr = print_pci_addr("xhci
");
3843 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3846 my $d = parse_usb_device($device->{host});
3847 $d->{usb3} = $device->{usb3};
3850 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3853 sub qemu_cpu_hotplug {
3854 my ($vmid, $conf, $vcpus) = @_;
3856 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3859 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3860 $sockets = $conf->{sockets} if $conf->{sockets};
3861 my $cores = $conf->{cores} || 1;
3862 my $maxcpus = $sockets * $cores;
3864 $vcpus = $maxcpus if !$vcpus;
3866 die "you can
't add more vcpus than maxcpus\n"
3867 if $vcpus > $maxcpus;
3869 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3871 if ($vcpus < $currentvcpus) {
3873 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3875 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3876 qemu_devicedel($vmid, "cpu$i");
3878 my $currentrunningvcpus = undef;
3880 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3881 last if scalar(@{$currentrunningvcpus}) == $i-1;
3882 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3886 #update conf after each succesfull cpu unplug
3887 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3888 PVE::QemuConfig->write_config($vmid, $conf);
3891 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3897 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3898 die "vcpus in running vm does not match its configuration\n"
3899 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3901 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3903 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3904 my $cpustr = print_cpu_device($conf, $i);
3905 qemu_deviceadd($vmid, $cpustr);
3908 my $currentrunningvcpus = undef;
3910 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3911 last if scalar(@{$currentrunningvcpus}) == $i;
3912 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3916 #update conf after each succesfull cpu hotplug
3917 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3918 PVE::QemuConfig->write_config($vmid, $conf);
3922 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3923 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3928 sub qemu_block_set_io_throttle {
3929 my ($vmid, $deviceid,
3930 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3931 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3932 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3933 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3935 return if !check_running($vmid) ;
3937 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3939 bps_rd => int($bps_rd),
3940 bps_wr => int($bps_wr),
3942 iops_rd => int($iops_rd),
3943 iops_wr => int($iops_wr),
3944 bps_max => int($bps_max),
3945 bps_rd_max => int($bps_rd_max),
3946 bps_wr_max => int($bps_wr_max),
3947 iops_max => int($iops_max),
3948 iops_rd_max => int($iops_rd_max),
3949 iops_wr_max => int($iops_wr_max),
3950 bps_max_length => int($bps_max_length),
3951 bps_rd_max_length => int($bps_rd_max_length),
3952 bps_wr_max_length => int($bps_wr_max_length),
3953 iops_max_length => int($iops_max_length),
3954 iops_rd_max_length => int($iops_rd_max_length),
3955 iops_wr_max_length => int($iops_wr_max_length),
3960 # old code, only used to shutdown old VM after update
3962 my ($fh, $timeout) = @_;
3964 my $sel = new IO::Select;
3971 while (scalar (@ready = $sel->can_read($timeout))) {
3973 if ($count = $fh->sysread($buf, 8192)) {
3974 if ($buf =~ /^(.*)\(qemu\) $/s) {
3981 if (!defined($count)) {
3988 die "monitor read timeout\n" if !scalar(@ready);
3993 # old code, only used to shutdown old VM after update
3994 sub vm_monitor_command {
3995 my ($vmid, $cmdstr, $nocheck) = @_;
4000 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4002 my $sname = "${var_run_tmpdir}/$vmid.mon";
4004 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
4005 die "unable to connect to VM $vmid socket - $!\n";
4009 # hack: migrate sometime blocks the monitor (when migrate_downtime
4011 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4012 $timeout = 60*60; # 1 hour
4016 my $data = __read_avail($sock, $timeout);
4018 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
4019 die "got unexpected qemu monitor banner\n";
4022 my $sel = new IO::Select;
4025 if (!scalar(my @ready = $sel->can_write($timeout))) {
4026 die "monitor write error - timeout";
4029 my $fullcmd = "$cmdstr\r";
4031 # syslog('info
', "VM $vmid monitor command: $cmdstr");
4034 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4035 die "monitor write error - $!";
4038 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
4042 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4043 $timeout = 60*60; # 1 hour
4044 } elsif ($cmdstr =~ m/^(eject|change)/) {
4045 $timeout = 60; # note: cdrom mount command is slow
4047 if ($res = __read_avail($sock, $timeout)) {
4049 my @lines = split("\r?\n", $res);
4051 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4053 $res = join("\n", @lines);
4061 syslog("err", "VM $vmid monitor command failed - $err");
4068 sub qemu_block_resize {
4069 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4071 my $running = check_running($vmid);
4073 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4075 return if !$running;
4077 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4081 sub qemu_volume_snapshot {
4082 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4084 my $running = check_running($vmid);
4086 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4087 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4089 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4093 sub qemu_volume_snapshot_delete {
4094 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4096 my $running = check_running($vmid);
4098 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4099 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4101 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4105 sub set_migration_caps {
4111 "auto-converge" => 1,
4113 "x-rdma-pin-all" => 0,
4118 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4120 for my $supported_capability (@$supported_capabilities) {
4122 capability => $supported_capability->{capability},
4123 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4127 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4130 my $fast_plug_option = {
4138 'vmstatestorage
' => 1,
4141 # hotplug changes in [PENDING]
4142 # $selection hash can be used to only apply specified options, for
4143 # example: { cores => 1 } (only apply changed 'cores
')
4144 # $errors ref is used to return error messages
4145 sub vmconfig_hotplug_pending {
4146 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4148 my $defaults = load_defaults();
4150 # commit values which do not have any impact on running VM first
4151 # Note: those option cannot raise errors, we we do not care about
4152 # $selection and always apply them.
4154 my $add_error = sub {
4155 my ($opt, $msg) = @_;
4156 $errors->{$opt} = "hotplug problem - $msg";
4160 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4161 if ($fast_plug_option->{$opt}) {
4162 $conf->{$opt} = $conf->{pending}->{$opt};
4163 delete $conf->{pending}->{$opt};
4169 PVE::QemuConfig->write_config($vmid, $conf);
4170 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4173 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4175 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4176 while (my ($opt, $force) = each %$pending_delete_hash) {
4177 next if $selection && !$selection->{$opt};
4179 if ($opt eq 'hotplug
') {
4180 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4181 } elsif ($opt eq 'tablet
') {
4182 die "skip\n" if !$hotplug_features->{usb};
4183 if ($defaults->{tablet}) {
4184 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4186 vm_deviceunplug($vmid, $conf, $opt);
4188 } elsif ($opt =~ m/^usb\d+/) {
4190 # since we cannot reliably hot unplug usb devices
4191 # we are disabling it
4192 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4193 vm_deviceunplug($vmid, $conf, $opt);
4194 } elsif ($opt eq 'vcpus
') {
4195 die "skip\n" if !$hotplug_features->{cpu};
4196 qemu_cpu_hotplug($vmid, $conf, undef);
4197 } elsif ($opt eq 'balloon
') {
4198 # enable balloon device is not hotpluggable
4199 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4200 } elsif ($fast_plug_option->{$opt}) {
4202 } elsif ($opt =~ m/^net(\d+)$/) {
4203 die "skip\n" if !$hotplug_features->{network};
4204 vm_deviceunplug($vmid, $conf, $opt);
4205 } elsif (is_valid_drivename($opt)) {
4206 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4207 vm_deviceunplug($vmid, $conf, $opt);
4208 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4209 } elsif ($opt =~ m/^memory$/) {
4210 die "skip\n" if !$hotplug_features->{memory};
4211 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4212 } elsif ($opt eq 'cpuunits
') {
4213 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4214 } elsif ($opt eq 'cpulimit
') {
4215 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4221 &$add_error($opt, $err) if $err ne "skip\n";
4223 # save new config if hotplug was successful
4224 delete $conf->{$opt};
4225 vmconfig_undelete_pending_option($conf, $opt);
4226 PVE::QemuConfig->write_config($vmid, $conf);
4227 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4231 foreach my $opt (keys %{$conf->{pending}}) {
4232 next if $selection && !$selection->{$opt};
4233 my $value = $conf->{pending}->{$opt};
4235 if ($opt eq 'hotplug
') {
4236 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4237 } elsif ($opt eq 'tablet
') {
4238 die "skip\n" if !$hotplug_features->{usb};
4240 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4241 } elsif ($value == 0) {
4242 vm_deviceunplug($vmid, $conf, $opt);
4244 } elsif ($opt =~ m/^usb\d+$/) {
4246 # since we cannot reliably hot unplug usb devices
4247 # we are disabling it
4248 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4249 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4250 die "skip\n" if !$d;
4251 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4252 } elsif ($opt eq 'vcpus
') {
4253 die "skip\n" if !$hotplug_features->{cpu};
4254 qemu_cpu_hotplug($vmid, $conf, $value);
4255 } elsif ($opt eq 'balloon
') {
4256 # enable/disable balloning device is not hotpluggable
4257 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4258 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4259 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4261 # allow manual ballooning if shares is set to zero
4262 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4263 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4264 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4266 } elsif ($opt =~ m/^net(\d+)$/) {
4267 # some changes can be done without hotplug
4268 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4269 $vmid, $opt, $value);
4270 } elsif (is_valid_drivename($opt)) {
4271 # some changes can be done without hotplug
4272 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4273 $vmid, $opt, $value, 1);
4274 } elsif ($opt =~ m/^memory$/) { #dimms
4275 die "skip\n" if !$hotplug_features->{memory};
4276 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4277 } elsif ($opt eq 'cpuunits
') {
4278 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4279 } elsif ($opt eq 'cpulimit
') {
4280 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4281 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4283 die "skip\n"; # skip non-hot-pluggable options
4287 &$add_error($opt, $err) if $err ne "skip\n";
4289 # save new config if hotplug was successful
4290 $conf->{$opt} = $value;
4291 delete $conf->{pending}->{$opt};
4292 PVE::QemuConfig->write_config($vmid, $conf);
4293 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4298 sub try_deallocate_drive {
4299 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4301 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4302 my $volid = $drive->{file};
4303 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4304 my $sid = PVE::Storage::parse_volume_id($volid);
4305 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4307 # check if the disk is really unused
4308 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4309 if is_volume_in_use($storecfg, $conf, $key, $volid);
4310 PVE::Storage::vdisk_free($storecfg, $volid);
4313 # If vm is not owner of this disk remove from config
4321 sub vmconfig_delete_or_detach_drive {
4322 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4324 my $drive = parse_drive($opt, $conf->{$opt});
4326 my $rpcenv = PVE::RPCEnvironment::get();
4327 my $authuser = $rpcenv->get_user();
4330 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4331 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4333 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4337 sub vmconfig_apply_pending {
4338 my ($vmid, $conf, $storecfg) = @_;
4342 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4343 while (my ($opt, $force) = each %$pending_delete_hash) {
4344 die "internal error" if $opt =~ m/^unused/;
4345 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4346 if (!defined($conf->{$opt})) {
4347 vmconfig_undelete_pending_option($conf, $opt);
4348 PVE::QemuConfig->write_config($vmid, $conf);
4349 } elsif (is_valid_drivename($opt)) {
4350 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4351 vmconfig_undelete_pending_option($conf, $opt);
4352 delete $conf->{$opt};
4353 PVE::QemuConfig->write_config($vmid, $conf);
4355 vmconfig_undelete_pending_option($conf, $opt);
4356 delete $conf->{$opt};
4357 PVE::QemuConfig->write_config($vmid, $conf);
4361 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4363 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4364 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4366 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4367 # skip if nothing changed
4368 } elsif (is_valid_drivename($opt)) {
4369 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4370 if defined($conf->{$opt});
4371 $conf->{$opt} = $conf->{pending}->{$opt};
4373 $conf->{$opt} = $conf->{pending}->{$opt};
4376 delete $conf->{pending}->{$opt};
4377 PVE::QemuConfig->write_config($vmid, $conf);
4381 my $safe_num_ne = sub {
4384 return 0 if !defined($a) && !defined($b);
4385 return 1 if !defined($a);
4386 return 1 if !defined($b);
4391 my $safe_string_ne = sub {
4394 return 0 if !defined($a) && !defined($b);
4395 return 1 if !defined($a);
4396 return 1 if !defined($b);
4401 sub vmconfig_update_net {
4402 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4404 my $newnet = parse_net($value);
4406 if ($conf->{$opt}) {
4407 my $oldnet = parse_net($conf->{$opt});
4409 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4410 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4411 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4412 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4414 # for non online change, we try to hot-unplug
4415 die "skip\n" if !$hotplug;
4416 vm_deviceunplug($vmid, $conf, $opt);
4419 die "internal error" if $opt !~ m/net(\d+)/;
4420 my $iface = "tap${vmid}i$1";
4422 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4423 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4424 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4425 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4426 PVE::Network::tap_unplug($iface);
4427 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4428 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4429 # Rate can be applied on its own but any change above needs to
4430 # include the rate in tap_plug since OVS resets everything.
4431 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4434 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4435 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4443 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4449 sub vmconfig_update_disk {
4450 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4452 # fixme: do we need force?
4454 my $drive = parse_drive($opt, $value);
4456 if ($conf->{$opt}) {
4458 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4460 my $media = $drive->{media} || 'disk
';
4461 my $oldmedia = $old_drive->{media} || 'disk
';
4462 die "unable to change media type\n" if $media ne $oldmedia;
4464 if (!drive_is_cdrom($old_drive)) {
4466 if ($drive->{file} ne $old_drive->{file}) {
4468 die "skip\n" if !$hotplug;
4470 # unplug and register as unused
4471 vm_deviceunplug($vmid, $conf, $opt);
4472 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4475 # update existing disk
4477 # skip non hotpluggable value
4478 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4479 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4480 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4481 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4486 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4487 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4488 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4489 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4490 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4491 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4492 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4493 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4494 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4495 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4496 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4497 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4498 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4499 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4500 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4501 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4502 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4503 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4505 qemu_block_set_io_throttle($vmid,"drive-$opt",
4506 ($drive->{mbps} || 0)*1024*1024,
4507 ($drive->{mbps_rd} || 0)*1024*1024,
4508 ($drive->{mbps_wr} || 0)*1024*1024,
4509 $drive->{iops} || 0,
4510 $drive->{iops_rd} || 0,
4511 $drive->{iops_wr} || 0,
4512 ($drive->{mbps_max} || 0)*1024*1024,
4513 ($drive->{mbps_rd_max} || 0)*1024*1024,
4514 ($drive->{mbps_wr_max} || 0)*1024*1024,
4515 $drive->{iops_max} || 0,
4516 $drive->{iops_rd_max} || 0,
4517 $drive->{iops_wr_max} || 0,
4518 $drive->{bps_max_length} || 1,
4519 $drive->{bps_rd_max_length} || 1,
4520 $drive->{bps_wr_max_length} || 1,
4521 $drive->{iops_max_length} || 1,
4522 $drive->{iops_rd_max_length} || 1,
4523 $drive->{iops_wr_max_length} || 1);
4532 if ($drive->{file} eq 'none
') {
4533 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4535 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4536 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4537 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4545 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4547 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4548 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4552 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4553 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
4555 PVE::QemuConfig->lock_config($vmid, sub {
4556 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4558 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4560 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4562 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4564 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4565 vmconfig_apply_pending($vmid, $conf, $storecfg);
4566 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4569 my $defaults = load_defaults();
4571 # set environment variable useful inside network script
4572 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4574 my $local_volumes = {};
4576 if ($targetstorage) {
4577 foreach_drive($conf, sub {
4578 my ($ds, $drive) = @_;
4580 return if drive_is_cdrom($drive);
4582 my $volid = $drive->{file};
4586 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
4588 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4589 return if $scfg->{shared};
4590 $local_volumes->{$ds} = [$volid, $storeid, $volname];
4595 foreach my $opt (sort keys %$local_volumes) {
4597 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
4598 my $drive = parse_drive($opt, $conf->{$opt});
4600 #if remote storage is specified, use default format
4601 if ($targetstorage && $targetstorage ne "1") {
4602 $storeid = $targetstorage;
4603 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4604 $format = $defFormat;
4606 #else we use same format than original
4607 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4608 $format = qemu_img_format($scfg, $volid);
4611 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
4612 my $newdrive = $drive;
4613 $newdrive->{format} = $format;
4614 $newdrive->{file} = $newvolid;
4615 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
4616 $local_volumes->{$opt} = $drivestr;
4617 #pass drive to conf for command line
4618 $conf->{$opt} = $drivestr;
4622 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4624 my $migrate_port = 0;
4627 if ($statefile eq 'tcp
') {
4628 my $localip = "localhost";
4629 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4630 my $nodename = PVE::INotify::nodename();
4632 if (!defined($migration_type)) {
4633 if (defined($datacenterconf->{migration}->{type})) {
4634 $migration_type = $datacenterconf->{migration}->{type};
4636 $migration_type = 'secure
';
4640 if ($migration_type eq 'insecure
') {
4641 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4642 if ($migrate_network_addr) {
4643 $localip = $migrate_network_addr;
4645 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4648 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4651 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4652 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4653 $migrate_uri = "tcp:${localip}:${migrate_port}";
4654 push @$cmd, '-incoming
', $migrate_uri;
4657 } elsif ($statefile eq 'unix
') {
4658 # should be default for secure migrations as a ssh TCP forward
4659 # tunnel is not deterministic reliable ready and fails regurarly
4660 # to set up in time, so use UNIX socket forwards
4661 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4662 unlink $socket_addr;
4664 $migrate_uri = "unix:$socket_addr";
4666 push @$cmd, '-incoming
', $migrate_uri;
4670 push @$cmd, '-loadstate
', $statefile;
4677 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4678 my $d = parse_hostpci($conf->{"hostpci$i"});
4680 my $pcidevices = $d->{pciid};
4681 foreach my $pcidevice (@$pcidevices) {
4682 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4684 my $info = pci_device_info("0000:$pciid");
4685 die "IOMMU not present\n" if !check_iommu_support();
4686 die "no pci device info for device '$pciid'\n" if !$info;
4687 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4688 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4692 PVE::Storage::activate_volumes($storecfg, $vollist);
4694 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4696 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4697 eval { run_command($cmd); };
4700 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4701 : $defaults->{cpuunits};
4703 my $start_timeout = $conf->{hugepages} ? 300 : 30;
4704 my %run_params = (timeout => $statefile ? undef : $start_timeout, umask => 0077);
4707 Slice => 'qemu
.slice
',
4709 CPUShares => $cpuunits
4712 if (my $cpulimit = $conf->{cpulimit}) {
4713 $properties{CPUQuota} = int($cpulimit * 100);
4715 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4717 if ($conf->{hugepages}) {
4720 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4721 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4723 PVE::QemuServer::Memory::hugepages_mount();
4724 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4727 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4728 run_command($cmd, %run_params);
4732 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4736 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4738 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4742 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4743 run_command($cmd, %run_params);
4748 # deactivate volumes if start fails
4749 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4750 die "start failed: $err";
4753 print "migration listens on $migrate_uri\n" if $migrate_uri;
4755 if ($statefile && $statefile ne 'tcp
' && $statefile ne 'unix
') {
4756 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4760 #start nbd server for storage migration
4761 if ($targetstorage) {
4762 my $nodename = PVE::INotify::nodename();
4763 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4764 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
4765 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4766 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4768 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet
', data => { host => "${localip}", port => "${migrate_port}" } } );
4770 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4772 foreach my $opt (sort keys %$local_volumes) {
4773 my $volid = $local_volumes->{$opt};
4774 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
4775 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
4776 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
4780 if ($migratedfrom) {
4782 set_migration_caps($vmid);
4787 print "spice listens on port $spice_port\n";
4788 if ($spice_ticket) {
4789 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4790 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4795 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4796 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4797 if $conf->{balloon};
4800 foreach my $opt (keys %$conf) {
4801 next if $opt !~ m/^net\d+$/;
4802 my $nicconf = parse_net($conf->{$opt});
4803 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4807 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4808 path => "machine/peripheral/balloon0",
4809 property => "guest-stats-polling-interval",
4810 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4816 my ($vmid, $execute, %params) = @_;
4818 my $cmd = { execute => $execute, arguments => \%params };
4819 vm_qmp_command($vmid, $cmd);
4822 sub vm_mon_cmd_nocheck {
4823 my ($vmid, $execute, %params) = @_;
4825 my $cmd = { execute => $execute, arguments => \%params };
4826 vm_qmp_command($vmid, $cmd, 1);
4829 sub vm_qmp_command {
4830 my ($vmid, $cmd, $nocheck) = @_;
4835 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4836 $timeout = $cmd->{arguments}->{timeout};
4837 delete $cmd->{arguments}->{timeout};
4841 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4842 my $sname = qmp_socket($vmid);
4843 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4844 my $qmpclient = PVE::QMPClient->new();
4846 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4847 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4848 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4849 if scalar(%{$cmd->{arguments}});
4850 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4852 die "unable to
open monitor
socket\n";
4856 syslog("err
", "VM
$vmid qmp command failed
- $err");
4863 sub vm_human_monitor_command {
4864 my ($vmid, $cmdline) = @_;
4869 execute => 'human-monitor-command',
4870 arguments => { 'command-line' => $cmdline},
4873 return vm_qmp_command($vmid, $cmd);
4876 sub vm_commandline {
4877 my ($storecfg, $vmid) = @_;
4879 my $conf = PVE::QemuConfig->load_config($vmid);
4881 my $defaults = load_defaults();
4883 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4885 return PVE::Tools::cmd2string($cmd);
4889 my ($vmid, $skiplock) = @_;
4891 PVE::QemuConfig->lock_config($vmid, sub {
4893 my $conf = PVE::QemuConfig->load_config($vmid);
4895 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4897 vm_mon_cmd($vmid, "system_reset
");
4901 sub get_vm_volumes {
4905 foreach_volid($conf, sub {
4906 my ($volid, $attr) = @_;
4908 return if $volid =~ m|^/|;
4910 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4913 push @$vollist, $volid;
4919 sub vm_stop_cleanup {
4920 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4925 my $vollist = get_vm_volumes($conf);
4926 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4929 foreach my $ext (qw(mon qmp pid vnc qga)) {
4930 unlink "/var/run/qemu-server/${vmid}.$ext";
4933 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4935 warn $@ if $@; # avoid errors - just warn
4938 # Note: use $nockeck to skip tests if VM configuration file exists.
4939 # We need that when migration VMs to other nodes (files already moved)
4940 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4942 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4944 $force = 1 if !defined($force) && !$shutdown;
4947 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4948 kill 15, $pid if $pid;
4949 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4950 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4954 PVE
::QemuConfig-
>lock_config($vmid, sub {
4956 my $pid = check_running
($vmid, $nocheck);
4961 $conf = PVE
::QemuConfig-
>load_config($vmid);
4962 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4963 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4964 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4965 $timeout = $opts->{down
} if $opts->{down
};
4969 $timeout = 60 if !defined($timeout);
4973 if (defined($conf) && $conf->{agent
}) {
4974 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4976 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4979 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4986 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4991 if ($count >= $timeout) {
4993 warn "VM still running - terminating now with SIGTERM\n";
4996 die "VM quit/powerdown failed - got timeout\n";
4999 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
5004 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
5007 die "VM quit/powerdown failed\n";
5015 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
5020 if ($count >= $timeout) {
5021 warn "VM still running - terminating now with SIGKILL\n";
5026 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
5031 my ($vmid, $skiplock) = @_;
5033 PVE
::QemuConfig-
>lock_config($vmid, sub {
5035 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5037 PVE
::QemuConfig-
>check_lock($conf)
5038 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5040 vm_mon_cmd
($vmid, "stop");
5045 my ($vmid, $skiplock, $nocheck) = @_;
5047 PVE
::QemuConfig-
>lock_config($vmid, sub {
5051 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5053 PVE
::QemuConfig-
>check_lock($conf)
5054 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5056 vm_mon_cmd
($vmid, "cont");
5059 vm_mon_cmd_nocheck
($vmid, "cont");
5065 my ($vmid, $skiplock, $key) = @_;
5067 PVE
::QemuConfig-
>lock_config($vmid, sub {
5069 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5071 # there is no qmp command, so we use the human monitor command
5072 vm_human_monitor_command
($vmid, "sendkey $key");
5077 my ($storecfg, $vmid, $skiplock) = @_;
5079 PVE
::QemuConfig-
>lock_config($vmid, sub {
5081 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5083 if (!check_running
($vmid)) {
5084 destroy_vm
($storecfg, $vmid, undef, $skiplock);
5086 die "VM $vmid is running - destroy failed\n";
5094 my ($filename, $buf) = @_;
5096 my $fh = IO
::File-
>new($filename, "w");
5097 return undef if !$fh;
5099 my $res = print $fh $buf;
5106 sub pci_device_info
{
5111 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
5112 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
5114 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
5115 return undef if !defined($irq) || $irq !~ m/^\d+$/;
5117 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
5118 return undef if !defined($vendor) || $vendor !~ s/^0x//;
5120 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
5121 return undef if !defined($product) || $product !~ s/^0x//;
5126 product
=> $product,
5132 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
5141 my $name = $dev->{name
};
5143 my $fn = "$pcisysfs/devices/$name/reset";
5145 return file_write
($fn, "1");
5148 sub pci_dev_bind_to_vfio
{
5151 my $name = $dev->{name
};
5153 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5155 if (!-d
$vfio_basedir) {
5156 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5158 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5160 my $testdir = "$vfio_basedir/$name";
5161 return 1 if -d
$testdir;
5163 my $data = "$dev->{vendor} $dev->{product}";
5164 return undef if !file_write
("$vfio_basedir/new_id", $data);
5166 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5167 if (!file_write
($fn, $name)) {
5168 return undef if -f
$fn;
5171 $fn = "$vfio_basedir/bind";
5172 if (! -d
$testdir) {
5173 return undef if !file_write
($fn, $name);
5179 sub pci_dev_group_bind_to_vfio
{
5182 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5184 if (!-d
$vfio_basedir) {
5185 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5187 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5189 # get IOMMU group devices
5190 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5191 my @devs = grep /^0000:/, readdir($D);
5194 foreach my $pciid (@devs) {
5195 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5197 # pci bridges, switches or root ports are not supported
5198 # they have a pci_bus subdirectory so skip them
5199 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5201 my $info = pci_device_info
($1);
5202 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5208 # vzdump restore implementaion
5210 sub tar_archive_read_firstfile
{
5211 my $archive = shift;
5213 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5215 # try to detect archive type first
5216 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5217 die "unable to open file '$archive'\n";
5218 my $firstfile = <$fh>;
5222 die "ERROR: archive contaions no data\n" if !$firstfile;
5228 sub tar_restore_cleanup
{
5229 my ($storecfg, $statfile) = @_;
5231 print STDERR
"starting cleanup\n";
5233 if (my $fd = IO
::File-
>new($statfile, "r")) {
5234 while (defined(my $line = <$fd>)) {
5235 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5238 if ($volid =~ m
|^/|) {
5239 unlink $volid || die 'unlink failed\n';
5241 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5243 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5245 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5247 print STDERR
"unable to parse line in statfile - $line";
5254 sub restore_archive
{
5255 my ($archive, $vmid, $user, $opts) = @_;
5257 my $format = $opts->{format
};
5260 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5261 $format = 'tar' if !$format;
5263 } elsif ($archive =~ m/\.tar$/) {
5264 $format = 'tar' if !$format;
5265 } elsif ($archive =~ m/.tar.lzo$/) {
5266 $format = 'tar' if !$format;
5268 } elsif ($archive =~ m/\.vma$/) {
5269 $format = 'vma' if !$format;
5270 } elsif ($archive =~ m/\.vma\.gz$/) {
5271 $format = 'vma' if !$format;
5273 } elsif ($archive =~ m/\.vma\.lzo$/) {
5274 $format = 'vma' if !$format;
5277 $format = 'vma' if !$format; # default
5280 # try to detect archive format
5281 if ($format eq 'tar') {
5282 return restore_tar_archive
($archive, $vmid, $user, $opts);
5284 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5288 sub restore_update_config_line
{
5289 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5291 return if $line =~ m/^\#qmdump\#/;
5292 return if $line =~ m/^\#vzdump\#/;
5293 return if $line =~ m/^lock:/;
5294 return if $line =~ m/^unused\d+:/;
5295 return if $line =~ m/^parent:/;
5296 return if $line =~ m/^template:/; # restored VM is never a template
5298 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5299 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5300 # try to convert old 1.X settings
5301 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5302 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5303 my ($model, $macaddr) = split(/\=/, $devconfig);
5304 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5307 bridge
=> "vmbr$ind",
5308 macaddr
=> $macaddr,
5310 my $netstr = print_net
($net);
5312 print $outfd "net$cookie->{netcount}: $netstr\n";
5313 $cookie->{netcount
}++;
5315 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5316 my ($id, $netstr) = ($1, $2);
5317 my $net = parse_net
($netstr);
5318 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5319 $netstr = print_net
($net);
5320 print $outfd "$id: $netstr\n";
5321 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5324 my $di = parse_drive
($virtdev, $value);
5325 if (defined($di->{backup
}) && !$di->{backup
}) {
5326 print $outfd "#$line";
5327 } elsif ($map->{$virtdev}) {
5328 delete $di->{format
}; # format can change on restore
5329 $di->{file
} = $map->{$virtdev};
5330 $value = print_drive
($vmid, $di);
5331 print $outfd "$virtdev: $value\n";
5341 my ($cfg, $vmid) = @_;
5343 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5345 my $volid_hash = {};
5346 foreach my $storeid (keys %$info) {
5347 foreach my $item (@{$info->{$storeid}}) {
5348 next if !($item->{volid
} && $item->{size
});
5349 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5350 $volid_hash->{$item->{volid
}} = $item;
5357 sub is_volume_in_use
{
5358 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5360 my $path = PVE
::Storage
::path
($storecfg, $volid);
5362 my $scan_config = sub {
5363 my ($cref, $snapname) = @_;
5365 foreach my $key (keys %$cref) {
5366 my $value = $cref->{$key};
5367 if (is_valid_drivename
($key)) {
5368 next if $skip_drive && $key eq $skip_drive;
5369 my $drive = parse_drive
($key, $value);
5370 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5371 return 1 if $volid eq $drive->{file
};
5372 if ($drive->{file
} =~ m!^/!) {
5373 return 1 if $drive->{file
} eq $path;
5375 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5377 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5379 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5387 return 1 if &$scan_config($conf);
5391 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5392 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5398 sub update_disksize
{
5399 my ($vmid, $conf, $volid_hash) = @_;
5403 # used and unused disks
5404 my $referenced = {};
5406 # Note: it is allowed to define multiple storages with same path (alias), so
5407 # we need to check both 'volid' and real 'path' (two different volid can point
5408 # to the same path).
5410 my $referencedpath = {};
5413 foreach my $opt (keys %$conf) {
5414 if (is_valid_drivename
($opt)) {
5415 my $drive = parse_drive
($opt, $conf->{$opt});
5416 my $volid = $drive->{file
};
5419 $referenced->{$volid} = 1;
5420 if ($volid_hash->{$volid} &&
5421 (my $path = $volid_hash->{$volid}->{path
})) {
5422 $referencedpath->{$path} = 1;
5425 next if drive_is_cdrom
($drive);
5426 next if !$volid_hash->{$volid};
5428 $drive->{size
} = $volid_hash->{$volid}->{size
};
5429 my $new = print_drive
($vmid, $drive);
5430 if ($new ne $conf->{$opt}) {
5432 $conf->{$opt} = $new;
5437 # remove 'unusedX' entry if volume is used
5438 foreach my $opt (keys %$conf) {
5439 next if $opt !~ m/^unused\d+$/;
5440 my $volid = $conf->{$opt};
5441 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5442 if ($referenced->{$volid} || ($path && $referencedpath->{$path})) {
5444 delete $conf->{$opt};
5447 $referenced->{$volid} = 1;
5448 $referencedpath->{$path} = 1 if $path;
5451 foreach my $volid (sort keys %$volid_hash) {
5452 next if $volid =~ m/vm-$vmid-state-/;
5453 next if $referenced->{$volid};
5454 my $path = $volid_hash->{$volid}->{path
};
5455 next if !$path; # just to be sure
5456 next if $referencedpath->{$path};
5458 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5459 $referencedpath->{$path} = 1; # avoid to add more than once (aliases)
5466 my ($vmid, $nolock) = @_;
5468 my $cfg = PVE
::Storage
::config
();
5470 my $volid_hash = scan_volids
($cfg, $vmid);
5472 my $updatefn = sub {
5475 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5477 PVE
::QemuConfig-
>check_lock($conf);
5480 foreach my $volid (keys %$volid_hash) {
5481 my $info = $volid_hash->{$volid};
5482 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5485 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5487 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5490 if (defined($vmid)) {
5494 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5497 my $vmlist = config_list
();
5498 foreach my $vmid (keys %$vmlist) {
5502 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5508 sub restore_vma_archive
{
5509 my ($archive, $vmid, $user, $opts, $comp) = @_;
5511 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5512 my $readfrom = $archive;
5517 my $qarchive = PVE
::Tools
::shellquote
($archive);
5518 if ($comp eq 'gzip') {
5519 $uncomp = "zcat $qarchive|";
5520 } elsif ($comp eq 'lzop') {
5521 $uncomp = "lzop -d -c $qarchive|";
5523 die "unknown compression method '$comp'\n";
5528 my $tmpdir = "/var/tmp/vzdumptmp$$";
5531 # disable interrupts (always do cleanups)
5535 local $SIG{HUP
} = sub { warn "got interrupt - ignored\n"; };
5537 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5538 POSIX
::mkfifo
($mapfifo, 0600);
5541 my $openfifo = sub {
5542 open($fifofh, '>', $mapfifo) || die $!;
5545 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5552 my $rpcenv = PVE
::RPCEnvironment
::get
();
5554 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5555 my $tmpfn = "$conffile.$$.tmp";
5557 # Note: $oldconf is undef if VM does not exists
5558 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5559 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5561 my $print_devmap = sub {
5562 my $virtdev_hash = {};
5564 my $cfgfn = "$tmpdir/qemu-server.conf";
5566 # we can read the config - that is already extracted
5567 my $fh = IO
::File-
>new($cfgfn, "r") ||
5568 "unable to read qemu-server.conf - $!\n";
5570 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5572 my $pve_firewall_dir = '/etc/pve/firewall';
5573 mkdir $pve_firewall_dir; # make sure the dir exists
5574 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5577 while (defined(my $line = <$fh>)) {
5578 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5579 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5580 die "archive does not contain data for drive '$virtdev'\n"
5581 if !$devinfo->{$devname};
5582 if (defined($opts->{storage
})) {
5583 $storeid = $opts->{storage
} || 'local';
5584 } elsif (!$storeid) {
5587 $format = 'raw' if !$format;
5588 $devinfo->{$devname}->{devname
} = $devname;
5589 $devinfo->{$devname}->{virtdev
} = $virtdev;
5590 $devinfo->{$devname}->{format
} = $format;
5591 $devinfo->{$devname}->{storeid
} = $storeid;
5593 # check permission on storage
5594 my $pool = $opts->{pool
}; # todo: do we need that?
5595 if ($user ne 'root@pam') {
5596 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5599 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5603 foreach my $devname (keys %$devinfo) {
5604 die "found no device mapping information for device '$devname'\n"
5605 if !$devinfo->{$devname}->{virtdev
};
5608 my $cfg = PVE
::Storage
::config
();
5610 # create empty/temp config
5612 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5613 foreach_drive
($oldconf, sub {
5614 my ($ds, $drive) = @_;
5616 return if drive_is_cdrom
($drive);
5618 my $volid = $drive->{file
};
5620 return if !$volid || $volid =~ m
|^/|;
5622 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5623 return if !$path || !$owner || ($owner != $vmid);
5625 # Note: only delete disk we want to restore
5626 # other volumes will become unused
5627 if ($virtdev_hash->{$ds}) {
5628 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5635 # delete vmstate files
5636 # since after the restore we have no snapshots anymore
5637 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5638 my $snap = $oldconf->{snapshots
}->{$snapname};
5639 if ($snap->{vmstate
}) {
5640 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5649 foreach my $virtdev (sort keys %$virtdev_hash) {
5650 my $d = $virtdev_hash->{$virtdev};
5651 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5652 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5654 # test if requested format is supported
5655 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5656 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5657 $d->{format
} = $defFormat if !$supported;
5659 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5660 $d->{format
}, undef, $alloc_size);
5661 print STDERR
"new volume ID is '$volid'\n";
5662 $d->{volid
} = $volid;
5663 my $path = PVE
::Storage
::path
($cfg, $volid);
5665 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5667 my $write_zeros = 1;
5668 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5672 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5674 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5675 $map->{$virtdev} = $volid;
5678 $fh->seek(0, 0) || die "seek failed - $!\n";
5680 my $outfd = new IO
::File
($tmpfn, "w") ||
5681 die "unable to write config for VM $vmid\n";
5683 my $cookie = { netcount
=> 0 };
5684 while (defined(my $line = <$fh>)) {
5685 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5698 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5699 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5701 $oldtimeout = alarm($timeout);
5708 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5709 my ($dev_id, $size, $devname) = ($1, $2, $3);
5710 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5711 } elsif ($line =~ m/^CTIME: /) {
5712 # we correctly received the vma config, so we can disable
5713 # the timeout now for disk allocation (set to 10 minutes, so
5714 # that we always timeout if something goes wrong)
5717 print $fifofh "done\n";
5718 my $tmp = $oldtimeout || 0;
5719 $oldtimeout = undef;
5725 print "restore vma archive: $cmd\n";
5726 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5730 alarm($oldtimeout) if $oldtimeout;
5733 foreach my $devname (keys %$devinfo) {
5734 my $volid = $devinfo->{$devname}->{volid
};
5735 push @$vollist, $volid if $volid;
5738 my $cfg = PVE
::Storage
::config
();
5739 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5747 foreach my $devname (keys %$devinfo) {
5748 my $volid = $devinfo->{$devname}->{volid
};
5751 if ($volid =~ m
|^/|) {
5752 unlink $volid || die 'unlink failed\n';
5754 PVE
::Storage
::vdisk_free
($cfg, $volid);
5756 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5758 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5765 rename($tmpfn, $conffile) ||
5766 die "unable to commit configuration file '$conffile'\n";
5768 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5770 eval { rescan
($vmid, 1); };
5774 sub restore_tar_archive
{
5775 my ($archive, $vmid, $user, $opts) = @_;
5777 if ($archive ne '-') {
5778 my $firstfile = tar_archive_read_firstfile
($archive);
5779 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5780 if $firstfile ne 'qemu-server.conf';
5783 my $storecfg = PVE
::Storage
::config
();
5785 # destroy existing data - keep empty config
5786 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5787 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5789 my $tocmd = "/usr/lib/qemu-server/qmextract";
5791 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5792 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5793 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5794 $tocmd .= ' --info' if $opts->{info
};
5796 # tar option "xf" does not autodetect compression when read from STDIN,
5797 # so we pipe to zcat
5798 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5799 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5801 my $tmpdir = "/var/tmp/vzdumptmp$$";
5804 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5805 local $ENV{VZDUMP_VMID
} = $vmid;
5806 local $ENV{VZDUMP_USER
} = $user;
5808 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5809 my $tmpfn = "$conffile.$$.tmp";
5811 # disable interrupts (always do cleanups)
5815 local $SIG{HUP
} = sub { print STDERR
"got interrupt - ignored\n"; };
5823 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5825 if ($archive eq '-') {
5826 print "extracting archive from STDIN\n";
5827 run_command
($cmd, input
=> "<&STDIN");
5829 print "extracting archive '$archive'\n";
5833 return if $opts->{info
};
5837 my $statfile = "$tmpdir/qmrestore.stat";
5838 if (my $fd = IO
::File-
>new($statfile, "r")) {
5839 while (defined (my $line = <$fd>)) {
5840 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5841 $map->{$1} = $2 if $1;
5843 print STDERR
"unable to parse line in statfile - $line\n";
5849 my $confsrc = "$tmpdir/qemu-server.conf";
5851 my $srcfd = new IO
::File
($confsrc, "r") ||
5852 die "unable to open file '$confsrc'\n";
5854 my $outfd = new IO
::File
($tmpfn, "w") ||
5855 die "unable to write config for VM $vmid\n";
5857 my $cookie = { netcount
=> 0 };
5858 while (defined (my $line = <$srcfd>)) {
5859 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5871 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5878 rename $tmpfn, $conffile ||
5879 die "unable to commit configuration file '$conffile'\n";
5881 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5883 eval { rescan
($vmid, 1); };
5887 sub foreach_storage_used_by_vm
{
5888 my ($conf, $func) = @_;
5892 foreach_drive
($conf, sub {
5893 my ($ds, $drive) = @_;
5894 return if drive_is_cdrom
($drive);
5896 my $volid = $drive->{file
};
5898 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5899 $sidhash->{$sid} = $sid if $sid;
5902 foreach my $sid (sort keys %$sidhash) {
5907 sub do_snapshots_with_qemu
{
5908 my ($storecfg, $volid) = @_;
5910 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5912 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5913 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5917 if ($volid =~ m/\.(qcow2|qed)$/){
5924 sub qga_check_running
{
5927 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5929 warn "Qemu Guest Agent is not running - $@";
5935 sub template_create
{
5936 my ($vmid, $conf, $disk) = @_;
5938 my $storecfg = PVE
::Storage
::config
();
5940 foreach_drive
($conf, sub {
5941 my ($ds, $drive) = @_;
5943 return if drive_is_cdrom
($drive);
5944 return if $disk && $ds ne $disk;
5946 my $volid = $drive->{file
};
5947 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5949 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5950 $drive->{file
} = $voliddst;
5951 $conf->{$ds} = print_drive
($vmid, $drive);
5952 PVE
::QemuConfig-
>write_config($vmid, $conf);
5956 sub qemu_img_convert
{
5957 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5959 my $storecfg = PVE
::Storage
::config
();
5960 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5961 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5963 if ($src_storeid && $dst_storeid) {
5965 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5967 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5968 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5970 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5971 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5973 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5974 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5977 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5978 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5979 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5980 if ($is_zero_initialized) {
5981 push @$cmd, "zeroinit:$dst_path";
5983 push @$cmd, $dst_path;
5988 if($line =~ m/\((\S+)\/100\
%\)/){
5990 my $transferred = int($size * $percent / 100);
5991 my $remaining = $size - $transferred;
5993 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5998 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6000 die "copy failed: $err" if $err;
6004 sub qemu_img_format
{
6005 my ($scfg, $volname) = @_;
6007 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6014 sub qemu_drive_mirror
{
6015 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
6017 $jobs = {} if !$jobs;
6021 $jobs->{"drive-$drive"} = {};
6023 if ($dst_volid =~ /^nbd:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+):exportname=(\S+)/) {
6026 my $exportname = $3;
6029 my $unixsocket = "/run/qemu-server/$vmid.mirror-drive-$drive";
6030 $qemu_target = "nbd+unix:///$exportname?socket=$unixsocket";
6031 my $cmd = ['socat', '-T30', "UNIX-LISTEN:$unixsocket,fork", "TCP:$server:$2,connect-timeout=5"];
6034 if (!defined($pid)) {
6035 die "forking socat tunnel failed\n";
6036 } elsif ($pid == 0) {
6038 warn "exec failed: $!\n";
6041 $jobs->{"drive-$drive"}->{pid
} = $pid;
6044 while (!-S
$unixsocket) {
6045 die "nbd connection helper timed out\n"
6050 my $storecfg = PVE
::Storage
::config
();
6051 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6053 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6055 $format = qemu_img_format
($dst_scfg, $dst_volname);
6057 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6059 $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
6062 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
6063 $opts->{format
} = $format if $format;
6065 print "drive mirror is starting for drive-$drive\n";
6067 eval { vm_mon_cmd
($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
6070 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6071 die "mirroring error: $err";
6074 qemu_drive_mirror_monitor
($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
6077 sub qemu_drive_mirror_monitor
{
6078 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
6081 my $err_complete = 0;
6084 die "storage migration timed out\n" if $err_complete > 300;
6086 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6088 my $running_mirror_jobs = {};
6089 foreach my $stat (@$stats) {
6090 next if $stat->{type
} ne 'mirror';
6091 $running_mirror_jobs->{$stat->{device
}} = $stat;
6094 my $readycounter = 0;
6096 foreach my $job (keys %$jobs) {
6098 if(defined($jobs->{$job}->{complete
}) && !defined($running_mirror_jobs->{$job})) {
6099 print "$job : finished\n";
6100 delete $jobs->{$job};
6104 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
6106 my $busy = $running_mirror_jobs->{$job}->{busy
};
6107 my $ready = $running_mirror_jobs->{$job}->{ready
};
6108 if (my $total = $running_mirror_jobs->{$job}->{len
}) {
6109 my $transferred = $running_mirror_jobs->{$job}->{offset
} || 0;
6110 my $remaining = $total - $transferred;
6111 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6113 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6116 $readycounter++ if $running_mirror_jobs->{$job}->{ready
};
6119 last if scalar(keys %$jobs) == 0;
6121 if ($readycounter == scalar(keys %$jobs)) {
6122 print "all mirroring jobs are ready \n";
6123 last if $skipcomplete; #do the complete later
6125 if ($vmiddst && $vmiddst != $vmid) {
6126 my $agent_running = $qga && qga_check_running
($vmid);
6127 if ($agent_running) {
6128 print "freeze filesystem\n";
6129 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6131 print "suspend vm\n";
6132 eval { PVE
::QemuServer
::vm_suspend
($vmid, 1); };
6135 # if we clone a disk for a new target vm, we don't switch the disk
6136 PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs);
6138 if ($agent_running) {
6139 print "unfreeze filesystem\n";
6140 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6142 print "resume vm\n";
6143 eval { PVE
::QemuServer
::vm_resume
($vmid, 1, 1); };
6149 foreach my $job (keys %$jobs) {
6150 # try to switch the disk if source and destination are on the same guest
6151 print "$job: Completing block job...\n";
6153 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> $job) };
6154 if ($@ =~ m/cannot be completed/) {
6155 print "$job: Block job cannot be completed, try again.\n";
6158 print "$job: Completed successfully.\n";
6159 $jobs->{$job}->{complete
} = 1;
6160 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6171 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6172 die "mirroring error: $err";
6177 sub qemu_blockjobs_cancel
{
6178 my ($vmid, $jobs) = @_;
6180 foreach my $job (keys %$jobs) {
6181 print "$job: Cancelling block job\n";
6182 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> $job); };
6183 $jobs->{$job}->{cancel
} = 1;
6187 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6189 my $running_jobs = {};
6190 foreach my $stat (@$stats) {
6191 $running_jobs->{$stat->{device
}} = $stat;
6194 foreach my $job (keys %$jobs) {
6196 if (defined($jobs->{$job}->{cancel
}) && !defined($running_jobs->{$job})) {
6197 print "$job: Done.\n";
6198 eval { qemu_blockjobs_finish_tunnel
($vmid, $job, $jobs->{$job}->{pid
}) } ;
6199 delete $jobs->{$job};
6203 last if scalar(keys %$jobs) == 0;
6209 sub qemu_blockjobs_finish_tunnel
{
6210 my ($vmid, $job, $cpid) = @_;
6214 for (my $i = 1; $i < 20; $i++) {
6215 my $waitpid = waitpid($cpid, WNOHANG
);
6216 last if (defined($waitpid) && ($waitpid == $cpid));
6220 } elsif ($i >= 15) {
6225 unlink "/run/qemu-server/$vmid.mirror-$job";
6229 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6230 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
6235 print "create linked clone of drive $drivename ($drive->{file})\n";
6236 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6237 push @$newvollist, $newvolid;
6240 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6241 $storeid = $storage if $storage;
6243 my $dst_format = resolve_dst_disk_format
($storecfg, $storeid, $volname, $format);
6244 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6246 print "create full clone of drive $drivename ($drive->{file})\n";
6247 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $dst_format, undef, ($size/1024));
6248 push @$newvollist, $newvolid;
6250 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
6252 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6253 if (!$running || $snapname) {
6254 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6257 my $kvmver = get_running_qemu_version
($vmid);
6258 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
6259 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6260 if $drive->{iothread
};
6263 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
6267 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6270 $disk->{format
} = undef;
6271 $disk->{file
} = $newvolid;
6272 $disk->{size
} = $size;
6277 # this only works if VM is running
6278 sub get_current_qemu_machine
{
6281 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6282 my $res = vm_qmp_command
($vmid, $cmd);
6284 my ($current, $default);
6285 foreach my $e (@$res) {
6286 $default = $e->{name
} if $e->{'is-default'};
6287 $current = $e->{name
} if $e->{'is-current'};
6290 # fallback to the default machine if current is not supported by qemu
6291 return $current || $default || 'pc';
6294 sub get_running_qemu_version
{
6296 my $cmd = { execute
=> 'query-version', arguments
=> {} };
6297 my $res = vm_qmp_command
($vmid, $cmd);
6298 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6301 sub qemu_machine_feature_enabled
{
6302 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6307 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6309 $current_major = $3;
6310 $current_minor = $4;
6312 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6314 $current_major = $1;
6315 $current_minor = $2;
6318 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6323 sub qemu_machine_pxe
{
6324 my ($vmid, $conf, $machine) = @_;
6326 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6328 foreach my $opt (keys %$conf) {
6329 next if $opt !~ m/^net(\d+)$/;
6330 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6332 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6333 return $machine.".pxe" if $romfile =~ m/pxe/;
6340 sub qemu_use_old_bios_files
{
6341 my ($machine_type) = @_;
6343 return if !$machine_type;
6345 my $use_old_bios_files = undef;
6347 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6349 $use_old_bios_files = 1;
6351 my $kvmver = kvm_user_version
();
6352 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6353 # load new efi bios files on migration. So this hack is required to allow
6354 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6355 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6356 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6359 return ($use_old_bios_files, $machine_type);
6362 sub create_efidisk
{
6363 my ($storecfg, $storeid, $vmid, $fmt) = @_;
6365 die "EFI vars default image not found\n" if ! -f
$OVMF_VARS;
6367 my $vars_size = PVE
::Tools
::convert_size
(-s
$OVMF_VARS, 'b' => 'kb');
6368 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
6369 PVE
::Storage
::activate_volumes
($storecfg, [$volid]);
6371 my $path = PVE
::Storage
::path
($storecfg, $volid);
6373 run_command
(['/usr/bin/qemu-img', 'convert', '-n', '-f', 'raw', '-O', $fmt, $OVMF_VARS, $path]);
6375 die "Copying EFI vars image failed: $@" if $@;
6377 return ($volid, $vars_size);
6384 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6385 my (undef, $id, $function) = @_;
6386 my $res = { id
=> $id, function
=> $function};
6387 push @{$devices->{$id}}, $res;
6390 # Entries should be sorted by functions.
6391 foreach my $id (keys %$devices) {
6392 my $dev = $devices->{$id};
6393 $devices->{$id} = [ sort { $a->{function
} <=> $b->{function
} } @$dev ];
6399 sub vm_iothreads_list
{
6402 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6405 foreach my $iothread (@$res) {
6406 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6413 my ($conf, $drive) = @_;
6417 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)) {
6419 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6425 my $controller = int($drive->{index} / $maxdev);
6426 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6428 return ($maxdev, $controller, $controller_prefix);
6431 sub add_hyperv_enlightenments
{
6432 my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough) = @_;
6434 return if $winversion < 6;
6435 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6437 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6439 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
6440 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6441 push @$cpuFlags , 'hv_vapic';
6442 push @$cpuFlags , 'hv_time';
6444 push @$cpuFlags , 'hv_spinlocks=0xffff';
6447 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
6448 push @$cpuFlags , 'hv_reset';
6449 push @$cpuFlags , 'hv_vpindex';
6450 push @$cpuFlags , 'hv_runtime';
6453 if ($winversion >= 7) {
6454 push @$cpuFlags , 'hv_relaxed';
6458 sub windows_version
{
6461 return 0 if !$ostype;
6465 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6467 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6469 } elsif ($ostype =~ m/^win(\d+)$/) {
6476 sub resolve_dst_disk_format
{
6477 my ($storecfg, $storeid, $src_volname, $format) = @_;
6478 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6481 # if no target format is specified, use the source disk format as hint
6483 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6484 $format = qemu_img_format
($scfg, $src_volname);
6490 # test if requested format is supported - else use default
6491 my $supported = grep { $_ eq $format } @$validFormats;
6492 $format = $defFormat if !$supported;
6496 sub resolve_first_disk
{
6498 my @disks = PVE
::QemuServer
::valid_drive_names
();
6500 foreach my $ds (reverse @disks) {
6501 next if !$conf->{$ds};
6502 my $disk = PVE
::QemuServer
::parse_drive
($ds, $conf->{$ds});
6503 next if PVE
::QemuServer
::drive_is_cdrom
($disk);
6509 sub generate_smbios1_uuid
{
6510 my ($uuid, $uuid_str);
6511 UUID
::generate
($uuid);
6512 UUID
::unparse
($uuid, $uuid_str);
6513 return "uuid=$uuid_str";
6516 # bash completion helper
6518 sub complete_backup_archives
{
6519 my ($cmdname, $pname, $cvalue) = @_;
6521 my $cfg = PVE
::Storage
::config
();
6525 if ($cvalue =~ m/^([^:]+):/) {
6529 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6532 foreach my $id (keys %$data) {
6533 foreach my $item (@{$data->{$id}}) {
6534 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6535 push @$res, $item->{volid
} if defined($item->{volid
});
6542 my $complete_vmid_full = sub {
6545 my $idlist = vmstatus
();
6549 foreach my $id (keys %$idlist) {
6550 my $d = $idlist->{$id};
6551 if (defined($running)) {
6552 next if $d->{template
};
6553 next if $running && $d->{status
} ne 'running';
6554 next if !$running && $d->{status
} eq 'running';
6563 return &$complete_vmid_full();
6566 sub complete_vmid_stopped
{
6567 return &$complete_vmid_full(0);
6570 sub complete_vmid_running
{
6571 return &$complete_vmid_full(1);
6574 sub complete_storage
{
6576 my $cfg = PVE
::Storage
::config
();
6577 my $ids = $cfg->{ids
};
6580 foreach my $sid (keys %$ids) {
6581 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6582 next if !$ids->{$sid}->{content
}->{images
};
6592 vm_mon_cmd
($vmid, 'nbd-server-stop');