1 package PVE
::QemuServer
;
22 use Storable
qw(dclone);
23 use PVE
::Exception
qw(raise raise_param_exc);
25 use PVE
::Tools
qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach);
26 use PVE
::JSONSchema
qw(get_standard_option);
27 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
32 use PVE
::RPCEnvironment
;
33 use PVE
::QemuServer
::PCI
qw(print_pci_addr print_pcie_addr);
34 use PVE
::QemuServer
::Memory
;
35 use PVE
::QemuServer
::USB
qw(parse_usb_device);
36 use Time
::HiRes
qw(gettimeofday);
37 use File
::Copy
qw(copy);
40 my $OVMF_CODE = '/usr/share/kvm/OVMF_CODE-pure-efi.fd';
41 my $OVMF_VARS = '/usr/share/kvm/OVMF_VARS-pure-efi.fd';
42 my $OVMF_IMG = '/usr/share/kvm/OVMF-pure-efi.fd';
44 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
46 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
48 # Note about locking: we use flock on the config file protect
49 # against concurent actions.
50 # Aditionaly, we have a 'lock' setting in the config file. This
51 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
52 # allowed when such lock is set. But you can ignore this kind of
53 # lock with the --skiplock flag.
55 cfs_register_file
('/qemu-server/',
59 PVE
::JSONSchema
::register_standard_option
('skiplock', {
60 description
=> "Ignore locks - only root is allowed to use this option.",
65 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
66 description
=> "Some command save/restore state from this location.",
72 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
73 description
=> "The name of the snapshot.",
74 type
=> 'string', format
=> 'pve-configid',
78 #no warnings 'redefine';
81 my ($controller, $vmid, $option, $value) = @_;
83 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
84 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
88 my $nodename = PVE
::INotify
::nodename
();
90 mkdir "/etc/pve/nodes/$nodename";
91 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
94 my $var_run_tmpdir = "/var/run/qemu-server";
95 mkdir $var_run_tmpdir;
97 my $lock_dir = "/var/lock/qemu-server";
100 my $pcisysfs = "/sys/bus/pci";
102 my $cpu_vendor_list = {
104 486 => 'GenuineIntel',
105 pentium
=> 'GenuineIntel',
106 pentium2
=> 'GenuineIntel',
107 pentium3
=> 'GenuineIntel',
108 coreduo
=> 'GenuineIntel',
109 core2duo
=> 'GenuineIntel',
110 Conroe
=> 'GenuineIntel',
111 Penryn
=> 'GenuineIntel',
112 Nehalem
=> 'GenuineIntel',
113 Westmere
=> 'GenuineIntel',
114 SandyBridge
=> 'GenuineIntel',
115 IvyBridge
=> 'GenuineIntel',
116 Haswell
=> 'GenuineIntel',
117 'Haswell-noTSX' => 'GenuineIntel',
118 Broadwell
=> 'GenuineIntel',
119 'Broadwell-noTSX' => 'GenuineIntel',
122 athlon
=> 'AuthenticAMD',
123 phenom
=> 'AuthenticAMD',
124 Opteron_G1
=> 'AuthenticAMD',
125 Opteron_G2
=> 'AuthenticAMD',
126 Opteron_G3
=> 'AuthenticAMD',
127 Opteron_G4
=> 'AuthenticAMD',
128 Opteron_G5
=> 'AuthenticAMD',
130 # generic types, use vendor from host node
140 description
=> "Emulated CPU type.",
142 enum
=> [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
143 format_description
=> 'cputype',
148 description
=> "Do not identify as a KVM virtual machine.",
159 enum
=> [qw(i6300esb ib700)],
160 description
=> "Watchdog type to emulate.",
161 default => 'i6300esb',
166 enum
=> [qw(reset shutdown poweroff pause debug none)],
167 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
171 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
177 description
=> "Specifies whether a VM will be started during system bootup.",
183 description
=> "Automatic restart after crash (currently ignored).",
188 type
=> 'string', format
=> 'pve-hotplug-features',
189 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'.",
190 default => 'network,disk,usb',
195 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
201 description
=> "Lock/unlock the VM.",
202 enum
=> [qw(migrate backup snapshot rollback)],
207 description
=> "Limit of CPU usage.",
208 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.",
216 description
=> "CPU weight for a VM.",
217 verbose_description
=> "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
225 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
232 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
238 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",
246 description
=> "Keybord layout for vnc server. Default is read from the '/etc/pve/datacenter.conf' configuration file.",
247 enum
=> PVE
::Tools
::kvmkeymaplist
(),
252 type
=> 'string', format
=> 'dns-name',
253 description
=> "Set a name for the VM. Only used on the configuration web interface.",
258 description
=> "SCSI controller model",
259 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
265 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
270 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
271 description
=> "Specify guest operating system.",
272 verbose_description
=> <<EODESC,
273 Specify guest operating system. This is used to enable special
274 optimization/features for specific operating systems:
277 other;; unspecified OS
278 wxp;; Microsoft Windows XP
279 w2k;; Microsoft Windows 2000
280 w2k3;; Microsoft Windows 2003
281 w2k8;; Microsoft Windows 2008
282 wvista;; Microsoft Windows Vista
283 win7;; Microsoft Windows 7
284 win8;; Microsoft Windows 8/2012
285 l24;; Linux 2.4 Kernel
286 l26;; Linux 2.6/3.X Kernel
287 solaris;; Solaris/OpenSolaris/OpenIndiania kernel
293 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
294 pattern
=> '[acdn]{1,4}',
299 type
=> 'string', format
=> 'pve-qm-bootdisk',
300 description
=> "Enable booting from specified disk.",
301 pattern
=> '(ide|sata|scsi|virtio)\d+',
306 description
=> "The number of CPUs. Please use option -sockets instead.",
313 description
=> "The number of CPU sockets.",
320 description
=> "The number of cores per socket.",
327 description
=> "Enable/disable NUMA.",
333 description
=> "Enable/disable hugepages memory.",
334 enum
=> [qw(any 2 1024)],
339 description
=> "Number of hotplugged vcpus.",
346 description
=> "Enable/disable ACPI.",
352 description
=> "Enable/disable Qemu GuestAgent.",
358 description
=> "Enable/disable KVM hardware virtualization.",
364 description
=> "Enable/disable time drift fix.",
370 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
375 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
380 description
=> "Select the VGA type.",
381 verbose_description
=> "Select the VGA type. If you want to use high resolution" .
382 " modes (>= 1280x1024x16) then you should use the options " .
383 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
384 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
385 "display sever. For win* OS you can select how many independent " .
386 "displays you want, Linux guests can add displays them self. " .
387 "You can also run without any graphic card, using a serial device" .
389 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
393 type
=> 'string', format
=> 'pve-qm-watchdog',
394 description
=> "Create a virtual hardware watchdog device.",
395 verbose_description
=> "Create a virtual hardware watchdog device. Once enabled" .
396 " (by a guest action), the watchdog must be periodically polled " .
397 "by an agent inside the guest or else the watchdog will reset " .
398 "the guest (or execute the respective action specified)",
403 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
404 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'.",
405 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
408 startup
=> get_standard_option
('pve-startup-order'),
412 description
=> "Enable/disable Template.",
418 description
=> "Arbitrary arguments passed to kvm.",
419 verbose_description
=> <<EODESCR,
420 Arbitrary arguments passed to kvm, for example:
422 args: -no-reboot -no-hpet
424 NOTE: this option is for experts only.
431 description
=> "Enable/disable the USB tablet device.",
432 verbose_description
=> "Enable/disable the USB tablet device. This device is " .
433 "usually needed to allow absolute mouse positioning with VNC. " .
434 "Else the mouse runs out of sync with normal VNC clients. " .
435 "If you're running lots of console-only guests on one host, " .
436 "you may consider disabling this to save some context switches. " .
437 "This is turned off by default if you use spice (-vga=qxl).",
442 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
446 migrate_downtime
=> {
449 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
455 type
=> 'string', format
=> 'pve-qm-ide',
456 typetext
=> 'volume',
457 description
=> "This is an alias for option -ide2",
461 description
=> "Emulated CPU type.",
465 parent
=> get_standard_option
('pve-snapshot-name', {
467 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
471 description
=> "Timestamp for snapshots.",
477 type
=> 'string', format
=> 'pve-volume-id',
478 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
481 description
=> "Specific the Qemu machine type.",
483 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
488 description
=> "Specify SMBIOS type 1 fields.",
489 type
=> 'string', format
=> 'pve-qm-smbios1',
496 description
=> "Sets the protection flag of the VM. This will disable the remove VM and remove disk operations.",
502 enum
=> [ qw(seabios ovmf) ],
503 description
=> "Select BIOS implementation.",
504 default => 'seabios',
508 # what about other qemu settings ?
510 #machine => 'string',
523 ##soundhw => 'string',
525 while (my ($k, $v) = each %$confdesc) {
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
529 my $MAX_IDE_DISKS = 4;
530 my $MAX_SCSI_DISKS = 14;
531 my $MAX_VIRTIO_DISKS = 16;
532 my $MAX_SATA_DISKS = 6;
533 my $MAX_USB_DEVICES = 5;
535 my $MAX_UNUSED_DISKS = 8;
536 my $MAX_HOSTPCI_DEVICES = 4;
537 my $MAX_SERIAL_PORTS = 4;
538 my $MAX_PARALLEL_PORTS = 3;
544 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
545 description
=> "CPUs accessing this NUMA node.",
546 format_description
=> "id[-id];...",
550 description
=> "Amount of memory this NUMA node provides.",
555 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
556 description
=> "Host NUMA nodes to use.",
557 format_description
=> "id[-id];...",
562 enum
=> [qw(preferred bind interleave)],
563 description
=> "NUMA allocation policy.",
567 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
570 type
=> 'string', format
=> $numa_fmt,
571 description
=> "NUMA topology.",
573 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
575 for (my $i = 0; $i < $MAX_NUMA; $i++) {
576 $confdesc->{"numa$i"} = $numadesc;
579 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
580 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
581 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
582 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
584 my $net_fmt_bridge_descr = <<__EOD__;
585 Bridge to attach the network device to. The Proxmox VE standard bridge
588 If you do not specify a bridge, we create a kvm user (NATed) network
589 device, which provides DHCP and DNS services. The following addresses
596 The DHCP server assign addresses to the guest starting from 10.0.2.15.
602 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
603 description
=> "MAC address. That address must be unique withing your network. This is automatically generated if not specified.",
604 format_description
=> "XX:XX:XX:XX:XX:XX",
609 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'.",
610 format_description
=> 'model',
611 enum
=> $nic_model_list,
614 (map { $_ => { keyAlias
=> 'model', alias
=> 'macaddr' }} @$nic_model_list),
617 description
=> $net_fmt_bridge_descr,
618 format_description
=> 'bridge',
623 minimum
=> 0, maximum
=> 16,
624 description
=> 'Number of packet queues to be used on the device.',
630 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
635 minimum
=> 1, maximum
=> 4094,
636 description
=> 'VLAN tag to apply to packets on this interface.',
641 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
642 description
=> 'VLAN trunks to pass through this interface.',
643 format_description
=> 'vlanid[;vlanid...]',
648 description
=> 'Whether this interface should be protected by the firewall.',
653 description
=> 'Whether this interface should be disconnected (like pulling the plug).',
660 type
=> 'string', format
=> $net_fmt,
661 description
=> "Specify network devices.",
664 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
666 for (my $i = 0; $i < $MAX_NETS; $i++) {
667 $confdesc->{"net$i"} = $netdesc;
670 PVE
::JSONSchema
::register_format
('pve-volume-id-or-qm-path', \
&verify_volume_id_or_qm_path
);
671 sub verify_volume_id_or_qm_path
{
672 my ($volid, $noerr) = @_;
674 if ($volid eq 'none' || $volid eq 'cdrom' || $volid =~ m
|^/|) {
678 # if its neither 'none' nor 'cdrom' nor a path, check if its a volume-id
679 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
681 return undef if $noerr;
689 my %drivedesc_base = (
690 volume
=> { alias
=> 'file' },
693 format
=> 'pve-volume-id-or-qm-path',
695 format_description
=> 'volume',
696 description
=> "The drive's backing volume.",
700 enum
=> [qw(cdrom disk)],
701 description
=> "The drive's media type.",
707 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
712 description
=> "Force the drive's physical geometry to have a specific head count.",
717 description
=> "Force the drive's physical geometry to have a specific sector count.",
722 enum
=> [qw(none lba auto)],
723 description
=> "Force disk geometry bios translation mode.",
728 description
=> "Whether the drive should be included when making snapshots.",
733 enum
=> [qw(none writethrough writeback unsafe directsync)],
734 description
=> "The drive's cache mode",
739 format_description
=> 'image format',
740 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
741 description
=> "The drive's backing file's data format.",
746 format
=> 'disk-size',
747 format_description
=> 'DiskSize',
748 description
=> "Disk size. This is purely informational and has no effect.",
753 description
=> "Whether the drive should be included when making backups.",
758 enum
=> [qw(enospc ignore report stop)],
759 description
=> 'Write error action.',
764 enum
=> [qw(native threads)],
765 description
=> 'AIO type to use.',
770 enum
=> [qw(ignore on)],
771 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
776 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
781 format
=> 'urlencoded',
782 format_description
=> 'serial',
783 maxLength
=> 20*3, # *3 since it's %xx url enoded
784 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
792 enum
=> [qw(ignore report stop)],
793 description
=> 'Read error action.',
798 my %iothread_fmt = ( iothread
=> {
800 description
=> "Whether to use iothreads for this drive",
807 format
=> 'urlencoded',
808 format_description
=> 'model',
809 maxLength
=> 40*3, # *3 since it's %xx url enoded
810 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
818 description
=> "Number of queues.",
824 my $add_throttle_desc = sub {
825 my ($key, $type, $what, $unit, $longunit, $minimum) = @_;
828 format_description
=> $unit,
829 description
=> "Maximum $what in $longunit.",
832 $d->{minimum
} = $minimum if defined($minimum);
833 $drivedesc_base{$key} = $d;
835 # throughput: (leaky bucket)
836 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes per second');
837 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes per second');
838 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes per second');
839 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes per second');
840 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes per second');
841 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes per second');
842 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations per second');
843 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations per second');
844 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations per second');
846 # pools: (pool of IO before throttling starts taking effect)
847 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes per second');
848 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes per second');
849 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes per second');
850 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations per second');
851 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations per second');
852 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations per second');
855 $add_throttle_desc->('bps_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
856 $add_throttle_desc->('bps_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
857 $add_throttle_desc->('bps_wr_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
858 $add_throttle_desc->('iops_max_length', 'integer', 'length of I/O bursts', 'seconds', 'seconds', 1);
859 $add_throttle_desc->('iops_rd_length', 'integer', 'length of read I/O bursts', 'seconds', 'seconds', 1);
860 $add_throttle_desc->('iops_wr_length', 'integer', 'length of write I/O bursts', 'seconds', 'seconds', 1);
867 PVE
::JSONSchema
::register_format
("pve-qm-ide", $ide_fmt);
871 type
=> 'string', format
=> $ide_fmt,
872 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
874 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
883 type
=> 'string', format
=> $scsi_fmt,
884 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
886 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
894 type
=> 'string', format
=> $sata_fmt,
895 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
897 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
906 type
=> 'string', format
=> $virtio_fmt,
907 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
909 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
920 volume
=> { alias
=> 'file' },
923 format
=> 'pve-volume-id-or-qm-path',
925 format_description
=> 'volume',
926 description
=> "The drive's backing volume.",
930 format_description
=> 'image format',
931 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
932 description
=> "The drive's backing file's data format.",
937 format
=> 'disk-size',
938 format_description
=> 'DiskSize',
939 description
=> "Disk size. This is purely informational and has no effect.",
946 type
=> 'string', format
=> $efidisk_fmt,
947 description
=> "Configure a Disk for storing EFI vars",
950 PVE
::JSONSchema
::register_standard_option
("pve-qm-efidisk", $efidisk_desc);
955 type
=> 'string', format
=> 'pve-qm-usb-device',
956 format_description
=> 'HOSTUSBDEVICE|spice',
957 description
=> <<EODESCR,
958 The Host USB device or port or the value 'spice'. HOSTUSBDEVICE syntax is:
960 'bus-port(.port)*' (decimal numbers) or
961 'vendor_id:product_id' (hexadeciaml numbers) or
964 You can use the 'lsusb -t' command to list existing usb devices.
966 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
968 The value 'spice' can be used to add a usb redirection devices for spice.
974 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).",
981 type
=> 'string', format
=> $usb_fmt,
982 description
=> "Configure an USB device (n is 0 to 4).",
984 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
986 # NOTE: the match-groups of this regex are used in parse_hostpci
987 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
992 pattern
=> qr/$PCIRE(;$PCIRE)*/,
993 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
994 description
=> <<EODESCR,
995 Host PCI device pass through. The PCI ID of a host's PCI device or a list
996 of PCI virtual functions of the host. HOSTPCIID syntax is:
998 'bus:dev.func' (hexadecimal numbers)
1000 You can us the 'lspci' command to list existing PCI devices.
1005 description
=> "Specify whether or not the device's ROM will be visible in the guest's memory map.",
1011 description
=> "Choose the PCI-express bus (needs the 'q35' machine model).",
1017 description
=> "Enable vfio-vga device support.",
1022 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
1026 type
=> 'string', format
=> 'pve-qm-hostpci',
1027 description
=> "Map host PCI devices into guest.",
1028 verbose_description
=> <<EODESCR,
1029 Map host PCI devices into guest.
1031 NOTE: This option allows direct access to host hardware. So it is no longer
1032 possible to migrate such machines - use with special care.
1034 CAUTION: Experimental! User reported problems with this option.
1037 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
1042 pattern
=> '(/dev/.+|socket)',
1043 description
=> "Create a serial device inside the VM (n is 0 to 3)",
1044 verbose_description
=> <<EODESCR,
1045 Create a serial device inside the VM (n is 0 to 3), and pass through a
1046 host serial device (i.e. /dev/ttyS0), or create a unix socket on the
1047 host side (use 'qm terminal' to open a terminal connection).
1049 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
1051 CAUTION: Experimental! User reported problems with this option.
1058 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
1059 description
=> "Map host parallel devices (n is 0 to 2).",
1060 verbose_description
=> <<EODESCR,
1061 Map host parallel devices (n is 0 to 2).
1063 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
1065 CAUTION: Experimental! User reported problems with this option.
1069 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
1070 $confdesc->{"parallel$i"} = $paralleldesc;
1073 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
1074 $confdesc->{"serial$i"} = $serialdesc;
1077 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
1078 $confdesc->{"hostpci$i"} = $hostpcidesc;
1081 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
1082 $drivename_hash->{"ide$i"} = 1;
1083 $confdesc->{"ide$i"} = $idedesc;
1086 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
1087 $drivename_hash->{"sata$i"} = 1;
1088 $confdesc->{"sata$i"} = $satadesc;
1091 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1092 $drivename_hash->{"scsi$i"} = 1;
1093 $confdesc->{"scsi$i"} = $scsidesc ;
1096 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1097 $drivename_hash->{"virtio$i"} = 1;
1098 $confdesc->{"virtio$i"} = $virtiodesc;
1101 $drivename_hash->{efidisk0
} = 1;
1102 $confdesc->{efidisk0
} = $efidisk_desc;
1104 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1105 $confdesc->{"usb$i"} = $usbdesc;
1110 type
=> 'string', format
=> 'pve-volume-id',
1111 description
=> "Reference to unused volumes. This is used internally, and should not be modified manually.",
1114 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1115 $confdesc->{"unused$i"} = $unuseddesc;
1118 my $kvm_api_version = 0;
1122 return $kvm_api_version if $kvm_api_version;
1124 my $fh = IO
::File-
>new("</dev/kvm") ||
1127 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1128 $kvm_api_version = $v;
1133 return $kvm_api_version;
1136 my $kvm_user_version;
1138 sub kvm_user_version
{
1140 return $kvm_user_version if $kvm_user_version;
1142 $kvm_user_version = 'unknown';
1146 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1147 $kvm_user_version = $2;
1151 eval { run_command
("kvm -version", outfunc
=> $code); };
1154 return $kvm_user_version;
1158 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1160 sub valid_drive_names
{
1161 # order is important - used to autoselect boot disk
1162 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1163 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1164 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1165 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))),
1169 sub is_valid_drivename
{
1172 return defined($drivename_hash->{$dev});
1177 return defined($confdesc->{$key});
1181 return $nic_model_list;
1184 sub os_list_description
{
1188 wxp
=> 'Windows XP',
1189 w2k
=> 'Windows 2000',
1190 w2k3
=>, 'Windows 2003',
1191 w2k8
=> 'Windows 2008',
1192 wvista
=> 'Windows Vista',
1193 win7
=> 'Windows 7',
1194 win8
=> 'Windows 8/2012',
1202 sub get_cdrom_path
{
1204 return $cdrom_path if $cdrom_path;
1206 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1207 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1208 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1212 my ($storecfg, $vmid, $cdrom) = @_;
1214 if ($cdrom eq 'cdrom') {
1215 return get_cdrom_path
();
1216 } elsif ($cdrom eq 'none') {
1218 } elsif ($cdrom =~ m
|^/|) {
1221 return PVE
::Storage
::path
($storecfg, $cdrom);
1225 # try to convert old style file names to volume IDs
1226 sub filename_to_volume_id
{
1227 my ($vmid, $file, $media) = @_;
1229 if (!($file eq 'none' || $file eq 'cdrom' ||
1230 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1232 return undef if $file =~ m
|/|;
1234 if ($media && $media eq 'cdrom') {
1235 $file = "local:iso/$file";
1237 $file = "local:$vmid/$file";
1244 sub verify_media_type
{
1245 my ($opt, $vtype, $media) = @_;
1250 if ($media eq 'disk') {
1252 } elsif ($media eq 'cdrom') {
1255 die "internal error";
1258 return if ($vtype eq $etype);
1260 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1263 sub cleanup_drive_path
{
1264 my ($opt, $storecfg, $drive) = @_;
1266 # try to convert filesystem paths to volume IDs
1268 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1269 ($drive->{file
} !~ m
|^/dev/.+|) &&
1270 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1271 ($drive->{file
} !~ m/^\d+$/)) {
1272 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1273 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1274 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1275 verify_media_type
($opt, $vtype, $drive->{media
});
1276 $drive->{file
} = $volid;
1279 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1282 sub parse_hotplug_features
{
1287 return $res if $data eq '0';
1289 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1291 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1292 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1295 die "invalid hotplug feature '$feature'\n";
1301 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1302 sub pve_verify_hotplug_features
{
1303 my ($value, $noerr) = @_;
1305 return $value if parse_hotplug_features
($value);
1307 return undef if $noerr;
1309 die "unable to parse hotplug option\n";
1312 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1313 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1314 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1315 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1316 # [,iothread=on][,serial=serial][,model=model]
1319 my ($key, $data) = @_;
1321 my ($interface, $index);
1323 if ($key =~ m/^([^\d]+)(\d+)$/) {
1330 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1331 : $confdesc->{$key}->{format
};
1333 warn "invalid drive key: $key\n";
1336 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1337 return undef if !$res;
1338 $res->{interface
} = $interface;
1339 $res->{index} = $index;
1342 foreach my $opt (qw(bps bps_rd bps_wr)) {
1343 if (my $bps = defined(delete $res->{$opt})) {
1344 if (defined($res->{"m$opt"})) {
1345 warn "both $opt and m$opt specified\n";
1349 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1353 # can't use the schema's 'requires' because of the mbps* => bps* "transforming aliases"
1354 for my $requirement (
1355 [bps_max_length
=> 'mbps_max'],
1356 [bps_rd_max_length
=> 'mbps_rd_max'],
1357 [bps_wr_max_length
=> 'mbps_wr_max'],
1358 [iops_max_length
=> 'iops_max'],
1359 [iops_rd_max_length
=> 'iops_rd_max'],
1360 [iops_wr_max_length
=> 'iops_wr_max']) {
1361 my ($option, $requires) = @$requirement;
1362 if ($res->{$option} && !$res->{$requires}) {
1363 warn "$option requires $requires\n";
1368 return undef if $error;
1370 return undef if $res->{mbps_rd
} && $res->{mbps
};
1371 return undef if $res->{mbps_wr
} && $res->{mbps
};
1372 return undef if $res->{iops_rd
} && $res->{iops
};
1373 return undef if $res->{iops_wr
} && $res->{iops
};
1375 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1376 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1377 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1378 return undef if $res->{interface
} eq 'virtio';
1381 if (my $size = $res->{size
}) {
1382 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1389 my ($vmid, $drive) = @_;
1390 my $data = { %$drive };
1391 delete $data->{$_} for qw(index interface);
1392 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1396 my($fh, $noerr) = @_;
1399 my $SG_GET_VERSION_NUM = 0x2282;
1401 my $versionbuf = "\x00" x
8;
1402 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1404 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1407 my $version = unpack("I", $versionbuf);
1408 if ($version < 30000) {
1409 die "scsi generic interface too old\n" if !$noerr;
1413 my $buf = "\x00" x
36;
1414 my $sensebuf = "\x00" x
8;
1415 my $cmd = pack("C x3 C x1", 0x12, 36);
1417 # see /usr/include/scsi/sg.h
1418 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";
1420 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1421 length($sensebuf), 0, length($buf), $buf,
1422 $cmd, $sensebuf, 6000);
1424 $ret = ioctl($fh, $SG_IO, $packet);
1426 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1430 my @res = unpack($sg_io_hdr_t, $packet);
1431 if ($res[17] || $res[18]) {
1432 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1437 (my $byte0, my $byte1, $res->{vendor
},
1438 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1440 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1441 $res->{type
} = $byte0 & 31;
1449 my $fh = IO
::File-
>new("+<$path") || return undef;
1450 my $res = scsi_inquiry
($fh, 1);
1456 sub machine_type_is_q35
{
1459 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1462 sub print_tabletdevice_full
{
1465 my $q35 = machine_type_is_q35
($conf);
1467 # we use uhci for old VMs because tablet driver was buggy in older qemu
1468 my $usbbus = $q35 ?
"ehci" : "uhci";
1470 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1473 sub print_drivedevice_full
{
1474 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1479 if ($drive->{interface
} eq 'virtio') {
1480 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1481 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1482 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1483 } elsif ($drive->{interface
} eq 'scsi') {
1485 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1486 my $unit = $drive->{index} % $maxdev;
1487 my $devicetype = 'hd';
1489 if (drive_is_cdrom
($drive)) {
1492 if ($drive->{file
} =~ m
|^/|) {
1493 $path = $drive->{file
};
1494 if (my $info = path_is_scsi
($path)) {
1495 if ($info->{type
} == 0) {
1496 $devicetype = 'block';
1497 } elsif ($info->{type
} == 1) { # tape
1498 $devicetype = 'generic';
1502 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1505 if($path =~ m/^iscsi\:\/\
//){
1506 $devicetype = 'generic';
1510 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1511 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1513 $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}";
1516 } elsif ($drive->{interface
} eq 'ide'){
1518 my $controller = int($drive->{index} / $maxdev);
1519 my $unit = $drive->{index} % $maxdev;
1520 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1522 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1523 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1524 $model = URI
::Escape
::uri_unescape
($model);
1525 $device .= ",model=$model";
1527 } elsif ($drive->{interface
} eq 'sata'){
1528 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1529 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1530 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1531 } elsif ($drive->{interface
} eq 'usb') {
1533 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1535 die "unsupported interface type";
1538 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1543 sub get_initiator_name
{
1546 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1547 while (defined(my $line = <$fh>)) {
1548 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1557 sub print_drive_full
{
1558 my ($storecfg, $vmid, $drive) = @_;
1561 my $volid = $drive->{file
};
1564 if (drive_is_cdrom
($drive)) {
1565 $path = get_iso_path
($storecfg, $vmid, $volid);
1567 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1569 $path = PVE
::Storage
::path
($storecfg, $volid);
1570 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1571 $format = qemu_img_format
($scfg, $volname);
1579 my @qemu_drive_options = qw(heads secs cyls trans media format cache snapshot rerror werror aio discard iops iops_rd iops_wr iops_max iops_rd_max iops_wr_max);
1580 foreach my $o (@qemu_drive_options) {
1581 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1583 if (my $serial = $drive->{serial
}) {
1584 $serial = URI
::Escape
::uri_unescape
($serial);
1585 $opts .= ",serial=$serial";
1588 $opts .= ",format=$format" if $format && !$drive->{format
};
1590 foreach my $o (qw(bps bps_rd bps_wr)) {
1591 my $v = $drive->{"m$o"};
1592 $opts .= ",$o=" . int($v*1024*1024) if $v;
1595 my $cache_direct = 0;
1597 if (my $cache = $drive->{cache
}) {
1598 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1599 } elsif (!drive_is_cdrom
($drive)) {
1600 $opts .= ",cache=none";
1604 # aio native works only with O_DIRECT
1605 if (!$drive->{aio
}) {
1607 $opts .= ",aio=native";
1609 $opts .= ",aio=threads";
1613 if (!drive_is_cdrom
($drive)) {
1615 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1616 $detectzeroes = 'off';
1617 } elsif ($drive->{discard
}) {
1618 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1620 # This used to be our default with discard not being specified:
1621 $detectzeroes = 'on';
1623 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1626 my $pathinfo = $path ?
"file=$path," : '';
1628 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1631 sub print_netdevice_full
{
1632 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1634 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1636 my $device = $net->{model
};
1637 if ($net->{model
} eq 'virtio') {
1638 $device = 'virtio-net-pci';
1641 my $pciaddr = print_pci_addr
("$netid", $bridges);
1642 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1643 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1644 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1645 my $vectors = $net->{queues
} * 2 + 2;
1646 $tmpstr .= ",vectors=$vectors,mq=on";
1648 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1650 if ($use_old_bios_files) {
1652 if ($device eq 'virtio-net-pci') {
1653 $romfile = 'pxe-virtio.rom';
1654 } elsif ($device eq 'e1000') {
1655 $romfile = 'pxe-e1000.rom';
1656 } elsif ($device eq 'ne2k') {
1657 $romfile = 'pxe-ne2k_pci.rom';
1658 } elsif ($device eq 'pcnet') {
1659 $romfile = 'pxe-pcnet.rom';
1660 } elsif ($device eq 'rtl8139') {
1661 $romfile = 'pxe-rtl8139.rom';
1663 $tmpstr .= ",romfile=$romfile" if $romfile;
1669 sub print_netdev_full
{
1670 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1673 if ($netid =~ m/^net(\d+)$/) {
1677 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1679 my $ifname = "tap${vmid}i$i";
1681 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1682 die "interface name '$ifname' is too long (max 15 character)\n"
1683 if length($ifname) >= 16;
1685 my $vhostparam = '';
1686 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1688 my $vmname = $conf->{name
} || "vm$vmid";
1691 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1693 if ($net->{bridge
}) {
1694 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1696 $netdev = "type=user,id=$netid,hostname=$vmname";
1699 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1705 sub print_cpu_device
{
1706 my ($conf, $id) = @_;
1708 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
1709 my $cpu = $nokvm ?
"qemu64" : "kvm64";
1710 if (my $cputype = $conf->{cpu
}) {
1711 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
1712 or die "Cannot parse cpu description: $cputype\n";
1713 $cpu = $cpuconf->{cputype
};
1717 $sockets = $conf->{sockets
} if $conf->{sockets
};
1718 my $cores = $conf->{cores
} || 1;
1720 my $current_core = ($id - 1) % $cores;
1721 my $current_socket = int(($id - $current_core)/$cores);
1723 return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
1726 sub drive_is_cdrom
{
1729 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1733 sub parse_number_sets
{
1736 foreach my $part (split(/;/, $set)) {
1737 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1738 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1739 push @$res, [ $1, $2 ];
1741 die "invalid range: $part\n";
1750 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1751 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1752 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1759 return undef if !$value;
1761 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1763 my @idlist = split(/;/, $res->{host
});
1764 delete $res->{host
};
1765 foreach my $id (@idlist) {
1766 if ($id =~ /^$PCIRE$/) {
1768 push @{$res->{pciid
}}, { id
=> $1, function
=> $2 };
1770 my $pcidevices = lspci
($1);
1771 $res->{pciid
} = $pcidevices->{$1};
1774 # should have been caught by parse_property_string already
1775 die "failed to parse PCI id: $id\n";
1781 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1785 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1790 if (!defined($res->{macaddr
})) {
1791 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
1792 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
});
1800 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1803 sub add_random_macs
{
1804 my ($settings) = @_;
1806 foreach my $opt (keys %$settings) {
1807 next if $opt !~ m/^net(\d+)$/;
1808 my $net = parse_net
($settings->{$opt});
1810 $settings->{$opt} = print_net
($net);
1814 sub vm_is_volid_owner
{
1815 my ($storecfg, $vmid, $volid) = @_;
1817 if ($volid !~ m
|^/|) {
1819 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1820 if ($owner && ($owner == $vmid)) {
1828 sub split_flagged_list
{
1829 my $text = shift || '';
1830 $text =~ s/[,;]/ /g;
1832 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1835 sub join_flagged_list
{
1836 my ($how, $lst) = @_;
1837 join $how, map { $lst->{$_} . $_ } keys %$lst;
1840 sub vmconfig_delete_pending_option
{
1841 my ($conf, $key, $force) = @_;
1843 delete $conf->{pending
}->{$key};
1844 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1845 $pending_delete_hash->{$key} = $force ?
'!' : '';
1846 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1849 sub vmconfig_undelete_pending_option
{
1850 my ($conf, $key) = @_;
1852 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1853 delete $pending_delete_hash->{$key};
1855 if (%$pending_delete_hash) {
1856 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1858 delete $conf->{pending
}->{delete};
1862 sub vmconfig_register_unused_drive
{
1863 my ($storecfg, $vmid, $conf, $drive) = @_;
1865 if (!drive_is_cdrom
($drive)) {
1866 my $volid = $drive->{file
};
1867 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1868 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1873 sub vmconfig_cleanup_pending
{
1876 # remove pending changes when nothing changed
1878 foreach my $opt (keys %{$conf->{pending
}}) {
1879 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1881 delete $conf->{pending
}->{$opt};
1885 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1886 my $pending_delete_hash = {};
1887 while (my ($opt, $force) = each %$current_delete_hash) {
1888 if (defined($conf->{$opt})) {
1889 $pending_delete_hash->{$opt} = $force;
1895 if (%$pending_delete_hash) {
1896 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1898 delete $conf->{pending
}->{delete};
1904 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1908 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1909 format_description
=> 'UUID',
1910 description
=> "Set SMBIOS1 UUID.",
1916 format_description
=> 'string',
1917 description
=> "Set SMBIOS1 version.",
1923 format_description
=> 'string',
1924 description
=> "Set SMBIOS1 serial number.",
1930 format_description
=> 'string',
1931 description
=> "Set SMBIOS1 manufacturer.",
1937 format_description
=> 'string',
1938 description
=> "Set SMBIOS1 product ID.",
1944 format_description
=> 'string',
1945 description
=> "Set SMBIOS1 SKU string.",
1951 format_description
=> 'string',
1952 description
=> "Set SMBIOS1 family string.",
1960 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1967 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1970 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1972 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1973 sub verify_bootdisk
{
1974 my ($value, $noerr) = @_;
1976 return $value if is_valid_drivename
($value);
1978 return undef if $noerr;
1980 die "invalid boot disk '$value'\n";
1983 sub parse_watchdog
{
1986 return undef if !$value;
1988 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1993 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1994 sub verify_usb_device
{
1995 my ($value, $noerr) = @_;
1997 return $value if parse_usb_device
($value);
1999 return undef if $noerr;
2001 die "unable to parse usb device\n";
2004 # add JSON properties for create and set function
2005 sub json_config_properties
{
2008 foreach my $opt (keys %$confdesc) {
2009 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
2010 $prop->{$opt} = $confdesc->{$opt};
2017 my ($key, $value) = @_;
2019 die "unknown setting '$key'\n" if !$confdesc->{$key};
2021 my $type = $confdesc->{$key}->{type
};
2023 if (!defined($value)) {
2024 die "got undefined value\n";
2027 if ($value =~ m/[\n\r]/) {
2028 die "property contains a line feed\n";
2031 if ($type eq 'boolean') {
2032 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
2033 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
2034 die "type check ('boolean') failed - got '$value'\n";
2035 } elsif ($type eq 'integer') {
2036 return int($1) if $value =~ m/^(\d+)$/;
2037 die "type check ('integer') failed - got '$value'\n";
2038 } elsif ($type eq 'number') {
2039 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
2040 die "type check ('number') failed - got '$value'\n";
2041 } elsif ($type eq 'string') {
2042 if (my $fmt = $confdesc->{$key}->{format
}) {
2043 PVE
::JSONSchema
::check_format
($fmt, $value);
2046 $value =~ s/^\"(.*)\"$/$1/;
2049 die "internal error"
2053 sub check_iommu_support
{
2054 #fixme : need to check IOMMU support
2055 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
2065 my $conf = PVE
::QemuConfig-
>config_file($vmid);
2066 utime undef, undef, $conf;
2070 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
2072 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
2074 my $conf = PVE
::QemuConfig-
>load_config($vmid);
2076 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
2078 # only remove disks owned by this VM
2079 foreach_drive
($conf, sub {
2080 my ($ds, $drive) = @_;
2082 return if drive_is_cdrom
($drive);
2084 my $volid = $drive->{file
};
2086 return if !$volid || $volid =~ m
|^/|;
2088 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2089 return if !$path || !$owner || ($owner != $vmid);
2091 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2094 if ($keep_empty_config) {
2095 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2100 # also remove unused disk
2102 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2105 PVE
::Storage
::foreach_volid
($dl, sub {
2106 my ($volid, $sid, $volname, $d) = @_;
2107 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2116 sub parse_vm_config
{
2117 my ($filename, $raw) = @_;
2119 return undef if !defined($raw);
2122 digest
=> Digest
::SHA
::sha1_hex
($raw),
2127 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2128 || die "got strange filename '$filename'";
2136 my @lines = split(/\n/, $raw);
2137 foreach my $line (@lines) {
2138 next if $line =~ m/^\s*$/;
2140 if ($line =~ m/^\[PENDING\]\s*$/i) {
2141 $section = 'pending';
2142 if (defined($descr)) {
2144 $conf->{description
} = $descr;
2147 $conf = $res->{$section} = {};
2150 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2152 if (defined($descr)) {
2154 $conf->{description
} = $descr;
2157 $conf = $res->{snapshots
}->{$section} = {};
2161 if ($line =~ m/^\#(.*)\s*$/) {
2162 $descr = '' if !defined($descr);
2163 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2167 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2168 $descr = '' if !defined($descr);
2169 $descr .= PVE
::Tools
::decode_text
($2);
2170 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2171 $conf->{snapstate
} = $1;
2172 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2175 $conf->{$key} = $value;
2176 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2178 if ($section eq 'pending') {
2179 $conf->{delete} = $value; # we parse this later
2181 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2183 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2186 eval { $value = check_type
($key, $value); };
2188 warn "vm $vmid - unable to parse value of '$key' - $@";
2190 $key = 'ide2' if $key eq 'cdrom';
2191 my $fmt = $confdesc->{$key}->{format
};
2192 if ($fmt && $fmt =~ /^pve-qm-(?:ide|scsi|virtio|sata)$/) {
2193 my $v = parse_drive
($key, $value);
2194 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2195 $v->{file
} = $volid;
2196 $value = print_drive
($vmid, $v);
2198 warn "vm $vmid - unable to parse value of '$key'\n";
2203 $conf->{$key} = $value;
2208 if (defined($descr)) {
2210 $conf->{description
} = $descr;
2212 delete $res->{snapstate
}; # just to be sure
2217 sub write_vm_config
{
2218 my ($filename, $conf) = @_;
2220 delete $conf->{snapstate
}; # just to be sure
2222 if ($conf->{cdrom
}) {
2223 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2224 $conf->{ide2
} = $conf->{cdrom
};
2225 delete $conf->{cdrom
};
2228 # we do not use 'smp' any longer
2229 if ($conf->{sockets
}) {
2230 delete $conf->{smp
};
2231 } elsif ($conf->{smp
}) {
2232 $conf->{sockets
} = $conf->{smp
};
2233 delete $conf->{cores
};
2234 delete $conf->{smp
};
2237 my $used_volids = {};
2239 my $cleanup_config = sub {
2240 my ($cref, $pending, $snapname) = @_;
2242 foreach my $key (keys %$cref) {
2243 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2244 $key eq 'snapstate' || $key eq 'pending';
2245 my $value = $cref->{$key};
2246 if ($key eq 'delete') {
2247 die "propertry 'delete' is only allowed in [PENDING]\n"
2249 # fixme: check syntax?
2252 eval { $value = check_type
($key, $value); };
2253 die "unable to parse value of '$key' - $@" if $@;
2255 $cref->{$key} = $value;
2257 if (!$snapname && is_valid_drivename
($key)) {
2258 my $drive = parse_drive
($key, $value);
2259 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2264 &$cleanup_config($conf);
2266 &$cleanup_config($conf->{pending
}, 1);
2268 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2269 die "internal error" if $snapname eq 'pending';
2270 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2273 # remove 'unusedX' settings if we re-add a volume
2274 foreach my $key (keys %$conf) {
2275 my $value = $conf->{$key};
2276 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2277 delete $conf->{$key};
2281 my $generate_raw_config = sub {
2282 my ($conf, $pending) = @_;
2286 # add description as comment to top of file
2287 if (defined(my $descr = $conf->{description
})) {
2289 foreach my $cl (split(/\n/, $descr)) {
2290 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2293 $raw .= "#\n" if $pending;
2297 foreach my $key (sort keys %$conf) {
2298 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2299 $raw .= "$key: $conf->{$key}\n";
2304 my $raw = &$generate_raw_config($conf);
2306 if (scalar(keys %{$conf->{pending
}})){
2307 $raw .= "\n[PENDING]\n";
2308 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2311 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2312 $raw .= "\n[$snapname]\n";
2313 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2323 # we use static defaults from our JSON schema configuration
2324 foreach my $key (keys %$confdesc) {
2325 if (defined(my $default = $confdesc->{$key}->{default})) {
2326 $res->{$key} = $default;
2330 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2331 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2337 my $vmlist = PVE
::Cluster
::get_vmlist
();
2339 return $res if !$vmlist || !$vmlist->{ids
};
2340 my $ids = $vmlist->{ids
};
2342 foreach my $vmid (keys %$ids) {
2343 my $d = $ids->{$vmid};
2344 next if !$d->{node
} || $d->{node
} ne $nodename;
2345 next if !$d->{type
} || $d->{type
} ne 'qemu';
2346 $res->{$vmid}->{exists} = 1;
2351 # test if VM uses local resources (to prevent migration)
2352 sub check_local_resources
{
2353 my ($conf, $noerr) = @_;
2357 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2358 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2360 foreach my $k (keys %$conf) {
2361 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2362 # sockets are safe: they will recreated be on the target side post-migrate
2363 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2364 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2367 die "VM uses local resources\n" if $loc_res && !$noerr;
2372 # check if used storages are available on all nodes (use by migrate)
2373 sub check_storage_availability
{
2374 my ($storecfg, $conf, $node) = @_;
2376 foreach_drive
($conf, sub {
2377 my ($ds, $drive) = @_;
2379 my $volid = $drive->{file
};
2382 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2385 # check if storage is available on both nodes
2386 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2387 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2391 # list nodes where all VM images are available (used by has_feature API)
2393 my ($conf, $storecfg) = @_;
2395 my $nodelist = PVE
::Cluster
::get_nodelist
();
2396 my $nodehash = { map { $_ => 1 } @$nodelist };
2397 my $nodename = PVE
::INotify
::nodename
();
2399 foreach_drive
($conf, sub {
2400 my ($ds, $drive) = @_;
2402 my $volid = $drive->{file
};
2405 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2407 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2408 if ($scfg->{disable
}) {
2410 } elsif (my $avail = $scfg->{nodes
}) {
2411 foreach my $node (keys %$nodehash) {
2412 delete $nodehash->{$node} if !$avail->{$node};
2414 } elsif (!$scfg->{shared
}) {
2415 foreach my $node (keys %$nodehash) {
2416 delete $nodehash->{$node} if $node ne $nodename
2426 my ($pidfile, $pid) = @_;
2428 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2432 return undef if !$line;
2433 my @param = split(/\0/, $line);
2435 my $cmd = $param[0];
2436 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2438 for (my $i = 0; $i < scalar (@param); $i++) {
2441 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2442 my $p = $param[$i+1];
2443 return 1 if $p && ($p eq $pidfile);
2452 my ($vmid, $nocheck, $node) = @_;
2454 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2456 die "unable to find configuration file for VM $vmid - no such machine\n"
2457 if !$nocheck && ! -f
$filename;
2459 my $pidfile = pidfile_name
($vmid);
2461 if (my $fd = IO
::File-
>new("<$pidfile")) {
2466 my $mtime = $st->mtime;
2467 if ($mtime > time()) {
2468 warn "file '$filename' modified in future\n";
2471 if ($line =~ m/^(\d+)$/) {
2473 if (check_cmdline
($pidfile, $pid)) {
2474 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2486 my $vzlist = config_list
();
2488 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2490 while (defined(my $de = $fd->read)) {
2491 next if $de !~ m/^(\d+)\.pid$/;
2493 next if !defined($vzlist->{$vmid});
2494 if (my $pid = check_running
($vmid)) {
2495 $vzlist->{$vmid}->{pid
} = $pid;
2503 my ($storecfg, $conf) = @_;
2505 my $bootdisk = $conf->{bootdisk
};
2506 return undef if !$bootdisk;
2507 return undef if !is_valid_drivename
($bootdisk);
2509 return undef if !$conf->{$bootdisk};
2511 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2512 return undef if !defined($drive);
2514 return undef if drive_is_cdrom
($drive);
2516 my $volid = $drive->{file
};
2517 return undef if !$volid;
2519 return $drive->{size
};
2522 my $last_proc_pid_stat;
2524 # get VM status information
2525 # This must be fast and should not block ($full == false)
2526 # We only query KVM using QMP if $full == true (this can be slow)
2528 my ($opt_vmid, $full) = @_;
2532 my $storecfg = PVE
::Storage
::config
();
2534 my $list = vzlist
();
2535 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2537 my $cpucount = $cpuinfo->{cpus
} || 1;
2539 foreach my $vmid (keys %$list) {
2540 next if $opt_vmid && ($vmid ne $opt_vmid);
2542 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2543 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2546 $d->{pid
} = $list->{$vmid}->{pid
};
2548 # fixme: better status?
2549 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2551 my $size = disksize
($storecfg, $conf);
2552 if (defined($size)) {
2553 $d->{disk
} = 0; # no info available
2554 $d->{maxdisk
} = $size;
2560 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2561 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2562 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2564 $d->{name
} = $conf->{name
} || "VM $vmid";
2565 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2567 if ($conf->{balloon
}) {
2568 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2569 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2580 $d->{diskwrite
} = 0;
2582 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2587 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2588 foreach my $dev (keys %$netdev) {
2589 next if $dev !~ m/^tap([1-9]\d*)i/;
2591 my $d = $res->{$vmid};
2594 $d->{netout
} += $netdev->{$dev}->{receive
};
2595 $d->{netin
} += $netdev->{$dev}->{transmit
};
2598 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2599 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2604 my $ctime = gettimeofday
;
2606 foreach my $vmid (keys %$list) {
2608 my $d = $res->{$vmid};
2609 my $pid = $d->{pid
};
2612 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2613 next if !$pstat; # not running
2615 my $used = $pstat->{utime} + $pstat->{stime
};
2617 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2619 if ($pstat->{vsize
}) {
2620 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2623 my $old = $last_proc_pid_stat->{$pid};
2625 $last_proc_pid_stat->{$pid} = {
2633 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2635 if ($dtime > 1000) {
2636 my $dutime = $used - $old->{used
};
2638 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2639 $last_proc_pid_stat->{$pid} = {
2645 $d->{cpu
} = $old->{cpu
};
2649 return $res if !$full;
2651 my $qmpclient = PVE
::QMPClient-
>new();
2653 my $ballooncb = sub {
2654 my ($vmid, $resp) = @_;
2656 my $info = $resp->{'return'};
2657 return if !$info->{max_mem
};
2659 my $d = $res->{$vmid};
2661 # use memory assigned to VM
2662 $d->{maxmem
} = $info->{max_mem
};
2663 $d->{balloon
} = $info->{actual
};
2665 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2666 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2667 $d->{freemem
} = $info->{free_mem
};
2670 $d->{ballooninfo
} = $info;
2673 my $blockstatscb = sub {
2674 my ($vmid, $resp) = @_;
2675 my $data = $resp->{'return'} || [];
2676 my $totalrdbytes = 0;
2677 my $totalwrbytes = 0;
2679 for my $blockstat (@$data) {
2680 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2681 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2683 $blockstat->{device
} =~ s/drive-//;
2684 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2686 $res->{$vmid}->{diskread
} = $totalrdbytes;
2687 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2690 my $statuscb = sub {
2691 my ($vmid, $resp) = @_;
2693 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2694 # this fails if ballon driver is not loaded, so this must be
2695 # the last commnand (following command are aborted if this fails).
2696 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2698 my $status = 'unknown';
2699 if (!defined($status = $resp->{'return'}->{status
})) {
2700 warn "unable to get VM status\n";
2704 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2707 foreach my $vmid (keys %$list) {
2708 next if $opt_vmid && ($vmid ne $opt_vmid);
2709 next if !$res->{$vmid}->{pid
}; # not running
2710 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2713 $qmpclient->queue_execute(undef, 1);
2715 foreach my $vmid (keys %$list) {
2716 next if $opt_vmid && ($vmid ne $opt_vmid);
2717 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2724 my ($conf, $func, @param) = @_;
2726 foreach my $ds (valid_drive_names
()) {
2727 next if !defined($conf->{$ds});
2729 my $drive = parse_drive
($ds, $conf->{$ds});
2732 &$func($ds, $drive, @param);
2737 my ($conf, $func, @param) = @_;
2741 my $test_volid = sub {
2742 my ($volid, $is_cdrom) = @_;
2746 $volhash->{$volid} = $is_cdrom || 0;
2749 foreach_drive
($conf, sub {
2750 my ($ds, $drive) = @_;
2751 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2754 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2755 my $snap = $conf->{snapshots
}->{$snapname};
2756 &$test_volid($snap->{vmstate
}, 0);
2757 foreach_drive
($snap, sub {
2758 my ($ds, $drive) = @_;
2759 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2763 foreach my $volid (keys %$volhash) {
2764 &$func($volid, $volhash->{$volid}, @param);
2768 sub vga_conf_has_spice
{
2771 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2776 sub config_to_command
{
2777 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2780 my $globalFlags = [];
2781 my $machineFlags = [];
2787 my $kvmver = kvm_user_version
();
2788 my $vernum = 0; # unknown
2789 my $ostype = $conf->{ostype
};
2790 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2791 $vernum = $1*1000000+$2*1000;
2792 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2793 $vernum = $1*1000000+$2*1000+$3;
2796 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2798 my $have_ovz = -f
'/proc/vz/vestat';
2800 my $q35 = machine_type_is_q35
($conf);
2801 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2802 my $machine_type = $forcemachine || $conf->{machine
};
2803 my $use_old_bios_files = undef;
2804 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2806 my $cpuunits = defined($conf->{cpuunits
}) ?
2807 $conf->{cpuunits
} : $defaults->{cpuunits
};
2809 push @$cmd, '/usr/bin/kvm';
2811 push @$cmd, '-id', $vmid;
2815 my $qmpsocket = qmp_socket
($vmid);
2816 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2817 push @$cmd, '-mon', "chardev=qmp,mode=control";
2820 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2822 push @$cmd, '-daemonize';
2824 if ($conf->{smbios1
}) {
2825 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2828 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2831 # prefer the OVMF_CODE variant
2832 if (-f
$OVMF_CODE) {
2833 $ovmfbase = $OVMF_CODE;
2834 } elsif (-f
$OVMF_IMG) {
2835 $ovmfbase = $OVMF_IMG;
2838 die "no uefi base img found\n" if !$ovmfbase;
2839 push @$cmd, '-drive', "if=pflash,unit=0,format=raw,readonly,file=$ovmfbase";
2841 if (defined($conf->{efidisk0
}) && ($ovmfbase eq $OVMF_CODE)) {
2842 my $d = PVE
::JSONSchema
::parse_property_string
($efidisk_fmt, $conf->{efidisk0
});
2843 my $format = $d->{format
} // 'raw';
2845 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($d->{file
}, 1);
2847 $path = PVE
::Storage
::path
($storecfg, $d->{file
});
2848 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2849 $format = qemu_img_format
($scfg, $volname);
2854 push @$cmd, '-drive', "if=pflash,unit=1,id=drive-efidisk0,format=$format,file=$path";
2855 } elsif ($ovmfbase eq $OVMF_CODE) {
2856 warn "using uefi without permanent efivars disk\n";
2857 my $ovmfvar_dst = "/tmp/$vmid-ovmf.fd";
2858 PVE
::Tools
::file_copy
($OVMF_VARS, $ovmfvar_dst, 256*1024);
2859 push @$cmd, '-drive', "if=pflash,unit=1,format=raw,file=$ovmfvar_dst";
2861 # if the base img is not OVMF_CODE, we do not have to bother
2862 # to create/use a vars image, since it will not be used anyway
2863 # this can only happen if someone manually deletes the OVMF_CODE image
2864 # or has an old pve-qemu-kvm version installed.
2865 # both should not happen, but we ignore it here
2870 # add usb controllers
2871 my @usbcontrollers = PVE
::QemuServer
::USB
::get_usb_controllers
($conf, $bridges, $q35, $usbdesc->{format
}, $MAX_USB_DEVICES);
2872 push @$devices, @usbcontrollers if @usbcontrollers;
2873 my $vga = $conf->{vga
};
2875 my $qxlnum = vga_conf_has_spice
($vga);
2876 $vga = 'qxl' if $qxlnum;
2879 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2880 $conf->{ostype
} eq 'win7' ||
2881 $conf->{ostype
} eq 'w2k8')) {
2888 # enable absolute mouse coordinates (needed by vnc)
2890 if (defined($conf->{tablet
})) {
2891 $tablet = $conf->{tablet
};
2893 $tablet = $defaults->{tablet
};
2894 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2895 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2898 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2902 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2903 my $d = parse_hostpci
($conf->{"hostpci$i"});
2906 my $pcie = $d->{pcie
};
2908 die "q35 machine model is not enabled" if !$q35;
2909 $pciaddr = print_pcie_addr
("hostpci$i");
2911 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2914 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2916 if ($d->{'x-vga'}) {
2917 $xvga = ',x-vga=on';
2920 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2921 push @$cpuFlags , 'hv_vendor_id=proxmox';
2923 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2927 my $pcidevices = $d->{pciid
};
2928 my $multifunction = 1 if @$pcidevices > 1;
2931 foreach my $pcidevice (@$pcidevices) {
2933 my $id = "hostpci$i";
2934 $id .= ".$j" if $multifunction;
2935 my $addr = $pciaddr;
2936 $addr .= ".$j" if $multifunction;
2937 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2940 $devicestr .= "$rombar$xvga";
2941 $devicestr .= ",multifunction=on" if $multifunction;
2944 push @$devices, '-device', $devicestr;
2950 my @usbdevices = PVE
::QemuServer
::USB
::get_usb_devices
($conf, $usbdesc->{format
}, $MAX_USB_DEVICES);
2951 push @$devices, @usbdevices if @usbdevices;
2953 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2954 if (my $path = $conf->{"serial$i"}) {
2955 if ($path eq 'socket') {
2956 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2957 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2958 push @$devices, '-device', "isa-serial,chardev=serial$i";
2960 die "no such serial device\n" if ! -c
$path;
2961 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2962 push @$devices, '-device', "isa-serial,chardev=serial$i";
2968 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2969 if (my $path = $conf->{"parallel$i"}) {
2970 die "no such parallel device\n" if ! -c
$path;
2971 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2972 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2973 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2977 my $vmname = $conf->{name
} || "vm$vmid";
2979 push @$cmd, '-name', $vmname;
2982 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2983 $sockets = $conf->{sockets
} if $conf->{sockets
};
2985 my $cores = $conf->{cores
} || 1;
2987 my $maxcpus = $sockets * $cores;
2989 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2991 my $allowed_vcpus = $cpuinfo->{cpus
};
2993 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2994 if ($allowed_vcpus < $maxcpus);
2996 if($hotplug_features->{cpu
} && qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 7)) {
2998 push @$cmd, '-smp', "1,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2999 for (my $i = 2; $i <= $vcpus; $i++) {
3000 my $cpustr = print_cpu_device
($conf,$i);
3001 push @$cmd, '-device', $cpustr;
3006 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3008 push @$cmd, '-nodefaults';
3010 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3012 my $bootindex_hash = {};
3014 foreach my $o (split(//, $bootorder)) {
3015 $bootindex_hash->{$o} = $i*100;
3019 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg";
3021 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3023 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3025 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3027 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3028 my $socket = vnc_socket
($vmid);
3029 push @$cmd, '-vnc', "unix:$socket,x509,password";
3031 push @$cmd, '-nographic';
3035 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3037 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3038 my $useLocaltime = $conf->{localtime};
3041 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3043 if ($ostype =~ m/^w/) { # windows
3044 $useLocaltime = 1 if !defined($conf->{localtime});
3046 # use time drift fix when acpi is enabled
3047 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3048 $tdf = 1 if !defined($conf->{tdf
});
3052 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3053 $ostype eq 'wvista') {
3054 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3055 push @$cmd, '-no-hpet';
3056 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3057 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3058 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3059 push @$cpuFlags , 'hv_time' if !$nokvm;
3061 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 6)) {
3062 push @$cpuFlags , 'hv_reset' if !$nokvm;
3063 push @$cpuFlags , 'hv_vpindex' if !$nokvm;
3064 push @$cpuFlags , 'hv_runtime' if !$nokvm;
3068 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3072 if ($ostype eq 'win7' || $ostype eq 'win8') {
3073 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3077 push @$rtcFlags, 'driftfix=slew' if $tdf;
3080 push @$machineFlags, 'accel=tcg';
3082 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3085 if ($machine_type) {
3086 push @$machineFlags, "type=${machine_type}";
3089 if ($conf->{startdate
}) {
3090 push @$rtcFlags, "base=$conf->{startdate}";
3091 } elsif ($useLocaltime) {
3092 push @$rtcFlags, 'base=localtime';
3095 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3096 if (my $cputype = $conf->{cpu
}) {
3097 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3098 or die "Cannot parse cpu description: $cputype\n";
3099 $cpu = $cpuconf->{cputype
};
3100 $kvm_off = 1 if $cpuconf->{hidden
};
3103 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3105 push @$cpuFlags , '-x2apic'
3106 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3108 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3110 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3112 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3114 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3115 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3118 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3120 push @$cpuFlags, 'kvm=off' if $kvm_off;
3122 my $cpu_vendor = $cpu_vendor_list->{$cpu} ||
3123 die "internal error"; # should not happen
3125 push @$cpuFlags, "vendor=${cpu_vendor}"
3126 if $cpu_vendor ne 'default';
3128 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3130 push @$cmd, '-cpu', $cpu;
3132 PVE
::QemuServer
::Memory
::config
($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
3134 push @$cmd, '-S' if $conf->{freeze
};
3136 # set keyboard layout
3137 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3138 push @$cmd, '-k', $kb if $kb;
3141 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3142 #push @$cmd, '-soundhw', 'es1370';
3143 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3145 if($conf->{agent
}) {
3146 my $qgasocket = qmp_socket
($vmid, 1);
3147 my $pciaddr = print_pci_addr
("qga0", $bridges);
3148 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3149 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3150 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3157 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3158 for(my $i = 1; $i < $qxlnum; $i++){
3159 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3160 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3163 # assume other OS works like Linux
3164 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3165 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3169 my $pciaddr = print_pci_addr
("spice", $bridges);
3171 my $nodename = PVE
::INotify
::nodename
();
3172 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3173 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3175 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3177 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3178 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3179 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3182 # enable balloon by default, unless explicitly disabled
3183 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3184 $pciaddr = print_pci_addr
("balloon0", $bridges);
3185 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3188 if ($conf->{watchdog
}) {
3189 my $wdopts = parse_watchdog
($conf->{watchdog
});
3190 $pciaddr = print_pci_addr
("watchdog", $bridges);
3191 my $watchdog = $wdopts->{model
} || 'i6300esb';
3192 push @$devices, '-device', "$watchdog$pciaddr";
3193 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3197 my $scsicontroller = {};
3198 my $ahcicontroller = {};
3199 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3201 # Add iscsi initiator name if available
3202 if (my $initiator = get_initiator_name
()) {
3203 push @$devices, '-iscsi', "initiator-name=$initiator";
3206 foreach_drive
($conf, sub {
3207 my ($ds, $drive) = @_;
3209 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3210 push @$vollist, $drive->{file
};
3213 $use_virtio = 1 if $ds =~ m/^virtio/;
3215 if (drive_is_cdrom
($drive)) {
3216 if ($bootindex_hash->{d
}) {
3217 $drive->{bootindex
} = $bootindex_hash->{d
};
3218 $bootindex_hash->{d
} += 1;
3221 if ($bootindex_hash->{c
}) {
3222 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3223 $bootindex_hash->{c
} += 1;
3227 if($drive->{interface
} eq 'virtio'){
3228 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3231 if ($drive->{interface
} eq 'scsi') {
3233 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3235 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3236 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3239 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3240 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3241 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3242 } elsif ($drive->{iothread
}) {
3243 warn "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n";
3247 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3248 $queues = ",num_queues=$drive->{queues}";
3251 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3252 $scsicontroller->{$controller}=1;
3255 if ($drive->{interface
} eq 'sata') {
3256 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3257 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3258 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3259 $ahcicontroller->{$controller}=1;
3262 if ($drive->{interface
} eq 'efidisk') {
3263 # this will be added somewhere else
3267 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3268 push @$devices, '-drive',$drive_cmd;
3269 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3272 for (my $i = 0; $i < $MAX_NETS; $i++) {
3273 next if !$conf->{"net$i"};
3274 my $d = parse_net
($conf->{"net$i"});
3277 $use_virtio = 1 if $d->{model
} eq 'virtio';
3279 if ($bootindex_hash->{n
}) {
3280 $d->{bootindex
} = $bootindex_hash->{n
};
3281 $bootindex_hash->{n
} += 1;
3284 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3285 push @$devices, '-netdev', $netdevfull;
3287 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3288 push @$devices, '-device', $netdevicefull;
3293 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3298 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3300 while (my ($k, $v) = each %$bridges) {
3301 $pciaddr = print_pci_addr
("pci.$k");
3302 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3307 if ($conf->{args
}) {
3308 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3312 push @$cmd, @$devices;
3313 push @$cmd, '-rtc', join(',', @$rtcFlags)
3314 if scalar(@$rtcFlags);
3315 push @$cmd, '-machine', join(',', @$machineFlags)
3316 if scalar(@$machineFlags);
3317 push @$cmd, '-global', join(',', @$globalFlags)
3318 if scalar(@$globalFlags);
3320 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3325 return "${var_run_tmpdir}/$vmid.vnc";
3331 my $res = vm_mon_cmd
($vmid, 'query-spice');
3333 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3337 my ($vmid, $qga) = @_;
3338 my $sockettype = $qga ?
'qga' : 'qmp';
3339 return "${var_run_tmpdir}/$vmid.$sockettype";
3344 return "${var_run_tmpdir}/$vmid.pid";
3347 sub vm_devices_list
{
3350 my $res = vm_mon_cmd
($vmid, 'query-pci');
3352 foreach my $pcibus (@$res) {
3353 foreach my $device (@{$pcibus->{devices
}}) {
3354 next if !$device->{'qdev_id'};
3355 if ($device->{'pci_bridge'}) {
3356 $devices->{$device->{'qdev_id'}} = 1;
3357 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3358 next if !$bridge_device->{'qdev_id'};
3359 $devices->{$bridge_device->{'qdev_id'}} = 1;
3360 $devices->{$device->{'qdev_id'}}++;
3363 $devices->{$device->{'qdev_id'}} = 1;
3368 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3369 foreach my $block (@$resblock) {
3370 if($block->{device
} =~ m/^drive-(\S+)/){
3375 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3376 foreach my $mice (@$resmice) {
3377 if ($mice->{name
} eq 'QEMU HID Tablet') {
3378 $devices->{tablet
} = 1;
3383 # for usb devices there is no query-usb
3384 # but we can iterate over the entries in
3385 # qom-list path=/machine/peripheral
3386 my $resperipheral = vm_mon_cmd
($vmid, 'qom-list', path
=> '/machine/peripheral');
3387 foreach my $per (@$resperipheral) {
3388 if ($per->{name
} =~ m/^usb\d+$/) {
3389 $devices->{$per->{name
}} = 1;
3397 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3399 my $q35 = machine_type_is_q35
($conf);
3401 my $devices_list = vm_devices_list
($vmid);
3402 return 1 if defined($devices_list->{$deviceid});
3404 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3406 if ($deviceid eq 'tablet') {
3408 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3410 } elsif ($deviceid =~ m/^usb(\d+)$/) {
3412 die "usb hotplug currently not reliable\n";
3413 # since we can't reliably hot unplug all added usb devices
3414 # and usb passthrough disables live migration
3415 # we disable usb hotplugging for now
3416 qemu_deviceadd
($vmid, PVE
::QemuServer
::USB
::print_usbdevice_full
($conf, $deviceid, $device));
3418 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3420 qemu_iothread_add
($vmid, $deviceid, $device);
3422 qemu_driveadd
($storecfg, $vmid, $device);
3423 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3425 qemu_deviceadd
($vmid, $devicefull);
3426 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3428 eval { qemu_drivedel
($vmid, $deviceid); };
3433 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3436 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3437 my $pciaddr = print_pci_addr
($deviceid);
3438 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3440 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3442 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3443 qemu_iothread_add
($vmid, $deviceid, $device);
3444 $devicefull .= ",iothread=iothread-$deviceid";
3447 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3448 $devicefull .= ",num_queues=$device->{queues}";
3451 qemu_deviceadd
($vmid, $devicefull);
3452 qemu_deviceaddverify
($vmid, $deviceid);
3454 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3456 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3457 qemu_driveadd
($storecfg, $vmid, $device);
3459 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3460 eval { qemu_deviceadd
($vmid, $devicefull); };
3462 eval { qemu_drivedel
($vmid, $deviceid); };
3467 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3469 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3471 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3472 my $use_old_bios_files = undef;
3473 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3475 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3476 qemu_deviceadd
($vmid, $netdevicefull);
3477 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3479 eval { qemu_netdevdel
($vmid, $deviceid); };
3484 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3487 my $pciaddr = print_pci_addr
($deviceid);
3488 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3490 qemu_deviceadd
($vmid, $devicefull);
3491 qemu_deviceaddverify
($vmid, $deviceid);
3494 die "can't hotplug device '$deviceid'\n";
3500 # fixme: this should raise exceptions on error!
3501 sub vm_deviceunplug
{
3502 my ($vmid, $conf, $deviceid) = @_;
3504 my $devices_list = vm_devices_list
($vmid);
3505 return 1 if !defined($devices_list->{$deviceid});
3507 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3509 if ($deviceid eq 'tablet') {
3511 qemu_devicedel
($vmid, $deviceid);
3513 } elsif ($deviceid =~ m/^usb\d+$/) {
3515 die "usb hotplug currently not reliable\n";
3516 # when unplugging usb devices this way,
3517 # there may be remaining usb controllers/hubs
3518 # so we disable it for now
3519 qemu_devicedel
($vmid, $deviceid);
3520 qemu_devicedelverify
($vmid, $deviceid);
3522 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3524 qemu_devicedel
($vmid, $deviceid);
3525 qemu_devicedelverify
($vmid, $deviceid);
3526 qemu_drivedel
($vmid, $deviceid);
3527 qemu_iothread_del
($conf, $vmid, $deviceid);
3529 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3531 qemu_devicedel
($vmid, $deviceid);
3532 qemu_devicedelverify
($vmid, $deviceid);
3533 qemu_iothread_del
($conf, $vmid, $deviceid);
3535 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3537 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3538 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3539 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3541 qemu_devicedel
($vmid, $deviceid);
3542 qemu_drivedel
($vmid, $deviceid);
3543 qemu_deletescsihw
($conf, $vmid, $deviceid);
3545 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3547 qemu_devicedel
($vmid, $deviceid);
3548 qemu_devicedelverify
($vmid, $deviceid);
3549 qemu_netdevdel
($vmid, $deviceid);
3552 die "can't unplug device '$deviceid'\n";
3558 sub qemu_deviceadd
{
3559 my ($vmid, $devicefull) = @_;
3561 $devicefull = "driver=".$devicefull;
3562 my %options = split(/[=,]/, $devicefull);
3564 vm_mon_cmd
($vmid, "device_add" , %options);
3567 sub qemu_devicedel
{
3568 my ($vmid, $deviceid) = @_;
3570 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3573 sub qemu_iothread_add
{
3574 my($vmid, $deviceid, $device) = @_;
3576 if ($device->{iothread
}) {
3577 my $iothreads = vm_iothreads_list
($vmid);
3578 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3582 sub qemu_iothread_del
{
3583 my($conf, $vmid, $deviceid) = @_;
3585 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3586 if ($device->{iothread
}) {
3587 my $iothreads = vm_iothreads_list
($vmid);
3588 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3592 sub qemu_objectadd
{
3593 my($vmid, $objectid, $qomtype) = @_;
3595 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3600 sub qemu_objectdel
{
3601 my($vmid, $objectid) = @_;
3603 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3609 my ($storecfg, $vmid, $device) = @_;
3611 my $drive = print_drive_full
($storecfg, $vmid, $device);
3612 $drive =~ s/\\/\\\\/g;
3613 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3615 # If the command succeeds qemu prints: "OK
"
3616 return 1 if $ret =~ m/OK/s;
3618 die "adding drive failed
: $ret\n";
3622 my($vmid, $deviceid) = @_;
3624 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3627 return 1 if $ret eq "";
3629 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3630 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3632 die "deleting drive
$deviceid failed
: $ret\n";
3635 sub qemu_deviceaddverify {
3636 my ($vmid, $deviceid) = @_;
3638 for (my $i = 0; $i <= 5; $i++) {
3639 my $devices_list = vm_devices_list($vmid);
3640 return 1 if defined($devices_list->{$deviceid});
3644 die "error on hotplug device
'$deviceid'\n";
3648 sub qemu_devicedelverify {
3649 my ($vmid, $deviceid) = @_;
3651 # need to verify that the device is correctly removed as device_del
3652 # is async and empty return is not reliable
3654 for (my $i = 0; $i <= 5; $i++) {
3655 my $devices_list = vm_devices_list($vmid);
3656 return 1 if !defined($devices_list->{$deviceid});
3660 die "error on hot-unplugging device
'$deviceid'\n";
3663 sub qemu_findorcreatescsihw {
3664 my ($storecfg, $conf, $vmid, $device) = @_;
3666 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3668 my $scsihwid="$controller_prefix$controller";
3669 my $devices_list = vm_devices_list($vmid);
3671 if(!defined($devices_list->{$scsihwid})) {
3672 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3678 sub qemu_deletescsihw {
3679 my ($conf, $vmid, $opt) = @_;
3681 my $device = parse_drive($opt, $conf->{$opt});
3683 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3684 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3688 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3690 my $devices_list = vm_devices_list($vmid);
3691 foreach my $opt (keys %{$devices_list}) {
3692 if (PVE::QemuServer::is_valid_drivename($opt)) {
3693 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3694 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3700 my $scsihwid="scsihw
$controller";
3702 vm_deviceunplug($vmid, $conf, $scsihwid);
3707 sub qemu_add_pci_bridge {
3708 my ($storecfg, $conf, $vmid, $device) = @_;
3714 print_pci_addr($device, $bridges);
3716 while (my ($k, $v) = each %$bridges) {
3719 return 1 if !defined($bridgeid) || $bridgeid < 1;
3721 my $bridge = "pci
.$bridgeid";
3722 my $devices_list = vm_devices_list($vmid);
3724 if (!defined($devices_list->{$bridge})) {
3725 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3731 sub qemu_set_link_status {
3732 my ($vmid, $device, $up) = @_;
3734 vm_mon_cmd($vmid, "set_link
", name => $device,
3735 up => $up ? JSON::true : JSON::false);
3738 sub qemu_netdevadd {
3739 my ($vmid, $conf, $device, $deviceid) = @_;
3741 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3742 my %options = split(/[=,]/, $netdev);
3744 vm_mon_cmd($vmid, "netdev_add
", %options);
3748 sub qemu_netdevdel {
3749 my ($vmid, $deviceid) = @_;
3751 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3754 sub qemu_usb_hotplug {
3755 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3759 # remove the old one first
3760 vm_deviceunplug($vmid, $conf, $deviceid);
3762 # check if xhci controller is necessary and available
3763 if ($device->{usb3}) {
3765 my $devicelist = vm_devices_list($vmid);
3767 if (!$devicelist->{xhci}) {
3768 my $pciaddr = print_pci_addr("xhci
");
3769 qemu_deviceadd($vmid, "nec-usb-xhci
,id
=xhci
$pciaddr");
3772 my $d = parse_usb_device($device->{host});
3773 $d->{usb3} = $device->{usb3};
3776 vm_deviceplug($storecfg, $conf, $vmid, $deviceid, $d);
3779 sub qemu_cpu_hotplug {
3780 my ($vmid, $conf, $vcpus) = @_;
3782 my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
3785 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3786 $sockets = $conf->{sockets} if $conf->{sockets};
3787 my $cores = $conf->{cores} || 1;
3788 my $maxcpus = $sockets * $cores;
3790 $vcpus = $maxcpus if !$vcpus;
3792 die "you can
't add more vcpus than maxcpus\n"
3793 if $vcpus > $maxcpus;
3795 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3797 if ($vcpus < $currentvcpus) {
3799 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3801 for (my $i = $currentvcpus; $i > $vcpus; $i--) {
3802 qemu_devicedel($vmid, "cpu$i");
3804 my $currentrunningvcpus = undef;
3806 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3807 last if scalar(@{$currentrunningvcpus}) == $i-1;
3808 raise_param_exc({ vcpus => "error unplugging cpu$i" }) if $retry > 5;
3812 #update conf after each succesfull cpu unplug
3813 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3814 PVE::QemuConfig->write_config($vmid, $conf);
3817 die "cpu hot-unplugging requires qemu version 2.7 or higher\n";
3823 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3824 die "vcpus in running vm does not match its configuration\n"
3825 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3827 if (qemu_machine_feature_enabled ($machine_type, undef, 2, 7)) {
3829 for (my $i = $currentvcpus+1; $i <= $vcpus; $i++) {
3830 my $cpustr = print_cpu_device($conf, $i);
3831 qemu_deviceadd($vmid, $cpustr);
3834 my $currentrunningvcpus = undef;
3836 $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3837 last if scalar(@{$currentrunningvcpus}) == $i;
3838 raise_param_exc({ vcpus => "error hotplugging cpu$i" }) if $retry > 10;
3842 #update conf after each succesfull cpu hotplug
3843 $conf->{vcpus} = scalar(@{$currentrunningvcpus});
3844 PVE::QemuConfig->write_config($vmid, $conf);
3848 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3849 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3854 sub qemu_block_set_io_throttle {
3855 my ($vmid, $deviceid,
3856 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3857 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max,
3858 $bps_max_length, $bps_rd_max_length, $bps_wr_max_length,
3859 $iops_max_length, $iops_rd_max_length, $iops_wr_max_length) = @_;
3861 return if !check_running($vmid) ;
3863 vm_mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
3865 bps_rd => int($bps_rd),
3866 bps_wr => int($bps_wr),
3868 iops_rd => int($iops_rd),
3869 iops_wr => int($iops_wr),
3870 bps_max => int($bps_max),
3871 bps_rd_max => int($bps_rd_max),
3872 bps_wr_max => int($bps_wr_max),
3873 iops_max => int($iops_max),
3874 iops_rd_max => int($iops_rd_max),
3875 iops_wr_max => int($iops_wr_max),
3876 bps_max_length => int($bps_max_length),
3877 bps_rd_max_length => int($bps_rd_max_length),
3878 bps_wr_max_length => int($bps_wr_max_length),
3879 iops_max_length => int($iops_max_length),
3880 iops_rd_max_length => int($iops_rd_max_length),
3881 iops_wr_max_length => int($iops_wr_max_length),
3886 # old code, only used to shutdown old VM after update
3888 my ($fh, $timeout) = @_;
3890 my $sel = new IO::Select;
3897 while (scalar (@ready = $sel->can_read($timeout))) {
3899 if ($count = $fh->sysread($buf, 8192)) {
3900 if ($buf =~ /^(.*)\(qemu\) $/s) {
3907 if (!defined($count)) {
3914 die "monitor read timeout\n" if !scalar(@ready);
3919 # old code, only used to shutdown old VM after update
3920 sub vm_monitor_command {
3921 my ($vmid, $cmdstr, $nocheck) = @_;
3926 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
3928 my $sname = "${var_run_tmpdir}/$vmid.mon";
3930 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3931 die "unable to connect to VM $vmid socket - $!\n";
3935 # hack: migrate sometime blocks the monitor (when migrate_downtime
3937 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3938 $timeout = 60*60; # 1 hour
3942 my $data = __read_avail($sock, $timeout);
3944 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3945 die "got unexpected qemu monitor banner\n";
3948 my $sel = new IO::Select;
3951 if (!scalar(my @ready = $sel->can_write($timeout))) {
3952 die "monitor write error - timeout";
3955 my $fullcmd = "$cmdstr\r";
3957 # syslog('info
', "VM $vmid monitor command: $cmdstr");
3960 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3961 die "monitor write error - $!";
3964 return if ($cmdstr eq 'q
') || ($cmdstr eq 'quit
');
3968 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3969 $timeout = 60*60; # 1 hour
3970 } elsif ($cmdstr =~ m/^(eject|change)/) {
3971 $timeout = 60; # note: cdrom mount command is slow
3973 if ($res = __read_avail($sock, $timeout)) {
3975 my @lines = split("\r?\n", $res);
3977 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3979 $res = join("\n", @lines);
3987 syslog("err", "VM $vmid monitor command failed - $err");
3994 sub qemu_block_resize {
3995 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3997 my $running = check_running($vmid);
3999 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4001 return if !$running;
4003 vm_mon_cmd($vmid, "block_resize", device => $deviceid, size => int($size));
4007 sub qemu_volume_snapshot {
4008 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4010 my $running = check_running($vmid);
4012 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4013 vm_mon_cmd($vmid, "snapshot-drive", device => $deviceid, name => $snap);
4015 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4019 sub qemu_volume_snapshot_delete {
4020 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4022 my $running = check_running($vmid);
4024 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4026 return if !$running;
4028 vm_mon_cmd($vmid, "delete-drive-snapshot", device => $deviceid, name => $snap);
4031 sub set_migration_caps {
4037 "auto-converge" => 1,
4039 "x-rdma-pin-all" => 0,
4044 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities");
4046 for my $supported_capability (@$supported_capabilities) {
4048 capability => $supported_capability->{capability},
4049 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4053 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
4056 my $fast_plug_option = {
4066 # hotplug changes in [PENDING]
4067 # $selection hash can be used to only apply specified options, for
4068 # example: { cores => 1 } (only apply changed 'cores
')
4069 # $errors ref is used to return error messages
4070 sub vmconfig_hotplug_pending {
4071 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4073 my $defaults = load_defaults();
4075 # commit values which do not have any impact on running VM first
4076 # Note: those option cannot raise errors, we we do not care about
4077 # $selection and always apply them.
4079 my $add_error = sub {
4080 my ($opt, $msg) = @_;
4081 $errors->{$opt} = "hotplug problem - $msg";
4085 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4086 if ($fast_plug_option->{$opt}) {
4087 $conf->{$opt} = $conf->{pending}->{$opt};
4088 delete $conf->{pending}->{$opt};
4094 PVE::QemuConfig->write_config($vmid, $conf);
4095 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4098 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4100 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4101 while (my ($opt, $force) = each %$pending_delete_hash) {
4102 next if $selection && !$selection->{$opt};
4104 if ($opt eq 'hotplug
') {
4105 die "skip\n" if ($conf->{hotplug} =~ /memory/);
4106 } elsif ($opt eq 'tablet
') {
4107 die "skip\n" if !$hotplug_features->{usb};
4108 if ($defaults->{tablet}) {
4109 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4111 vm_deviceunplug($vmid, $conf, $opt);
4113 } elsif ($opt =~ m/^usb\d+/) {
4115 # since we cannot reliably hot unplug usb devices
4116 # we are disabling it
4117 die "skip\n" if !$hotplug_features->{usb} || $conf->{$opt} =~ m/spice/i;
4118 vm_deviceunplug($vmid, $conf, $opt);
4119 } elsif ($opt eq 'vcpus
') {
4120 die "skip\n" if !$hotplug_features->{cpu};
4121 qemu_cpu_hotplug($vmid, $conf, undef);
4122 } elsif ($opt eq 'balloon
') {
4123 # enable balloon device is not hotpluggable
4124 die "skip\n" if !defined($conf->{balloon}) || $conf->{balloon};
4125 } elsif ($fast_plug_option->{$opt}) {
4127 } elsif ($opt =~ m/^net(\d+)$/) {
4128 die "skip\n" if !$hotplug_features->{network};
4129 vm_deviceunplug($vmid, $conf, $opt);
4130 } elsif (is_valid_drivename($opt)) {
4131 die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4132 vm_deviceunplug($vmid, $conf, $opt);
4133 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4134 } elsif ($opt =~ m/^memory$/) {
4135 die "skip\n" if !$hotplug_features->{memory};
4136 PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4137 } elsif ($opt eq 'cpuunits
') {
4138 cgroups_write("cpu", $vmid, "cpu.shares", $defaults->{cpuunits});
4139 } elsif ($opt eq 'cpulimit
') {
4140 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", -1);
4146 &$add_error($opt, $err) if $err ne "skip\n";
4148 # save new config if hotplug was successful
4149 delete $conf->{$opt};
4150 vmconfig_undelete_pending_option($conf, $opt);
4151 PVE::QemuConfig->write_config($vmid, $conf);
4152 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4156 foreach my $opt (keys %{$conf->{pending}}) {
4157 next if $selection && !$selection->{$opt};
4158 my $value = $conf->{pending}->{$opt};
4160 if ($opt eq 'hotplug
') {
4161 die "skip\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4162 } elsif ($opt eq 'tablet
') {
4163 die "skip\n" if !$hotplug_features->{usb};
4165 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4166 } elsif ($value == 0) {
4167 vm_deviceunplug($vmid, $conf, $opt);
4169 } elsif ($opt =~ m/^usb\d+$/) {
4171 # since we cannot reliably hot unplug usb devices
4172 # we are disabling it
4173 die "skip\n" if !$hotplug_features->{usb} || $value =~ m/spice/i;
4174 my $d = eval { PVE::JSONSchema::parse_property_string($usbdesc->{format}, $value) };
4175 die "skip\n" if !$d;
4176 qemu_usb_hotplug($storecfg, $conf, $vmid, $opt, $d);
4177 } elsif ($opt eq 'vcpus
') {
4178 die "skip\n" if !$hotplug_features->{cpu};
4179 qemu_cpu_hotplug($vmid, $conf, $value);
4180 } elsif ($opt eq 'balloon
') {
4181 # enable/disable balloning device is not hotpluggable
4182 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4183 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4184 die "skip\n" if $old_balloon_enabled != $new_balloon_enabled;
4186 # allow manual ballooning if shares is set to zero
4187 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4188 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4189 vm_mon_cmd($vmid, "balloon", value => $balloon*1024*1024);
4191 } elsif ($opt =~ m/^net(\d+)$/) {
4192 # some changes can be done without hotplug
4193 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4194 $vmid, $opt, $value);
4195 } elsif (is_valid_drivename($opt)) {
4196 # some changes can be done without hotplug
4197 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4198 $vmid, $opt, $value, 1);
4199 } elsif ($opt =~ m/^memory$/) { #dimms
4200 die "skip\n" if !$hotplug_features->{memory};
4201 $value = PVE::QemuServer::Memory::qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4202 } elsif ($opt eq 'cpuunits
') {
4203 cgroups_write("cpu", $vmid, "cpu.shares", $conf->{pending}->{$opt});
4204 } elsif ($opt eq 'cpulimit
') {
4205 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4206 cgroups_write("cpu", $vmid, "cpu.cfs_quota_us", $cpulimit);
4208 die "skip\n"; # skip non-hot-pluggable options
4212 &$add_error($opt, $err) if $err ne "skip\n";
4214 # save new config if hotplug was successful
4215 $conf->{$opt} = $value;
4216 delete $conf->{pending}->{$opt};
4217 PVE::QemuConfig->write_config($vmid, $conf);
4218 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4223 sub try_deallocate_drive {
4224 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4226 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4227 my $volid = $drive->{file};
4228 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4229 my $sid = PVE::Storage::parse_volume_id($volid);
4230 $rpcenv->check($authuser, "/storage/$sid", ['Datastore
.AllocateSpace
']);
4232 # check if the disk is really unused
4233 die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
4234 if is_volume_in_use($storecfg, $conf, $key, $volid);
4235 PVE::Storage::vdisk_free($storecfg, $volid);
4238 # If vm is not owner of this disk remove from config
4246 sub vmconfig_delete_or_detach_drive {
4247 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4249 my $drive = parse_drive($opt, $conf->{$opt});
4251 my $rpcenv = PVE::RPCEnvironment::get();
4252 my $authuser = $rpcenv->get_user();
4255 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM
.Config
.Disk
']);
4256 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4258 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4262 sub vmconfig_apply_pending {
4263 my ($vmid, $conf, $storecfg) = @_;
4267 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4268 while (my ($opt, $force) = each %$pending_delete_hash) {
4269 die "internal error" if $opt =~ m/^unused/;
4270 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4271 if (!defined($conf->{$opt})) {
4272 vmconfig_undelete_pending_option($conf, $opt);
4273 PVE::QemuConfig->write_config($vmid, $conf);
4274 } elsif (is_valid_drivename($opt)) {
4275 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4276 vmconfig_undelete_pending_option($conf, $opt);
4277 delete $conf->{$opt};
4278 PVE::QemuConfig->write_config($vmid, $conf);
4280 vmconfig_undelete_pending_option($conf, $opt);
4281 delete $conf->{$opt};
4282 PVE::QemuConfig->write_config($vmid, $conf);
4286 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4288 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4289 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4291 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4292 # skip if nothing changed
4293 } elsif (is_valid_drivename($opt)) {
4294 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4295 if defined($conf->{$opt});
4296 $conf->{$opt} = $conf->{pending}->{$opt};
4298 $conf->{$opt} = $conf->{pending}->{$opt};
4301 delete $conf->{pending}->{$opt};
4302 PVE::QemuConfig->write_config($vmid, $conf);
4306 my $safe_num_ne = sub {
4309 return 0 if !defined($a) && !defined($b);
4310 return 1 if !defined($a);
4311 return 1 if !defined($b);
4316 my $safe_string_ne = sub {
4319 return 0 if !defined($a) && !defined($b);
4320 return 1 if !defined($a);
4321 return 1 if !defined($b);
4326 sub vmconfig_update_net {
4327 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4329 my $newnet = parse_net($value);
4331 if ($conf->{$opt}) {
4332 my $oldnet = parse_net($conf->{$opt});
4334 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4335 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4336 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4337 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4339 # for non online change, we try to hot-unplug
4340 die "skip\n" if !$hotplug;
4341 vm_deviceunplug($vmid, $conf, $opt);
4344 die "internal error" if $opt !~ m/net(\d+)/;
4345 my $iface = "tap${vmid}i$1";
4347 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4348 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4349 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4350 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4351 PVE::Network::tap_unplug($iface);
4352 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4353 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4354 # Rate can be applied on its own but any change above needs to
4355 # include the rate in tap_plug since OVS resets everything.
4356 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4359 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4360 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4368 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4374 sub vmconfig_update_disk {
4375 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4377 # fixme: do we need force?
4379 my $drive = parse_drive($opt, $value);
4381 if ($conf->{$opt}) {
4383 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4385 my $media = $drive->{media} || 'disk
';
4386 my $oldmedia = $old_drive->{media} || 'disk
';
4387 die "unable to change media type\n" if $media ne $oldmedia;
4389 if (!drive_is_cdrom($old_drive)) {
4391 if ($drive->{file} ne $old_drive->{file}) {
4393 die "skip\n" if !$hotplug;
4395 # unplug and register as unused
4396 vm_deviceunplug($vmid, $conf, $opt);
4397 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4400 # update existing disk
4402 # skip non hotpluggable value
4403 if (&$safe_string_ne($drive->{discard}, $old_drive->{discard}) ||
4404 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4405 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4406 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4411 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4412 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4413 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4414 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4415 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4416 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4417 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4418 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4419 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4420 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4421 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4422 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max}) ||
4423 &$safe_num_ne($drive->{bps_max_length}, $old_drive->{bps_max_length}) ||
4424 &$safe_num_ne($drive->{bps_rd_max_length}, $old_drive->{bps_rd_max_length}) ||
4425 &$safe_num_ne($drive->{bps_wr_max_length}, $old_drive->{bps_wr_max_length}) ||
4426 &$safe_num_ne($drive->{iops_max_length}, $old_drive->{iops_max_length}) ||
4427 &$safe_num_ne($drive->{iops_rd_max_length}, $old_drive->{iops_rd_max_length}) ||
4428 &$safe_num_ne($drive->{iops_wr_max_length}, $old_drive->{iops_wr_max_length})) {
4430 qemu_block_set_io_throttle($vmid,"drive-$opt",
4431 ($drive->{mbps} || 0)*1024*1024,
4432 ($drive->{mbps_rd} || 0)*1024*1024,
4433 ($drive->{mbps_wr} || 0)*1024*1024,
4434 $drive->{iops} || 0,
4435 $drive->{iops_rd} || 0,
4436 $drive->{iops_wr} || 0,
4437 ($drive->{mbps_max} || 0)*1024*1024,
4438 ($drive->{mbps_rd_max} || 0)*1024*1024,
4439 ($drive->{mbps_wr_max} || 0)*1024*1024,
4440 $drive->{iops_max} || 0,
4441 $drive->{iops_rd_max} || 0,
4442 $drive->{iops_wr_max} || 0,
4443 $drive->{bps_max_length} || 1,
4444 $drive->{bps_rd_max_length} || 1,
4445 $drive->{bps_wr_max_length} || 1,
4446 $drive->{iops_max_length} || 1,
4447 $drive->{iops_rd_max_length} || 1,
4448 $drive->{iops_wr_max_length} || 1);
4457 if ($drive->{file} eq 'none
') {
4458 vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt");
4460 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4461 vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked
4462 vm_mon_cmd($vmid, "change", device => "drive-$opt",target => "$path") if $path;
4470 die "skip\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4472 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4473 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4477 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4478 $forcemachine, $spice_ticket, $migration_network, $migration_type) = @_;
4480 PVE::QemuConfig->lock_config($vmid, sub {
4481 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4483 die "you can't start a vm
if it
's a template\n" if PVE::QemuConfig->is_template($conf);
4485 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4487 die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
4489 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4490 vmconfig_apply_pending($vmid, $conf, $storecfg);
4491 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4494 my $defaults = load_defaults();
4496 # set environment variable useful inside network script
4497 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4499 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4501 my $migrate_port = 0;
4504 if ($statefile eq 'tcp
') {
4505 my $localip = "localhost";
4506 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter
.cfg
');
4507 my $nodename = PVE::INotify::nodename();
4509 if ($migration_type eq 'insecure
') {
4510 my $migrate_network_addr = PVE::Cluster::get_local_migration_ip($migration_network);
4511 if ($migrate_network_addr) {
4512 $localip = $migrate_network_addr;
4514 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4517 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4520 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4521 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4522 $migrate_uri = "tcp:${localip}:${migrate_port}";
4523 push @$cmd, '-incoming
', $migrate_uri;
4526 } elsif ($statefile eq 'unix
') {
4527 # should be default for secure migrations as a ssh TCP forward
4528 # tunnel is not deterministic reliable ready and fails regurarly
4529 # to set up in time, so use UNIX socket forwards
4530 my $socket_addr = "/run/qemu-server/$vmid.migrate";
4531 unlink $socket_addr;
4533 $migrate_uri = "unix:$socket_addr";
4535 push @$cmd, '-incoming
', $migrate_uri;
4539 push @$cmd, '-loadstate
', $statefile;
4546 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4547 my $d = parse_hostpci($conf->{"hostpci$i"});
4549 my $pcidevices = $d->{pciid};
4550 foreach my $pcidevice (@$pcidevices) {
4551 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4553 my $info = pci_device_info("0000:$pciid");
4554 die "IOMMU not present\n" if !check_iommu_support();
4555 die "no pci device info for device '$pciid'\n" if !$info;
4556 die "can't unbind
/bind pci group to vfio
'$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4557 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4561 PVE::Storage::activate_volumes($storecfg, $vollist);
4563 if (!check_running($vmid, 1) && -d "/sys/fs/cgroup/systemd/qemu.slice/$vmid.scope") {
4565 push @$cmd, '/bin/systemctl
', 'stop
', "$vmid.scope";
4566 eval { run_command($cmd); };
4569 my $cpuunits = defined($conf->{cpuunits}) ? $conf->{cpuunits}
4570 : $defaults->{cpuunits};
4572 my %run_params = (timeout => $statefile ? undef : 30, umask => 0077);
4575 Slice => 'qemu
.slice
',
4577 CPUShares => $cpuunits
4580 if (my $cpulimit = $conf->{cpulimit}) {
4581 $properties{CPUQuota} = int($cpulimit * 100);
4583 $properties{timeout} = 10 if $statefile; # setting up the scope shoul be quick
4585 if ($conf->{hugepages}) {
4588 my $hugepages_topology = PVE::QemuServer::Memory::hugepages_topology($conf);
4589 my $hugepages_host_topology = PVE::QemuServer::Memory::hugepages_host_topology();
4591 PVE::QemuServer::Memory::hugepages_mount();
4592 PVE::QemuServer::Memory::hugepages_allocate($hugepages_topology, $hugepages_host_topology);
4595 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4596 run_command($cmd, %run_params);
4600 PVE::QemuServer::Memory::hugepages_reset($hugepages_host_topology);
4604 PVE::QemuServer::Memory::hugepages_pre_deallocate($hugepages_topology);
4606 eval { PVE::QemuServer::Memory::hugepages_update_locked($code); };
4610 PVE::Tools::enter_systemd_scope($vmid, "Proxmox VE VM $vmid", %properties);
4611 run_command($cmd, %run_params);
4616 # deactivate volumes if start fails
4617 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4618 die "start failed: $err";
4621 print "migration listens on $migrate_uri\n" if $migrate_uri;
4623 if ($statefile && $statefile ne 'tcp
') {
4624 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4628 if ($migratedfrom) {
4631 set_migration_caps($vmid);
4636 print "spice listens on port $spice_port\n";
4637 if ($spice_ticket) {
4638 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4639 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4645 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4646 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4647 if $conf->{balloon};
4650 foreach my $opt (keys %$conf) {
4651 next if $opt !~ m/^net\d+$/;
4652 my $nicconf = parse_net($conf->{$opt});
4653 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4657 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4658 path => "machine/peripheral/balloon0",
4659 property => "guest-stats-polling-interval",
4660 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4666 my ($vmid, $execute, %params) = @_;
4668 my $cmd = { execute => $execute, arguments => \%params };
4669 vm_qmp_command($vmid, $cmd);
4672 sub vm_mon_cmd_nocheck {
4673 my ($vmid, $execute, %params) = @_;
4675 my $cmd = { execute => $execute, arguments => \%params };
4676 vm_qmp_command($vmid, $cmd, 1);
4679 sub vm_qmp_command {
4680 my ($vmid, $cmd, $nocheck) = @_;
4685 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4686 $timeout = $cmd->{arguments}->{timeout};
4687 delete $cmd->{arguments}->{timeout};
4691 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4692 my $sname = qmp_socket($vmid);
4693 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4694 my $qmpclient = PVE::QMPClient->new();
4696 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4697 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4698 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4699 if scalar(%{$cmd->{arguments}});
4700 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4702 die "unable to
open monitor
socket\n";
4706 syslog("err
", "VM
$vmid qmp command failed
- $err");
4713 sub vm_human_monitor_command {
4714 my ($vmid, $cmdline) = @_;
4719 execute => 'human-monitor-command',
4720 arguments => { 'command-line' => $cmdline},
4723 return vm_qmp_command($vmid, $cmd);
4726 sub vm_commandline {
4727 my ($storecfg, $vmid) = @_;
4729 my $conf = PVE::QemuConfig->load_config($vmid);
4731 my $defaults = load_defaults();
4733 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4735 return PVE::Tools::cmd2string($cmd);
4739 my ($vmid, $skiplock) = @_;
4741 PVE::QemuConfig->lock_config($vmid, sub {
4743 my $conf = PVE::QemuConfig->load_config($vmid);
4745 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4747 vm_mon_cmd($vmid, "system_reset
");
4751 sub get_vm_volumes {
4755 foreach_volid($conf, sub {
4756 my ($volid, $is_cdrom) = @_;
4758 return if $volid =~ m|^/|;
4760 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4763 push @$vollist, $volid;
4769 sub vm_stop_cleanup {
4770 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4775 my $vollist = get_vm_volumes($conf);
4776 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4779 foreach my $ext (qw(mon qmp pid vnc qga)) {
4780 unlink "/var/run/qemu-server/${vmid}.$ext";
4783 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4785 warn $@ if $@; # avoid errors - just warn
4788 # Note: use $nockeck to skip tests if VM configuration file exists.
4789 # We need that when migration VMs to other nodes (files already moved)
4790 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4792 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4794 $force = 1 if !defined($force) && !$shutdown;
4797 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4798 kill 15, $pid if $pid;
4799 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4800 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4804 PVE
::QemuConfig-
>lock_config($vmid, sub {
4806 my $pid = check_running
($vmid, $nocheck);
4811 $conf = PVE
::QemuConfig-
>load_config($vmid);
4812 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4813 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4814 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4815 $timeout = $opts->{down
} if $opts->{down
};
4819 $timeout = 60 if !defined($timeout);
4823 if (defined($conf) && $conf->{agent
}) {
4824 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4826 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4829 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4836 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4841 if ($count >= $timeout) {
4843 warn "VM still running - terminating now with SIGTERM\n";
4846 die "VM quit/powerdown failed - got timeout\n";
4849 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4854 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4857 die "VM quit/powerdown failed\n";
4865 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4870 if ($count >= $timeout) {
4871 warn "VM still running - terminating now with SIGKILL\n";
4876 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4881 my ($vmid, $skiplock) = @_;
4883 PVE
::QemuConfig-
>lock_config($vmid, sub {
4885 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4887 PVE
::QemuConfig-
>check_lock($conf)
4888 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4890 vm_mon_cmd
($vmid, "stop");
4895 my ($vmid, $skiplock, $nocheck) = @_;
4897 PVE
::QemuConfig-
>lock_config($vmid, sub {
4901 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4903 PVE
::QemuConfig-
>check_lock($conf)
4904 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4906 vm_mon_cmd
($vmid, "cont");
4909 vm_mon_cmd_nocheck
($vmid, "cont");
4915 my ($vmid, $skiplock, $key) = @_;
4917 PVE
::QemuConfig-
>lock_config($vmid, sub {
4919 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4921 # there is no qmp command, so we use the human monitor command
4922 vm_human_monitor_command
($vmid, "sendkey $key");
4927 my ($storecfg, $vmid, $skiplock) = @_;
4929 PVE
::QemuConfig-
>lock_config($vmid, sub {
4931 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4933 if (!check_running
($vmid)) {
4934 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4936 die "VM $vmid is running - destroy failed\n";
4944 my ($filename, $buf) = @_;
4946 my $fh = IO
::File-
>new($filename, "w");
4947 return undef if !$fh;
4949 my $res = print $fh $buf;
4956 sub pci_device_info
{
4961 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4962 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4964 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4965 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4967 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4968 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4970 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4971 return undef if !defined($product) || $product !~ s/^0x//;
4976 product
=> $product,
4982 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4991 my $name = $dev->{name
};
4993 my $fn = "$pcisysfs/devices/$name/reset";
4995 return file_write
($fn, "1");
4998 sub pci_dev_bind_to_vfio
{
5001 my $name = $dev->{name
};
5003 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5005 if (!-d
$vfio_basedir) {
5006 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5008 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5010 my $testdir = "$vfio_basedir/$name";
5011 return 1 if -d
$testdir;
5013 my $data = "$dev->{vendor} $dev->{product}";
5014 return undef if !file_write
("$vfio_basedir/new_id", $data);
5016 my $fn = "$pcisysfs/devices/$name/driver/unbind";
5017 if (!file_write
($fn, $name)) {
5018 return undef if -f
$fn;
5021 $fn = "$vfio_basedir/bind";
5022 if (! -d
$testdir) {
5023 return undef if !file_write
($fn, $name);
5029 sub pci_dev_group_bind_to_vfio
{
5032 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5034 if (!-d
$vfio_basedir) {
5035 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5037 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5039 # get IOMMU group devices
5040 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5041 my @devs = grep /^0000:/, readdir($D);
5044 foreach my $pciid (@devs) {
5045 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5047 # pci bridges, switches or root ports are not supported
5048 # they have a pci_bus subdirectory so skip them
5049 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5051 my $info = pci_device_info
($1);
5052 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5058 # vzdump restore implementaion
5060 sub tar_archive_read_firstfile
{
5061 my $archive = shift;
5063 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5065 # try to detect archive type first
5066 my $pid = open (my $fh, '-|', 'tar', 'tf', $archive) ||
5067 die "unable to open file '$archive'\n";
5068 my $firstfile = <$fh>;
5072 die "ERROR: archive contaions no data\n" if !$firstfile;
5078 sub tar_restore_cleanup
{
5079 my ($storecfg, $statfile) = @_;
5081 print STDERR
"starting cleanup\n";
5083 if (my $fd = IO
::File-
>new($statfile, "r")) {
5084 while (defined(my $line = <$fd>)) {
5085 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5088 if ($volid =~ m
|^/|) {
5089 unlink $volid || die 'unlink failed\n';
5091 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5093 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5095 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5097 print STDERR
"unable to parse line in statfile - $line";
5104 sub restore_archive
{
5105 my ($archive, $vmid, $user, $opts) = @_;
5107 my $format = $opts->{format
};
5110 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5111 $format = 'tar' if !$format;
5113 } elsif ($archive =~ m/\.tar$/) {
5114 $format = 'tar' if !$format;
5115 } elsif ($archive =~ m/.tar.lzo$/) {
5116 $format = 'tar' if !$format;
5118 } elsif ($archive =~ m/\.vma$/) {
5119 $format = 'vma' if !$format;
5120 } elsif ($archive =~ m/\.vma\.gz$/) {
5121 $format = 'vma' if !$format;
5123 } elsif ($archive =~ m/\.vma\.lzo$/) {
5124 $format = 'vma' if !$format;
5127 $format = 'vma' if !$format; # default
5130 # try to detect archive format
5131 if ($format eq 'tar') {
5132 return restore_tar_archive
($archive, $vmid, $user, $opts);
5134 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5138 sub restore_update_config_line
{
5139 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5141 return if $line =~ m/^\#qmdump\#/;
5142 return if $line =~ m/^\#vzdump\#/;
5143 return if $line =~ m/^lock:/;
5144 return if $line =~ m/^unused\d+:/;
5145 return if $line =~ m/^parent:/;
5146 return if $line =~ m/^template:/; # restored VM is never a template
5148 my $dc = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
5149 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5150 # try to convert old 1.X settings
5151 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5152 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5153 my ($model, $macaddr) = split(/\=/, $devconfig);
5154 $macaddr = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if !$macaddr || $unique;
5157 bridge
=> "vmbr$ind",
5158 macaddr
=> $macaddr,
5160 my $netstr = print_net
($net);
5162 print $outfd "net$cookie->{netcount}: $netstr\n";
5163 $cookie->{netcount
}++;
5165 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5166 my ($id, $netstr) = ($1, $2);
5167 my $net = parse_net
($netstr);
5168 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
($dc->{mac_prefix
}) if $net->{macaddr
};
5169 $netstr = print_net
($net);
5170 print $outfd "$id: $netstr\n";
5171 } elsif ($line =~ m/^((ide|scsi|virtio|sata|efidisk)\d+):\s*(\S+)\s*$/) {
5174 my $di = parse_drive
($virtdev, $value);
5175 if (defined($di->{backup
}) && !$di->{backup
}) {
5176 print $outfd "#$line";
5177 } elsif ($map->{$virtdev}) {
5178 delete $di->{format
}; # format can change on restore
5179 $di->{file
} = $map->{$virtdev};
5180 $value = print_drive
($vmid, $di);
5181 print $outfd "$virtdev: $value\n";
5191 my ($cfg, $vmid) = @_;
5193 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5195 my $volid_hash = {};
5196 foreach my $storeid (keys %$info) {
5197 foreach my $item (@{$info->{$storeid}}) {
5198 next if !($item->{volid
} && $item->{size
});
5199 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5200 $volid_hash->{$item->{volid
}} = $item;
5207 sub is_volume_in_use
{
5208 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5210 my $path = PVE
::Storage
::path
($storecfg, $volid);
5212 my $scan_config = sub {
5213 my ($cref, $snapname) = @_;
5215 foreach my $key (keys %$cref) {
5216 my $value = $cref->{$key};
5217 if (is_valid_drivename
($key)) {
5218 next if $skip_drive && $key eq $skip_drive;
5219 my $drive = parse_drive
($key, $value);
5220 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5221 return 1 if $volid eq $drive->{file
};
5222 if ($drive->{file
} =~ m!^/!) {
5223 return 1 if $drive->{file
} eq $path;
5225 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5227 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5229 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5237 return 1 if &$scan_config($conf);
5241 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5242 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5248 sub update_disksize
{
5249 my ($vmid, $conf, $volid_hash) = @_;
5255 # Note: it is allowed to define multiple storages with same path (alias), so
5256 # we need to check both 'volid' and real 'path' (two different volid can point
5257 # to the same path).
5262 foreach my $opt (keys %$conf) {
5263 if (is_valid_drivename
($opt)) {
5264 my $drive = parse_drive
($opt, $conf->{$opt});
5265 my $volid = $drive->{file
};
5268 $used->{$volid} = 1;
5269 if ($volid_hash->{$volid} &&
5270 (my $path = $volid_hash->{$volid}->{path
})) {
5271 $usedpath->{$path} = 1;
5274 next if drive_is_cdrom
($drive);
5275 next if !$volid_hash->{$volid};
5277 $drive->{size
} = $volid_hash->{$volid}->{size
};
5278 my $new = print_drive
($vmid, $drive);
5279 if ($new ne $conf->{$opt}) {
5281 $conf->{$opt} = $new;
5286 # remove 'unusedX' entry if volume is used
5287 foreach my $opt (keys %$conf) {
5288 next if $opt !~ m/^unused\d+$/;
5289 my $volid = $conf->{$opt};
5290 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5291 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5293 delete $conf->{$opt};
5297 foreach my $volid (sort keys %$volid_hash) {
5298 next if $volid =~ m/vm-$vmid-state-/;
5299 next if $used->{$volid};
5300 my $path = $volid_hash->{$volid}->{path
};
5301 next if !$path; # just to be sure
5302 next if $usedpath->{$path};
5304 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5305 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5312 my ($vmid, $nolock) = @_;
5314 my $cfg = PVE
::Storage
::config
();
5316 my $volid_hash = scan_volids
($cfg, $vmid);
5318 my $updatefn = sub {
5321 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5323 PVE
::QemuConfig-
>check_lock($conf);
5326 foreach my $volid (keys %$volid_hash) {
5327 my $info = $volid_hash->{$volid};
5328 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5331 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5333 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5336 if (defined($vmid)) {
5340 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5343 my $vmlist = config_list
();
5344 foreach my $vmid (keys %$vmlist) {
5348 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5354 sub restore_vma_archive
{
5355 my ($archive, $vmid, $user, $opts, $comp) = @_;
5357 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5358 my $readfrom = $archive;
5363 my $qarchive = PVE
::Tools
::shellquote
($archive);
5364 if ($comp eq 'gzip') {
5365 $uncomp = "zcat $qarchive|";
5366 } elsif ($comp eq 'lzop') {
5367 $uncomp = "lzop -d -c $qarchive|";
5369 die "unknown compression method '$comp'\n";
5374 my $tmpdir = "/var/tmp/vzdumptmp$$";
5377 # disable interrupts (always do cleanups)
5378 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5379 warn "got interrupt - ignored\n";
5382 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5383 POSIX
::mkfifo
($mapfifo, 0600);
5386 my $openfifo = sub {
5387 open($fifofh, '>', $mapfifo) || die $!;
5390 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5397 my $rpcenv = PVE
::RPCEnvironment
::get
();
5399 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5400 my $tmpfn = "$conffile.$$.tmp";
5402 # Note: $oldconf is undef if VM does not exists
5403 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5404 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5406 my $print_devmap = sub {
5407 my $virtdev_hash = {};
5409 my $cfgfn = "$tmpdir/qemu-server.conf";
5411 # we can read the config - that is already extracted
5412 my $fh = IO
::File-
>new($cfgfn, "r") ||
5413 "unable to read qemu-server.conf - $!\n";
5415 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5417 my $pve_firewall_dir = '/etc/pve/firewall';
5418 mkdir $pve_firewall_dir; # make sure the dir exists
5419 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5422 while (defined(my $line = <$fh>)) {
5423 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5424 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5425 die "archive does not contain data for drive '$virtdev'\n"
5426 if !$devinfo->{$devname};
5427 if (defined($opts->{storage
})) {
5428 $storeid = $opts->{storage
} || 'local';
5429 } elsif (!$storeid) {
5432 $format = 'raw' if !$format;
5433 $devinfo->{$devname}->{devname
} = $devname;
5434 $devinfo->{$devname}->{virtdev
} = $virtdev;
5435 $devinfo->{$devname}->{format
} = $format;
5436 $devinfo->{$devname}->{storeid
} = $storeid;
5438 # check permission on storage
5439 my $pool = $opts->{pool
}; # todo: do we need that?
5440 if ($user ne 'root@pam') {
5441 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5444 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5448 foreach my $devname (keys %$devinfo) {
5449 die "found no device mapping information for device '$devname'\n"
5450 if !$devinfo->{$devname}->{virtdev
};
5453 my $cfg = PVE
::Storage
::config
();
5455 # create empty/temp config
5457 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5458 foreach_drive
($oldconf, sub {
5459 my ($ds, $drive) = @_;
5461 return if drive_is_cdrom
($drive);
5463 my $volid = $drive->{file
};
5465 return if !$volid || $volid =~ m
|^/|;
5467 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5468 return if !$path || !$owner || ($owner != $vmid);
5470 # Note: only delete disk we want to restore
5471 # other volumes will become unused
5472 if ($virtdev_hash->{$ds}) {
5473 eval { PVE
::Storage
::vdisk_free
($cfg, $volid); };
5480 # delete vmstate files
5481 # since after the restore we have no snapshots anymore
5482 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5483 my $snap = $oldconf->{snapshots
}->{$snapname};
5484 if ($snap->{vmstate
}) {
5485 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5494 foreach my $virtdev (sort keys %$virtdev_hash) {
5495 my $d = $virtdev_hash->{$virtdev};
5496 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5497 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5499 # test if requested format is supported
5500 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5501 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5502 $d->{format
} = $defFormat if !$supported;
5504 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5505 $d->{format
}, undef, $alloc_size);
5506 print STDERR
"new volume ID is '$volid'\n";
5507 $d->{volid
} = $volid;
5508 my $path = PVE
::Storage
::path
($cfg, $volid);
5510 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5512 my $write_zeros = 1;
5513 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5517 print $fifofh "format=$d->{format}:${write_zeros}:$d->{devname}=$path\n";
5519 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5520 $map->{$virtdev} = $volid;
5523 $fh->seek(0, 0) || die "seek failed - $!\n";
5525 my $outfd = new IO
::File
($tmpfn, "w") ||
5526 die "unable to write config for VM $vmid\n";
5528 my $cookie = { netcount
=> 0 };
5529 while (defined(my $line = <$fh>)) {
5530 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5539 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5540 die "interrupted by signal\n";
5542 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5544 $oldtimeout = alarm($timeout);
5551 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5552 my ($dev_id, $size, $devname) = ($1, $2, $3);
5553 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5554 } elsif ($line =~ m/^CTIME: /) {
5555 # we correctly received the vma config, so we can disable
5556 # the timeout now for disk allocation (set to 10 minutes, so
5557 # that we always timeout if something goes wrong)
5560 print $fifofh "done\n";
5561 my $tmp = $oldtimeout || 0;
5562 $oldtimeout = undef;
5568 print "restore vma archive: $cmd\n";
5569 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5573 alarm($oldtimeout) if $oldtimeout;
5576 foreach my $devname (keys %$devinfo) {
5577 my $volid = $devinfo->{$devname}->{volid
};
5578 push @$vollist, $volid if $volid;
5581 my $cfg = PVE
::Storage
::config
();
5582 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5590 foreach my $devname (keys %$devinfo) {
5591 my $volid = $devinfo->{$devname}->{volid
};
5594 if ($volid =~ m
|^/|) {
5595 unlink $volid || die 'unlink failed\n';
5597 PVE
::Storage
::vdisk_free
($cfg, $volid);
5599 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5601 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5608 rename($tmpfn, $conffile) ||
5609 die "unable to commit configuration file '$conffile'\n";
5611 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5613 eval { rescan
($vmid, 1); };
5617 sub restore_tar_archive
{
5618 my ($archive, $vmid, $user, $opts) = @_;
5620 if ($archive ne '-') {
5621 my $firstfile = tar_archive_read_firstfile
($archive);
5622 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5623 if $firstfile ne 'qemu-server.conf';
5626 my $storecfg = PVE
::Storage
::config
();
5628 # destroy existing data - keep empty config
5629 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5630 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5632 my $tocmd = "/usr/lib/qemu-server/qmextract";
5634 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5635 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5636 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5637 $tocmd .= ' --info' if $opts->{info
};
5639 # tar option "xf" does not autodetect compression when read from STDIN,
5640 # so we pipe to zcat
5641 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5642 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5644 my $tmpdir = "/var/tmp/vzdumptmp$$";
5647 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5648 local $ENV{VZDUMP_VMID
} = $vmid;
5649 local $ENV{VZDUMP_USER
} = $user;
5651 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5652 my $tmpfn = "$conffile.$$.tmp";
5654 # disable interrupts (always do cleanups)
5655 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5656 print STDERR
"got interrupt - ignored\n";
5661 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5662 die "interrupted by signal\n";
5665 if ($archive eq '-') {
5666 print "extracting archive from STDIN\n";
5667 run_command
($cmd, input
=> "<&STDIN");
5669 print "extracting archive '$archive'\n";
5673 return if $opts->{info
};
5677 my $statfile = "$tmpdir/qmrestore.stat";
5678 if (my $fd = IO
::File-
>new($statfile, "r")) {
5679 while (defined (my $line = <$fd>)) {
5680 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5681 $map->{$1} = $2 if $1;
5683 print STDERR
"unable to parse line in statfile - $line\n";
5689 my $confsrc = "$tmpdir/qemu-server.conf";
5691 my $srcfd = new IO
::File
($confsrc, "r") ||
5692 die "unable to open file '$confsrc'\n";
5694 my $outfd = new IO
::File
($tmpfn, "w") ||
5695 die "unable to write config for VM $vmid\n";
5697 my $cookie = { netcount
=> 0 };
5698 while (defined (my $line = <$srcfd>)) {
5699 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5711 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5718 rename $tmpfn, $conffile ||
5719 die "unable to commit configuration file '$conffile'\n";
5721 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5723 eval { rescan
($vmid, 1); };
5727 sub foreach_writable_storage
{
5728 my ($conf, $func) = @_;
5732 foreach my $ds (keys %$conf) {
5733 next if !is_valid_drivename
($ds);
5735 my $drive = parse_drive
($ds, $conf->{$ds});
5737 next if drive_is_cdrom
($drive);
5739 my $volid = $drive->{file
};
5741 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5742 $sidhash->{$sid} = $sid if $sid;
5745 foreach my $sid (sort keys %$sidhash) {
5750 sub do_snapshots_with_qemu
{
5751 my ($storecfg, $volid) = @_;
5753 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5755 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5756 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5760 if ($volid =~ m/\.(qcow2|qed)$/){
5767 sub qga_check_running
{
5770 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5772 warn "Qemu Guest Agent are not running - $@";
5778 sub template_create
{
5779 my ($vmid, $conf, $disk) = @_;
5781 my $storecfg = PVE
::Storage
::config
();
5783 foreach_drive
($conf, sub {
5784 my ($ds, $drive) = @_;
5786 return if drive_is_cdrom
($drive);
5787 return if $disk && $ds ne $disk;
5789 my $volid = $drive->{file
};
5790 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5792 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5793 $drive->{file
} = $voliddst;
5794 $conf->{$ds} = print_drive
($vmid, $drive);
5795 PVE
::QemuConfig-
>write_config($vmid, $conf);
5799 sub qemu_img_convert
{
5800 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5802 my $storecfg = PVE
::Storage
::config
();
5803 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5804 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5806 if ($src_storeid && $dst_storeid) {
5808 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5810 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5811 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5813 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5814 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5816 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5817 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5820 push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
5821 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5822 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5823 if ($is_zero_initialized) {
5824 push @$cmd, "zeroinit:$dst_path";
5826 push @$cmd, $dst_path;
5831 if($line =~ m/\((\S+)\/100\
%\)/){
5833 my $transferred = int($size * $percent / 100);
5834 my $remaining = $size - $transferred;
5836 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5841 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5843 die "copy failed: $err" if $err;
5847 sub qemu_img_format
{
5848 my ($scfg, $volname) = @_;
5850 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5857 sub qemu_drive_mirror
{
5858 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5860 my $storecfg = PVE
::Storage
::config
();
5861 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5863 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5865 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5867 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5869 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5871 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5872 $opts->{format
} = $format if $format;
5874 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5876 my $finish_job = sub {
5878 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5879 my $stat = @$stats[0];
5886 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5888 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5889 my $stat = @$stats[0];
5890 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5891 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5893 my $busy = $stat->{busy
};
5894 my $ready = $stat->{ready
};
5896 if (my $total = $stat->{len
}) {
5897 my $transferred = $stat->{offset
} || 0;
5898 my $remaining = $total - $transferred;
5899 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5901 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5905 if ($stat->{ready
} eq 'true') {
5907 last if $vmiddst != $vmid;
5909 # try to switch the disk if source and destination are on the same guest
5910 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5915 die $@ if $@ !~ m/cannot be completed/;
5924 my $cancel_job = sub {
5925 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5930 eval { &$cancel_job(); };
5931 die "mirroring error: $err";
5934 if ($vmiddst != $vmid) {
5935 # if we clone a disk for a new target vm, we don't switch the disk
5936 &$cancel_job(); # so we call block-job-cancel
5941 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5942 $newvmid, $storage, $format, $full, $newvollist) = @_;
5947 print "create linked clone of drive $drivename ($drive->{file})\n";
5948 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5949 push @$newvollist, $newvolid;
5951 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5952 $storeid = $storage if $storage;
5954 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5956 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5957 $format = qemu_img_format
($scfg, $volname);
5960 # test if requested format is supported - else use default
5961 my $supported = grep { $_ eq $format } @$validFormats;
5962 $format = $defFormat if !$supported;
5964 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5966 print "create full clone of drive $drivename ($drive->{file})\n";
5967 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5968 push @$newvollist, $newvolid;
5970 PVE
::Storage
::activate_volumes
($storecfg, [$newvolid]);
5972 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
5973 if (!$running || $snapname) {
5974 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
5977 my $kvmver = get_running_qemu_version
($vmid);
5978 if (!qemu_machine_feature_enabled
(undef, $kvmver, 2, 7)) {
5979 die "drive-mirror with iothread requires qemu version 2.7 or higher\n"
5980 if $drive->{iothread
};
5983 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
5987 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5990 $disk->{format
} = undef;
5991 $disk->{file
} = $newvolid;
5992 $disk->{size
} = $size;
5997 # this only works if VM is running
5998 sub get_current_qemu_machine
{
6001 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6002 my $res = vm_qmp_command
($vmid, $cmd);
6004 my ($current, $default);
6005 foreach my $e (@$res) {
6006 $default = $e->{name
} if $e->{'is-default'};
6007 $current = $e->{name
} if $e->{'is-current'};
6010 # fallback to the default machine if current is not supported by qemu
6011 return $current || $default || 'pc';
6014 sub get_running_qemu_version
{
6016 my $cmd = { execute
=> 'query-version', arguments
=> {} };
6017 my $res = vm_qmp_command
($vmid, $cmd);
6018 return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
6021 sub qemu_machine_feature_enabled
{
6022 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6027 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6029 $current_major = $3;
6030 $current_minor = $4;
6032 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6034 $current_major = $1;
6035 $current_minor = $2;
6038 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6043 sub qemu_machine_pxe
{
6044 my ($vmid, $conf, $machine) = @_;
6046 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6048 foreach my $opt (keys %$conf) {
6049 next if $opt !~ m/^net(\d+)$/;
6050 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6052 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6053 return $machine.".pxe" if $romfile =~ m/pxe/;
6060 sub qemu_use_old_bios_files
{
6061 my ($machine_type) = @_;
6063 return if !$machine_type;
6065 my $use_old_bios_files = undef;
6067 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6069 $use_old_bios_files = 1;
6071 my $kvmver = kvm_user_version
();
6072 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6073 # load new efi bios files on migration. So this hack is required to allow
6074 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6075 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6076 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6079 return ($use_old_bios_files, $machine_type);
6086 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6087 my (undef, $id, $function) = @_;
6088 my $res = { id
=> $id, function
=> $function};
6089 push @{$devices->{$id}}, $res;
6095 sub vm_iothreads_list
{
6098 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6101 foreach my $iothread (@$res) {
6102 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6109 my ($conf, $drive) = @_;
6113 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6115 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6121 my $controller = int($drive->{index} / $maxdev);
6122 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6124 return ($maxdev, $controller, $controller_prefix);
6127 # bash completion helper
6129 sub complete_backup_archives
{
6130 my ($cmdname, $pname, $cvalue) = @_;
6132 my $cfg = PVE
::Storage
::config
();
6136 if ($cvalue =~ m/^([^:]+):/) {
6140 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6143 foreach my $id (keys %$data) {
6144 foreach my $item (@{$data->{$id}}) {
6145 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6146 push @$res, $item->{volid
} if defined($item->{volid
});
6153 my $complete_vmid_full = sub {
6156 my $idlist = vmstatus
();
6160 foreach my $id (keys %$idlist) {
6161 my $d = $idlist->{$id};
6162 if (defined($running)) {
6163 next if $d->{template
};
6164 next if $running && $d->{status
} ne 'running';
6165 next if !$running && $d->{status
} eq 'running';
6174 return &$complete_vmid_full();
6177 sub complete_vmid_stopped
{
6178 return &$complete_vmid_full(0);
6181 sub complete_vmid_running
{
6182 return &$complete_vmid_full(1);
6185 sub complete_storage
{
6187 my $cfg = PVE
::Storage
::config
();
6188 my $ids = $cfg->{ids
};
6191 foreach my $sid (keys %$ids) {
6192 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6193 next if !$ids->{$sid}->{content
}->{images
};