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 $IPV6RE);
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 PVE
::QemuServer
::Cloudinit
;
37 use Time
::HiRes
qw(gettimeofday);
38 use File
::Copy
qw(copy);
41 my $OVMF_CODE = '/usr/share/kvm/OVMF_CODE-pure-efi.fd';
42 my $OVMF_VARS = '/usr/share/kvm/OVMF_VARS-pure-efi.fd';
44 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
46 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
48 my $QEMU_FORMAT_RE = qr/raw|cow|qcow|qcow2|qed|vmdk|cloop/;
50 # Note about locking: we use flock on the config file protect
51 # against concurent actions.
52 # Aditionaly, we have a 'lock' setting in the config file. This
53 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
54 # allowed when such lock is set. But you can ignore this kind of
55 # lock with the --skiplock flag.
57 cfs_register_file
('/qemu-server/',
61 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
62 description
=> "Some command save/restore state from this location.",
68 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
69 description
=> "The name of the snapshot.",
70 type
=> 'string', format
=> 'pve-configid',
74 PVE
::JSONSchema
::register_standard_option
('pve-qm-image-format', {
76 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
77 description
=> "The drive's backing file's data format.",
81 #no warnings 'redefine';
84 my ($controller, $vmid, $option, $value) = @_;
86 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
87 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
91 my $nodename = PVE
::INotify
::nodename
();
93 mkdir "/etc/pve/nodes/$nodename";
94 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
97 my $var_run_tmpdir = "/var/run/qemu-server";
98 mkdir $var_run_tmpdir;
100 my $lock_dir = "/var/lock/qemu-server";
103 my $pcisysfs = "/sys/bus/pci";
105 my $cpu_vendor_list = {
107 486 => 'GenuineIntel',
108 pentium
=> 'GenuineIntel',
109 pentium2
=> 'GenuineIntel',
110 pentium3
=> 'GenuineIntel',
111 coreduo
=> 'GenuineIntel',
112 core2duo
=> 'GenuineIntel',
113 Conroe
=> 'GenuineIntel',
114 Penryn
=> 'GenuineIntel',
115 Nehalem
=> 'GenuineIntel',
116 'Nehalem-IBRS' => 'GenuineIntel',
117 Westmere
=> 'GenuineIntel',
118 'Westmere-IBRS' => 'GenuineIntel',
119 SandyBridge
=> 'GenuineIntel',
120 'SandyBridge-IBRS' => 'GenuineIntel',
121 IvyBridge
=> 'GenuineIntel',
122 'IvyBridge-IBRS' => 'GenuineIntel',
123 Haswell
=> 'GenuineIntel',
124 'Haswell-IBRS' => 'GenuineIntel',
125 'Haswell-noTSX' => 'GenuineIntel',
126 'Haswell-noTSX-IBRS' => 'GenuineIntel',
127 Broadwell
=> 'GenuineIntel',
128 'Broadwell-IBRS' => 'GenuineIntel',
129 'Broadwell-noTSX' => 'GenuineIntel',
130 'Broadwell-noTSX-IBRS' => 'GenuineIntel',
131 'Skylake-Client' => 'GenuineIntel',
132 'Skylake-Client-IBRS' => 'GenuineIntel',
133 'Skylake-Server' => 'GenuineIntel',
134 'Skylake-Server-IBRS' => 'GenuineIntel',
137 athlon
=> 'AuthenticAMD',
138 phenom
=> 'AuthenticAMD',
139 Opteron_G1
=> 'AuthenticAMD',
140 Opteron_G2
=> 'AuthenticAMD',
141 Opteron_G3
=> 'AuthenticAMD',
142 Opteron_G4
=> 'AuthenticAMD',
143 Opteron_G5
=> 'AuthenticAMD',
144 EPYC
=> 'AuthenticAMD',
145 'EPYC-IBPB' => 'AuthenticAMD',
147 # generic types, use vendor from host node
156 my $cpu_flag = qr/[+-](pcid|spec-ctrl)/;
160 description
=> "Emulated CPU type.",
162 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
167 description
=> "Do not identify as a KVM virtual machine.",
173 description
=> "List of additional CPU flags separated by ';'."
174 . " Use '+FLAG' to enable, '-FLAG' to disable a flag."
175 . " Currently supported flags: 'pcid', 'spec-ctrl'.",
176 format_description
=> '+FLAG[;-FLAG...]',
178 pattern
=> qr/$cpu_flag(;$cpu_flag)*/,
187 enum
=> [qw(i6300esb ib700)],
188 description
=> "Watchdog type to emulate.",
189 default => 'i6300esb',
194 enum
=> [qw(reset shutdown poweroff pause debug none)],
195 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
199 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
205 description
=> "Specifies whether a VM will be started during system bootup.",
211 description
=> "Automatic restart after crash (currently ignored).",
216 type
=> 'string', format
=> 'pve-hotplug-features',
217 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'.",
218 default => 'network,disk,usb',
223 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
229 description
=> "Lock/unlock the VM.",
230 enum
=> [qw(migrate backup snapshot rollback)],
235 description
=> "Limit of CPU usage.",
236 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.",
244 description
=> "CPU weight for a VM.",
245 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.",
253 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
260 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
266 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",
274 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.".
275 "It should not be necessary to set it.",
276 enum
=> PVE
::Tools
::kvmkeymaplist
(),
281 type
=> 'string', format
=> 'dns-name',
282 description
=> "Set a name for the VM. Only used on the configuration web interface.",
287 description
=> "SCSI controller model",
288 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
294 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
299 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 win10 l24 l26 solaris)],
300 description
=> "Specify guest operating system.",
301 verbose_description
=> <<EODESC,
302 Specify guest operating system. This is used to enable special
303 optimization/features for specific operating systems:
306 other;; unspecified OS
307 wxp;; Microsoft Windows XP
308 w2k;; Microsoft Windows 2000
309 w2k3;; Microsoft Windows 2003
310 w2k8;; Microsoft Windows 2008
311 wvista;; Microsoft Windows Vista
312 win7;; Microsoft Windows 7
313 win8;; Microsoft Windows 8/2012/2012r2
314 win10;; Microsoft Windows 10/2016
315 l24;; Linux 2.4 Kernel
316 l26;; Linux 2.6/3.X Kernel
317 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
323 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
324 pattern
=> '[acdn]{1,4}',
329 type
=> 'string', format
=> 'pve-qm-bootdisk',
330 description
=> "Enable booting from specified disk.",
331 pattern
=> '(ide|sata|scsi|virtio)\d+',
336 description
=> "The number of CPUs. Please use option -sockets instead.",
343 description
=> "The number of CPU sockets.",
350 description
=> "The number of cores per socket.",
357 description
=> "Enable/disable NUMA.",
363 description
=> "Enable/disable hugepages memory.",
364 enum
=> [qw(any 2 1024)],
369 description
=> "Number of hotplugged vcpus.",
376 description
=> "Enable/disable ACPI.",
382 description
=> "Enable/disable Qemu GuestAgent.",
388 description
=> "Enable/disable KVM hardware virtualization.",
394 description
=> "Enable/disable time drift fix.",
400 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
405 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
410 description
=> "Select the VGA type.",
411 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
412 " modes (>= 1280x1024x16) then you should use the options " .
413 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
414 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
415 "display sever. For win* OS you can select how many independent " .
416 "displays you want, Linux guests can add displays them self. " .
417 "You can also run without any graphic card, using a serial device" .
419 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
423 type
=> 'string', format
=> 'pve-qm-watchdog',
424 description
=> "Create a virtual hardware watchdog device.",
425 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
426 " (by a guest action), the watchdog must be periodically polled " .
427 "by an agent inside the guest or else the watchdog will reset " .
428 "the guest (or execute the respective action specified)",
433 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
434 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'.",
435 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
438 startup
=> get_standard_option
('pve-startup-order'),
442 description
=> "Enable/disable Template.",
448 description
=> "Arbitrary arguments passed to kvm.",
449 verbose_description
=> <<EODESCR,
450 Arbitrary arguments passed to kvm, for example:
452 args: -no-reboot -no-hpet
454 NOTE: this option is for experts only.
461 description
=> "Enable/disable the USB tablet device.",
462 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
463 "usually needed to allow absolute mouse positioning with VNC. " .
464 "Else the mouse runs out of sync with normal VNC clients. " .
465 "If you're running lots of console-only guests on one host, " .
466 "you may consider disabling this to save some context switches. " .
467 "This is turned off by default if you use spice (-vga=qxl).",
472 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
476 migrate_downtime
=> {
479 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
485 type
=> 'string', format
=> 'pve-qm-ide',
486 typetext
=> '<volume>',
487 description
=> "This is an alias for option -ide2",
491 description
=> "Emulated CPU type.",
495 parent
=> get_standard_option
('pve-snapshot-name', {
497 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
501 description
=> "Timestamp for snapshots.",
507 type
=> 'string', format
=> 'pve-volume-id',
508 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
510 vmstatestorage
=> get_standard_option
('pve-storage-id', {
511 description
=> "Default storage for VM state volumes/files.",
515 description
=> "Specific the Qemu machine type.",
517 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
522 description
=> "Specify SMBIOS type 1 fields.",
523 type
=> 'string', format
=> 'pve-qm-smbios1',
530 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
536 enum
=> [ qw(seabios ovmf) ],
537 description
=> "Select BIOS implementation.",
538 default => 'seabios',
542 my $confdesc_cloudinit = {
546 description
=> 'Specifies the cloud-init configuration format. The default depends on the configured operating system type (`ostype`. We use the `nocloud` format for Linux, and `configdrive2` for windows.',
547 enum
=> ['configdrive2', 'nocloud'],
552 description
=> "cloud-init: User name to change ssh keys and password for instead of the image's configured default user.",
557 description
=> 'cloud-init: Password to assign the user. Using this is generally not recommended. Use ssh keys instead. Also note that older cloud-init versions do not support hashed passwords.',
562 description
=> "cloud-init: Sets DNS search domains for a container. Create will automatically use the setting from the host if neither searchdomain nor nameserver are set.",
566 type
=> 'string', format
=> 'address-list',
567 description
=> "cloud-init: Sets DNS server IP address for a container. Create will automatically use the setting from the host if neither searchdomain nor nameserver are set.",
572 format
=> 'urlencoded',
573 description
=> "cloud-init: Setup public SSH keys (one key per line, OpenSSH format).",
577 # what about other qemu settings ?
579 #machine => 'string',
592 ##soundhw => 'string',
594 while (my ($k, $v) = each %$confdesc) {
595 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
598 my $MAX_IDE_DISKS = 4;
599 my $MAX_SCSI_DISKS = 14;
600 my $MAX_VIRTIO_DISKS = 16;
601 my $MAX_SATA_DISKS = 6;
602 my $MAX_USB_DEVICES = 5;
604 my $MAX_UNUSED_DISKS = 8;
605 my $MAX_HOSTPCI_DEVICES = 4;
606 my $MAX_SERIAL_PORTS = 4;
607 my $MAX_PARALLEL_PORTS = 3;
613 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
614 description
=> "CPUs accessing this NUMA node.",
615 format_description
=> "id[-id];...",
619 description
=> "Amount of memory this NUMA node provides.",
624 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
625 description
=> "Host NUMA nodes to use.",
626 format_description
=> "id[-id];...",
631 enum
=> [qw(preferred bind interleave)],
632 description
=> "NUMA allocation policy.",
636 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
639 type
=> 'string', format
=> $numa_fmt,
640 description
=> "NUMA topology.",
642 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
644 for (my $i = 0; $i < $MAX_NUMA; $i++) {
645 $confdesc->{"numa$i"} = $numadesc;
648 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
649 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
650 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
651 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
653 my $net_fmt_bridge_descr = <<__EOD__;
654 Bridge to attach the network device to. The Proxmox VE standard bridge
657 If you do not specify a bridge, we create a kvm user (NATed) network
658 device, which provides DHCP and DNS services. The following addresses
665 The DHCP server assign addresses to the guest starting from 10.0.2.15.
671 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
672 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
673 format_description
=> "XX:XX:XX:XX:XX:XX",
678 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'.",
679 enum
=> $nic_model_list,
682 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
685 description
=> $net_fmt_bridge_descr,
686 format_description
=> 'bridge',
691 minimum
=> 0, maximum
=> 16,
692 description
=> 'Number of packet queues to be used on the device.',
698 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
703 minimum
=> 1, maximum
=> 4094,
704 description
=> 'VLAN tag to apply to packets on this interface.',
709 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
710 description
=> 'VLAN trunks to pass through this interface.',
711 format_description
=> 'vlanid[;vlanid...]',
716 description
=> 'Whether this interface should be protected by the firewall.',
721 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
728 type
=> 'string', format
=> $net_fmt,
729 description
=> "Specify network devices.",
732 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
737 format
=> 'pve-ipv4-config',
738 format_description
=> 'IPv4Format/CIDR',
739 description
=> 'IPv4 address in CIDR format.',
746 format_description
=> 'GatewayIPv4',
747 description
=> 'Default gateway for IPv4 traffic.',
753 format
=> 'pve-ipv6-config',
754 format_description
=> 'IPv6Format/CIDR',
755 description
=> 'IPv6 address in CIDR format.',
762 format_description
=> 'GatewayIPv6',
763 description
=> 'Default gateway for IPv6 traffic.',
768 PVE
::JSONSchema
::register_format
('pve-qm-ipconfig', $ipconfig_fmt);
771 type
=> 'string', format
=> 'pve-qm-ipconfig',
772 description
=> <<'EODESCR',
773 cloud-init: Specify IP addresses and gateways for the corresponding interface.
775 IP addresses use CIDR notation, gateways are optional but need an IP of the same type specified.
777 The special string 'dhcp' can be used for IP addresses to use DHCP, in which case no explicit gateway should be provided.
778 For IPv6 the special string 'auto' can be used to use stateless autoconfiguration.
780 If cloud-init is enabled and neither an IPv4 nor an IPv6 address is specified, it defaults to using dhcp on IPv4.
783 PVE
::JSONSchema
::register_standard_option
("pve-qm-ipconfig", $netdesc);
785 for (my $i = 0; $i < $MAX_NETS; $i++) {
786 $confdesc->{"net$i"} = $netdesc;
787 $confdesc_cloudinit->{"ipconfig$i"} = $ipconfigdesc;
790 foreach my $key (keys %$confdesc_cloudinit) {
791 $confdesc->{$key} = $confdesc_cloudinit->{$key};
794 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
795 sub verify_volume_id_or_qm_path
{
796 my ($volid, $noerr) = @_;
798 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
802 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
803 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
805 return undef if $noerr;
813 my %drivedesc_base = (
814 volume
=> { alias
=> 'file' },
817 format
=> 'pve-volume-id-or-qm-path',
819 format_description
=> 'volume',
820 description
=> "The drive's backing volume.",
824 enum
=> [qw(cdrom disk)],
825 description
=> "The drive's media type.",
831 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
836 description
=> "Force the drive's physical geometry to have a specific head count.",
841 description
=> "Force the drive's physical geometry to have a specific sector count.",
846 enum
=> [qw(none lba auto)],
847 description
=> "Force disk geometry bios translation mode.",
852 description
=> "Controls qemu's snapshot mode feature."
853 . " If activated, changes made to the disk are temporary and will"
854 . " be discarded when the VM is shutdown.",
859 enum
=> [qw(none writethrough writeback unsafe directsync)],
860 description
=> "The drive's cache mode",
863 format
=> get_standard_option
('pve-qm-image-format'),
866 format
=> 'disk-size',
867 format_description
=> 'DiskSize',
868 description
=> "Disk size. This is purely informational and has no effect.",
873 description
=> "Whether the drive should be included when making backups.",
878 description
=> 'Whether the drive should considered for replication jobs.',
884 enum
=> [qw(ignore report stop)],
885 description
=> 'Read error action.',
890 enum
=> [qw(enospc ignore report stop)],
891 description
=> 'Write error action.',
896 enum
=> [qw(native threads)],
897 description
=> 'AIO type to use.',
902 enum
=> [qw(ignore on)],
903 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
908 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
913 format
=> 'urlencoded',
914 format_description
=> 'serial',
915 maxLength
=> 20*3, # *3 since it's %xx url enoded
916 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
921 description
=> 'Mark this locally-managed volume as available on all nodes',
922 verbose_description
=> "Mark this locally-managed volume as available on all nodes.\n\nWARNING: This option does not share the volume automatically, it assumes it is shared already!",
928 my %iothread_fmt = ( iothread
=> {
930 description
=> "Whether to use iothreads for this drive",
937 format
=> 'urlencoded',
938 format_description
=> 'model',
939 maxLength
=> 40*3, # *3 since it's %xx url enoded
940 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
948 description
=> "Number of queues.",
954 my %scsiblock_fmt = (
957 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",
963 my $add_throttle_desc = sub {
964 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
967 format_description
=> $unit,
968 description
=> "Maximum $what in $longunit.",
971 $d->{minimum
} = $minimum if defined($minimum);
972 $drivedesc_base{$key} = $d;
974 # throughput: (leaky bucket)
975 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
976 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
977 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
978 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
979 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
980 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
981 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
982 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
983 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
985 # pools: (pool of IO before throttling starts taking effect)
986 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
987 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
988 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
989 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
990 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
991 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
994 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
995 $add_throttle_desc->('bps_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
996 $add_throttle_desc->('bps_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
997 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
998 $add_throttle_desc->('iops_rd_max_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
999 $add_throttle_desc->('iops_wr_max_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
1002 $drivedesc_base{'bps_rd_length'} = { alias
=> 'bps_rd_max_length' };
1003 $drivedesc_base{'bps_wr_length'} = { alias
=> 'bps_wr_max_length' };
1004 $drivedesc_base{'iops_rd_length'} = { alias
=> 'iops_rd_max_length' };
1005 $drivedesc_base{'iops_wr_length'} = { alias
=> 'iops_wr_max_length' };
1011 PVE
::JSONSchema
::register_format
("pve-qm-ide", $ide_fmt);
1015 type
=> 'string', format
=> $ide_fmt,
1016 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
1018 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
1028 type
=> 'string', format
=> $scsi_fmt,
1029 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
1031 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
1038 type
=> 'string', format
=> $sata_fmt,
1039 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
1041 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
1049 type
=> 'string', format
=> $virtio_fmt,
1050 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
1052 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
1054 my $alldrive_fmt = {
1063 volume
=> { alias
=> 'file' },
1066 format
=> 'pve-volume-id-or-qm-path',
1068 format_description
=> 'volume',
1069 description
=> "The drive's backing volume.",
1071 format
=> get_standard_option
('pve-qm-image-format'),
1074 format
=> 'disk-size',
1075 format_description
=> 'DiskSize',
1076 description
=> "Disk size. This is purely informational and has no effect.",
1081 my $efidisk_desc = {
1083 type
=> 'string', format
=> $efidisk_fmt,
1084 description
=> "Configure a Disk for storing EFI vars",
1087 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
1092 type
=> 'string', format
=> 'pve-qm-usb-device',
1093 format_description
=> 'HOSTUSBDEVICE|spice',
1094 description
=> <<EODESCR,
1095 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
1097 'bus-port(.port)*' (decimal numbers) or
1098 'vendor_id:product_id' (hexadeciaml numbers) or
1101 You can use the 'lsusb -t' command to list existing usb devices.
1103 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1105 The value 'spice' can be used to add a usb redirection devices for spice.
1111 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).",
1118 type
=> 'string', format
=> $usb_fmt,
1119 description
=> "Configure an USB device (n is 0 to 4).",
1121 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
1123 # NOTE: the match-groups of this regex are used in parse_hostpci
1124 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
1129 pattern
=> qr/$PCIRE(;$PCIRE)*/,
1130 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
1131 description
=> <<EODESCR,
1132 Host PCI device pass through. The PCI ID of a host's PCI device or a list
1133 of PCI virtual functions of the host. HOSTPCIID syntax is:
1135 'bus:dev.func' (hexadecimal numbers)
1137 You can us the 'lspci' command to list existing PCI devices.
1142 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1148 pattern
=> '[^,;]+',
1149 format_description
=> 'string',
1150 description
=> "Custom pci device rom filename (must be located in /usr/share/kvm/).",
1155 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1161 description
=> "Enable vfio-vga device support.",
1166 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1170 type
=> 'string', format
=> 'pve-qm-hostpci',
1171 description
=> "Map host PCI devices into guest.",
1172 verbose_description
=> <<EODESCR,
1173 Map host PCI devices into guest.
1175 NOTE: This option allows direct access to host hardware. So it is no longer
1176 possible to migrate such machines - use with special care.
1178 CAUTION: Experimental! User reported problems with this option.
1181 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1186 pattern
=> '(/dev/.+|socket)',
1187 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1188 verbose_description
=> <<EODESCR,
1189 Create a serial device inside the VM (n is 0 to 3), and pass through a
1190 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1191 host side (use 'qm terminal' to open a terminal connection).
1193 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1195 CAUTION: Experimental! User reported problems with this option.
1202 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1203 description
=> "Map host parallel devices (n is 0 to 2).",
1204 verbose_description
=> <<EODESCR,
1205 Map host parallel devices (n is 0 to 2).
1207 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1209 CAUTION: Experimental! User reported problems with this option.
1213 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1214 $confdesc->{"parallel$i"} = $paralleldesc;
1217 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1218 $confdesc->{"serial$i"} = $serialdesc;
1221 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1222 $confdesc->{"hostpci$i"} = $hostpcidesc;
1225 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1226 $drivename_hash->{"ide$i"} = 1;
1227 $confdesc->{"ide$i"} = $idedesc;
1230 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1231 $drivename_hash->{"sata$i"} = 1;
1232 $confdesc->{"sata$i"} = $satadesc;
1235 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1236 $drivename_hash->{"scsi$i"} = 1;
1237 $confdesc->{"scsi$i"} = $scsidesc ;
1240 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1241 $drivename_hash->{"virtio$i"} = 1;
1242 $confdesc->{"virtio$i"} = $virtiodesc;
1245 $drivename_hash->{efidisk0
} = 1;
1246 $confdesc->{efidisk0
} = $efidisk_desc;
1248 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1249 $confdesc->{"usb$i"} = $usbdesc;
1254 type
=> 'string', format
=> 'pve-volume-id',
1255 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1258 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1259 $confdesc->{"unused$i"} = $unuseddesc;
1262 my $kvm_api_version = 0;
1266 return $kvm_api_version if $kvm_api_version;
1268 my $fh = IO
::File-
>new("</dev/kvm") ||
1271 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1272 $kvm_api_version = $v;
1277 return $kvm_api_version;
1280 my $kvm_user_version;
1282 sub kvm_user_version
{
1284 return $kvm_user_version if $kvm_user_version;
1286 $kvm_user_version = 'unknown';
1290 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1291 $kvm_user_version = $2;
1295 eval { run_command
("kvm -version", outfunc
=> $code); };
1298 return $kvm_user_version;
1302 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1304 sub valid_drive_names
{
1305 # order is important - used to autoselect boot disk
1306 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1307 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1308 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1309 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1313 sub is_valid_drivename
{
1316 return defined($drivename_hash->{$dev});
1321 return defined($confdesc->{$key});
1325 return $nic_model_list;
1328 sub os_list_description
{
1332 wxp
=> 'Windows XP',
1333 w2k
=> 'Windows 2000',
1334 w2k3
=>, 'Windows 2003',
1335 w2k8
=> 'Windows 2008',
1336 wvista
=> 'Windows Vista',
1337 win7
=> 'Windows 7',
1338 win8
=> 'Windows 8/2012',
1339 win10
=> 'Windows 10/2016',
1347 sub get_cdrom_path
{
1349 return $cdrom_path if $cdrom_path;
1351 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1352 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1353 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1357 my ($storecfg, $vmid, $cdrom) = @_;
1359 if ($cdrom eq 'cdrom') {
1360 return get_cdrom_path
();
1361 } elsif ($cdrom eq 'none') {
1363 } elsif ($cdrom =~ m
|^/|) {
1366 return PVE
::Storage
::path
($storecfg, $cdrom);
1370 # try to convert old style file names to volume IDs
1371 sub filename_to_volume_id
{
1372 my ($vmid, $file, $media) = @_;
1374 if (!($file eq 'none' || $file eq 'cdrom' ||
1375 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1377 return undef if $file =~ m
|/|;
1379 if ($media && $media eq 'cdrom') {
1380 $file = "local:iso/$file";
1382 $file = "local:$vmid/$file";
1389 sub verify_media_type
{
1390 my ($opt, $vtype, $media) = @_;
1395 if ($media eq 'disk') {
1397 } elsif ($media eq 'cdrom') {
1400 die "internal error";
1403 return if ($vtype eq $etype);
1405 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1408 sub cleanup_drive_path
{
1409 my ($opt, $storecfg, $drive) = @_;
1411 # try to convert filesystem paths to volume IDs
1413 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1414 ($drive->{file
} !~ m
|^/dev/.+|) &&
1415 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1416 ($drive->{file
} !~ m/^\d+$/)) {
1417 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1418 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1419 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1420 verify_media_type
($opt, $vtype, $drive->{media
});
1421 $drive->{file
} = $volid;
1424 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1427 sub parse_hotplug_features
{
1432 return $res if $data eq '0';
1434 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1436 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1437 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1440 die "invalid hotplug feature '$feature'\n";
1446 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1447 sub pve_verify_hotplug_features
{
1448 my ($value, $noerr) = @_;
1450 return $value if parse_hotplug_features
($value);
1452 return undef if $noerr;
1454 die "unable to parse hotplug option\n";
1457 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1458 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1459 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1460 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1461 # [,iothread=on][,serial=serial][,model=model]
1464 my ($key, $data) = @_;
1466 my ($interface, $index);
1468 if ($key =~ m/^([^\d]+)(\d+)$/) {
1475 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1476 : $confdesc->{$key}->{format
};
1478 warn "invalid drive key: $key\n";
1481 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1482 return undef if !$res;
1483 $res->{interface
} = $interface;
1484 $res->{index} = $index;
1487 foreach my $opt (qw(bps bps_rd bps_wr)) {
1488 if (my $bps = defined(delete $res->{$opt})) {
1489 if (defined($res->{"m$opt"})) {
1490 warn "both $opt and m$opt specified\n";
1494 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1498 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1499 for my $requirement (
1500 [mbps_max
=> 'mbps'],
1501 [mbps_rd_max
=> 'mbps_rd'],
1502 [mbps_wr_max
=> 'mbps_wr'],
1503 [miops_max
=> 'miops'],
1504 [miops_rd_max
=> 'miops_rd'],
1505 [miops_wr_max
=> 'miops_wr'],
1506 [bps_max_length
=> 'mbps_max'],
1507 [bps_rd_max_length
=> 'mbps_rd_max'],
1508 [bps_wr_max_length
=> 'mbps_wr_max'],
1509 [iops_max_length
=> 'iops_max'],
1510 [iops_rd_max_length
=> 'iops_rd_max'],
1511 [iops_wr_max_length
=> 'iops_wr_max']) {
1512 my ($option, $requires) = @$requirement;
1513 if ($res->{$option} && !$res->{$requires}) {
1514 warn "$option requires $requires\n";
1519 return undef if $error;
1521 return undef if $res->{mbps_rd
} && $res->{mbps
};
1522 return undef if $res->{mbps_wr
} && $res->{mbps
};
1523 return undef if $res->{iops_rd
} && $res->{iops
};
1524 return undef if $res->{iops_wr
} && $res->{iops
};
1526 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1527 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1528 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1529 return undef if $res->{interface
} eq 'virtio';
1532 if (my $size = $res->{size
}) {
1533 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1540 my ($vmid, $drive) = @_;
1541 my $data = { %$drive };
1542 delete $data->{$_} for qw(index interface);
1543 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1547 my($fh, $noerr) = @_;
1550 my $SG_GET_VERSION_NUM = 0x2282;
1552 my $versionbuf = "\x00" x
8;
1553 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1555 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1558 my $version = unpack("I", $versionbuf);
1559 if ($version < 30000) {
1560 die "scsi generic interface too old\n" if !$noerr;
1564 my $buf = "\x00" x
36;
1565 my $sensebuf = "\x00" x
8;
1566 my $cmd = pack("C x3 C x1", 0x12, 36);
1568 # see /usr/include/scsi/sg.h
1569 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";
1571 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1572 length($sensebuf), 0, length($buf), $buf,
1573 $cmd, $sensebuf, 6000);
1575 $ret = ioctl($fh, $SG_IO, $packet);
1577 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1581 my @res = unpack($sg_io_hdr_t, $packet);
1582 if ($res[17] || $res[18]) {
1583 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1588 (my $byte0, my $byte1, $res->{vendor
},
1589 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1591 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1592 $res->{type
} = $byte0 & 31;
1600 my $fh = IO
::File-
>new("+<$path") || return undef;
1601 my $res = scsi_inquiry
($fh, 1);
1607 sub machine_type_is_q35
{
1610 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1613 sub print_tabletdevice_full
{
1616 my $q35 = machine_type_is_q35
($conf);
1618 # we use uhci for old VMs because tablet driver was buggy in older qemu
1619 my $usbbus = $q35 ?
"ehci" : "uhci";
1621 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1624 sub print_drivedevice_full
{
1625 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1630 if ($drive->{interface
} eq 'virtio') {
1631 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1632 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1633 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1634 } elsif ($drive->{interface
} eq 'scsi') {
1636 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1637 my $unit = $drive->{index} % $maxdev;
1638 my $devicetype = 'hd';
1640 if (drive_is_cdrom
($drive)) {
1643 if ($drive->{file
} =~ m
|^/|) {
1644 $path = $drive->{file
};
1645 if (my $info = path_is_scsi
($path)) {
1646 if ($info->{type
} == 0 && $drive->{scsiblock
}) {
1647 $devicetype = 'block';
1648 } elsif ($info->{type
} == 1) { # tape
1649 $devicetype = 'generic';
1653 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1656 if($path =~ m/^iscsi\:\/\
//){
1657 $devicetype = 'generic';
1661 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1662 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1664 $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}";
1667 } elsif ($drive->{interface
} eq 'ide'){
1669 my $controller = int($drive->{index} / $maxdev);
1670 my $unit = $drive->{index} % $maxdev;
1671 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1673 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1674 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1675 $model = URI
::Escape
::uri_unescape
($model);
1676 $device .= ",model=$model";
1678 } elsif ($drive->{interface
} eq 'sata'){
1679 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1680 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1681 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1682 } elsif ($drive->{interface
} eq 'usb') {
1684 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1686 die "unsupported interface type";
1689 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1694 sub get_initiator_name
{
1697 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1698 while (defined(my $line = <$fh>)) {
1699 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1708 sub print_drive_full
{
1709 my ($storecfg, $vmid, $drive) = @_;
1712 my $volid = $drive->{file
};
1715 if (drive_is_cdrom
($drive)) {
1716 $path = get_iso_path
($storecfg, $vmid, $volid);
1718 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1720 $path = PVE
::Storage
::path
($storecfg, $volid);
1721 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1722 $format = qemu_img_format
($scfg, $volname);
1730 my @qemu_drive_options = qw(heads secs cyls trans media format cache rerror werror aio discard);
1731 foreach my $o (@qemu_drive_options) {
1732 $opts .= ",$o=$drive->{$o}" if defined($drive->{$o});
1735 # snapshot only accepts on|off
1736 if (defined($drive->{snapshot
})) {
1737 my $v = $drive->{snapshot
} ?
'on' : 'off';
1738 $opts .= ",snapshot=$v";
1741 foreach my $type (['', '-total'], [_rd
=> '-read'], [_wr
=> '-write']) {
1742 my ($dir, $qmpname) = @$type;
1743 if (my $v = $drive->{"mbps$dir"}) {
1744 $opts .= ",throttling.bps$qmpname=".int($v*1024*1024);
1746 if (my $v = $drive->{"mbps${dir}_max"}) {
1747 $opts .= ",throttling.bps$qmpname-max=".int($v*1024*1024);
1749 if (my $v = $drive->{"bps${dir}_max_length"}) {
1750 $opts .= ",throttling.bps$qmpname-max-length=$v";
1752 if (my $v = $drive->{"iops${dir}"}) {
1753 $opts .= ",throttling.iops$qmpname=$v";
1755 if (my $v = $drive->{"iops${dir}_max"}) {
1756 $opts .= ",throttling.iops$qmpname-max=$v";
1758 if (my $v = $drive->{"iops${dir}_max_length"}) {
1759 $opts .= ",throttling.iops$qmpname-max-length=$v";
1763 if (my $serial = $drive->{serial
}) {
1764 $serial = URI
::Escape
::uri_unescape
($serial);
1765 $opts .= ",serial=$serial";
1768 $opts .= ",format=$format" if $format && !$drive->{format
};
1770 my $cache_direct = 0;
1772 if (my $cache = $drive->{cache
}) {
1773 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1774 } elsif (!drive_is_cdrom
($drive)) {
1775 $opts .= ",cache=none";
1779 # aio native works only with O_DIRECT
1780 if (!$drive->{aio
}) {
1782 $opts .= ",aio=native";
1784 $opts .= ",aio=threads";
1788 if (!drive_is_cdrom
($drive)) {
1790 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1791 $detectzeroes = 'off';
1792 } elsif ($drive->{discard
}) {
1793 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1795 # This used to be our default with discard not being specified:
1796 $detectzeroes = 'on';
1798 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1801 my $pathinfo = $path ?
"file=$path," : '';
1803 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1806 sub print_netdevice_full
{
1807 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1809 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1811 my $device = $net->{model
};
1812 if ($net->{model
} eq 'virtio') {
1813 $device = 'virtio-net-pci';
1816 my $pciaddr = print_pci_addr
("$netid", $bridges);
1817 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1818 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1819 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1820 my $vectors = $net->{queues
} * 2 + 2;
1821 $tmpstr .= ",vectors=$vectors,mq=on";
1823 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1825 if ($use_old_bios_files) {
1827 if ($device eq 'virtio-net-pci') {
1828 $romfile = 'pxe-virtio.rom';
1829 } elsif ($device eq 'e1000') {
1830 $romfile = 'pxe-e1000.rom';
1831 } elsif ($device eq 'ne2k') {
1832 $romfile = 'pxe-ne2k_pci.rom';
1833 } elsif ($device eq 'pcnet') {
1834 $romfile = 'pxe-pcnet.rom';
1835 } elsif ($device eq 'rtl8139') {
1836 $romfile = 'pxe-rtl8139.rom';
1838 $tmpstr .= ",romfile=$romfile" if $romfile;
1844 sub print_netdev_full
{
1845 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1848 if ($netid =~ m/^net(\d+)$/) {
1852 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1854 my $ifname = "tap${vmid}i$i";
1856 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1857 die "interface name '$ifname' is too long (max 15 character)\n"
1858 if length($ifname) >= 16;
1860 my $vhostparam = '';
1861 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1863 my $vmname = $conf->{name
} || "vm$vmid";
1866 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1868 if ($net->{bridge
}) {
1869 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1871 $netdev = "type=user,id=$netid,hostname=$vmname";
1874 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1880 sub print_cpu_device
{
1881 my ($conf, $id) = @_;
1883 my $kvm = $conf->{kvm
} // 1;
1884 my $cpu = $kvm ?
"kvm64" : "qemu64";
1885 if (my $cputype = $conf->{cpu
}) {
1886 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1887 or die "Cannot parse cpu description: $cputype\n";
1888 $cpu = $cpuconf->{cputype
};
1891 my $cores = $conf->{cores
} || 1;
1893 my $current_core = ($id - 1) % $cores;
1894 my $current_socket = int(($id - 1 - $current_core)/$cores);
1896 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1899 sub drive_is_cloudinit
{
1901 return $drive->{file
} =~ m
@[:/]vm-\d
+-cloudinit
(?
:\
.$QEMU_FORMAT_RE)?
$@;
1904 sub drive_is_cdrom
{
1905 my ($drive, $exclude_cloudinit) = @_;
1907 return 0 if $exclude_cloudinit && drive_is_cloudinit
($drive);
1909 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1913 sub parse_number_sets
{
1916 foreach my $part (split(/;/, $set)) {
1917 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1918 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1919 push @$res, [ $1, $2 ];
1921 die "invalid range: $part\n";
1930 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1931 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1932 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1939 return undef if !$value;
1941 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1943 my @idlist = split(/;/, $res->{host
});
1944 delete $res->{host
};
1945 foreach my $id (@idlist) {
1946 if ($id =~ /^$PCIRE$/) {
1948 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1950 my $pcidevices = lspci
($1);
1951 $res->{pciid
} = $pcidevices->{$1};
1954 # should have been caught by parse_property_string already
1955 die "failed to parse PCI id: $id\n";
1961 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1965 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1970 if (!defined($res->{macaddr
})) {
1971 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1972 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1977 # ipconfigX ip=cidr,gw=ip,ip6=cidr,gw6=ip
1978 sub parse_ipconfig
{
1981 my $res = eval { PVE
::JSONSchema
::parse_property_string
($ipconfig_fmt, $data) };
1987 if ($res->{gw
} && !$res->{ip
}) {
1988 warn 'gateway specified without specifying an IP address';
1991 if ($res->{gw6
} && !$res->{ip6
}) {
1992 warn 'IPv6 gateway specified without specifying an IPv6 address';
1995 if ($res->{gw
} && $res->{ip
} eq 'dhcp') {
1996 warn 'gateway specified together with DHCP';
1999 if ($res->{gw6
} && $res->{ip6
} !~ /^$IPV6RE/) {
2001 warn "IPv6 gateway specified together with $res->{ip6} address";
2005 if (!$res->{ip
} && !$res->{ip6
}) {
2006 return { ip
=> 'dhcp', ip6
=> 'dhcp' };
2015 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
2018 sub add_random_macs
{
2019 my ($settings) = @_;
2021 foreach my $opt (keys %$settings) {
2022 next if $opt !~ m/^net(\d+)$/;
2023 my $net = parse_net
($settings->{$opt});
2025 $settings->{$opt} = print_net
($net);
2029 sub vm_is_volid_owner
{
2030 my ($storecfg, $vmid, $volid) = @_;
2032 if ($volid !~ m
|^/|) {
2034 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
2035 if ($owner && ($owner == $vmid)) {
2043 sub split_flagged_list
{
2044 my $text = shift || '';
2045 $text =~ s/[,;]/ /g;
2047 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
2050 sub join_flagged_list
{
2051 my ($how, $lst) = @_;
2052 join $how, map { $lst->{$_} . $_ } keys %$lst;
2055 sub vmconfig_delete_pending_option
{
2056 my ($conf, $key, $force) = @_;
2058 delete $conf->{pending
}->{$key};
2059 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
2060 $pending_delete_hash->{$key} = $force ?
'!' : '';
2061 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
2064 sub vmconfig_undelete_pending_option
{
2065 my ($conf, $key) = @_;
2067 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
2068 delete $pending_delete_hash->{$key};
2070 if (%$pending_delete_hash) {
2071 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
2073 delete $conf->{pending
}->{delete};
2077 sub vmconfig_register_unused_drive
{
2078 my ($storecfg, $vmid, $conf, $drive) = @_;
2080 if (drive_is_cloudinit
($drive)) {
2081 eval { PVE
::Storage
::vdisk_free
($storecfg, $drive->{file
}) };
2083 } elsif (!drive_is_cdrom
($drive)) {
2084 my $volid = $drive->{file
};
2085 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
2086 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
2091 sub vmconfig_cleanup_pending
{
2094 # remove pending changes when nothing changed
2096 foreach my $opt (keys %{$conf->{pending
}}) {
2097 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
2099 delete $conf->{pending
}->{$opt};
2103 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
2104 my $pending_delete_hash = {};
2105 while (my ($opt, $force) = each %$current_delete_hash) {
2106 if (defined($conf->{$opt})) {
2107 $pending_delete_hash->{$opt} = $force;
2113 if (%$pending_delete_hash) {
2114 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
2116 delete $conf->{pending
}->{delete};
2122 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
2126 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
2127 format_description
=> 'UUID',
2128 description
=> "Set SMBIOS1 UUID.",
2134 format_description
=> 'string',
2135 description
=> "Set SMBIOS1 version.",
2141 format_description
=> 'string',
2142 description
=> "Set SMBIOS1 serial number.",
2148 format_description
=> 'string',
2149 description
=> "Set SMBIOS1 manufacturer.",
2155 format_description
=> 'string',
2156 description
=> "Set SMBIOS1 product ID.",
2162 format_description
=> 'string',
2163 description
=> "Set SMBIOS1 SKU string.",
2169 format_description
=> 'string',
2170 description
=> "Set SMBIOS1 family string.",
2178 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
2185 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
2188 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
2190 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
2191 sub verify_bootdisk
{
2192 my ($value, $noerr) = @_;
2194 return $value if is_valid_drivename
($value);
2196 return undef if $noerr;
2198 die "invalid boot disk '$value'\n";
2201 sub parse_watchdog
{
2204 return undef if !$value;
2206 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
2211 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
2212 sub verify_usb_device
{
2213 my ($value, $noerr) = @_;
2215 return $value if parse_usb_device
($value);
2217 return undef if $noerr;
2219 die "unable to parse usb device\n";
2222 # add JSON properties for create and set function
2223 sub json_config_properties
{
2226 foreach my $opt (keys %$confdesc) {
2227 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2228 $prop->{$opt} = $confdesc->{$opt};
2234 # return copy of $confdesc_cloudinit to generate documentation
2235 sub cloudinit_config_properties
{
2237 return dclone
($confdesc_cloudinit);
2241 my ($key, $value) = @_;
2243 die "unknown setting '$key'\n" if !$confdesc->{$key};
2245 my $type = $confdesc->{$key}->{type
};
2247 if (!defined($value)) {
2248 die "got undefined value\n";
2251 if ($value =~ m/[\n\r]/) {
2252 die "property contains a line feed\n";
2255 if ($type eq 'boolean') {
2256 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2257 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2258 die "type check ('boolean') failed - got '$value'\n";
2259 } elsif ($type eq 'integer') {
2260 return int($1) if $value =~ m/^(\d+)$/;
2261 die "type check ('integer') failed - got '$value'\n";
2262 } elsif ($type eq 'number') {
2263 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2264 die "type check ('number') failed - got '$value'\n";
2265 } elsif ($type eq 'string') {
2266 if (my $fmt = $confdesc->{$key}->{format
}) {
2267 PVE
::JSONSchema
::check_format
($fmt, $value);
2270 $value =~ s/^\"(.*)\"$/$1/;
2273 die "internal error"
2277 sub check_iommu_support
{
2278 #fixme : need to check IOMMU support
2279 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2289 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2290 utime undef, undef, $conf;
2294 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2296 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2298 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2300 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2302 if ($conf->{template
}) {
2303 # check if any base image is still used by a linked clone
2304 foreach_drive
($conf, sub {
2305 my ($ds, $drive) = @_;
2307 return if drive_is_cdrom
($drive);
2309 my $volid = $drive->{file
};
2311 return if !$volid || $volid =~ m
|^/|;
2313 die "base volume '$volid' is still in use by linked cloned\n"
2314 if PVE
::Storage
::volume_is_base_and_used
($storecfg, $volid);
2319 # only remove disks owned by this VM
2320 foreach_drive
($conf, sub {
2321 my ($ds, $drive) = @_;
2323 return if drive_is_cdrom
($drive, 1);
2325 my $volid = $drive->{file
};
2327 return if !$volid || $volid =~ m
|^/|;
2329 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2330 return if !$path || !$owner || ($owner != $vmid);
2333 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2335 warn "Could not remove disk '$volid', check manually: $@" if $@;
2339 if ($keep_empty_config) {
2340 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2345 # also remove unused disk
2347 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2350 PVE
::Storage
::foreach_volid
($dl, sub {
2351 my ($volid, $sid, $volname, $d) = @_;
2352 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2361 sub parse_vm_config
{
2362 my ($filename, $raw) = @_;
2364 return undef if !defined($raw);
2367 digest
=> Digest
::SHA
::sha1_hex
($raw),
2372 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2373 || die "got strange filename '$filename'";
2381 my @lines = split(/\n/, $raw);
2382 foreach my $line (@lines) {
2383 next if $line =~ m/^\s*$/;
2385 if ($line =~ m/^\[PENDING\]\s*$/i) {
2386 $section = 'pending';
2387 if (defined($descr)) {
2389 $conf->{description
} = $descr;
2392 $conf = $res->{$section} = {};
2395 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2397 if (defined($descr)) {
2399 $conf->{description
} = $descr;
2402 $conf = $res->{snapshots
}->{$section} = {};
2406 if ($line =~ m/^\#(.*)\s*$/) {
2407 $descr = '' if !defined($descr);
2408 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2412 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2413 $descr = '' if !defined($descr);
2414 $descr .= PVE
::Tools
::decode_text
($2);
2415 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2416 $conf->{snapstate
} = $1;
2417 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2420 $conf->{$key} = $value;
2421 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2423 if ($section eq 'pending') {
2424 $conf->{delete} = $value; # we parse this later
2426 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2428 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(.+?)\s*$/) {
2431 eval { $value = check_type
($key, $value); };
2433 warn "vm $vmid - unable to parse value of '$key' - $@";
2435 $key = 'ide2' if $key eq 'cdrom';
2436 my $fmt = $confdesc->{$key}->{format
};
2437 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2438 my $v = parse_drive
($key, $value);
2439 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2440 $v->{file
} = $volid;
2441 $value = print_drive
($vmid, $v);
2443 warn "vm $vmid - unable to parse value of '$key'\n";
2448 $conf->{$key} = $value;
2453 if (defined($descr)) {
2455 $conf->{description
} = $descr;
2457 delete $res->{snapstate
}; # just to be sure
2462 sub write_vm_config
{
2463 my ($filename, $conf) = @_;
2465 delete $conf->{snapstate
}; # just to be sure
2467 if ($conf->{cdrom
}) {
2468 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2469 $conf->{ide2
} = $conf->{cdrom
};
2470 delete $conf->{cdrom
};
2473 # we do not use 'smp' any longer
2474 if ($conf->{sockets
}) {
2475 delete $conf->{smp
};
2476 } elsif ($conf->{smp
}) {
2477 $conf->{sockets
} = $conf->{smp
};
2478 delete $conf->{cores
};
2479 delete $conf->{smp
};
2482 my $used_volids = {};
2484 my $cleanup_config = sub {
2485 my ($cref, $pending, $snapname) = @_;
2487 foreach my $key (keys %$cref) {
2488 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2489 $key eq 'snapstate' || $key eq 'pending';
2490 my $value = $cref->{$key};
2491 if ($key eq 'delete') {
2492 die "propertry 'delete' is only allowed in [PENDING]\n"
2494 # fixme: check syntax?
2497 eval { $value = check_type
($key, $value); };
2498 die "unable to parse value of '$key' - $@" if $@;
2500 $cref->{$key} = $value;
2502 if (!$snapname && is_valid_drivename
($key)) {
2503 my $drive = parse_drive
($key, $value);
2504 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2509 &$cleanup_config($conf);
2511 &$cleanup_config($conf->{pending
}, 1);
2513 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2514 die "internal error" if $snapname eq 'pending';
2515 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2518 # remove 'unusedX' settings if we re-add a volume
2519 foreach my $key (keys %$conf) {
2520 my $value = $conf->{$key};
2521 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2522 delete $conf->{$key};
2526 my $generate_raw_config = sub {
2527 my ($conf, $pending) = @_;
2531 # add description as comment to top of file
2532 if (defined(my $descr = $conf->{description
})) {
2534 foreach my $cl (split(/\n/, $descr)) {
2535 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2538 $raw .= "#\n" if $pending;
2542 foreach my $key (sort keys %$conf) {
2543 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2544 $raw .= "$key: $conf->{$key}\n";
2549 my $raw = &$generate_raw_config($conf);
2551 if (scalar(keys %{$conf->{pending
}})){
2552 $raw .= "\n[PENDING]\n";
2553 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2556 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2557 $raw .= "\n[$snapname]\n";
2558 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2568 # we use static defaults from our JSON schema configuration
2569 foreach my $key (keys %$confdesc) {
2570 if (defined(my $default = $confdesc->{$key}->{default})) {
2571 $res->{$key} = $default;
2579 my $vmlist = PVE
::Cluster
::get_vmlist
();
2581 return $res if !$vmlist || !$vmlist->{ids
};
2582 my $ids = $vmlist->{ids
};
2584 foreach my $vmid (keys %$ids) {
2585 my $d = $ids->{$vmid};
2586 next if !$d->{node
} || $d->{node
} ne $nodename;
2587 next if !$d->{type
} || $d->{type
} ne 'qemu';
2588 $res->{$vmid}->{exists} = 1;
2593 # test if VM uses local resources (to prevent migration)
2594 sub check_local_resources
{
2595 my ($conf, $noerr) = @_;
2599 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2600 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2602 foreach my $k (keys %$conf) {
2603 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2604 # sockets are safe: they will recreated be on the target side post-migrate
2605 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2606 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2609 die "VM uses local resources\n" if $loc_res && !$noerr;
2614 # check if used storages are available on all nodes (use by migrate)
2615 sub check_storage_availability
{
2616 my ($storecfg, $conf, $node) = @_;
2618 foreach_drive
($conf, sub {
2619 my ($ds, $drive) = @_;
2621 my $volid = $drive->{file
};
2624 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2627 # check if storage is available on both nodes
2628 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2629 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2633 # list nodes where all VM images are available (used by has_feature API)
2635 my ($conf, $storecfg) = @_;
2637 my $nodelist = PVE
::Cluster
::get_nodelist
();
2638 my $nodehash = { map { $_ => 1 } @$nodelist };
2639 my $nodename = PVE
::INotify
::nodename
();
2641 foreach_drive
($conf, sub {
2642 my ($ds, $drive) = @_;
2644 my $volid = $drive->{file
};
2647 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2649 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2650 if ($scfg->{disable
}) {
2652 } elsif (my $avail = $scfg->{nodes
}) {
2653 foreach my $node (keys %$nodehash) {
2654 delete $nodehash->{$node} if !$avail->{$node};
2656 } elsif (!$scfg->{shared
}) {
2657 foreach my $node (keys %$nodehash) {
2658 delete $nodehash->{$node} if $node ne $nodename
2668 my ($pidfile, $pid) = @_;
2670 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2674 return undef if !$line;
2675 my @param = split(/\0/, $line);
2677 my $cmd = $param[0];
2678 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2680 for (my $i = 0; $i < scalar (@param); $i++) {
2683 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2684 my $p = $param[$i+1];
2685 return 1 if $p && ($p eq $pidfile);
2694 my ($vmid, $nocheck, $node) = @_;
2696 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2698 die "unable to find configuration file for VM $vmid - no such machine\n"
2699 if !$nocheck && ! -f
$filename;
2701 my $pidfile = pidfile_name
($vmid);
2703 if (my $fd = IO
::File-
>new("<$pidfile")) {
2708 my $mtime = $st->mtime;
2709 if ($mtime > time()) {
2710 warn "file '$filename' modified in future\n";
2713 if ($line =~ m/^(\d+)$/) {
2715 if (check_cmdline
($pidfile, $pid)) {
2716 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2728 my $vzlist = config_list
();
2730 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2732 while (defined(my $de = $fd->read)) {
2733 next if $de !~ m/^(\d+)\.pid$/;
2735 next if !defined($vzlist->{$vmid});
2736 if (my $pid = check_running
($vmid)) {
2737 $vzlist->{$vmid}->{pid
} = $pid;
2745 my ($storecfg, $conf) = @_;
2747 my $bootdisk = $conf->{bootdisk
};
2748 return undef if !$bootdisk;
2749 return undef if !is_valid_drivename
($bootdisk);
2751 return undef if !$conf->{$bootdisk};
2753 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2754 return undef if !defined($drive);
2756 return undef if drive_is_cdrom
($drive);
2758 my $volid = $drive->{file
};
2759 return undef if !$volid;
2761 return $drive->{size
};
2764 my $last_proc_pid_stat;
2766 # get VM status information
2767 # This must be fast and should not block ($full == false)
2768 # We only query KVM using QMP if $full == true (this can be slow)
2770 my ($opt_vmid, $full) = @_;
2774 my $storecfg = PVE
::Storage
::config
();
2776 my $list = vzlist
();
2777 my $defaults = load_defaults
();
2779 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2781 my $cpucount = $cpuinfo->{cpus
} || 1;
2783 foreach my $vmid (keys %$list) {
2784 next if $opt_vmid && ($vmid ne $opt_vmid);
2786 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2787 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2790 $d->{pid
} = $list->{$vmid}->{pid
};
2792 # fixme: better status?
2793 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2795 my $size = disksize
($storecfg, $conf);
2796 if (defined($size)) {
2797 $d->{disk
} = 0; # no info available
2798 $d->{maxdisk
} = $size;
2804 $d->{cpus
} = ($conf->{sockets
} || $defaults->{sockets
})
2805 * ($conf->{cores
} || $defaults->{cores
});
2806 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2807 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2809 $d->{name
} = $conf->{name
} || "VM $vmid";
2810 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024)
2811 : $defaults->{memory
}*(1024*1024);
2813 if ($conf->{balloon
}) {
2814 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2815 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
}
2816 : $defaults->{shares
};
2827 $d->{diskwrite
} = 0;
2829 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2831 $d->{serial
} = 1 if conf_has_serial
($conf);
2836 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2837 foreach my $dev (keys %$netdev) {
2838 next if $dev !~ m/^tap([1-9]\d*)i/;
2840 my $d = $res->{$vmid};
2843 $d->{netout
} += $netdev->{$dev}->{receive
};
2844 $d->{netin
} += $netdev->{$dev}->{transmit
};
2847 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2848 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2853 my $ctime = gettimeofday
;
2855 foreach my $vmid (keys %$list) {
2857 my $d = $res->{$vmid};
2858 my $pid = $d->{pid
};
2861 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2862 next if !$pstat; # not running
2864 my $used = $pstat->{utime} + $pstat->{stime
};
2866 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2868 if ($pstat->{vsize
}) {
2869 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2872 my $old = $last_proc_pid_stat->{$pid};
2874 $last_proc_pid_stat->{$pid} = {
2882 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2884 if ($dtime > 1000) {
2885 my $dutime = $used - $old->{used
};
2887 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2888 $last_proc_pid_stat->{$pid} = {
2894 $d->{cpu
} = $old->{cpu
};
2898 return $res if !$full;
2900 my $qmpclient = PVE
::QMPClient-
>new();
2902 my $ballooncb = sub {
2903 my ($vmid, $resp) = @_;
2905 my $info = $resp->{'return'};
2906 return if !$info->{max_mem
};
2908 my $d = $res->{$vmid};
2910 # use memory assigned to VM
2911 $d->{maxmem
} = $info->{max_mem
};
2912 $d->{balloon
} = $info->{actual
};
2914 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2915 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2916 $d->{freemem
} = $info->{free_mem
};
2919 $d->{ballooninfo
} = $info;
2922 my $blockstatscb = sub {
2923 my ($vmid, $resp) = @_;
2924 my $data = $resp->{'return'} || [];
2925 my $totalrdbytes = 0;
2926 my $totalwrbytes = 0;
2928 for my $blockstat (@$data) {
2929 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2930 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2932 $blockstat->{device
} =~ s/drive-//;
2933 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2935 $res->{$vmid}->{diskread
} = $totalrdbytes;
2936 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2939 my $statuscb = sub {
2940 my ($vmid, $resp) = @_;
2942 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2943 # this fails if ballon driver is not loaded, so this must be
2944 # the last commnand (following command are aborted if this fails).
2945 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2947 my $status = 'unknown';
2948 if (!defined($status = $resp->{'return'}->{status
})) {
2949 warn "unable to get VM status\n";
2953 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2956 foreach my $vmid (keys %$list) {
2957 next if $opt_vmid && ($vmid ne $opt_vmid);
2958 next if !$res->{$vmid}->{pid
}; # not running
2959 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2962 $qmpclient->queue_execute(undef, 2);
2964 foreach my $vmid (keys %$list) {
2965 next if $opt_vmid && ($vmid ne $opt_vmid);
2966 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2973 my ($conf, $func, @param) = @_;
2975 foreach my $ds (valid_drive_names
()) {
2976 next if !defined($conf->{$ds});
2978 my $drive = parse_drive
($ds, $conf->{$ds});
2981 &$func($ds, $drive, @param);
2986 my ($conf, $func, @param) = @_;
2990 my $test_volid = sub {
2991 my ($volid, $is_cdrom, $replicate, $shared, $snapname) = @_;
2995 $volhash->{$volid}->{cdrom
} //= 1;
2996 $volhash->{$volid}->{cdrom
} = 0 if !$is_cdrom;
2998 $volhash->{$volid}->{replicate
} //= 0;
2999 $volhash->{$volid}->{replicate
} = 1 if $replicate;
3001 $volhash->{$volid}->{shared
} //= 0;
3002 $volhash->{$volid}->{shared
} = 1 if $shared;
3004 $volhash->{$volid}->{referenced_in_config
} //= 0;
3005 $volhash->{$volid}->{referenced_in_config
} = 1 if !defined($snapname);
3007 $volhash->{$volid}->{referenced_in_snapshot
}->{$snapname} = 1
3008 if defined($snapname);
3011 foreach_drive
($conf, sub {
3012 my ($ds, $drive) = @_;
3013 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, $drive->{shared
}, undef);
3016 foreach my $snapname (keys %{$conf->{snapshots
}}) {
3017 my $snap = $conf->{snapshots
}->{$snapname};
3018 $test_volid->($snap->{vmstate
}, 0, 1, $snapname);
3019 foreach_drive
($snap, sub {
3020 my ($ds, $drive) = @_;
3021 $test_volid->($drive->{file
}, drive_is_cdrom
($drive), $drive->{replicate
} // 1, $drive->{shared
}, $snapname);
3025 foreach my $volid (keys %$volhash) {
3026 &$func($volid, $volhash->{$volid}, @param);
3030 sub conf_has_serial
{
3033 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
3034 if ($conf->{"serial$i"}) {
3042 sub vga_conf_has_spice
{
3045 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
3050 sub config_to_command
{
3051 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
3054 my $globalFlags = [];
3055 my $machineFlags = [];
3061 my $kvmver = kvm_user_version
();
3062 my $vernum = 0; # unknown
3063 my $ostype = $conf->{ostype
};
3064 my $winversion = windows_version
($ostype);
3065 my $kvm = $conf->{kvm
} // 1;
3067 die "KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.\n" if (!$cpuinfo->{hvm
} && $kvm);
3069 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
3070 $vernum = $1*1000000+$2*1000;
3071 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
3072 $vernum = $1*1000000+$2*1000+$3;
3075 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
3077 my $have_ovz = -f
'/proc/vz/vestat';
3079 my $q35 = machine_type_is_q35
($conf);
3080 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
3081 my $machine_type = $forcemachine || $conf->{machine
};
3082 my $use_old_bios_files = undef;
3083 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3085 my $cpuunits = defined($conf->{cpuunits
}) ?
3086 $conf->{cpuunits
} : $defaults->{cpuunits
};
3088 push @$cmd, '/usr/bin/kvm';
3090 push @$cmd, '-id', $vmid;
3092 my $vmname = $conf->{name
} || "vm$vmid";
3094 push @$cmd, '-name', $vmname;
3098 my $qmpsocket = qmp_socket
($vmid);
3099 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
3100 push @$cmd, '-mon', "chardev=qmp,mode=control";
3103 push @$cmd, '-pidfile' , pidfile_name
($vmid);
3105 push @$cmd, '-daemonize';
3107 if ($conf->{smbios1
}) {
3108 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
3111 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
3112 die "uefi base image not found\n" if ! -f
$OVMF_CODE;
3116 if (my $efidisk = $conf->{efidisk0
}) {
3117 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $efidisk);
3118 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
3119 $format = $d->{format
};
3121 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
3122 if (!defined($format)) {
3123 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
3124 $format = qemu_img_format
($scfg, $volname);
3128 die "efidisk format must be specified\n"
3129 if !defined($format);
3132 warn "no efidisk configured! Using temporary efivars disk.\n";
3133 $path = "/tmp/$vmid-ovmf.fd";
3134 PVE
::Tools
::file_copy
($OVMF_VARS, $path, -s
$OVMF_VARS);
3138 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$OVMF_CODE";
3139 push @$cmd, '-drive', "if=pflash,unit=1,format=$format,id=drive-efidisk0,file=$path";
3143 # add usb controllers
3144 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
3145 push @$devices, @usbcontrollers if @usbcontrollers;
3146 my $vga = $conf->{vga
};
3148 my $qxlnum = vga_conf_has_spice
($vga);
3149 $vga = 'qxl' if $qxlnum;
3152 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 9)) {
3153 $vga = (!$winversion || $winversion >= 6) ?
'std' : 'cirrus';
3155 $vga = ($winversion >= 6) ?
'std' : 'cirrus';
3159 # enable absolute mouse coordinates (needed by vnc)
3161 if (defined($conf->{tablet
})) {
3162 $tablet = $conf->{tablet
};
3164 $tablet = $defaults->{tablet
};
3165 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
3166 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
3169 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
3172 my $gpu_passthrough;
3175 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
3176 my $d = parse_hostpci
($conf->{"hostpci$i"});
3179 my $pcie = $d->{pcie
};
3181 die "q35 machine model is not enabled" if !$q35;
3182 $pciaddr = print_pcie_addr
("hostpci$i");
3184 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
3187 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
3188 my $romfile = $d->{romfile
};
3191 if ($d->{'x-vga'}) {
3192 $xvga = ',x-vga=on';
3195 $gpu_passthrough = 1;
3197 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
3201 my $pcidevices = $d->{pciid
};
3202 my $multifunction = 1 if @$pcidevices > 1;
3205 foreach my $pcidevice (@$pcidevices) {
3207 my $id = "hostpci$i";
3208 $id .= ".$j" if $multifunction;
3209 my $addr = $pciaddr;
3210 $addr .= ".$j" if $multifunction;
3211 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
3214 $devicestr .= "$rombar$xvga";
3215 $devicestr .= ",multifunction=on" if $multifunction;
3216 $devicestr .= ",romfile=/usr/share/kvm/$romfile" if $romfile;
3219 push @$devices, '-device', $devicestr;
3225 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
3226 push @$devices, @usbdevices if @usbdevices;
3228 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
3229 if (my $path = $conf->{"serial$i"}) {
3230 if ($path eq 'socket') {
3231 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
3232 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
3233 push @$devices, '-device', "isa-serial,chardev=serial$i";
3235 die "no such serial device\n" if ! -c
$path;
3236 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
3237 push @$devices, '-device', "isa-serial,chardev=serial$i";
3243 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
3244 if (my $path = $conf->{"parallel$i"}) {
3245 die "no such parallel device\n" if ! -c
$path;
3246 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
3247 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
3248 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
3254 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
3255 $sockets = $conf->{sockets
} if $conf->{sockets
};
3257 my $cores = $conf->{cores
} || 1;
3259 my $maxcpus = $sockets * $cores;
3261 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3263 my $allowed_vcpus = $cpuinfo->{cpus
};
3265 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3266 if ($allowed_vcpus < $maxcpus);
3268 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
3270 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3271 for (my $i = 2; $i <= $vcpus; $i++) {
3272 my $cpustr = print_cpu_device
($conf,$i);
3273 push @$cmd, '-device', $cpustr;
3278 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3280 push @$cmd, '-nodefaults';
3282 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3284 my $bootindex_hash = {};
3286 foreach my $o (split(//, $bootorder)) {
3287 $bootindex_hash->{$o} = $i*100;
3291 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3293 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3295 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3297 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3299 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3300 my $socket = vnc_socket
($vmid);
3301 push @$cmd, '-vnc', "unix:$socket,x509,password";
3303 push @$cmd, '-nographic';
3307 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3309 my $useLocaltime = $conf->{localtime};
3311 if ($winversion >= 5) { # windows
3312 $useLocaltime = 1 if !defined($conf->{localtime});
3314 # use time drift fix when acpi is enabled
3315 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3316 $tdf = 1 if !defined($conf->{tdf
});
3320 if ($winversion >= 6) {
3321 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3322 push @$cmd, '-no-hpet';
3325 push @$rtcFlags, 'driftfix=slew' if $tdf;
3328 push @$machineFlags, 'accel=tcg';
3331 if ($machine_type) {
3332 push @$machineFlags, "type=${machine_type}";
3335 if ($conf->{startdate
}) {
3336 push @$rtcFlags, "base=$conf->{startdate}";
3337 } elsif ($useLocaltime) {
3338 push @$rtcFlags, 'base=localtime';
3341 my $cpu = $kvm ?
"kvm64" : "qemu64";
3342 if (my $cputype = $conf->{cpu
}) {
3343 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3344 or die "Cannot parse cpu description: $cputype\n";
3345 $cpu = $cpuconf->{cputype
};
3346 $kvm_off = 1 if $cpuconf->{hidden
};
3348 if (defined(my $flags = $cpuconf->{flags
})) {
3349 push @$cpuFlags, split(";", $flags);
3353 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3355 push @$cpuFlags , '-x2apic'
3356 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3358 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3360 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3362 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3364 push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
3365 push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
3368 add_hyperv_enlightenments
($cpuFlags, $winversion, $machine_type, $kvmver, $conf->{bios
}, $gpu_passthrough) if $kvm;
3370 push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm;
3372 push @$cpuFlags, 'kvm=off' if $kvm_off;
3374 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3375 die "internal error"; # should not happen
3377 push @$cpuFlags, "vendor=${cpu_vendor}"
3378 if $cpu_vendor ne 'default';
3380 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3382 push @$cmd, '-cpu', $cpu;
3384 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3386 push @$cmd, '-S' if $conf->{freeze
};
3388 push @$cmd, '-k', $conf->{keyboard
} if defined($conf->{keyboard
});
3391 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3392 #push @$cmd, '-soundhw', 'es1370';
3393 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3395 if($conf->{agent
}) {
3396 my $qgasocket = qmp_socket
($vmid, 1);
3397 my $pciaddr = print_pci_addr
("qga0", $bridges);
3398 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3399 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3400 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3408 for(my $i = 1; $i < $qxlnum; $i++){
3409 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3410 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3413 # assume other OS works like Linux
3414 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3415 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3419 my $pciaddr = print_pci_addr
("spice", $bridges);
3421 my $nodename = PVE
::INotify
::nodename
();
3422 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3423 my @nodeaddrs = PVE
::Tools
::getaddrinfo_all
('localhost', family
=> $pfamily);
3424 die "failed to get an ip address of type $pfamily for 'localhost'\n" if !@nodeaddrs;
3425 my $localhost = PVE
::Network
::addr_to_ip
($nodeaddrs[0]->{addr
});
3426 $spice_port = PVE
::Tools
::next_spice_port
($pfamily, $localhost);
3428 push @$devices, '-spice', "tls-port=${spice_port},addr=$localhost,tls-ciphers=HIGH,seamless-migration=on";
3430 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3431 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3432 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3435 # enable balloon by default, unless explicitly disabled
3436 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3437 $pciaddr = print_pci_addr
("balloon0", $bridges);
3438 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3441 if ($conf->{watchdog
}) {
3442 my $wdopts = parse_watchdog
($conf->{watchdog
});
3443 $pciaddr = print_pci_addr
("watchdog", $bridges);
3444 my $watchdog = $wdopts->{model
} || 'i6300esb';
3445 push @$devices, '-device', "$watchdog$pciaddr";
3446 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3450 my $scsicontroller = {};
3451 my $ahcicontroller = {};
3452 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3454 # Add iscsi initiator name if available
3455 if (my $initiator = get_initiator_name
()) {
3456 push @$devices, '-iscsi', "initiator-name=$initiator";
3459 foreach_drive
($conf, sub {
3460 my ($ds, $drive) = @_;
3462 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3463 push @$vollist, $drive->{file
};
3466 # ignore efidisk here, already added in bios/fw handling code above
3467 return if $drive->{interface
} eq 'efidisk';
3469 $use_virtio = 1 if $ds =~ m/^virtio/;
3471 if (drive_is_cdrom
($drive)) {
3472 if ($bootindex_hash->{d
}) {
3473 $drive->{bootindex
} = $bootindex_hash->{d
};
3474 $bootindex_hash->{d
} += 1;
3477 if ($bootindex_hash->{c
}) {
3478 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3479 $bootindex_hash->{c
} += 1;
3483 if($drive->{interface
} eq 'virtio'){
3484 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3487 if ($drive->{interface
} eq 'scsi') {
3489 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3491 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3492 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3495 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3496 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3497 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3498 } elsif ($drive->{iothread
}) {
3499 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3503 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3504 $queues = ",num_queues=$drive->{queues}";
3507 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3508 $scsicontroller->{$controller}=1;
3511 if ($drive->{interface
} eq 'sata') {
3512 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3513 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3514 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3515 $ahcicontroller->{$controller}=1;
3518 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3519 push @$devices, '-drive',$drive_cmd;
3520 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3523 for (my $i = 0; $i < $MAX_NETS; $i++) {
3524 next if !$conf->{"net$i"};
3525 my $d = parse_net
($conf->{"net$i"});
3528 $use_virtio = 1 if $d->{model
} eq 'virtio';
3530 if ($bootindex_hash->{n
}) {
3531 $d->{bootindex
} = $bootindex_hash->{n
};
3532 $bootindex_hash->{n
} += 1;
3535 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3536 push @$devices, '-netdev', $netdevfull;
3538 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3539 push @$devices, '-device', $netdevicefull;
3544 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3549 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3551 while (my ($k, $v) = each %$bridges) {
3552 $pciaddr = print_pci_addr
("pci.$k");
3553 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3558 if ($conf->{args
}) {
3559 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3563 push @$cmd, @$devices;
3564 push @$cmd, '-rtc', join(',', @$rtcFlags)
3565 if scalar(@$rtcFlags);
3566 push @$cmd, '-machine', join(',', @$machineFlags)
3567 if scalar(@$machineFlags);
3568 push @$cmd, '-global', join(',', @$globalFlags)
3569 if scalar(@$globalFlags);
3571 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3576 return "${var_run_tmpdir}/$vmid.vnc";
3582 my $res = vm_mon_cmd
($vmid, 'query-spice');
3584 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3588 my ($vmid, $qga) = @_;
3589 my $sockettype = $qga ?
'qga' : 'qmp';
3590 return "${var_run_tmpdir}/$vmid.$sockettype";
3595 return "${var_run_tmpdir}/$vmid.pid";
3598 sub vm_devices_list
{
3601 my $res = vm_mon_cmd
($vmid, 'query-pci');
3603 foreach my $pcibus (@$res) {
3604 foreach my $device (@{$pcibus->{devices
}}) {
3605 next if !$device->{'qdev_id'};
3606 if ($device->{'pci_bridge'}) {
3607 $devices->{$device->{'qdev_id'}} = 1;
3608 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3609 next if !$bridge_device->{'qdev_id'};
3610 $devices->{$bridge_device->{'qdev_id'}} = 1;
3611 $devices->{$device->{'qdev_id'}}++;
3614 $devices->{$device->{'qdev_id'}} = 1;
3619 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3620 foreach my $block (@$resblock) {
3621 if($block->{device
} =~ m/^drive-(\S+)/){
3626 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3627 foreach my $mice (@$resmice) {
3628 if ($mice->{name
} eq 'QEMU HID Tablet') {
3629 $devices->{tablet
} = 1;
3634 # for usb devices there is no query-usb
3635 # but we can iterate over the entries in
3636 # qom-list path=/machine/peripheral
3637 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3638 foreach my $per (@$resperipheral) {
3639 if ($per->{name
} =~ m/^usb\d+$/) {
3640 $devices->{$per->{name
}} = 1;
3648 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3650 my $q35 = machine_type_is_q35
($conf);
3652 my $devices_list = vm_devices_list
($vmid);
3653 return 1 if defined($devices_list->{$deviceid});
3655 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3657 if ($deviceid eq 'tablet') {
3659 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3661 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3663 die "usb hotplug currently not reliable\n";
3664 # since we can't reliably hot unplug all added usb devices
3665 # and usb passthrough disables live migration
3666 # we disable usb hotplugging for now
3667 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3669 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3671 qemu_iothread_add
($vmid, $deviceid, $device);
3673 qemu_driveadd
($storecfg, $vmid, $device);
3674 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3676 qemu_deviceadd
($vmid, $devicefull);
3677 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3679 eval { qemu_drivedel
($vmid, $deviceid); };
3684 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3687 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3688 my $pciaddr = print_pci_addr
($deviceid);
3689 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3691 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3693 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3694 qemu_iothread_add
($vmid, $deviceid, $device);
3695 $devicefull .= ",iothread=iothread-$deviceid";
3698 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3699 $devicefull .= ",num_queues=$device->{queues}";
3702 qemu_deviceadd
($vmid, $devicefull);
3703 qemu_deviceaddverify
($vmid, $deviceid);
3705 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3707 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3708 qemu_driveadd
($storecfg, $vmid, $device);
3710 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3711 eval { qemu_deviceadd
($vmid, $devicefull); };
3713 eval { qemu_drivedel
($vmid, $deviceid); };
3718 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3720 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3722 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3723 my $use_old_bios_files = undef;
3724 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3726 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3727 qemu_deviceadd
($vmid, $netdevicefull);
3728 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3730 eval { qemu_netdevdel
($vmid, $deviceid); };
3735 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3738 my $pciaddr = print_pci_addr
($deviceid);
3739 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3741 qemu_deviceadd
($vmid, $devicefull);
3742 qemu_deviceaddverify
($vmid, $deviceid);
3745 die "can't hotplug device '$deviceid'\n";
3751 # fixme: this should raise exceptions on error!
3752 sub vm_deviceunplug
{
3753 my ($vmid, $conf, $deviceid) = @_;
3755 my $devices_list = vm_devices_list
($vmid);
3756 return 1 if !defined($devices_list->{$deviceid});
3758 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3760 if ($deviceid eq 'tablet') {
3762 qemu_devicedel
($vmid, $deviceid);
3764 } elsif ($deviceid =~ m/^usb\d+$/) {
3766 die "usb hotplug currently not reliable\n";
3767 # when unplugging usb devices this way,
3768 # there may be remaining usb controllers/hubs
3769 # so we disable it for now
3770 qemu_devicedel
($vmid, $deviceid);
3771 qemu_devicedelverify
($vmid, $deviceid);
3773 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3775 qemu_devicedel
($vmid, $deviceid);
3776 qemu_devicedelverify
($vmid, $deviceid);
3777 qemu_drivedel
($vmid, $deviceid);
3778 qemu_iothread_del
($conf, $vmid, $deviceid);
3780 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3782 qemu_devicedel
($vmid, $deviceid);
3783 qemu_devicedelverify
($vmid, $deviceid);
3784 qemu_iothread_del
($conf, $vmid, $deviceid);
3786 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3788 qemu_devicedel
($vmid, $deviceid);
3789 qemu_drivedel
($vmid, $deviceid);
3790 qemu_deletescsihw
($conf, $vmid, $deviceid);
3792 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3794 qemu_devicedel
($vmid, $deviceid);
3795 qemu_devicedelverify
($vmid, $deviceid);
3796 qemu_netdevdel
($vmid, $deviceid);
3799 die "can't unplug device '$deviceid'\n";
3805 sub qemu_deviceadd
{
3806 my ($vmid, $devicefull) = @_;
3808 $devicefull = "driver=".$devicefull;
3809 my %options = split(/[=,]/, $devicefull);
3811 vm_mon_cmd
($vmid, "device_add" , %options);
3814 sub qemu_devicedel
{
3815 my ($vmid, $deviceid) = @_;
3817 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3820 sub qemu_iothread_add
{
3821 my($vmid, $deviceid, $device) = @_;
3823 if ($device->{iothread
}) {
3824 my $iothreads = vm_iothreads_list
($vmid);
3825 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3829 sub qemu_iothread_del
{
3830 my($conf, $vmid, $deviceid) = @_;
3832 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3833 if ($device->{iothread
}) {
3834 my $iothreads = vm_iothreads_list
($vmid);
3835 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3839 sub qemu_objectadd
{
3840 my($vmid, $objectid, $qomtype) = @_;
3842 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3847 sub qemu_objectdel
{
3848 my($vmid, $objectid) = @_;
3850 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3856 my ($storecfg, $vmid, $device) = @_;
3858 my $drive = print_drive_full
($storecfg, $vmid, $device);
3859 $drive =~ s/\\/\\\\/g;
3860 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3862 # If the command succeeds qemu prints: "OK
"
3863 return 1 if $ret =~ m/OK/s;
3865 die "adding drive failed
: $ret\n";
3869 my($vmid, $deviceid) = @_;
3871 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3874 return 1 if $ret eq "";
3876 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3877 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3879 die "deleting drive
$deviceid failed
: $ret\n";
3882 sub qemu_deviceaddverify {
3883 my ($vmid, $deviceid) = @_;
3885 for (my $i = 0; $i <= 5; $i++) {
3886 my $devices_list = vm_devices_list($vmid);
3887 return 1 if defined($devices_list->{$deviceid});
3891 die "error on hotplug device
'$deviceid'\n";
3895 sub qemu_devicedelverify {
3896 my ($vmid, $deviceid) = @_;
3898 # need to verify that the device is correctly removed as device_del
3899 # is async and empty return is not reliable
3901 for (my $i = 0; $i <= 5; $i++) {
3902 my $devices_list = vm_devices_list($vmid);
3903 return 1 if !defined($devices_list->{$deviceid});
3907 die "error on hot-unplugging device
'$deviceid'\n";
3910 sub qemu_findorcreatescsihw {
3911 my ($storecfg, $conf, $vmid, $device) = @_;
3913 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3915 my $scsihwid="$controller_prefix$controller";
3916 my $devices_list = vm_devices_list($vmid);
3918 if(!defined($devices_list->{$scsihwid})) {
3919 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3925 sub qemu_deletescsihw {
3926 my ($conf, $vmid, $opt) = @_;
3928 my $device = parse_drive($opt, $conf->{$opt});
3930 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3931 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3935 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3937 my $devices_list = vm_devices_list($vmid);
3938 foreach my $opt (keys %{$devices_list}) {
3939 if (PVE::QemuServer::is_valid_drivename($opt)) {
3940 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3941 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3947 my $scsihwid="scsihw
$controller";
3949 vm_deviceunplug($vmid, $conf, $scsihwid);
3954 sub qemu_add_pci_bridge {
3955 my ($storecfg, $conf, $vmid, $device) = @_;
3961 print_pci_addr($device, $bridges);
3963 while (my ($k, $v) = each %$bridges) {
3966 return 1 if !defined($bridgeid) || $bridgeid < 1;
3968 my $bridge = "pci
.$bridgeid";
3969 my $devices_list = vm_devices_list($vmid);
3971 if (!defined($devices_list->{$bridge})) {
3972 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3978 sub qemu_set_link_status {
3979 my ($vmid, $device, $up) = @_;
3981 vm_mon_cmd($vmid, "set_link
", name => $device,
3982 up => $up ? JSON::true : JSON::false);
3985 sub qemu_netdevadd {
3986 my ($vmid, $conf, $device, $deviceid) = @_;
3988 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3989 my %options = split(/[=,]/, $netdev);
3991 vm_mon_cmd($vmid, "netdev_add
", %options);
3995 sub qemu_netdevdel {
3996 my ($vmid, $deviceid) = @_;
3998 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
4001 sub qemu_usb_hotplug {
4002 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
4006 # remove the old one first
4007 vm_deviceunplug($vmid, $conf, $deviceid);
4009 # check if xhci controller is necessary and available
4010 if ($device->{usb3}) {
4012 my $devicelist = vm_devices_list($vmid);
4014 if (!$devicelist->{xhci}) {
4015 my $pciaddr = print_pci_addr("xhci
");
4016 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
4019 my $d = parse_usb_device($device->{host});
4020 $d->{usb3} = $device->{usb3};
4023 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
4026 sub qemu_cpu_hotplug {
4027 my ($vmid, $conf, $vcpus) = @_;
4029 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
4032 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
4033 $sockets = $conf->{sockets} if $conf->{sockets};
4034 my $cores = $conf->{cores} || 1;
4035 my $maxcpus = $sockets * $cores;
4037 $vcpus = $maxcpus if !$vcpus;
4039 die "you can
't add more vcpus than maxcpus\n"
4040 if $vcpus > $maxcpus;
4042 my $currentvcpus = $conf->{vcpus} || $maxcpus;
4044 if ($vcpus < $currentvcpus) {
4046 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
4048 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
4049 qemu_devicedel($vmid, "cpu$i");
4051 my $currentrunningvcpus = undef;
4053 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
4054 last if scalar(@{$currentrunningvcpus}) == $i-1;
4055 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
4059 #update conf after each succesfull cpu unplug
4060 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
4061 PVE::QemuConfig->write_config($vmid, $conf);
4064 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
4070 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
4071 die "vcpus in running vm does not match its configuration\n"
4072 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
4074 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
4076 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
4077 my $cpustr = print_cpu_device($conf, $i);
4078 qemu_deviceadd($vmid, $cpustr);
4081 my $currentrunningvcpus = undef;
4083 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
4084 last if scalar(@{$currentrunningvcpus}) == $i;
4085 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
4089 #update conf after each succesfull cpu hotplug
4090 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
4091 PVE::QemuConfig->write_config($vmid, $conf);
4095 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
4096 vm_mon_cmd($vmid, "cpu-add", id => int($i));
4101 sub qemu_block_set_io_throttle {
4102 my ($vmid, $deviceid,
4103 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
4104 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
4105 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
4106 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
4108 return if !check_running($vmid) ;
4110 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
4112 bps_rd => int($bps_rd),
4113 bps_wr => int($bps_wr),
4115 iops_rd => int($iops_rd),
4116 iops_wr => int($iops_wr),
4117 bps_max => int($bps_max),
4118 bps_rd_max => int($bps_rd_max),
4119 bps_wr_max => int($bps_wr_max),
4120 iops_max => int($iops_max),
4121 iops_rd_max => int($iops_rd_max),
4122 iops_wr_max => int($iops_wr_max),
4123 bps_max_length => int($bps_max_length),
4124 bps_rd_max_length => int($bps_rd_max_length),
4125 bps_wr_max_length => int($bps_wr_max_length),
4126 iops_max_length => int($iops_max_length),
4127 iops_rd_max_length => int($iops_rd_max_length),
4128 iops_wr_max_length => int($iops_wr_max_length),
4133 # old code, only used to shutdown old VM after update
4135 my ($fh, $timeout) = @_;
4137 my $sel = new IO::Select;
4144 while (scalar (@ready = $sel->can_read($timeout))) {
4146 if ($count = $fh->sysread($buf, 8192)) {
4147 if ($buf =~ /^(.*)\(qemu\) $/s) {
4154 if (!defined($count)) {
4161 die "monitor read timeout\n" if !scalar(@ready);
4166 sub qemu_block_resize {
4167 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4169 my $running = check_running($vmid);
4171 $size = 0 if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4173 return if !$running;
4175 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4179 sub qemu_volume_snapshot {
4180 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4182 my $running = check_running($vmid);
4184 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4185 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4187 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4191 sub qemu_volume_snapshot_delete {
4192 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4194 my $running = check_running($vmid);
4196 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4197 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4199 PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4203 sub set_migration_caps {
4209 "auto-converge" => 1,
4211 "x-rdma-pin-all" => 0,
4216 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4218 for my $supported_capability (@$supported_capabilities) {
4220 capability => $supported_capability->{capability},
4221 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4225 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4228 my $fast_plug_option = {
4236 'vmstatestorage
' => 1,
4239 # hotplug changes in [PENDING]
4240 # $selection hash can be used to only apply specified options, for
4241 # example: { cores => 1 } (only apply changed 'cores
')
4242 # $errors ref is used to return error messages
4243 sub vmconfig_hotplug_pending {
4244 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4246 my $defaults = load_defaults();
4248 # commit values which do not have any impact on running VM first
4249 # Note: those option cannot raise errors, we we do not care about
4250 # $selection and always apply them.
4252 my $add_error = sub {
4253 my ($opt, $msg) = @_;
4254 $errors->{$opt} = "hotplug problem - $msg";
4258 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4259 if ($fast_plug_option->{$opt}) {
4260 $conf->{$opt} = $conf->{pending}->{$opt};
4261 delete $conf->{pending}->{$opt};
4267 PVE::QemuConfig->write_config($vmid, $conf);
4268 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4271 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4273 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4274 while (my ($opt, $force) = each %$pending_delete_hash) {
4275 next if $selection && !$selection->{$opt};
4277 if ($opt eq 'hotplug
') {
4278 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4279 } elsif ($opt eq 'tablet
') {
4280 die "skip\n" if !$hotplug_features->{usb};
4281 if ($defaults->{tablet}) {
4282 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4284 vm_deviceunplug($vmid, $conf, $opt);
4286 } elsif ($opt =~ m/^usb\d+/) {
4288 # since we cannot reliably hot unplug usb devices
4289 # we are disabling it
4290 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4291 vm_deviceunplug($vmid, $conf, $opt);
4292 } elsif ($opt eq 'vcpus
') {
4293 die "skip\n" if !$hotplug_features->{cpu};
4294 qemu_cpu_hotplug($vmid, $conf, undef);
4295 } elsif ($opt eq 'balloon
') {
4296 # enable balloon device is not hotpluggable
4297 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4298 } elsif ($fast_plug_option->{$opt}) {
4300 } elsif ($opt =~ m/^net(\d+)$/) {
4301 die "skip\n" if !$hotplug_features->{network};
4302 vm_deviceunplug($vmid, $conf, $opt);
4303 } elsif (is_valid_drivename($opt)) {
4304 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4305 vm_deviceunplug($vmid, $conf, $opt);
4306 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4307 } elsif ($opt =~ m/^memory$/) {
4308 die "skip\n" if !$hotplug_features->{memory};
4309 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4310 } elsif ($opt eq 'cpuunits
') {
4311 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4312 } elsif ($opt eq 'cpulimit
') {
4313 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4319 &$add_error($opt, $err) if $err ne "skip\n";
4321 # save new config if hotplug was successful
4322 delete $conf->{$opt};
4323 vmconfig_undelete_pending_option($conf, $opt);
4324 PVE::QemuConfig->write_config($vmid, $conf);
4325 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4329 my $apply_pending_cloudinit;
4330 $apply_pending_cloudinit = sub {
4331 my ($key, $value) = @_;
4332 $apply_pending_cloudinit = sub {}; # once is enough
4334 my @cloudinit_opts = keys %$confdesc_cloudinit;
4335 foreach my $opt (keys %{$conf->{pending}}) {
4336 next if !grep { $_ eq $opt } @cloudinit_opts;
4337 $conf->{$opt} = delete $conf->{pending}->{$opt};
4340 my $new_conf = { %$conf };
4341 $new_conf->{$key} = $value;
4342 PVE::QemuServer::Cloudinit::generate_cloudinitconfig($new_conf, $vmid);
4345 foreach my $opt (keys %{$conf->{pending}}) {
4346 next if $selection && !$selection->{$opt};
4347 my $value = $conf->{pending}->{$opt};
4349 if ($opt eq 'hotplug
') {
4350 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4351 } elsif ($opt eq 'tablet
') {
4352 die "skip\n" if !$hotplug_features->{usb};
4354 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4355 } elsif ($value == 0) {
4356 vm_deviceunplug($vmid, $conf, $opt);
4358 } elsif ($opt =~ m/^usb\d+$/) {
4360 # since we cannot reliably hot unplug usb devices
4361 # we are disabling it
4362 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4363 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4364 die "skip\n" if !$d;
4365 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4366 } elsif ($opt eq 'vcpus
') {
4367 die "skip\n" if !$hotplug_features->{cpu};
4368 qemu_cpu_hotplug($vmid, $conf, $value);
4369 } elsif ($opt eq 'balloon
') {
4370 # enable/disable balloning device is not hotpluggable
4371 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4372 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4373 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4375 # allow manual ballooning if shares is set to zero
4376 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4377 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4378 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4380 } elsif ($opt =~ m/^net(\d+)$/) {
4381 # some changes can be done without hotplug
4382 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4383 $vmid, $opt, $value);
4384 } elsif (is_valid_drivename($opt)) {
4385 # some changes can be done without hotplug
4386 my $drive = parse_drive($opt, $value);
4387 if (drive_is_cloudinit($drive)) {
4388 &$apply_pending_cloudinit($opt, $value);
4390 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4391 $vmid, $opt, $value, 1);
4392 } elsif ($opt =~ m/^memory$/) { #dimms
4393 die "skip\n" if !$hotplug_features->{memory};
4394 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4395 } elsif ($opt eq 'cpuunits
') {
4396 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4397 } elsif ($opt eq 'cpulimit
') {
4398 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4399 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4401 die "skip\n"; # skip non-hot-pluggable options
4405 &$add_error($opt, $err) if $err ne "skip\n";
4407 # save new config if hotplug was successful
4408 $conf->{$opt} = $value;
4409 delete $conf->{pending}->{$opt};
4410 PVE::QemuConfig->write_config($vmid, $conf);
4411 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4416 sub try_deallocate_drive {
4417 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4419 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4420 my $volid = $drive->{file};
4421 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4422 my $sid = PVE::Storage::parse_volume_id($volid);
4423 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4425 # check if the disk is really unused
4426 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4427 if is_volume_in_use($storecfg, $conf, $key, $volid);
4428 PVE::Storage::vdisk_free($storecfg, $volid);
4431 # If vm is not owner of this disk remove from config
4439 sub vmconfig_delete_or_detach_drive {
4440 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4442 my $drive = parse_drive($opt, $conf->{$opt});
4444 my $rpcenv = PVE::RPCEnvironment::get();
4445 my $authuser = $rpcenv->get_user();
4448 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4449 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4451 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4455 sub vmconfig_apply_pending {
4456 my ($vmid, $conf, $storecfg) = @_;
4460 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4461 while (my ($opt, $force) = each %$pending_delete_hash) {
4462 die "internal error" if $opt =~ m/^unused/;
4463 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4464 if (!defined($conf->{$opt})) {
4465 vmconfig_undelete_pending_option($conf, $opt);
4466 PVE::QemuConfig->write_config($vmid, $conf);
4467 } elsif (is_valid_drivename($opt)) {
4468 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4469 vmconfig_undelete_pending_option($conf, $opt);
4470 delete $conf->{$opt};
4471 PVE::QemuConfig->write_config($vmid, $conf);
4473 vmconfig_undelete_pending_option($conf, $opt);
4474 delete $conf->{$opt};
4475 PVE::QemuConfig->write_config($vmid, $conf);
4479 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4481 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4482 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4484 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4485 # skip if nothing changed
4486 } elsif (is_valid_drivename($opt)) {
4487 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4488 if defined($conf->{$opt});
4489 $conf->{$opt} = $conf->{pending}->{$opt};
4491 $conf->{$opt} = $conf->{pending}->{$opt};
4494 delete $conf->{pending}->{$opt};
4495 PVE::QemuConfig->write_config($vmid, $conf);
4499 my $safe_num_ne = sub {
4502 return 0 if !defined($a) && !defined($b);
4503 return 1 if !defined($a);
4504 return 1 if !defined($b);
4509 my $safe_string_ne = sub {
4512 return 0 if !defined($a) && !defined($b);
4513 return 1 if !defined($a);
4514 return 1 if !defined($b);
4519 sub vmconfig_update_net {
4520 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4522 my $newnet = parse_net($value);
4524 if ($conf->{$opt}) {
4525 my $oldnet = parse_net($conf->{$opt});
4527 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4528 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4529 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4530 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4532 # for non online change, we try to hot-unplug
4533 die "skip\n" if !$hotplug;
4534 vm_deviceunplug($vmid, $conf, $opt);
4537 die "internal error" if $opt !~ m/net(\d+)/;
4538 my $iface = "tap${vmid}i$1";
4540 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4541 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4542 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4543 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4544 PVE::Network::tap_unplug($iface);
4545 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4546 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4547 # Rate can be applied on its own but any change above needs to
4548 # include the rate in tap_plug since OVS resets everything.
4549 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4552 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4553 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4561 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4567 sub vmconfig_update_disk {
4568 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4570 # fixme: do we need force?
4572 my $drive = parse_drive($opt, $value);
4574 if ($conf->{$opt}) {
4576 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4578 my $media = $drive->{media} || 'disk
';
4579 my $oldmedia = $old_drive->{media} || 'disk
';
4580 die "unable to change media type\n" if $media ne $oldmedia;
4582 if (!drive_is_cdrom($old_drive)) {
4584 if ($drive->{file} ne $old_drive->{file}) {
4586 die "skip\n" if !$hotplug;
4588 # unplug and register as unused
4589 vm_deviceunplug($vmid, $conf, $opt);
4590 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4593 # update existing disk
4595 # skip non hotpluggable value
4596 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4597 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4598 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4599 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4604 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4605 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4606 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4607 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4608 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4609 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4610 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4611 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4612 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4613 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4614 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4615 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4616 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4617 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4618 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4619 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4620 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4621 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4623 qemu_block_set_io_throttle($vmid,"drive-$opt",
4624 ($drive->{mbps} || 0)*1024*1024,
4625 ($drive->{mbps_rd} || 0)*1024*1024,
4626 ($drive->{mbps_wr} || 0)*1024*1024,
4627 $drive->{iops} || 0,
4628 $drive->{iops_rd} || 0,
4629 $drive->{iops_wr} || 0,
4630 ($drive->{mbps_max} || 0)*1024*1024,
4631 ($drive->{mbps_rd_max} || 0)*1024*1024,
4632 ($drive->{mbps_wr_max} || 0)*1024*1024,
4633 $drive->{iops_max} || 0,
4634 $drive->{iops_rd_max} || 0,
4635 $drive->{iops_wr_max} || 0,
4636 $drive->{bps_max_length} || 1,
4637 $drive->{bps_rd_max_length} || 1,
4638 $drive->{bps_wr_max_length} || 1,
4639 $drive->{iops_max_length} || 1,
4640 $drive->{iops_rd_max_length} || 1,
4641 $drive->{iops_wr_max_length} || 1);
4650 if ($drive->{file} eq 'none
') {
4651 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4652 if (drive_is_cloudinit($old_drive)) {
4653 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive);
4656 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4657 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4658 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4666 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4668 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4669 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4673 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4674 $forcemachine, $spice_ticket, $migration_network, $migration_type, $targetstorage) = @_;
4676 PVE::QemuConfig->lock_config($vmid, sub {
4677 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4679 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4681 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4683 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4685 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4686 vmconfig_apply_pending($vmid, $conf, $storecfg);
4687 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4690 PVE::QemuServer::Cloudinit::generate_cloudinitconfig($conf, $vmid);
4692 my $defaults = load_defaults();
4694 # set environment variable useful inside network script
4695 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4697 my $local_volumes = {};
4699 if ($targetstorage) {
4700 foreach_drive($conf, sub {
4701 my ($ds, $drive) = @_;
4703 return if drive_is_cdrom($drive);
4705 my $volid = $drive->{file};
4709 my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
4711 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4712 return if $scfg->{shared};
4713 $local_volumes->{$ds} = [$volid, $storeid, $volname];
4718 foreach my $opt (sort keys %$local_volumes) {
4720 my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
4721 my $drive = parse_drive($opt, $conf->{$opt});
4723 #if remote storage is specified, use default format
4724 if ($targetstorage && $targetstorage ne "1") {
4725 $storeid = $targetstorage;
4726 my ($defFormat, $validFormats) = PVE::Storage::storage_default_format($storecfg, $storeid);
4727 $format = $defFormat;
4729 #else we use same format than original
4730 my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
4731 $format = qemu_img_format($scfg, $volid);
4734 my $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, undef, ($drive->{size}/1024));
4735 my $newdrive = $drive;
4736 $newdrive->{format} = $format;
4737 $newdrive->{file} = $newvolid;
4738 my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
4739 $local_volumes->{$opt} = $drivestr;
4740 #pass drive to conf for command line
4741 $conf->{$opt} = $drivestr;
4745 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4747 my $migrate_port = 0;
4750 if ($statefile eq 'tcp
') {
4751 my $localip = "localhost";
4752 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4753 my $nodename = PVE::INotify::nodename();
4755 if (!defined($migration_type)) {
4756 if (defined($datacenterconf->{migration}->{type})) {
4757 $migration_type = $datacenterconf->{migration}->{type};
4759 $migration_type = 'secure
';
4763 if ($migration_type eq 'insecure
') {
4764 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4765 if ($migrate_network_addr) {
4766 $localip = $migrate_network_addr;
4768 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4771 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4774 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4775 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4776 $migrate_uri = "tcp:${localip}:${migrate_port}";
4777 push @$cmd, '-incoming
', $migrate_uri;
4780 } elsif ($statefile eq 'unix
') {
4781 # should be default for secure migrations as a ssh TCP forward
4782 # tunnel is not deterministic reliable ready and fails regurarly
4783 # to set up in time, so use UNIX socket forwards
4784 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4785 unlink $socket_addr;
4787 $migrate_uri = "unix:$socket_addr";
4789 push @$cmd, '-incoming
', $migrate_uri;
4793 push @$cmd, '-loadstate
', $statefile;
4800 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4801 my $d = parse_hostpci($conf->{"hostpci$i"});
4803 my $pcidevices = $d->{pciid};
4804 foreach my $pcidevice (@$pcidevices) {
4805 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4807 my $info = pci_device_info("0000:$pciid");
4808 die "IOMMU not present\n" if !check_iommu_support();
4809 die "no pci device info for device '$pciid'\n" if !$info;
4810 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4811 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4815 PVE::Storage::activate_volumes($storecfg, $vollist);
4817 if (!check_running($vmid, 1)) {
4819 run_command(['/bin/systemctl
', 'stop
', "$vmid.scope"],
4820 outfunc => sub {}, errfunc => sub {});
4824 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4825 : $defaults->{cpuunits};
4827 my $start_timeout = $conf->{hugepages} ? 300 : 30;
4828 my %run_params = (timeout => $statefile ? undef : $start_timeout, umask => 0077);
4831 Slice => 'qemu
.slice
',
4833 CPUShares => $cpuunits
4836 if (my $cpulimit = $conf->{cpulimit}) {
4837 $properties{CPUQuota} = int($cpulimit * 100);
4839 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4841 if ($conf->{hugepages}) {
4844 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4845 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4847 PVE::QemuServer::Memory::hugepages_mount();
4848 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4851 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4852 run_command($cmd, %run_params);
4856 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4860 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4862 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4866 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4867 run_command($cmd, %run_params);
4872 # deactivate volumes if start fails
4873 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4874 die "start failed: $err";
4877 print "migration listens on $migrate_uri\n" if $migrate_uri;
4879 if ($statefile && $statefile ne 'tcp
' && $statefile ne 'unix
') {
4880 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4884 #start nbd server for storage migration
4885 if ($targetstorage) {
4886 my $nodename = PVE::INotify::nodename();
4887 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4888 my $localip = $migrate_network_addr ? $migrate_network_addr : PVE::Cluster::remote_node_ip($nodename, 1);
4889 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4890 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4892 vm_mon_cmd_nocheck($vmid, "nbd-server-start", addr => { type => 'inet
', data => { host => "${localip}", port => "${migrate_port}" } } );
4894 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4896 foreach my $opt (sort keys %$local_volumes) {
4897 my $volid = $local_volumes->{$opt};
4898 vm_mon_cmd_nocheck($vmid, "nbd-server-add", device => "drive-$opt", writable => JSON::true );
4899 my $migrate_storage_uri = "nbd:${localip}:${migrate_port}:exportname=drive-$opt";
4900 print "storage migration listens on $migrate_storage_uri volume:$volid\n";
4904 if ($migratedfrom) {
4906 set_migration_caps($vmid);
4911 print "spice listens on port $spice_port\n";
4912 if ($spice_ticket) {
4913 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4914 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4919 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4920 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4921 if $conf->{balloon};
4924 foreach my $opt (keys %$conf) {
4925 next if $opt !~ m/^net\d+$/;
4926 my $nicconf = parse_net($conf->{$opt});
4927 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4931 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4932 path => "machine/peripheral/balloon0",
4933 property => "guest-stats-polling-interval",
4934 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4940 my ($vmid, $execute, %params) = @_;
4942 my $cmd = { execute => $execute, arguments => \%params };
4943 vm_qmp_command($vmid, $cmd);
4946 sub vm_mon_cmd_nocheck {
4947 my ($vmid, $execute, %params) = @_;
4949 my $cmd = { execute => $execute, arguments => \%params };
4950 vm_qmp_command($vmid, $cmd, 1);
4953 sub vm_qmp_command {
4954 my ($vmid, $cmd, $nocheck) = @_;
4959 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4960 $timeout = $cmd->{arguments}->{timeout};
4961 delete $cmd->{arguments}->{timeout};
4965 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4966 my $sname = qmp_socket($vmid);
4967 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4968 my $qmpclient = PVE::QMPClient->new();
4970 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4972 die "unable to open monitor socket\n";
4976 syslog("err", "VM $vmid qmp command failed - $err");
4983 sub vm_human_monitor_command {
4984 my ($vmid, $cmdline) = @_;
4989 execute => 'human-monitor-command
',
4990 arguments => { 'command-line
' => $cmdline},
4993 return vm_qmp_command($vmid, $cmd);
4996 sub vm_commandline {
4997 my ($storecfg, $vmid) = @_;
4999 my $conf = PVE::QemuConfig->load_config($vmid);
5001 my $defaults = load_defaults();
5003 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
5005 return PVE::Tools::cmd2string($cmd);
5009 my ($vmid, $skiplock) = @_;
5011 PVE::QemuConfig->lock_config($vmid, sub {
5013 my $conf = PVE::QemuConfig->load_config($vmid);
5015 PVE::QemuConfig->check_lock($conf) if !$skiplock;
5017 vm_mon_cmd($vmid, "system_reset");
5021 sub get_vm_volumes {
5025 foreach_volid($conf, sub {
5026 my ($volid, $attr) = @_;
5028 return if $volid =~ m|^/|;
5030 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
5033 push @$vollist, $volid;
5039 sub vm_stop_cleanup {
5040 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
5045 my $vollist = get_vm_volumes($conf);
5046 PVE::Storage::deactivate_volumes($storecfg, $vollist);
5049 foreach my $ext (qw(mon qmp pid vnc qga)) {
5050 unlink "/var/run/qemu-server/${vmid}.$ext";
5053 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
5055 warn $@ if $@; # avoid errors - just warn
5058 # Note: use $nockeck to skip tests if VM configuration file exists.
5059 # We need that when migration VMs to other nodes (files already moved)
5060 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
5062 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
5064 $force = 1 if !defined($force) && !$shutdown;
5067 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
5068 kill 15, $pid if $pid;
5069 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
5070 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
5074 PVE
::QemuConfig-
>lock_config($vmid, sub {
5076 my $pid = check_running
($vmid, $nocheck);
5081 $conf = PVE
::QemuConfig-
>load_config($vmid);
5082 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
5083 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
5084 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
5085 $timeout = $opts->{down
} if $opts->{down
};
5089 $timeout = 60 if !defined($timeout);
5093 if (defined($conf) && $conf->{agent
}) {
5094 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
5096 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
5099 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
5106 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
5111 if ($count >= $timeout) {
5113 warn "VM still running - terminating now with SIGTERM\n";
5116 die "VM quit/powerdown failed - got timeout\n";
5119 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
5124 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
5127 die "VM quit/powerdown failed\n";
5135 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
5140 if ($count >= $timeout) {
5141 warn "VM still running - terminating now with SIGKILL\n";
5146 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
5151 my ($vmid, $skiplock) = @_;
5153 PVE
::QemuConfig-
>lock_config($vmid, sub {
5155 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5157 PVE
::QemuConfig-
>check_lock($conf)
5158 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5160 vm_mon_cmd
($vmid, "stop");
5165 my ($vmid, $skiplock, $nocheck) = @_;
5167 PVE
::QemuConfig-
>lock_config($vmid, sub {
5171 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5173 PVE
::QemuConfig-
>check_lock($conf)
5174 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
5176 vm_mon_cmd
($vmid, "cont");
5179 vm_mon_cmd_nocheck
($vmid, "cont");
5185 my ($vmid, $skiplock, $key) = @_;
5187 PVE
::QemuConfig-
>lock_config($vmid, sub {
5189 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5191 # there is no qmp command, so we use the human monitor command
5192 vm_human_monitor_command
($vmid, "sendkey $key");
5197 my ($storecfg, $vmid, $skiplock) = @_;
5199 PVE
::QemuConfig-
>lock_config($vmid, sub {
5201 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5203 if (!check_running
($vmid)) {
5204 destroy_vm
($storecfg, $vmid, undef, $skiplock);
5206 die "VM $vmid is running - destroy failed\n";
5214 my ($filename, $buf) = @_;
5216 my $fh = IO
::File-
>new($filename, "w");
5217 return undef if !$fh;
5219 my $res = print $fh $buf;
5226 sub pci_device_info
{
5231 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
5232 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
5234 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
5235 return undef if !defined($irq) || $irq !~ m/^\d+$/;
5237 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
5238 return undef if !defined($vendor) || $vendor !~ s/^0x//;
5240 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
5241 return undef if !defined($product) || $product !~ s/^0x//;
5246 product
=> $product,
5252 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
5261 my $name = $dev->{name
};
5263 my $fn = "$pcisysfs/devices/$name/reset";
5265 return file_write
($fn, "1");
5268 sub pci_dev_bind_to_vfio
{
5271 my $name = $dev->{name
};
5273 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5275 if (!-d
$vfio_basedir) {
5276 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5278 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5280 my $testdir = "$vfio_basedir/$name";
5281 return 1 if -d
$testdir;
5283 my $data = "$dev->{vendor} $dev->{product}";
5284 return undef if !file_write
("$vfio_basedir/new_id", $data);
5286 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5287 if (!file_write
($fn, $name)) {
5288 return undef if -f
$fn;
5291 $fn = "$vfio_basedir/bind";
5292 if (! -d
$testdir) {
5293 return undef if !file_write
($fn, $name);
5299 sub pci_dev_group_bind_to_vfio
{
5302 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5304 if (!-d
$vfio_basedir) {
5305 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5307 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5309 # get IOMMU group devices
5310 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5311 my @devs = grep /^0000:/, readdir($D);
5314 foreach my $pciid (@devs) {
5315 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5317 # pci bridges, switches or root ports are not supported
5318 # they have a pci_bus subdirectory so skip them
5319 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5321 my $info = pci_device_info
($1);
5322 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5328 # vzdump restore implementaion
5330 sub tar_archive_read_firstfile
{
5331 my $archive = shift;
5333 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5335 # try to detect archive type first
5336 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5337 die "unable to open file '$archive'\n";
5338 my $firstfile = <$fh>;
5342 die "ERROR: archive contaions no data\n" if !$firstfile;
5348 sub tar_restore_cleanup
{
5349 my ($storecfg, $statfile) = @_;
5351 print STDERR
"starting cleanup\n";
5353 if (my $fd = IO
::File-
>new($statfile, "r")) {
5354 while (defined(my $line = <$fd>)) {
5355 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5358 if ($volid =~ m
|^/|) {
5359 unlink $volid || die 'unlink failed\n';
5361 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5363 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5365 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5367 print STDERR
"unable to parse line in statfile - $line";
5374 sub restore_archive
{
5375 my ($archive, $vmid, $user, $opts) = @_;
5377 my $format = $opts->{format
};
5380 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5381 $format = 'tar' if !$format;
5383 } elsif ($archive =~ m/\.tar$/) {
5384 $format = 'tar' if !$format;
5385 } elsif ($archive =~ m/.tar.lzo$/) {
5386 $format = 'tar' if !$format;
5388 } elsif ($archive =~ m/\.vma$/) {
5389 $format = 'vma' if !$format;
5390 } elsif ($archive =~ m/\.vma\.gz$/) {
5391 $format = 'vma' if !$format;
5393 } elsif ($archive =~ m/\.vma\.lzo$/) {
5394 $format = 'vma' if !$format;
5397 $format = 'vma' if !$format; # default
5400 # try to detect archive format
5401 if ($format eq 'tar') {
5402 return restore_tar_archive
($archive, $vmid, $user, $opts);
5404 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5408 sub restore_update_config_line
{
5409 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5411 return if $line =~ m/^\#qmdump\#/;
5412 return if $line =~ m/^\#vzdump\#/;
5413 return if $line =~ m/^lock:/;
5414 return if $line =~ m/^unused\d+:/;
5415 return if $line =~ m/^parent:/;
5416 return if $line =~ m/^template:/; # restored VM is never a template
5418 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5419 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5420 # try to convert old 1.X settings
5421 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5422 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5423 my ($model, $macaddr) = split(/\=/, $devconfig);
5424 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5427 bridge
=> "vmbr$ind",
5428 macaddr
=> $macaddr,
5430 my $netstr = print_net
($net);
5432 print $outfd "net$cookie->{netcount}: $netstr\n";
5433 $cookie->{netcount
}++;
5435 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5436 my ($id, $netstr) = ($1, $2);
5437 my $net = parse_net
($netstr);
5438 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5439 $netstr = print_net
($net);
5440 print $outfd "$id: $netstr\n";
5441 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5444 my $di = parse_drive
($virtdev, $value);
5445 if (defined($di->{backup
}) && !$di->{backup
}) {
5446 print $outfd "#$line";
5447 } elsif ($map->{$virtdev}) {
5448 delete $di->{format
}; # format can change on restore
5449 $di->{file
} = $map->{$virtdev};
5450 $value = print_drive
($vmid, $di);
5451 print $outfd "$virtdev: $value\n";
5455 } elsif (($line =~ m/^(smbios1: )(.*)/) && $unique) {
5456 my ($uuid, $uuid_str);
5457 UUID
::generate
($uuid);
5458 UUID
::unparse
($uuid, $uuid_str);
5459 my $smbios1 = parse_smbios1
($2);
5460 $smbios1->{uuid
} = $uuid_str;
5461 print $outfd $1.print_smbios1
($smbios1)."\n";
5468 my ($cfg, $vmid) = @_;
5470 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5472 my $volid_hash = {};
5473 foreach my $storeid (keys %$info) {
5474 foreach my $item (@{$info->{$storeid}}) {
5475 next if !($item->{volid
} && $item->{size
});
5476 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5477 $volid_hash->{$item->{volid
}} = $item;
5484 sub is_volume_in_use
{
5485 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5487 my $path = PVE
::Storage
::path
($storecfg, $volid);
5489 my $scan_config = sub {
5490 my ($cref, $snapname) = @_;
5492 foreach my $key (keys %$cref) {
5493 my $value = $cref->{$key};
5494 if (is_valid_drivename
($key)) {
5495 next if $skip_drive && $key eq $skip_drive;
5496 my $drive = parse_drive
($key, $value);
5497 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5498 return 1 if $volid eq $drive->{file
};
5499 if ($drive->{file
} =~ m!^/!) {
5500 return 1 if $drive->{file
} eq $path;
5502 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5504 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5506 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5514 return 1 if &$scan_config($conf);
5518 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5519 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5525 sub update_disksize
{
5526 my ($vmid, $conf, $volid_hash) = @_;
5530 # used and unused disks
5531 my $referenced = {};
5533 # Note: it is allowed to define multiple storages with same path (alias), so
5534 # we need to check both 'volid' and real 'path' (two different volid can point
5535 # to the same path).
5537 my $referencedpath = {};
5540 foreach my $opt (keys %$conf) {
5541 if (is_valid_drivename
($opt)) {
5542 my $drive = parse_drive
($opt, $conf->{$opt});
5543 my $volid = $drive->{file
};
5546 $referenced->{$volid} = 1;
5547 if ($volid_hash->{$volid} &&
5548 (my $path = $volid_hash->{$volid}->{path
})) {
5549 $referencedpath->{$path} = 1;
5552 next if drive_is_cdrom
($drive);
5553 next if !$volid_hash->{$volid};
5555 $drive->{size
} = $volid_hash->{$volid}->{size
};
5556 my $new = print_drive
($vmid, $drive);
5557 if ($new ne $conf->{$opt}) {
5559 $conf->{$opt} = $new;
5564 # remove 'unusedX' entry if volume is used
5565 foreach my $opt (keys %$conf) {
5566 next if $opt !~ m/^unused\d+$/;
5567 my $volid = $conf->{$opt};
5568 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5569 if ($referenced->{$volid} || ($path && $referencedpath->{$path})) {
5571 delete $conf->{$opt};
5574 $referenced->{$volid} = 1;
5575 $referencedpath->{$path} = 1 if $path;
5578 foreach my $volid (sort keys %$volid_hash) {
5579 next if $volid =~ m/vm-$vmid-state-/;
5580 next if $referenced->{$volid};
5581 my $path = $volid_hash->{$volid}->{path
};
5582 next if !$path; # just to be sure
5583 next if $referencedpath->{$path};
5585 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5586 $referencedpath->{$path} = 1; # avoid to add more than once (aliases)
5593 my ($vmid, $nolock) = @_;
5595 my $cfg = PVE
::Storage
::config
();
5597 my $volid_hash = scan_volids
($cfg, $vmid);
5599 my $updatefn = sub {
5602 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5604 PVE
::QemuConfig-
>check_lock($conf);
5607 foreach my $volid (keys %$volid_hash) {
5608 my $info = $volid_hash->{$volid};
5609 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5612 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5614 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5617 if (defined($vmid)) {
5621 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5624 my $vmlist = config_list
();
5625 foreach my $vmid (keys %$vmlist) {
5629 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5635 sub restore_vma_archive
{
5636 my ($archive, $vmid, $user, $opts, $comp) = @_;
5638 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5639 my $readfrom = $archive;
5644 my $qarchive = PVE
::Tools
::shellquote
($archive);
5645 if ($comp eq 'gzip') {
5646 $uncomp = "zcat $qarchive|";
5647 } elsif ($comp eq 'lzop') {
5648 $uncomp = "lzop -d -c $qarchive|";
5650 die "unknown compression method '$comp'\n";
5655 my $tmpdir = "/var/tmp/vzdumptmp$$";
5658 # disable interrupts (always do cleanups)
5662 local $SIG{HUP
} = sub { warn "got interrupt - ignored\n"; };
5664 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5665 POSIX
::mkfifo
($mapfifo, 0600);
5668 my $openfifo = sub {
5669 open($fifofh, '>', $mapfifo) || die $!;
5672 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5679 my $rpcenv = PVE
::RPCEnvironment
::get
();
5681 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5682 my $tmpfn = "$conffile.$$.tmp";
5684 # Note: $oldconf is undef if VM does not exists
5685 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5686 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5688 my $print_devmap = sub {
5689 my $virtdev_hash = {};
5691 my $cfgfn = "$tmpdir/qemu-server.conf";
5693 # we can read the config - that is already extracted
5694 my $fh = IO
::File-
>new($cfgfn, "r") ||
5695 "unable to read qemu-server.conf - $!\n";
5697 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5699 my $pve_firewall_dir = '/etc/pve/firewall';
5700 mkdir $pve_firewall_dir; # make sure the dir exists
5701 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5704 while (defined(my $line = <$fh>)) {
5705 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5706 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5707 die "archive does not contain data for drive '$virtdev'\n"
5708 if !$devinfo->{$devname};
5709 if (defined($opts->{storage
})) {
5710 $storeid = $opts->{storage
} || 'local';
5711 } elsif (!$storeid) {
5714 $format = 'raw' if !$format;
5715 $devinfo->{$devname}->{devname
} = $devname;
5716 $devinfo->{$devname}->{virtdev
} = $virtdev;
5717 $devinfo->{$devname}->{format
} = $format;
5718 $devinfo->{$devname}->{storeid
} = $storeid;
5720 # check permission on storage
5721 my $pool = $opts->{pool
}; # todo: do we need that?
5722 if ($user ne 'root@pam') {
5723 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5726 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5730 foreach my $devname (keys %$devinfo) {
5731 die "found no device mapping information for device '$devname'\n"
5732 if !$devinfo->{$devname}->{virtdev
};
5735 my $cfg = PVE
::Storage
::config
();
5737 # create empty/temp config
5739 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5740 foreach_drive
($oldconf, sub {
5741 my ($ds, $drive) = @_;
5743 return if drive_is_cdrom
($drive);
5745 my $volid = $drive->{file
};
5747 return if !$volid || $volid =~ m
|^/|;
5749 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5750 return if !$path || !$owner || ($owner != $vmid);
5752 # Note: only delete disk we want to restore
5753 # other volumes will become unused
5754 if ($virtdev_hash->{$ds}) {
5755 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5762 # delete vmstate files
5763 # since after the restore we have no snapshots anymore
5764 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5765 my $snap = $oldconf->{snapshots
}->{$snapname};
5766 if ($snap->{vmstate
}) {
5767 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5776 foreach my $virtdev (sort keys %$virtdev_hash) {
5777 my $d = $virtdev_hash->{$virtdev};
5778 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5779 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5781 # test if requested format is supported
5782 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5783 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5784 $d->{format
} = $defFormat if !$supported;
5786 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5787 $d->{format
}, undef, $alloc_size);
5788 print STDERR
"new volume ID is '$volid'\n";
5789 $d->{volid
} = $volid;
5790 my $path = PVE
::Storage
::path
($cfg, $volid);
5792 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5794 my $write_zeros = 1;
5795 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5799 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5801 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5802 $map->{$virtdev} = $volid;
5805 $fh->seek(0, 0) || die "seek failed - $!\n";
5807 my $outfd = new IO
::File
($tmpfn, "w") ||
5808 die "unable to write config for VM $vmid\n";
5810 my $cookie = { netcount
=> 0 };
5811 while (defined(my $line = <$fh>)) {
5812 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5825 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5826 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5828 $oldtimeout = alarm($timeout);
5835 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5836 my ($dev_id, $size, $devname) = ($1, $2, $3);
5837 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5838 } elsif ($line =~ m/^CTIME: /) {
5839 # we correctly received the vma config, so we can disable
5840 # the timeout now for disk allocation (set to 10 minutes, so
5841 # that we always timeout if something goes wrong)
5844 print $fifofh "done\n";
5845 my $tmp = $oldtimeout || 0;
5846 $oldtimeout = undef;
5852 print "restore vma archive: $cmd\n";
5853 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5857 alarm($oldtimeout) if $oldtimeout;
5860 foreach my $devname (keys %$devinfo) {
5861 my $volid = $devinfo->{$devname}->{volid
};
5862 push @$vollist, $volid if $volid;
5865 my $cfg = PVE
::Storage
::config
();
5866 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5874 foreach my $devname (keys %$devinfo) {
5875 my $volid = $devinfo->{$devname}->{volid
};
5878 if ($volid =~ m
|^/|) {
5879 unlink $volid || die 'unlink failed\n';
5881 PVE
::Storage
::vdisk_free
($cfg, $volid);
5883 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5885 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5892 rename($tmpfn, $conffile) ||
5893 die "unable to commit configuration file '$conffile'\n";
5895 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5897 eval { rescan
($vmid, 1); };
5901 sub restore_tar_archive
{
5902 my ($archive, $vmid, $user, $opts) = @_;
5904 if ($archive ne '-') {
5905 my $firstfile = tar_archive_read_firstfile
($archive);
5906 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5907 if $firstfile ne 'qemu-server.conf';
5910 my $storecfg = PVE
::Storage
::config
();
5912 # destroy existing data - keep empty config
5913 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5914 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5916 my $tocmd = "/usr/lib/qemu-server/qmextract";
5918 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5919 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5920 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5921 $tocmd .= ' --info' if $opts->{info
};
5923 # tar option "xf" does not autodetect compression when read from STDIN,
5924 # so we pipe to zcat
5925 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5926 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5928 my $tmpdir = "/var/tmp/vzdumptmp$$";
5931 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5932 local $ENV{VZDUMP_VMID
} = $vmid;
5933 local $ENV{VZDUMP_USER
} = $user;
5935 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5936 my $tmpfn = "$conffile.$$.tmp";
5938 # disable interrupts (always do cleanups)
5942 local $SIG{HUP
} = sub { print STDERR
"got interrupt - ignored\n"; };
5950 local $SIG{PIPE
} = sub { die "interrupted by signal\n"; };
5952 if ($archive eq '-') {
5953 print "extracting archive from STDIN\n";
5954 run_command
($cmd, input
=> "<&STDIN");
5956 print "extracting archive '$archive'\n";
5960 return if $opts->{info
};
5964 my $statfile = "$tmpdir/qmrestore.stat";
5965 if (my $fd = IO
::File-
>new($statfile, "r")) {
5966 while (defined (my $line = <$fd>)) {
5967 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5968 $map->{$1} = $2 if $1;
5970 print STDERR
"unable to parse line in statfile - $line\n";
5976 my $confsrc = "$tmpdir/qemu-server.conf";
5978 my $srcfd = new IO
::File
($confsrc, "r") ||
5979 die "unable to open file '$confsrc'\n";
5981 my $outfd = new IO
::File
($tmpfn, "w") ||
5982 die "unable to write config for VM $vmid\n";
5984 my $cookie = { netcount
=> 0 };
5985 while (defined (my $line = <$srcfd>)) {
5986 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5998 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
6005 rename $tmpfn, $conffile ||
6006 die "unable to commit configuration file '$conffile'\n";
6008 PVE
::Cluster
::cfs_update
(); # make sure we read new file
6010 eval { rescan
($vmid, 1); };
6014 sub foreach_storage_used_by_vm
{
6015 my ($conf, $func) = @_;
6019 foreach_drive
($conf, sub {
6020 my ($ds, $drive) = @_;
6021 return if drive_is_cdrom
($drive);
6023 my $volid = $drive->{file
};
6025 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
6026 $sidhash->{$sid} = $sid if $sid;
6029 foreach my $sid (sort keys %$sidhash) {
6034 sub do_snapshots_with_qemu
{
6035 my ($storecfg, $volid) = @_;
6037 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
6039 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
6040 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
6044 if ($volid =~ m/\.(qcow2|qed)$/){
6051 sub qga_check_running
{
6054 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
6056 warn "Qemu Guest Agent is not running - $@";
6062 sub template_create
{
6063 my ($vmid, $conf, $disk) = @_;
6065 my $storecfg = PVE
::Storage
::config
();
6067 foreach_drive
($conf, sub {
6068 my ($ds, $drive) = @_;
6070 return if drive_is_cdrom
($drive);
6071 return if $disk && $ds ne $disk;
6073 my $volid = $drive->{file
};
6074 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6076 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6077 $drive->{file
} = $voliddst;
6078 $conf->{$ds} = print_drive
($vmid, $drive);
6079 PVE
::QemuConfig-
>write_config($vmid, $conf);
6083 sub qemu_img_convert
{
6084 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
6086 my $storecfg = PVE
::Storage
::config
();
6087 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6088 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6090 if ($src_storeid && $dst_storeid) {
6092 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6094 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6095 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6097 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6098 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6100 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6101 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6104 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
6105 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6106 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
6107 if ($is_zero_initialized) {
6108 push @$cmd, "zeroinit:$dst_path";
6110 push @$cmd, $dst_path;
6115 if($line =~ m/\((\S+)\/100\
%\)/){
6117 my $transferred = int($size * $percent / 100);
6118 my $remaining = $size - $transferred;
6120 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6125 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6127 die "copy failed: $err" if $err;
6131 sub qemu_img_format
{
6132 my ($scfg, $volname) = @_;
6134 if ($scfg->{path
} && $volname =~ m/\.($QEMU_FORMAT_RE)$/) {
6141 sub qemu_drive_mirror
{
6142 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $skipcomplete, $qga) = @_;
6144 $jobs = {} if !$jobs;
6148 $jobs->{"drive-$drive"} = {};
6150 if ($dst_volid =~ /^nbd:/) {
6151 $qemu_target = $dst_volid;
6154 my $storecfg = PVE
::Storage
::config
();
6155 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6157 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6159 $format = qemu_img_format
($dst_scfg, $dst_volname);
6161 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6163 $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
6166 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
6167 $opts->{format
} = $format if $format;
6169 print "drive mirror is starting for drive-$drive\n";
6171 eval { vm_mon_cmd
($vmid, "drive-mirror", %$opts); }; #if a job already run for this device,it's throw an error
6174 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6175 die "mirroring error: $err";
6178 qemu_drive_mirror_monitor
($vmid, $vmiddst, $jobs, $skipcomplete, $qga);
6181 sub qemu_drive_mirror_monitor
{
6182 my ($vmid, $vmiddst, $jobs, $skipcomplete, $qga) = @_;
6185 my $err_complete = 0;
6188 die "storage migration timed out\n" if $err_complete > 300;
6190 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6192 my $running_mirror_jobs = {};
6193 foreach my $stat (@$stats) {
6194 next if $stat->{type
} ne 'mirror';
6195 $running_mirror_jobs->{$stat->{device
}} = $stat;
6198 my $readycounter = 0;
6200 foreach my $job (keys %$jobs) {
6202 if(defined($jobs->{$job}->{complete
}) && !defined($running_mirror_jobs->{$job})) {
6203 print "$job : finished\n";
6204 delete $jobs->{$job};
6208 die "$job: mirroring has been cancelled\n" if !defined($running_mirror_jobs->{$job});
6210 my $busy = $running_mirror_jobs->{$job}->{busy
};
6211 my $ready = $running_mirror_jobs->{$job}->{ready
};
6212 if (my $total = $running_mirror_jobs->{$job}->{len
}) {
6213 my $transferred = $running_mirror_jobs->{$job}->{offset
} || 0;
6214 my $remaining = $total - $transferred;
6215 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6217 print "$job: transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6220 $readycounter++ if $running_mirror_jobs->{$job}->{ready
};
6223 last if scalar(keys %$jobs) == 0;
6225 if ($readycounter == scalar(keys %$jobs)) {
6226 print "all mirroring jobs are ready \n";
6227 last if $skipcomplete; #do the complete later
6229 if ($vmiddst && $vmiddst != $vmid) {
6230 my $agent_running = $qga && qga_check_running
($vmid);
6231 if ($agent_running) {
6232 print "freeze filesystem\n";
6233 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6235 print "suspend vm\n";
6236 eval { PVE
::QemuServer
::vm_suspend
($vmid, 1); };
6239 # if we clone a disk for a new target vm, we don't switch the disk
6240 PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs);
6242 if ($agent_running) {
6243 print "unfreeze filesystem\n";
6244 eval { PVE
::QemuServer
::vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6246 print "resume vm\n";
6247 eval { PVE
::QemuServer
::vm_resume
($vmid, 1, 1); };
6253 foreach my $job (keys %$jobs) {
6254 # try to switch the disk if source and destination are on the same guest
6255 print "$job: Completing block job...\n";
6257 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> $job) };
6258 if ($@ =~ m/cannot be completed/) {
6259 print "$job: Block job cannot be completed, try again.\n";
6262 print "$job: Completed successfully.\n";
6263 $jobs->{$job}->{complete
} = 1;
6274 eval { PVE
::QemuServer
::qemu_blockjobs_cancel
($vmid, $jobs) };
6275 die "mirroring error: $err";
6280 sub qemu_blockjobs_cancel
{
6281 my ($vmid, $jobs) = @_;
6283 foreach my $job (keys %$jobs) {
6284 print "$job: Cancelling block job\n";
6285 eval { vm_mon_cmd
($vmid, "block-job-cancel", device
=> $job); };
6286 $jobs->{$job}->{cancel
} = 1;
6290 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6292 my $running_jobs = {};
6293 foreach my $stat (@$stats) {
6294 $running_jobs->{$stat->{device
}} = $stat;
6297 foreach my $job (keys %$jobs) {
6299 if (defined($jobs->{$job}->{cancel
}) && !defined($running_jobs->{$job})) {
6300 print "$job: Done.\n";
6301 delete $jobs->{$job};
6305 last if scalar(keys %$jobs) == 0;
6312 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6313 $newvmid, $storage, $format, $full, $newvollist, $jobs, $skipcomplete, $qga) = @_;
6318 print "create linked clone of drive $drivename ($drive->{file})\n";
6319 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6320 push @$newvollist, $newvolid;
6323 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6324 $storeid = $storage if $storage;
6326 my $dst_format = resolve_dst_disk_format
($storecfg, $storeid, $volname, $format);
6327 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6329 print "create full clone of drive $drivename ($drive->{file})\n";
6331 if (drive_is_cloudinit
($drive)) {
6332 $name = "vm-$newvmid-cloudinit";
6333 # cloudinit only supports raw and qcow2 atm:
6334 if ($dst_format eq 'qcow2') {
6336 } elsif ($dst_format ne 'raw') {
6337 die "clone: unhandled format for cloudinit image\n";
6340 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $dst_format, $name, ($size/1024));
6341 push @$newvollist, $newvolid;
6343 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
6345 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6346 if (!$running || $snapname) {
6347 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6350 my $kvmver = get_running_qemu_version
($vmid);
6351 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
6352 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
6353 if $drive->{iothread
};
6356 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit, $jobs, $skipcomplete, $qga);
6360 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6363 $disk->{format
} = undef;
6364 $disk->{file
} = $newvolid;
6365 $disk->{size
} = $size;
6370 # this only works if VM is running
6371 sub get_current_qemu_machine
{
6374 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6375 my $res = vm_qmp_command
($vmid, $cmd);
6377 my ($current, $default);
6378 foreach my $e (@$res) {
6379 $default = $e->{name
} if $e->{'is-default'};
6380 $current = $e->{name
} if $e->{'is-current'};
6383 # fallback to the default machine if current is not supported by qemu
6384 return $current || $default || 'pc';
6387 sub get_running_qemu_version
{
6389 my $cmd = { execute
=> 'query-version', arguments
=> {} };
6390 my $res = vm_qmp_command
($vmid, $cmd);
6391 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6394 sub qemu_machine_feature_enabled
{
6395 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6400 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6402 $current_major = $3;
6403 $current_minor = $4;
6405 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6407 $current_major = $1;
6408 $current_minor = $2;
6411 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6416 sub qemu_machine_pxe
{
6417 my ($vmid, $conf, $machine) = @_;
6419 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6421 foreach my $opt (keys %$conf) {
6422 next if $opt !~ m/^net(\d+)$/;
6423 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6425 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6426 return $machine.".pxe" if $romfile =~ m/pxe/;
6433 sub qemu_use_old_bios_files
{
6434 my ($machine_type) = @_;
6436 return if !$machine_type;
6438 my $use_old_bios_files = undef;
6440 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6442 $use_old_bios_files = 1;
6444 my $kvmver = kvm_user_version
();
6445 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6446 # load new efi bios files on migration. So this hack is required to allow
6447 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6448 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6449 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6452 return ($use_old_bios_files, $machine_type);
6455 sub create_efidisk
{
6456 my ($storecfg, $storeid, $vmid, $fmt) = @_;
6458 die "EFI vars default image not found\n" if ! -f
$OVMF_VARS;
6460 my $vars_size = PVE
::Tools
::convert_size
(-s
$OVMF_VARS, 'b' => 'kb');
6461 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
6462 PVE
::Storage
::activate_volumes
($storecfg, [$volid]);
6464 my $path = PVE
::Storage
::path
($storecfg, $volid);
6466 run_command
(['/usr/bin/qemu-img', 'convert', '-n', '-f', 'raw', '-O', $fmt, $OVMF_VARS, $path]);
6468 die "Copying EFI vars image failed: $@" if $@;
6470 return ($volid, $vars_size);
6477 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6478 my (undef, $id, $function) = @_;
6479 my $res = { id
=> $id, function
=> $function};
6480 push @{$devices->{$id}}, $res;
6483 # Entries should be sorted by functions.
6484 foreach my $id (keys %$devices) {
6485 my $dev = $devices->{$id};
6486 $devices->{$id} = [ sort { $a->{function
} <=> $b->{function
} } @$dev ];
6492 sub vm_iothreads_list
{
6495 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6498 foreach my $iothread (@$res) {
6499 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6506 my ($conf, $drive) = @_;
6510 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)) {
6512 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6518 my $controller = int($drive->{index} / $maxdev);
6519 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6521 return ($maxdev, $controller, $controller_prefix);
6524 sub add_hyperv_enlightenments
{
6525 my ($cpuFlags, $winversion, $machine_type, $kvmver, $bios, $gpu_passthrough) = @_;
6527 return if $winversion < 6;
6528 return if $bios && $bios eq 'ovmf' && $winversion < 8;
6530 push @$cpuFlags , 'hv_vendor_id=proxmox' if $gpu_passthrough;
6532 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
6533 push @$cpuFlags , 'hv_spinlocks=0x1fff';
6534 push @$cpuFlags , 'hv_vapic';
6535 push @$cpuFlags , 'hv_time';
6537 push @$cpuFlags , 'hv_spinlocks=0xffff';
6540 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
6541 push @$cpuFlags , 'hv_reset';
6542 push @$cpuFlags , 'hv_vpindex';
6543 push @$cpuFlags , 'hv_runtime';
6546 if ($winversion >= 7) {
6547 push @$cpuFlags , 'hv_relaxed';
6551 sub windows_version
{
6554 return 0 if !$ostype;
6558 if($ostype eq 'wxp' || $ostype eq 'w2k3' || $ostype eq 'w2k') {
6560 } elsif($ostype eq 'w2k8' || $ostype eq 'wvista') {
6562 } elsif ($ostype =~ m/^win(\d+)$/) {
6569 sub resolve_dst_disk_format
{
6570 my ($storecfg, $storeid, $src_volname, $format) = @_;
6571 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6574 # if no target format is specified, use the source disk format as hint
6576 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6577 $format = qemu_img_format
($scfg, $src_volname);
6583 # test if requested format is supported - else use default
6584 my $supported = grep { $_ eq $format } @$validFormats;
6585 $format = $defFormat if !$supported;
6589 sub resolve_first_disk
{
6591 my @disks = PVE
::QemuServer
::valid_drive_names
();
6593 foreach my $ds (reverse @disks) {
6594 next if !$conf->{$ds};
6595 my $disk = PVE
::QemuServer
::parse_drive
($ds, $conf->{$ds});
6596 next if PVE
::QemuServer
::drive_is_cdrom
($disk);
6602 sub generate_smbios1_uuid
{
6603 my ($uuid, $uuid_str);
6604 UUID
::generate
($uuid);
6605 UUID
::unparse
($uuid, $uuid_str);
6606 return "uuid=$uuid_str";
6609 # bash completion helper
6611 sub complete_backup_archives
{
6612 my ($cmdname, $pname, $cvalue) = @_;
6614 my $cfg = PVE
::Storage
::config
();
6618 if ($cvalue =~ m/^([^:]+):/) {
6622 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6625 foreach my $id (keys %$data) {
6626 foreach my $item (@{$data->{$id}}) {
6627 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6628 push @$res, $item->{volid
} if defined($item->{volid
});
6635 my $complete_vmid_full = sub {
6638 my $idlist = vmstatus
();
6642 foreach my $id (keys %$idlist) {
6643 my $d = $idlist->{$id};
6644 if (defined($running)) {
6645 next if $d->{template
};
6646 next if $running && $d->{status
} ne 'running';
6647 next if !$running && $d->{status
} eq 'running';
6656 return &$complete_vmid_full();
6659 sub complete_vmid_stopped
{
6660 return &$complete_vmid_full(0);
6663 sub complete_vmid_running
{
6664 return &$complete_vmid_full(1);
6667 sub complete_storage
{
6669 my $cfg = PVE
::Storage
::config
();
6670 my $ids = $cfg->{ids
};
6673 foreach my $sid (keys %$ids) {
6674 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6675 next if !$ids->{$sid}->{content
}->{images
};