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 Time
::HiRes
qw(gettimeofday);
34 use File
::Copy
qw(copy);
37 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
39 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
41 # Note about locking: we use flock on the config file protect
42 # against concurent actions.
43 # Aditionaly, we have a 'lock' setting in the config file. This
44 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
45 # allowed when such lock is set. But you can ignore this kind of
46 # lock with the --skiplock flag.
48 cfs_register_file
('/qemu-server/',
52 PVE
::JSONSchema
::register_standard_option
('skiplock', {
53 description
=> "Ignore locks - only root is allowed to use this option.",
58 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
59 description
=> "Some command save/restore state from this location.",
65 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
66 description
=> "The name of the snapshot.",
67 type
=> 'string', format
=> 'pve-configid',
71 #no warnings 'redefine';
74 my ($controller, $vmid, $option, $value) = @_;
76 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
77 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
81 my $nodename = PVE
::INotify
::nodename
();
83 mkdir "/etc/pve/nodes/$nodename";
84 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
87 my $var_run_tmpdir = "/var/run/qemu-server";
88 mkdir $var_run_tmpdir;
90 my $lock_dir = "/var/lock/qemu-server";
93 my $pcisysfs = "/sys/bus/pci";
97 description
=> "Emulated CPU type.",
99 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Haswell-noTSX Broadwell Broadwell-noTSX Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
100 format_description
=> 'cputype',
105 description
=> "Do not identify as a KVM virtual machine.",
116 enum
=> [qw(i6300esb ib700)],
117 description
=> "Watchdog type to emulate.",
118 default => 'i6300esb',
123 enum
=> [qw(reset shutdown poweroff pause debug none)],
124 description
=> "The action to perform if after activation the guest fails to poll the watchdog in time.",
128 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', $watchdog_fmt);
134 description
=> "Specifies whether a VM will be started during system bootup.",
140 description
=> "Automatic restart after crash (currently ignored).",
145 type
=> 'string', format
=> 'pve-hotplug-features',
146 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'.",
147 default => 'network,disk,usb',
152 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
158 description
=> "Lock/unlock the VM.",
159 enum
=> [qw(migrate backup snapshot rollback)],
164 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.",
172 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.",
180 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
187 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
193 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",
201 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
202 enum
=> PVE
::Tools
::kvmkeymaplist
(),
207 type
=> 'string', format
=> 'dns-name',
208 description
=> "Set a name for the VM. Only used on the configuration web interface.",
213 description
=> "scsi controller model",
214 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
220 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
225 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
226 description
=> <<EODESC,
227 Used to enable special optimization/features for specific
230 other => unspecified OS
231 wxp => Microsoft Windows XP
232 w2k => Microsoft Windows 2000
233 w2k3 => Microsoft Windows 2003
234 w2k8 => Microsoft Windows 2008
235 wvista => Microsoft Windows Vista
236 win7 => Microsoft Windows 7
237 win8 => Microsoft Windows 8/2012
238 l24 => Linux 2.4 Kernel
239 l26 => Linux 2.6/3.X Kernel
240 solaris => solaris/opensolaris/openindiania kernel
242 other|l24|l26|solaris ... no special behaviour
243 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
249 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
250 pattern
=> '[acdn]{1,4}',
255 type
=> 'string', format
=> 'pve-qm-bootdisk',
256 description
=> "Enable booting from specified disk.",
257 pattern
=> '(ide|sata|scsi|virtio)\d+',
262 description
=> "The number of CPUs. Please use option -sockets instead.",
269 description
=> "The number of CPU sockets.",
276 description
=> "The number of cores per socket.",
283 description
=> "Enable/disable NUMA.",
289 description
=> "Number of hotplugged vcpus.",
296 description
=> "Enable/disable ACPI.",
302 description
=> "Enable/disable Qemu GuestAgent.",
308 description
=> "Enable/disable KVM hardware virtualization.",
314 description
=> "Enable/disable time drift fix.",
320 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
325 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
330 description
=> "Select the VGA type. If you want to use high resolution" .
331 " modes (>= 1280x1024x16) then you should use the options " .
332 "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
333 "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
334 "display sever. For win* OS you can select how many independent " .
335 "displays you want, Linux guests can add displays them self. " .
336 "You can also run without any graphic card, using a serial device" .
338 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
342 type
=> 'string', format
=> 'pve-qm-watchdog',
343 description
=> "Create a virtual hardware watchdog device. Once enabled" .
344 " (by a guest action), the watchdog must be periodically polled " .
345 "by an agent inside the guest or else the watchdog will reset " .
346 "the guest (or execute the respective action specified)",
351 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
352 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'.",
353 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
356 startup
=> get_standard_option
('pve-startup-order'),
360 description
=> "Enable/disable Template.",
366 description
=> <<EODESCR,
367 NOTE: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
369 args: -no-reboot -no-hpet
376 description
=> "Enable/disable the USB tablet device. This device is " .
377 "usually needed to allow absolute mouse positioning with VNC. " .
378 "Else the mouse runs out of sync with normal VNC clients. " .
379 "If you're running lots of console-only guests on one host, " .
380 "you may consider disabling this to save some context switches. " .
381 "This is turned off by default if you use spice (-vga=qxl).",
386 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
390 migrate_downtime
=> {
393 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
399 type
=> 'string', format
=> 'pve-qm-drive',
400 typetext
=> 'volume',
401 description
=> "This is an alias for option -ide2",
405 description
=> "Emulated CPU type.",
409 parent
=> get_standard_option
('pve-snapshot-name', {
411 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
415 description
=> "Timestamp for snapshots.",
421 type
=> 'string', format
=> 'pve-volume-id',
422 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
425 description
=> "Specific the Qemu machine type.",
427 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
432 description
=> "Specify SMBIOS type 1 fields.",
433 type
=> 'string', format
=> 'pve-qm-smbios1',
440 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
446 enum
=> [ qw(seabios ovmf) ],
447 description
=> "Select BIOS implementation.",
448 default => 'seabios',
452 # what about other qemu settings ?
454 #machine => 'string',
467 ##soundhw => 'string',
469 while (my ($k, $v) = each %$confdesc) {
470 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
473 my $MAX_IDE_DISKS = 4;
474 my $MAX_SCSI_DISKS = 14;
475 my $MAX_VIRTIO_DISKS = 16;
476 my $MAX_SATA_DISKS = 6;
477 my $MAX_USB_DEVICES = 5;
479 my $MAX_UNUSED_DISKS = 8;
480 my $MAX_HOSTPCI_DEVICES = 4;
481 my $MAX_SERIAL_PORTS = 4;
482 my $MAX_PARALLEL_PORTS = 3;
484 my $MAX_MEM = 4194304;
485 my $STATICMEM = 1024;
490 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
491 description
=> "CPUs accessing this numa node.",
492 format_description
=> "id[-id];...",
496 description
=> "Amount of memory this numa node provides.",
497 format_description
=> "mb",
502 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
503 description
=> "host numa nodes to use",
504 format_description
=> "id[-id];...",
509 enum
=> [qw(preferred bind interleave)],
510 format_description
=> 'preferred|bind|interleave',
511 description
=> "numa allocation policy.",
515 PVE
::JSONSchema
::register_format
('pve-qm-numanode', $numa_fmt);
518 type
=> 'string', format
=> $numa_fmt,
519 description
=> "numa topology",
521 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
523 for (my $i = 0; $i < $MAX_NUMA; $i++) {
524 $confdesc->{"numa$i"} = $numadesc;
527 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
528 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
529 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
530 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
535 pattern
=> qr/[0-9a-f]{2}(?::[0-9a-f]{2}){5}/i,
536 description
=> "MAC address",
537 format_description
=> "XX:XX:XX:XX:XX:XX",
540 model
=> { alias
=> 'macaddr', default_key
=> 1 },
541 (map { $_ => { group
=> 'model' } } @$nic_model_list),
544 description
=> 'Bridge to attach the network device to.',
545 format_description
=> 'bridge',
550 minimum
=> 0, maximum
=> 16,
551 description
=> 'Number of packet queues to be used on the device.',
552 format_description
=> 'number',
558 description
=> 'Rate limit in mbps as floating point number.',
559 format_description
=> 'mbps',
564 minimum
=> 2, maximum
=> 4094,
565 description
=> 'VLAN tag to apply to packets on this interface.',
566 format_description
=> 'vlanid',
571 pattern
=> qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
572 description
=> 'VLAN trunks to pass through this interface.',
573 format_description
=> 'id;id...',
578 description
=> 'Whether this interface should be protected by the firewall.',
579 format_description
=> '0|1',
584 description
=> 'Whether this interface should be DISconnected (like pulling the plug).',
585 format_description
=> '0|1',
591 type
=> 'string', format
=> 'pve-qm-net',
592 description
=> <<EODESCR,
593 Specify network devices.
595 MODEL is one of: $nic_model_list_txt
597 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
598 automatically generated if not specified.
600 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
602 Option 'rate' is used to limit traffic bandwidth from and to this interface. It is specified as floating point number, unit is 'Megabytes per second'.
604 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
610 The DHCP server assign addresses to the guest starting from 10.0.2.15.
614 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
616 for (my $i = 0; $i < $MAX_NETS; $i++) {
617 $confdesc->{"net$i"} = $netdesc;
620 PVE
::JSONSchema
::register_format
('pve-volume-id-or-none', \
&verify_volume_id_or_none
);
621 sub verify_volume_id_or_none
{
622 my ($volid, $noerr) = @_;
624 return $volid if $volid eq 'none';
625 $volid = eval { PVE
::JSONSchema
::check_format
('pve-volume-id', $volid, '') };
627 return undef if $noerr;
635 my %drivedesc_base = (
636 volume
=> { alias
=> 'file' },
639 format
=> 'pve-volume-id-or-none',
641 format_description
=> 'volume',
642 description
=> "The drive's backing volume.",
646 format_description
=> 'cdrom|disk',
647 enum
=> [qw(cdrom disk)],
648 description
=> "The drive's media type.",
654 format_description
=> 'count',
655 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
660 format_description
=> 'count',
661 description
=> "Force the drive's physical geometry to have a specific head count.",
666 format_description
=> 'count',
667 description
=> "Force the drive's physical geometry to have a specific sector count.",
672 format_description
=> 'none|lba|auto',
673 enum
=> [qw(none lba auto)],
674 description
=> "Force disk geometry bios translation mode.",
679 format_description
=> 'on|off',
680 description
=> "Whether the drive should be included when making snapshots.",
685 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
686 enum
=> [qw(none writethrough writeback unsafe directsync)],
687 description
=> "The drive's cache mode",
692 format_description
=> 'drive format',
693 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
694 description
=> "The drive's backing file's data format.",
699 format
=> 'disk-size',
700 description
=> "Disk size. This is purely informational and has no effect.",
705 format_description
=> 'on|off',
706 description
=> "Whether the drive should be included when making backups.",
711 format_description
=> 'enospc|ignore|report|stop',
712 enum
=> [qw(enospc ignore report stop)],
713 description
=> 'Write error action.',
718 format_description
=> 'native|threads',
719 enum
=> [qw(native threads)],
720 description
=> 'AIO type to use.',
725 format_description
=> 'ignore|on',
726 enum
=> [qw(ignore on)],
727 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
732 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
737 format
=> 'urlencoded',
738 format_description
=> 'serial',
739 maxLength
=> 20*3, # *3 since it's %xx url enoded
740 description
=> "The drive's reported serial number, url-encoded, up to 20 bytes long.",
748 format_description
=> 'ignore|report|stop',
749 enum
=> [qw(ignore report stop)],
750 description
=> 'Read error action.',
755 my %iothread_fmt = ( iothread
=> {
757 format_description
=> 'off|on',
758 description
=> "Whether to use iothreads for this drive",
765 format
=> 'urlencoded',
766 format_description
=> 'model',
767 maxLength
=> 40*3, # *3 since it's %xx url enoded
768 description
=> "The drive's reported model name, url-encoded, up to 40 bytes long.",
776 format_description
=> 'nbqueues',
777 description
=> "Number of queues.",
783 my $add_throttle_desc = sub {
784 my ($key, $type, $what, $size, $longsize) = @_;
785 $drivedesc_base{$key} = {
787 format_description
=> $size,
788 description
=> "Maximum $what speed in $longsize per second.",
792 # throughput: (leaky bucket)
793 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
794 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
795 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
796 $add_throttle_desc->('mbps', 'number', 'r/w speed', 'mbps', 'megabytes');
797 $add_throttle_desc->('mbps_rd', 'number', 'read speed', 'mbps', 'megabytes');
798 $add_throttle_desc->('mbps_wr', 'number', 'write speed', 'mbps', 'megabytes');
799 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
800 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
801 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
803 # pools: (pool of IO before throttling starts taking effect)
804 $add_throttle_desc->('mbps_max', 'number', 'unthrottled r/w pool', 'mbps', 'megabytes');
805 $add_throttle_desc->('mbps_rd_max', 'number', 'unthrottled read pool', 'mbps', 'megabytes');
806 $add_throttle_desc->('mbps_wr_max', 'number', 'unthrottled write pool', 'mbps', 'megabytes');
807 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
808 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
809 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
819 type
=> 'string', format
=> $ide_fmt,
820 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
822 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
831 type
=> 'string', format
=> $scsi_fmt,
832 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
834 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
842 type
=> 'string', format
=> $sata_fmt,
843 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
845 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
854 type
=> 'string', format
=> $virtio_fmt,
855 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
857 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
870 type
=> 'string', format
=> 'pve-qm-usb-device',
871 format_description
=> 'HOSTUSBDEVICE|spice',
872 description
=> 'The Host USB device or port or the value spice',
877 format_description
=> 'yes|no',
878 description
=> 'Specifies whether if given host option is a USB3 device or port',
884 type
=> 'string', format
=> $usb_fmt,
885 description
=> <<EODESCR,
886 Configure an USB device (n is 0 to 4). This can be used to
887 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
889 'bus-port(.port)*' (decimal numbers) or
890 'vendor_id:product_id' (hexadeciaml numbers) or
893 You can use the 'lsusb -t' command to list existing usb devices.
895 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
897 The value 'spice' can be used to add a usb redirection devices for spice.
899 The 'usb3' option determines whether the device is a USB3 device or not (this does currently not work reliably with spice redirection and is then ignored).
903 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
905 # NOTE: the match-groups of this regex are used in parse_hostpci
906 my $PCIRE = qr/([a-f0-9]{2}:[a-f0-9]{2})(?:\.([a-f0-9]))?/;
911 pattern
=> qr/$PCIRE(;$PCIRE)*/,
912 format_description
=> 'HOSTPCIID[;HOSTPCIID2...]',
913 description
=> "The PCI ID of a host's PCI device or a list of PCI virtual functions of the host.",
931 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', $hostpci_fmt);
935 type
=> 'string', format
=> 'pve-qm-hostpci',
936 description
=> <<EODESCR,
937 Map host pci devices. HOSTPCIDEVICE syntax is:
939 'bus:dev.func' (hexadecimal numbers)
941 You can us the 'lspci' command to list existing pci devices.
943 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
945 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
947 Experimental: user reported problems with this option.
950 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
955 pattern
=> '(/dev/.+|socket)',
956 description
=> <<EODESCR,
957 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side (use 'qm terminal' to open a terminal connection).
959 NOTE: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
961 Experimental: user reported problems with this option.
968 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
969 description
=> <<EODESCR,
970 Map host parallel devices (n is 0 to 2).
972 NOTE: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
974 Experimental: user reported problems with this option.
978 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
979 $confdesc->{"parallel$i"} = $paralleldesc;
982 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
983 $confdesc->{"serial$i"} = $serialdesc;
986 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
987 $confdesc->{"hostpci$i"} = $hostpcidesc;
990 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
991 $drivename_hash->{"ide$i"} = 1;
992 $confdesc->{"ide$i"} = $idedesc;
995 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
996 $drivename_hash->{"sata$i"} = 1;
997 $confdesc->{"sata$i"} = $satadesc;
1000 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
1001 $drivename_hash->{"scsi$i"} = 1;
1002 $confdesc->{"scsi$i"} = $scsidesc ;
1005 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
1006 $drivename_hash->{"virtio$i"} = 1;
1007 $confdesc->{"virtio$i"} = $virtiodesc;
1010 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
1011 $confdesc->{"usb$i"} = $usbdesc;
1016 type
=> 'string', format
=> 'pve-volume-id',
1017 description
=> "Reference to unused volumes.",
1020 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
1021 $confdesc->{"unused$i"} = $unuseddesc;
1024 my $kvm_api_version = 0;
1028 return $kvm_api_version if $kvm_api_version;
1030 my $fh = IO
::File-
>new("</dev/kvm") ||
1033 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
1034 $kvm_api_version = $v;
1039 return $kvm_api_version;
1042 my $kvm_user_version;
1044 sub kvm_user_version
{
1046 return $kvm_user_version if $kvm_user_version;
1048 $kvm_user_version = 'unknown';
1052 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
1053 $kvm_user_version = $2;
1057 eval { run_command
("kvm -version", outfunc
=> $code); };
1060 return $kvm_user_version;
1064 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
1066 sub valid_drive_names
{
1067 # order is important - used to autoselect boot disk
1068 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
1069 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
1070 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
1071 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
1074 sub is_valid_drivename
{
1077 return defined($drivename_hash->{$dev});
1082 return defined($confdesc->{$key});
1086 return $nic_model_list;
1089 sub os_list_description
{
1093 wxp
=> 'Windows XP',
1094 w2k
=> 'Windows 2000',
1095 w2k3
=>, 'Windows 2003',
1096 w2k8
=> 'Windows 2008',
1097 wvista
=> 'Windows Vista',
1098 win7
=> 'Windows 7',
1099 win8
=> 'Windows 8/2012',
1107 sub get_cdrom_path
{
1109 return $cdrom_path if $cdrom_path;
1111 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
1112 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
1113 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
1117 my ($storecfg, $vmid, $cdrom) = @_;
1119 if ($cdrom eq 'cdrom') {
1120 return get_cdrom_path
();
1121 } elsif ($cdrom eq 'none') {
1123 } elsif ($cdrom =~ m
|^/|) {
1126 return PVE
::Storage
::path
($storecfg, $cdrom);
1130 # try to convert old style file names to volume IDs
1131 sub filename_to_volume_id
{
1132 my ($vmid, $file, $media) = @_;
1134 if (!($file eq 'none' || $file eq 'cdrom' ||
1135 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
1137 return undef if $file =~ m
|/|;
1139 if ($media && $media eq 'cdrom') {
1140 $file = "local:iso/$file";
1142 $file = "local:$vmid/$file";
1149 sub verify_media_type
{
1150 my ($opt, $vtype, $media) = @_;
1155 if ($media eq 'disk') {
1157 } elsif ($media eq 'cdrom') {
1160 die "internal error";
1163 return if ($vtype eq $etype);
1165 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1168 sub cleanup_drive_path
{
1169 my ($opt, $storecfg, $drive) = @_;
1171 # try to convert filesystem paths to volume IDs
1173 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1174 ($drive->{file
} !~ m
|^/dev/.+|) &&
1175 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1176 ($drive->{file
} !~ m/^\d+$/)) {
1177 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1178 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1179 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1180 verify_media_type
($opt, $vtype, $drive->{media
});
1181 $drive->{file
} = $volid;
1184 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1187 sub parse_hotplug_features
{
1192 return $res if $data eq '0';
1194 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1196 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1197 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1200 warn "ignoring unknown hotplug feature '$feature'\n";
1206 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1207 sub pve_verify_hotplug_features
{
1208 my ($value, $noerr) = @_;
1210 return $value if parse_hotplug_features
($value);
1212 return undef if $noerr;
1214 die "unable to parse hotplug option\n";
1217 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1218 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1219 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1220 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1221 # [,iothread=on][,serial=serial][,model=model]
1224 my ($key, $data) = @_;
1226 my ($interface, $index);
1228 if ($key =~ m/^([^\d]+)(\d+)$/) {
1235 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1236 : $confdesc->{$key}->{format
};
1238 warn "invalid drive key: $key\n";
1241 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1242 return undef if !$res;
1243 $res->{interface
} = $interface;
1244 $res->{index} = $index;
1247 foreach my $opt (qw(bps bps_rd bps_wr)) {
1248 if (my $bps = defined(delete $res->{$opt})) {
1249 if (defined($res->{"m$opt"})) {
1250 warn "both $opt and m$opt specified\n";
1254 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1257 return undef if $error;
1259 return undef if $res->{mbps_rd
} && $res->{mbps
};
1260 return undef if $res->{mbps_wr
} && $res->{mbps
};
1261 return undef if $res->{iops_rd
} && $res->{iops
};
1262 return undef if $res->{iops_wr
} && $res->{iops
};
1264 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1265 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1266 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1267 return undef if $res->{interface
} eq 'virtio';
1270 if (my $size = $res->{size
}) {
1271 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1278 my ($vmid, $drive) = @_;
1279 my $data = { %$drive };
1280 delete $data->{$_} for qw(index interface);
1281 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1285 my($fh, $noerr) = @_;
1288 my $SG_GET_VERSION_NUM = 0x2282;
1290 my $versionbuf = "\x00" x
8;
1291 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1293 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1296 my $version = unpack("I", $versionbuf);
1297 if ($version < 30000) {
1298 die "scsi generic interface too old\n" if !$noerr;
1302 my $buf = "\x00" x
36;
1303 my $sensebuf = "\x00" x
8;
1304 my $cmd = pack("C x3 C x1", 0x12, 36);
1306 # see /usr/include/scsi/sg.h
1307 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";
1309 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1310 length($sensebuf), 0, length($buf), $buf,
1311 $cmd, $sensebuf, 6000);
1313 $ret = ioctl($fh, $SG_IO, $packet);
1315 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1319 my @res = unpack($sg_io_hdr_t, $packet);
1320 if ($res[17] || $res[18]) {
1321 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1326 (my $byte0, my $byte1, $res->{vendor
},
1327 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1329 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1330 $res->{type
} = $byte0 & 31;
1338 my $fh = IO
::File-
>new("+<$path") || return undef;
1339 my $res = scsi_inquiry
($fh, 1);
1345 sub machine_type_is_q35
{
1348 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1351 sub print_tabletdevice_full
{
1354 my $q35 = machine_type_is_q35
($conf);
1356 # we use uhci for old VMs because tablet driver was buggy in older qemu
1357 my $usbbus = $q35 ?
"ehci" : "uhci";
1359 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1362 sub print_drivedevice_full
{
1363 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1368 if ($drive->{interface
} eq 'virtio') {
1369 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1370 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1371 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1372 } elsif ($drive->{interface
} eq 'scsi') {
1374 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1375 my $unit = $drive->{index} % $maxdev;
1376 my $devicetype = 'hd';
1378 if (drive_is_cdrom
($drive)) {
1381 if ($drive->{file
} =~ m
|^/|) {
1382 $path = $drive->{file
};
1383 if (my $info = path_is_scsi
($path)) {
1384 if ($info->{type
} == 0) {
1385 $devicetype = 'block';
1386 } elsif ($info->{type
} == 1) { # tape
1387 $devicetype = 'generic';
1391 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1394 if($path =~ m/^iscsi\:\/\
//){
1395 $devicetype = 'generic';
1399 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1400 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1402 $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}";
1405 } elsif ($drive->{interface
} eq 'ide'){
1407 my $controller = int($drive->{index} / $maxdev);
1408 my $unit = $drive->{index} % $maxdev;
1409 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1411 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1412 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1413 $model = URI
::Escape
::uri_unescape
($model);
1414 $device .= ",model=$model";
1416 } elsif ($drive->{interface
} eq 'sata'){
1417 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1418 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1419 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1420 } elsif ($drive->{interface
} eq 'usb') {
1422 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1424 die "unsupported interface type";
1427 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1432 sub get_initiator_name
{
1435 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1436 while (defined(my $line = <$fh>)) {
1437 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1446 sub print_drive_full
{
1447 my ($storecfg, $vmid, $drive) = @_;
1450 my $volid = $drive->{file
};
1453 if (drive_is_cdrom
($drive)) {
1454 $path = get_iso_path
($storecfg, $vmid, $volid);
1456 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1458 $path = PVE
::Storage
::path
($storecfg, $volid);
1459 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1460 $format = qemu_img_format
($scfg, $volname);
1468 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);
1469 foreach my $o (@qemu_drive_options) {
1470 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1472 if (my $serial = $drive->{serial
}) {
1473 $serial = URI
::Escape
::uri_unescape
($serial);
1474 $opts .= ",serial=$serial";
1477 $opts .= ",format=$format" if $format && !$drive->{format
};
1479 foreach my $o (qw(bps bps_rd bps_wr)) {
1480 my $v = $drive->{"m$o"};
1481 $opts .= ",$o=" . int($v*1024*1024) if $v;
1484 my $cache_direct = 0;
1486 if (my $cache = $drive->{cache
}) {
1487 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1488 } elsif (!drive_is_cdrom
($drive)) {
1489 $opts .= ",cache=none";
1493 # aio native works only with O_DIRECT
1494 if (!$drive->{aio
}) {
1496 $opts .= ",aio=native";
1498 $opts .= ",aio=threads";
1502 if (!drive_is_cdrom
($drive)) {
1504 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1505 $detectzeroes = 'off';
1506 } elsif ($drive->{discard
}) {
1507 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1509 # This used to be our default with discard not being specified:
1510 $detectzeroes = 'on';
1512 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1515 my $pathinfo = $path ?
"file=$path," : '';
1517 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1520 sub print_netdevice_full
{
1521 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1523 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1525 my $device = $net->{model
};
1526 if ($net->{model
} eq 'virtio') {
1527 $device = 'virtio-net-pci';
1530 my $pciaddr = print_pci_addr
("$netid", $bridges);
1531 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1532 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1533 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1534 my $vectors = $net->{queues
} * 2 + 2;
1535 $tmpstr .= ",vectors=$vectors,mq=on";
1537 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1539 if ($use_old_bios_files) {
1541 if ($device eq 'virtio-net-pci') {
1542 $romfile = 'pxe-virtio.rom';
1543 } elsif ($device eq 'e1000') {
1544 $romfile = 'pxe-e1000.rom';
1545 } elsif ($device eq 'ne2k') {
1546 $romfile = 'pxe-ne2k_pci.rom';
1547 } elsif ($device eq 'pcnet') {
1548 $romfile = 'pxe-pcnet.rom';
1549 } elsif ($device eq 'rtl8139') {
1550 $romfile = 'pxe-rtl8139.rom';
1552 $tmpstr .= ",romfile=$romfile" if $romfile;
1558 sub print_netdev_full
{
1559 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1562 if ($netid =~ m/^net(\d+)$/) {
1566 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1568 my $ifname = "tap${vmid}i$i";
1570 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1571 die "interface name '$ifname' is too long (max 15 character)\n"
1572 if length($ifname) >= 16;
1574 my $vhostparam = '';
1575 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1577 my $vmname = $conf->{name
} || "vm$vmid";
1580 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1582 if ($net->{bridge
}) {
1583 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1585 $netdev = "type=user,id=$netid,hostname=$vmname";
1588 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1593 sub drive_is_cdrom
{
1596 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1600 sub parse_number_sets
{
1603 foreach my $part (split(/;/, $set)) {
1604 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
1605 die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
1606 push @$res, [ $1, $2 ];
1608 die "invalid range: $part\n";
1617 my $res = PVE
::JSONSchema
::parse_property_string
($numa_fmt, $data);
1618 $res->{cpus
} = parse_number_sets
($res->{cpus
}) if defined($res->{cpus
});
1619 $res->{hostnodes
} = parse_number_sets
($res->{hostnodes
}) if defined($res->{hostnodes
});
1626 return undef if !$value;
1628 my $res = PVE
::JSONSchema
::parse_property_string
($hostpci_fmt, $value);
1630 my @idlist = split(/;/, $res->{host
});
1631 delete $res->{host
};
1632 foreach my $id (@idlist) {
1633 if ($id =~ /^$PCIRE$/) {
1634 push @{$res->{pciid
}}, { id
=> $1, function
=> ($2//'0') };
1636 # should have been caught by parse_property_string already
1637 die "failed to parse PCI id: $id\n";
1643 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1647 my $res = eval { PVE
::JSONSchema
::parse_property_string
($net_fmt, $data) };
1652 $res->{macaddr
} = PVE
::Tools
::random_ether_addr
() if !defined($res->{macaddr
});
1659 return PVE
::JSONSchema
::print_property_string
($net, $net_fmt);
1662 sub add_random_macs
{
1663 my ($settings) = @_;
1665 foreach my $opt (keys %$settings) {
1666 next if $opt !~ m/^net(\d+)$/;
1667 my $net = parse_net
($settings->{$opt});
1669 $settings->{$opt} = print_net
($net);
1673 sub vm_is_volid_owner
{
1674 my ($storecfg, $vmid, $volid) = @_;
1676 if ($volid !~ m
|^/|) {
1678 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1679 if ($owner && ($owner == $vmid)) {
1687 sub split_flagged_list
{
1688 my $text = shift || '';
1689 $text =~ s/[,;]/ /g;
1691 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1694 sub join_flagged_list
{
1695 my ($how, $lst) = @_;
1696 join $how, map { $lst->{$_} . $_ } keys %$lst;
1699 sub vmconfig_delete_pending_option
{
1700 my ($conf, $key, $force) = @_;
1702 delete $conf->{pending
}->{$key};
1703 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1704 $pending_delete_hash->{$key} = $force ?
'!' : '';
1705 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1708 sub vmconfig_undelete_pending_option
{
1709 my ($conf, $key) = @_;
1711 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1712 delete $pending_delete_hash->{$key};
1714 if (%$pending_delete_hash) {
1715 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1717 delete $conf->{pending
}->{delete};
1721 sub vmconfig_register_unused_drive
{
1722 my ($storecfg, $vmid, $conf, $drive) = @_;
1724 if (!drive_is_cdrom
($drive)) {
1725 my $volid = $drive->{file
};
1726 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1727 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1732 sub vmconfig_cleanup_pending
{
1735 # remove pending changes when nothing changed
1737 foreach my $opt (keys %{$conf->{pending
}}) {
1738 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1740 delete $conf->{pending
}->{$opt};
1744 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1745 my $pending_delete_hash = {};
1746 while (my ($opt, $force) = each %$current_delete_hash) {
1747 if (defined($conf->{$opt})) {
1748 $pending_delete_hash->{$opt} = $force;
1754 if (%$pending_delete_hash) {
1755 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1757 delete $conf->{pending
}->{delete};
1763 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1767 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1768 format_description
=> 'UUID',
1774 format_description
=> 'str',
1780 format_description
=> 'str',
1786 format_description
=> 'name',
1792 format_description
=> 'name',
1798 format_description
=> 'str',
1804 format_description
=> 'str',
1812 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_fmt, $data) };
1819 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_fmt);
1822 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_fmt);
1824 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1825 sub verify_bootdisk
{
1826 my ($value, $noerr) = @_;
1828 return $value if is_valid_drivename
($value);
1830 return undef if $noerr;
1832 die "invalid boot disk '$value'\n";
1835 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1837 my ($value, $noerr) = @_;
1839 return $value if parse_net
($value);
1841 return undef if $noerr;
1843 die "unable to parse network options\n";
1846 sub parse_watchdog
{
1849 return undef if !$value;
1851 my $res = eval { PVE
::JSONSchema
::parse_property_string
($watchdog_fmt, $value) };
1856 sub parse_usb_device
{
1859 return undef if !$value;
1862 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1863 $res->{vendorid
} = $2;
1864 $res->{productid
} = $4;
1865 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1866 $res->{hostbus
} = $1;
1867 $res->{hostport
} = $2;
1868 } elsif ($value =~ m/^spice$/i) {
1877 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1878 sub verify_usb_device
{
1879 my ($value, $noerr) = @_;
1881 return $value if parse_usb_device
($value);
1883 return undef if $noerr;
1885 die "unable to parse usb device\n";
1888 # add JSON properties for create and set function
1889 sub json_config_properties
{
1892 foreach my $opt (keys %$confdesc) {
1893 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1894 $prop->{$opt} = $confdesc->{$opt};
1901 my ($key, $value) = @_;
1903 die "unknown setting '$key'\n" if !$confdesc->{$key};
1905 my $type = $confdesc->{$key}->{type
};
1907 if (!defined($value)) {
1908 die "got undefined value\n";
1911 if ($value =~ m/[\n\r]/) {
1912 die "property contains a line feed\n";
1915 if ($type eq 'boolean') {
1916 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1917 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1918 die "type check ('boolean') failed - got '$value'\n";
1919 } elsif ($type eq 'integer') {
1920 return int($1) if $value =~ m/^(\d+)$/;
1921 die "type check ('integer') failed - got '$value'\n";
1922 } elsif ($type eq 'number') {
1923 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1924 die "type check ('number') failed - got '$value'\n";
1925 } elsif ($type eq 'string') {
1926 if (my $fmt = $confdesc->{$key}->{format
}) {
1927 if ($fmt eq 'pve-qm-drive') {
1928 # special case - we need to pass $key to parse_drive()
1929 my $drive = parse_drive
($key, $value);
1930 return $value if $drive;
1931 die "unable to parse drive options\n";
1933 PVE
::JSONSchema
::check_format
($fmt, $value);
1936 $value =~ s/^\"(.*)\"$/$1/;
1939 die "internal error"
1943 sub check_iommu_support
{
1944 #fixme : need to check IOMMU support
1945 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1955 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1956 utime undef, undef, $conf;
1960 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1962 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1964 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1966 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1968 # only remove disks owned by this VM
1969 foreach_drive
($conf, sub {
1970 my ($ds, $drive) = @_;
1972 return if drive_is_cdrom
($drive);
1974 my $volid = $drive->{file
};
1976 return if !$volid || $volid =~ m
|^/|;
1978 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1979 return if !$path || !$owner || ($owner != $vmid);
1981 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1984 if ($keep_empty_config) {
1985 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1990 # also remove unused disk
1992 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1995 PVE
::Storage
::foreach_volid
($dl, sub {
1996 my ($volid, $sid, $volname, $d) = @_;
1997 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2006 sub parse_vm_config
{
2007 my ($filename, $raw) = @_;
2009 return undef if !defined($raw);
2012 digest
=> Digest
::SHA
::sha1_hex
($raw),
2017 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2018 || die "got strange filename '$filename'";
2026 my @lines = split(/\n/, $raw);
2027 foreach my $line (@lines) {
2028 next if $line =~ m/^\s*$/;
2030 if ($line =~ m/^\[PENDING\]\s*$/i) {
2031 $section = 'pending';
2032 if (defined($descr)) {
2034 $conf->{description
} = $descr;
2037 $conf = $res->{$section} = {};
2040 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2042 if (defined($descr)) {
2044 $conf->{description
} = $descr;
2047 $conf = $res->{snapshots
}->{$section} = {};
2051 if ($line =~ m/^\#(.*)\s*$/) {
2052 $descr = '' if !defined($descr);
2053 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2057 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2058 $descr = '' if !defined($descr);
2059 $descr .= PVE
::Tools
::decode_text
($2);
2060 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2061 $conf->{snapstate
} = $1;
2062 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2065 $conf->{$key} = $value;
2066 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2068 if ($section eq 'pending') {
2069 $conf->{delete} = $value; # we parse this later
2071 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2073 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2076 eval { $value = check_type
($key, $value); };
2078 warn "vm $vmid - unable to parse value of '$key' - $@";
2080 my $fmt = $confdesc->{$key}->{format
};
2081 if ($fmt && $fmt eq 'pve-qm-drive') {
2082 my $v = parse_drive
($key, $value);
2083 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2084 $v->{file
} = $volid;
2085 $value = print_drive
($vmid, $v);
2087 warn "vm $vmid - unable to parse value of '$key'\n";
2092 if ($key eq 'cdrom') {
2093 $conf->{ide2
} = $value;
2095 $conf->{$key} = $value;
2101 if (defined($descr)) {
2103 $conf->{description
} = $descr;
2105 delete $res->{snapstate
}; # just to be sure
2110 sub write_vm_config
{
2111 my ($filename, $conf) = @_;
2113 delete $conf->{snapstate
}; # just to be sure
2115 if ($conf->{cdrom
}) {
2116 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2117 $conf->{ide2
} = $conf->{cdrom
};
2118 delete $conf->{cdrom
};
2121 # we do not use 'smp' any longer
2122 if ($conf->{sockets
}) {
2123 delete $conf->{smp
};
2124 } elsif ($conf->{smp
}) {
2125 $conf->{sockets
} = $conf->{smp
};
2126 delete $conf->{cores
};
2127 delete $conf->{smp
};
2130 my $used_volids = {};
2132 my $cleanup_config = sub {
2133 my ($cref, $pending, $snapname) = @_;
2135 foreach my $key (keys %$cref) {
2136 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2137 $key eq 'snapstate' || $key eq 'pending';
2138 my $value = $cref->{$key};
2139 if ($key eq 'delete') {
2140 die "propertry 'delete' is only allowed in [PENDING]\n"
2142 # fixme: check syntax?
2145 eval { $value = check_type
($key, $value); };
2146 die "unable to parse value of '$key' - $@" if $@;
2148 $cref->{$key} = $value;
2150 if (!$snapname && is_valid_drivename
($key)) {
2151 my $drive = parse_drive
($key, $value);
2152 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2157 &$cleanup_config($conf);
2159 &$cleanup_config($conf->{pending
}, 1);
2161 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2162 die "internal error" if $snapname eq 'pending';
2163 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2166 # remove 'unusedX' settings if we re-add a volume
2167 foreach my $key (keys %$conf) {
2168 my $value = $conf->{$key};
2169 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2170 delete $conf->{$key};
2174 my $generate_raw_config = sub {
2175 my ($conf, $pending) = @_;
2179 # add description as comment to top of file
2180 if (defined(my $descr = $conf->{description
})) {
2182 foreach my $cl (split(/\n/, $descr)) {
2183 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2186 $raw .= "#\n" if $pending;
2190 foreach my $key (sort keys %$conf) {
2191 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2192 $raw .= "$key: $conf->{$key}\n";
2197 my $raw = &$generate_raw_config($conf);
2199 if (scalar(keys %{$conf->{pending
}})){
2200 $raw .= "\n[PENDING]\n";
2201 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2204 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2205 $raw .= "\n[$snapname]\n";
2206 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2216 # we use static defaults from our JSON schema configuration
2217 foreach my $key (keys %$confdesc) {
2218 if (defined(my $default = $confdesc->{$key}->{default})) {
2219 $res->{$key} = $default;
2223 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2224 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2230 my $vmlist = PVE
::Cluster
::get_vmlist
();
2232 return $res if !$vmlist || !$vmlist->{ids
};
2233 my $ids = $vmlist->{ids
};
2235 foreach my $vmid (keys %$ids) {
2236 my $d = $ids->{$vmid};
2237 next if !$d->{node
} || $d->{node
} ne $nodename;
2238 next if !$d->{type
} || $d->{type
} ne 'qemu';
2239 $res->{$vmid}->{exists} = 1;
2244 # test if VM uses local resources (to prevent migration)
2245 sub check_local_resources
{
2246 my ($conf, $noerr) = @_;
2250 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2251 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2253 foreach my $k (keys %$conf) {
2254 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2255 # sockets are safe: they will recreated be on the target side post-migrate
2256 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2257 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2260 die "VM uses local resources\n" if $loc_res && !$noerr;
2265 # check if used storages are available on all nodes (use by migrate)
2266 sub check_storage_availability
{
2267 my ($storecfg, $conf, $node) = @_;
2269 foreach_drive
($conf, sub {
2270 my ($ds, $drive) = @_;
2272 my $volid = $drive->{file
};
2275 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2278 # check if storage is available on both nodes
2279 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2280 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2284 # list nodes where all VM images are available (used by has_feature API)
2286 my ($conf, $storecfg) = @_;
2288 my $nodelist = PVE
::Cluster
::get_nodelist
();
2289 my $nodehash = { map { $_ => 1 } @$nodelist };
2290 my $nodename = PVE
::INotify
::nodename
();
2292 foreach_drive
($conf, sub {
2293 my ($ds, $drive) = @_;
2295 my $volid = $drive->{file
};
2298 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2300 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2301 if ($scfg->{disable
}) {
2303 } elsif (my $avail = $scfg->{nodes
}) {
2304 foreach my $node (keys %$nodehash) {
2305 delete $nodehash->{$node} if !$avail->{$node};
2307 } elsif (!$scfg->{shared
}) {
2308 foreach my $node (keys %$nodehash) {
2309 delete $nodehash->{$node} if $node ne $nodename
2319 my ($pidfile, $pid) = @_;
2321 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2325 return undef if !$line;
2326 my @param = split(/\0/, $line);
2328 my $cmd = $param[0];
2329 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2331 for (my $i = 0; $i < scalar (@param); $i++) {
2334 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2335 my $p = $param[$i+1];
2336 return 1 if $p && ($p eq $pidfile);
2345 my ($vmid, $nocheck, $node) = @_;
2347 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2349 die "unable to find configuration file for VM $vmid - no such machine\n"
2350 if !$nocheck && ! -f
$filename;
2352 my $pidfile = pidfile_name
($vmid);
2354 if (my $fd = IO
::File-
>new("<$pidfile")) {
2359 my $mtime = $st->mtime;
2360 if ($mtime > time()) {
2361 warn "file '$filename' modified in future\n";
2364 if ($line =~ m/^(\d+)$/) {
2366 if (check_cmdline
($pidfile, $pid)) {
2367 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2379 my $vzlist = config_list
();
2381 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2383 while (defined(my $de = $fd->read)) {
2384 next if $de !~ m/^(\d+)\.pid$/;
2386 next if !defined($vzlist->{$vmid});
2387 if (my $pid = check_running
($vmid)) {
2388 $vzlist->{$vmid}->{pid
} = $pid;
2396 my ($storecfg, $conf) = @_;
2398 my $bootdisk = $conf->{bootdisk
};
2399 return undef if !$bootdisk;
2400 return undef if !is_valid_drivename
($bootdisk);
2402 return undef if !$conf->{$bootdisk};
2404 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2405 return undef if !defined($drive);
2407 return undef if drive_is_cdrom
($drive);
2409 my $volid = $drive->{file
};
2410 return undef if !$volid;
2412 return $drive->{size
};
2415 my $last_proc_pid_stat;
2417 # get VM status information
2418 # This must be fast and should not block ($full == false)
2419 # We only query KVM using QMP if $full == true (this can be slow)
2421 my ($opt_vmid, $full) = @_;
2425 my $storecfg = PVE
::Storage
::config
();
2427 my $list = vzlist
();
2428 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2430 my $cpucount = $cpuinfo->{cpus
} || 1;
2432 foreach my $vmid (keys %$list) {
2433 next if $opt_vmid && ($vmid ne $opt_vmid);
2435 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2436 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2439 $d->{pid
} = $list->{$vmid}->{pid
};
2441 # fixme: better status?
2442 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2444 my $size = disksize
($storecfg, $conf);
2445 if (defined($size)) {
2446 $d->{disk
} = 0; # no info available
2447 $d->{maxdisk
} = $size;
2453 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2454 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2455 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2457 $d->{name
} = $conf->{name
} || "VM $vmid";
2458 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2460 if ($conf->{balloon
}) {
2461 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2462 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2473 $d->{diskwrite
} = 0;
2475 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2480 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2481 foreach my $dev (keys %$netdev) {
2482 next if $dev !~ m/^tap([1-9]\d*)i/;
2484 my $d = $res->{$vmid};
2487 $d->{netout
} += $netdev->{$dev}->{receive
};
2488 $d->{netin
} += $netdev->{$dev}->{transmit
};
2491 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2492 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2497 my $ctime = gettimeofday
;
2499 foreach my $vmid (keys %$list) {
2501 my $d = $res->{$vmid};
2502 my $pid = $d->{pid
};
2505 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2506 next if !$pstat; # not running
2508 my $used = $pstat->{utime} + $pstat->{stime
};
2510 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2512 if ($pstat->{vsize
}) {
2513 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2516 my $old = $last_proc_pid_stat->{$pid};
2518 $last_proc_pid_stat->{$pid} = {
2526 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2528 if ($dtime > 1000) {
2529 my $dutime = $used - $old->{used
};
2531 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2532 $last_proc_pid_stat->{$pid} = {
2538 $d->{cpu
} = $old->{cpu
};
2542 return $res if !$full;
2544 my $qmpclient = PVE
::QMPClient-
>new();
2546 my $ballooncb = sub {
2547 my ($vmid, $resp) = @_;
2549 my $info = $resp->{'return'};
2550 return if !$info->{max_mem
};
2552 my $d = $res->{$vmid};
2554 # use memory assigned to VM
2555 $d->{maxmem
} = $info->{max_mem
};
2556 $d->{balloon
} = $info->{actual
};
2558 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2559 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2560 $d->{freemem
} = $info->{free_mem
};
2563 $d->{ballooninfo
} = $info;
2566 my $blockstatscb = sub {
2567 my ($vmid, $resp) = @_;
2568 my $data = $resp->{'return'} || [];
2569 my $totalrdbytes = 0;
2570 my $totalwrbytes = 0;
2572 for my $blockstat (@$data) {
2573 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2574 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2576 $blockstat->{device
} =~ s/drive-//;
2577 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2579 $res->{$vmid}->{diskread
} = $totalrdbytes;
2580 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2583 my $statuscb = sub {
2584 my ($vmid, $resp) = @_;
2586 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2587 # this fails if ballon driver is not loaded, so this must be
2588 # the last commnand (following command are aborted if this fails).
2589 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2591 my $status = 'unknown';
2592 if (!defined($status = $resp->{'return'}->{status
})) {
2593 warn "unable to get VM status\n";
2597 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2600 foreach my $vmid (keys %$list) {
2601 next if $opt_vmid && ($vmid ne $opt_vmid);
2602 next if !$res->{$vmid}->{pid
}; # not running
2603 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2606 $qmpclient->queue_execute(undef, 1);
2608 foreach my $vmid (keys %$list) {
2609 next if $opt_vmid && ($vmid ne $opt_vmid);
2610 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2617 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2620 my $current_size = 1024;
2621 my $dimm_size = 512;
2622 return if $current_size == $memory;
2624 for (my $j = 0; $j < 8; $j++) {
2625 for (my $i = 0; $i < 32; $i++) {
2626 my $name = "dimm${dimm_id}";
2628 my $numanode = $i % $sockets;
2629 $current_size += $dimm_size;
2630 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2631 return $current_size if $current_size >= $memory;
2637 sub foreach_reverse_dimm
{
2638 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2641 my $current_size = 4177920;
2642 my $dimm_size = 65536;
2643 return if $current_size == $memory;
2645 for (my $j = 0; $j < 8; $j++) {
2646 for (my $i = 0; $i < 32; $i++) {
2647 my $name = "dimm${dimm_id}";
2649 my $numanode = $i % $sockets;
2650 $current_size -= $dimm_size;
2651 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2652 return $current_size if $current_size <= $memory;
2659 my ($conf, $func) = @_;
2661 foreach my $ds (valid_drive_names
()) {
2662 next if !defined($conf->{$ds});
2664 my $drive = parse_drive
($ds, $conf->{$ds});
2667 &$func($ds, $drive);
2672 my ($conf, $func) = @_;
2676 my $test_volid = sub {
2677 my ($volid, $is_cdrom) = @_;
2681 $volhash->{$volid} = $is_cdrom || 0;
2684 foreach_drive
($conf, sub {
2685 my ($ds, $drive) = @_;
2686 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2689 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2690 my $snap = $conf->{snapshots
}->{$snapname};
2691 &$test_volid($snap->{vmstate
}, 0);
2692 foreach_drive
($snap, sub {
2693 my ($ds, $drive) = @_;
2694 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2698 foreach my $volid (keys %$volhash) {
2699 &$func($volid, $volhash->{$volid});
2703 sub vga_conf_has_spice
{
2706 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2711 sub config_to_command
{
2712 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2715 my $globalFlags = [];
2716 my $machineFlags = [];
2722 my $kvmver = kvm_user_version
();
2723 my $vernum = 0; # unknown
2724 my $ostype = $conf->{ostype
};
2725 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2726 $vernum = $1*1000000+$2*1000;
2727 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2728 $vernum = $1*1000000+$2*1000+$3;
2731 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2733 my $have_ovz = -f
'/proc/vz/vestat';
2735 my $q35 = machine_type_is_q35
($conf);
2736 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2737 my $machine_type = $forcemachine || $conf->{machine
};
2738 my $use_old_bios_files = undef;
2739 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2741 my $cpuunits = defined($conf->{cpuunits
}) ?
2742 $conf->{cpuunits
} : $defaults->{cpuunits
};
2744 push @$cmd, '/usr/bin/systemd-run';
2745 push @$cmd, '--scope';
2746 push @$cmd, '--slice', "qemu";
2747 push @$cmd, '--unit', $vmid;
2748 # set KillMode=none, so that systemd don't kill those scopes
2749 # at shutdown (pve-manager service should stop the VMs instead)
2750 push @$cmd, '-p', "KillMode=none";
2751 push @$cmd, '-p', "CPUShares=$cpuunits";
2752 if ($conf->{cpulimit
}) {
2753 my $cpulimit = int($conf->{cpulimit
} * 100);
2754 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2757 push @$cmd, '/usr/bin/kvm';
2759 push @$cmd, '-id', $vmid;
2763 my $qmpsocket = qmp_socket
($vmid);
2764 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2765 push @$cmd, '-mon', "chardev=qmp,mode=control";
2768 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2770 push @$cmd, '-daemonize';
2772 if ($conf->{smbios1
}) {
2773 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2776 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2777 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2778 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2779 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2780 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2781 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2782 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2786 # the q35 chipset support native usb2, so we enable usb controller
2787 # by default for this machine type
2788 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2790 $pciaddr = print_pci_addr
("piix3", $bridges);
2791 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2794 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2795 next if !$conf->{"usb$i"};
2796 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2797 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2800 # include usb device config
2801 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2804 # add usb3 controller if needed
2807 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2808 next if !$conf->{"usb$i"};
2809 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2810 next if !$d || !$d->{usb3
};
2814 $pciaddr = print_pci_addr
("xhci", $bridges);
2815 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2817 my $vga = $conf->{vga
};
2819 my $qxlnum = vga_conf_has_spice
($vga);
2820 $vga = 'qxl' if $qxlnum;
2823 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2824 $conf->{ostype
} eq 'win7' ||
2825 $conf->{ostype
} eq 'w2k8')) {
2832 # enable absolute mouse coordinates (needed by vnc)
2834 if (defined($conf->{tablet
})) {
2835 $tablet = $conf->{tablet
};
2837 $tablet = $defaults->{tablet
};
2838 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2839 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2842 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2846 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2847 my $d = parse_hostpci
($conf->{"hostpci$i"});
2850 my $pcie = $d->{pcie
};
2852 die "q35 machine model is not enabled" if !$q35;
2853 $pciaddr = print_pcie_addr
("hostpci$i");
2855 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2858 my $rombar = defined($d->{rombar
}) && !$d->{rombar
} ?
',rombar=0' : '';
2860 if ($d->{'x-vga'}) {
2861 $xvga = ',x-vga=on';
2864 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2865 push @$cpuFlags , 'hv_vendor_id=proxmox';
2867 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2871 my $pcidevices = $d->{pciid
};
2872 my $multifunction = 1 if @$pcidevices > 1;
2875 foreach my $pcidevice (@$pcidevices) {
2877 my $id = "hostpci$i";
2878 $id .= ".$j" if $multifunction;
2879 my $addr = $pciaddr;
2880 $addr .= ".$j" if $multifunction;
2881 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2884 $devicestr .= "$rombar$xvga";
2885 $devicestr .= ",multifunction=on" if $multifunction;
2888 push @$devices, '-device', $devicestr;
2894 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2895 next if !$conf->{"usb$i"};
2896 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2899 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2901 if (defined($d->{usb3
}) && $d->{usb3
}) {
2902 $usbbus = ',bus=xhci.0';
2905 if (defined($d->{host
})) {
2906 $d = parse_usb_device
($d->{host
});
2907 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2908 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2909 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2910 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2911 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2912 # usb redir support for spice, currently no usb3
2913 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2914 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2920 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2921 if (my $path = $conf->{"serial$i"}) {
2922 if ($path eq 'socket') {
2923 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2924 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2925 push @$devices, '-device', "isa-serial,chardev=serial$i";
2927 die "no such serial device\n" if ! -c
$path;
2928 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2929 push @$devices, '-device', "isa-serial,chardev=serial$i";
2935 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2936 if (my $path = $conf->{"parallel$i"}) {
2937 die "no such parallel device\n" if ! -c
$path;
2938 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2939 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2940 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2944 my $vmname = $conf->{name
} || "vm$vmid";
2946 push @$cmd, '-name', $vmname;
2949 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2950 $sockets = $conf->{sockets
} if $conf->{sockets
};
2952 my $cores = $conf->{cores
} || 1;
2954 my $maxcpus = $sockets * $cores;
2956 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2958 my $allowed_vcpus = $cpuinfo->{cpus
};
2960 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2961 if ($allowed_vcpus < $maxcpus);
2963 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2965 push @$cmd, '-nodefaults';
2967 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2969 my $bootindex_hash = {};
2971 foreach my $o (split(//, $bootorder)) {
2972 $bootindex_hash->{$o} = $i*100;
2976 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2978 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2980 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2982 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2984 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2985 my $socket = vnc_socket
($vmid);
2986 push @$cmd, '-vnc', "unix:$socket,x509,password";
2988 push @$cmd, '-nographic';
2992 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2994 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2995 my $useLocaltime = $conf->{localtime};
2998 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3000 if ($ostype =~ m/^w/) { # windows
3001 $useLocaltime = 1 if !defined($conf->{localtime});
3003 # use time drift fix when acpi is enabled
3004 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3005 $tdf = 1 if !defined($conf->{tdf
});
3009 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3010 $ostype eq 'wvista') {
3011 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3012 push @$cmd, '-no-hpet';
3013 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3014 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3015 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3016 push @$cpuFlags , 'hv_time' if !$nokvm;
3019 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3023 if ($ostype eq 'win7' || $ostype eq 'win8') {
3024 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3028 push @$rtcFlags, 'driftfix=slew' if $tdf;
3031 push @$machineFlags, 'accel=tcg';
3033 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3036 if ($machine_type) {
3037 push @$machineFlags, "type=${machine_type}";
3040 if ($conf->{startdate
}) {
3041 push @$rtcFlags, "base=$conf->{startdate}";
3042 } elsif ($useLocaltime) {
3043 push @$rtcFlags, 'base=localtime';
3046 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3047 if (my $cputype = $conf->{cpu
}) {
3048 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpu_fmt, $cputype)
3049 or die "Cannot parse cpu description: $cputype\n";
3050 $cpu = $cpuconf->{cputype
};
3051 $kvm_off = 1 if $cpuconf->{hidden
};
3054 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3056 push @$cpuFlags , '-x2apic'
3057 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3059 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3061 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3063 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3065 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3066 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3069 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3071 push @$cpuFlags, 'kvm=off' if $kvm_off;
3073 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3075 push @$cmd, '-cpu', $cpu;
3077 my $memory = $conf->{memory
} || $defaults->{memory
};
3078 my $static_memory = 0;
3079 my $dimm_memory = 0;
3081 if ($hotplug_features->{memory
}) {
3082 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3083 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3084 $static_memory = $STATICMEM;
3085 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3086 $dimm_memory = $memory - $static_memory;
3087 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3091 $static_memory = $memory;
3092 push @$cmd, '-m', $static_memory;
3095 if ($conf->{numa
}) {
3097 my $numa_totalmemory = undef;
3098 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3099 next if !$conf->{"numa$i"};
3100 my $numa = parse_numa
($conf->{"numa$i"});
3103 die "missing numa node$i memory value\n" if !$numa->{memory
};
3104 my $numa_memory = $numa->{memory
};
3105 $numa_totalmemory += $numa_memory;
3106 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3109 my $cpulists = $numa->{cpus
};
3110 die "missing numa node$i cpus\n" if !defined($cpulists);
3111 my $cpus = join(',', map {
3112 my ($start, $end) = @$_;
3113 defined($end) ?
"$start-$end" : $start
3117 my $hostnodelists = $numa->{hostnodes
};
3118 if (defined($hostnodelists)) {
3120 foreach my $hostnoderange (@$hostnodelists) {
3121 my ($start, $end) = @$hostnoderange;
3122 $hostnodes .= ',' if $hostnodes;
3123 $hostnodes .= $start;
3124 $hostnodes .= "-$end" if defined($end);
3126 for (my $i = $start; $i <= $end; ++$i ) {
3127 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3132 my $policy = $numa->{policy
};
3133 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3134 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3137 push @$cmd, '-object', $numa_object;
3138 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3141 die "total memory for NUMA nodes must be equal to vm static memory\n"
3142 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3144 #if no custom tology, we split memory and cores across numa nodes
3145 if(!$numa_totalmemory) {
3147 my $numa_memory = ($static_memory / $sockets) . "M";
3149 for (my $i = 0; $i < $sockets; $i++) {
3151 my $cpustart = ($cores * $i);
3152 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3153 my $cpus = $cpustart;
3154 $cpus .= "-$cpuend" if $cpuend;
3156 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3157 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3162 if ($hotplug_features->{memory
}) {
3163 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3164 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3165 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3166 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3168 #if dimm_memory is not aligned to dimm map
3169 if($current_size > $memory) {
3170 $conf->{memory
} = $current_size;
3171 PVE
::QemuConfig-
>write_config($vmid, $conf);
3176 push @$cmd, '-S' if $conf->{freeze
};
3178 # set keyboard layout
3179 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3180 push @$cmd, '-k', $kb if $kb;
3183 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3184 #push @$cmd, '-soundhw', 'es1370';
3185 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3187 if($conf->{agent
}) {
3188 my $qgasocket = qmp_socket
($vmid, 1);
3189 my $pciaddr = print_pci_addr
("qga0", $bridges);
3190 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3191 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3192 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3199 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3200 for(my $i = 1; $i < $qxlnum; $i++){
3201 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3202 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3205 # assume other OS works like Linux
3206 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3207 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3211 my $pciaddr = print_pci_addr
("spice", $bridges);
3213 my $nodename = PVE
::INotify
::nodename
();
3214 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3215 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3217 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3219 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3220 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3221 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3224 # enable balloon by default, unless explicitly disabled
3225 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3226 $pciaddr = print_pci_addr
("balloon0", $bridges);
3227 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3230 if ($conf->{watchdog
}) {
3231 my $wdopts = parse_watchdog
($conf->{watchdog
});
3232 $pciaddr = print_pci_addr
("watchdog", $bridges);
3233 my $watchdog = $wdopts->{model
} || 'i6300esb';
3234 push @$devices, '-device', "$watchdog$pciaddr";
3235 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3239 my $scsicontroller = {};
3240 my $ahcicontroller = {};
3241 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3243 # Add iscsi initiator name if available
3244 if (my $initiator = get_initiator_name
()) {
3245 push @$devices, '-iscsi', "initiator-name=$initiator";
3248 foreach_drive
($conf, sub {
3249 my ($ds, $drive) = @_;
3251 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3252 push @$vollist, $drive->{file
};
3255 $use_virtio = 1 if $ds =~ m/^virtio/;
3257 if (drive_is_cdrom
($drive)) {
3258 if ($bootindex_hash->{d
}) {
3259 $drive->{bootindex
} = $bootindex_hash->{d
};
3260 $bootindex_hash->{d
} += 1;
3263 if ($bootindex_hash->{c
}) {
3264 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3265 $bootindex_hash->{c
} += 1;
3269 if($drive->{interface
} eq 'virtio'){
3270 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3273 if ($drive->{interface
} eq 'scsi') {
3275 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3277 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3278 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3281 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3282 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3283 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3287 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3288 $queues = ",num_queues=$drive->{queues}";
3291 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3292 $scsicontroller->{$controller}=1;
3295 if ($drive->{interface
} eq 'sata') {
3296 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3297 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3298 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3299 $ahcicontroller->{$controller}=1;
3302 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3303 push @$devices, '-drive',$drive_cmd;
3304 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3307 for (my $i = 0; $i < $MAX_NETS; $i++) {
3308 next if !$conf->{"net$i"};
3309 my $d = parse_net
($conf->{"net$i"});
3312 $use_virtio = 1 if $d->{model
} eq 'virtio';
3314 if ($bootindex_hash->{n
}) {
3315 $d->{bootindex
} = $bootindex_hash->{n
};
3316 $bootindex_hash->{n
} += 1;
3319 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3320 push @$devices, '-netdev', $netdevfull;
3322 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3323 push @$devices, '-device', $netdevicefull;
3328 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3333 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3335 while (my ($k, $v) = each %$bridges) {
3336 $pciaddr = print_pci_addr
("pci.$k");
3337 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3342 if ($conf->{args
}) {
3343 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3347 push @$cmd, @$devices;
3348 push @$cmd, '-rtc', join(',', @$rtcFlags)
3349 if scalar(@$rtcFlags);
3350 push @$cmd, '-machine', join(',', @$machineFlags)
3351 if scalar(@$machineFlags);
3352 push @$cmd, '-global', join(',', @$globalFlags)
3353 if scalar(@$globalFlags);
3355 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3360 return "${var_run_tmpdir}/$vmid.vnc";
3366 my $res = vm_mon_cmd
($vmid, 'query-spice');
3368 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3372 my ($vmid, $qga) = @_;
3373 my $sockettype = $qga ?
'qga' : 'qmp';
3374 return "${var_run_tmpdir}/$vmid.$sockettype";
3379 return "${var_run_tmpdir}/$vmid.pid";
3382 sub vm_devices_list
{
3385 my $res = vm_mon_cmd
($vmid, 'query-pci');
3387 foreach my $pcibus (@$res) {
3388 foreach my $device (@{$pcibus->{devices
}}) {
3389 next if !$device->{'qdev_id'};
3390 if ($device->{'pci_bridge'}) {
3391 $devices->{$device->{'qdev_id'}} = 1;
3392 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3393 next if !$bridge_device->{'qdev_id'};
3394 $devices->{$bridge_device->{'qdev_id'}} = 1;
3395 $devices->{$device->{'qdev_id'}}++;
3398 $devices->{$device->{'qdev_id'}} = 1;
3403 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3404 foreach my $block (@$resblock) {
3405 if($block->{device
} =~ m/^drive-(\S+)/){
3410 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3411 foreach my $mice (@$resmice) {
3412 if ($mice->{name
} eq 'QEMU HID Tablet') {
3413 $devices->{tablet
} = 1;
3422 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3424 my $q35 = machine_type_is_q35
($conf);
3426 my $devices_list = vm_devices_list
($vmid);
3427 return 1 if defined($devices_list->{$deviceid});
3429 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3431 if ($deviceid eq 'tablet') {
3433 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3435 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3437 qemu_iothread_add
($vmid, $deviceid, $device);
3439 qemu_driveadd
($storecfg, $vmid, $device);
3440 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3442 qemu_deviceadd
($vmid, $devicefull);
3443 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3445 eval { qemu_drivedel
($vmid, $deviceid); };
3450 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3453 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3454 my $pciaddr = print_pci_addr
($deviceid);
3455 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3457 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3459 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3460 qemu_iothread_add
($vmid, $deviceid, $device);
3461 $devicefull .= ",iothread=iothread-$deviceid";
3464 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3465 $devicefull .= ",num_queues=$device->{queues}";
3468 qemu_deviceadd
($vmid, $devicefull);
3469 qemu_deviceaddverify
($vmid, $deviceid);
3471 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3473 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3474 qemu_driveadd
($storecfg, $vmid, $device);
3476 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3477 eval { qemu_deviceadd
($vmid, $devicefull); };
3479 eval { qemu_drivedel
($vmid, $deviceid); };
3484 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3486 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3488 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3489 my $use_old_bios_files = undef;
3490 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3492 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3493 qemu_deviceadd
($vmid, $netdevicefull);
3494 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3496 eval { qemu_netdevdel
($vmid, $deviceid); };
3501 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3504 my $pciaddr = print_pci_addr
($deviceid);
3505 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3507 qemu_deviceadd
($vmid, $devicefull);
3508 qemu_deviceaddverify
($vmid, $deviceid);
3511 die "can't hotplug device '$deviceid'\n";
3517 # fixme: this should raise exceptions on error!
3518 sub vm_deviceunplug
{
3519 my ($vmid, $conf, $deviceid) = @_;
3521 my $devices_list = vm_devices_list
($vmid);
3522 return 1 if !defined($devices_list->{$deviceid});
3524 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3526 if ($deviceid eq 'tablet') {
3528 qemu_devicedel
($vmid, $deviceid);
3530 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3532 qemu_devicedel
($vmid, $deviceid);
3533 qemu_devicedelverify
($vmid, $deviceid);
3534 qemu_drivedel
($vmid, $deviceid);
3535 qemu_iothread_del
($conf, $vmid, $deviceid);
3537 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3539 qemu_devicedel
($vmid, $deviceid);
3540 qemu_devicedelverify
($vmid, $deviceid);
3541 qemu_iothread_del
($conf, $vmid, $deviceid);
3543 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3545 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3546 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3547 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3549 qemu_devicedel
($vmid, $deviceid);
3550 qemu_drivedel
($vmid, $deviceid);
3551 qemu_deletescsihw
($conf, $vmid, $deviceid);
3553 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3555 qemu_devicedel
($vmid, $deviceid);
3556 qemu_devicedelverify
($vmid, $deviceid);
3557 qemu_netdevdel
($vmid, $deviceid);
3560 die "can't unplug device '$deviceid'\n";
3566 sub qemu_deviceadd
{
3567 my ($vmid, $devicefull) = @_;
3569 $devicefull = "driver=".$devicefull;
3570 my %options = split(/[=,]/, $devicefull);
3572 vm_mon_cmd
($vmid, "device_add" , %options);
3575 sub qemu_devicedel
{
3576 my ($vmid, $deviceid) = @_;
3578 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3581 sub qemu_iothread_add
{
3582 my($vmid, $deviceid, $device) = @_;
3584 if ($device->{iothread
}) {
3585 my $iothreads = vm_iothreads_list
($vmid);
3586 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3590 sub qemu_iothread_del
{
3591 my($conf, $vmid, $deviceid) = @_;
3593 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3594 if ($device->{iothread
}) {
3595 my $iothreads = vm_iothreads_list
($vmid);
3596 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3600 sub qemu_objectadd
{
3601 my($vmid, $objectid, $qomtype) = @_;
3603 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3608 sub qemu_objectdel
{
3609 my($vmid, $objectid) = @_;
3611 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3617 my ($storecfg, $vmid, $device) = @_;
3619 my $drive = print_drive_full
($storecfg, $vmid, $device);
3620 $drive =~ s/\\/\\\\/g;
3621 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3623 # If the command succeeds qemu prints: "OK
"
3624 return 1 if $ret =~ m/OK/s;
3626 die "adding drive failed
: $ret\n";
3630 my($vmid, $deviceid) = @_;
3632 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3635 return 1 if $ret eq "";
3637 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3638 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3640 die "deleting drive
$deviceid failed
: $ret\n";
3643 sub qemu_deviceaddverify {
3644 my ($vmid, $deviceid) = @_;
3646 for (my $i = 0; $i <= 5; $i++) {
3647 my $devices_list = vm_devices_list($vmid);
3648 return 1 if defined($devices_list->{$deviceid});
3652 die "error on hotplug device
'$deviceid'\n";
3656 sub qemu_devicedelverify {
3657 my ($vmid, $deviceid) = @_;
3659 # need to verify that the device is correctly removed as device_del
3660 # is async and empty return is not reliable
3662 for (my $i = 0; $i <= 5; $i++) {
3663 my $devices_list = vm_devices_list($vmid);
3664 return 1 if !defined($devices_list->{$deviceid});
3668 die "error on hot-unplugging device
'$deviceid'\n";
3671 sub qemu_findorcreatescsihw {
3672 my ($storecfg, $conf, $vmid, $device) = @_;
3674 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3676 my $scsihwid="$controller_prefix$controller";
3677 my $devices_list = vm_devices_list($vmid);
3679 if(!defined($devices_list->{$scsihwid})) {
3680 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3686 sub qemu_deletescsihw {
3687 my ($conf, $vmid, $opt) = @_;
3689 my $device = parse_drive($opt, $conf->{$opt});
3691 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3692 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3696 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3698 my $devices_list = vm_devices_list($vmid);
3699 foreach my $opt (keys %{$devices_list}) {
3700 if (PVE::QemuServer::is_valid_drivename($opt)) {
3701 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3702 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3708 my $scsihwid="scsihw
$controller";
3710 vm_deviceunplug($vmid, $conf, $scsihwid);
3715 sub qemu_add_pci_bridge {
3716 my ($storecfg, $conf, $vmid, $device) = @_;
3722 print_pci_addr($device, $bridges);
3724 while (my ($k, $v) = each %$bridges) {
3727 return 1 if !defined($bridgeid) || $bridgeid < 1;
3729 my $bridge = "pci
.$bridgeid";
3730 my $devices_list = vm_devices_list($vmid);
3732 if (!defined($devices_list->{$bridge})) {
3733 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3739 sub qemu_set_link_status {
3740 my ($vmid, $device, $up) = @_;
3742 vm_mon_cmd($vmid, "set_link
", name => $device,
3743 up => $up ? JSON::true : JSON::false);
3746 sub qemu_netdevadd {
3747 my ($vmid, $conf, $device, $deviceid) = @_;
3749 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3750 my %options = split(/[=,]/, $netdev);
3752 vm_mon_cmd($vmid, "netdev_add
", %options);
3756 sub qemu_netdevdel {
3757 my ($vmid, $deviceid) = @_;
3759 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3762 sub qemu_cpu_hotplug {
3763 my ($vmid, $conf, $vcpus) = @_;
3766 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3767 $sockets = $conf->{sockets} if $conf->{sockets};
3768 my $cores = $conf->{cores} || 1;
3769 my $maxcpus = $sockets * $cores;
3771 $vcpus = $maxcpus if !$vcpus;
3773 die "you can
't add more vcpus than maxcpus\n"
3774 if $vcpus > $maxcpus;
3776 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3777 die "online cpu unplug is not yet possible\n"
3778 if $vcpus < $currentvcpus;
3780 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3781 die "vcpus in running vm is different than configuration\n"
3782 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3784 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3785 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3789 sub qemu_memory_hotplug {
3790 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3792 return $value if !check_running($vmid);
3794 my $memory = $conf->{memory} || $defaults->{memory};
3795 $value = $defaults->{memory} if !$value;
3796 return $value if $value == $memory;
3798 my $static_memory = $STATICMEM;
3799 my $dimm_memory = $memory - $static_memory;
3801 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3802 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3806 $sockets = $conf->{sockets} if $conf->{sockets};
3808 if($value > $memory) {
3810 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3811 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3813 return if $current_size <= $conf->{memory};
3815 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3817 eval { qemu_objectdel($vmid, "mem-
$name"); };
3821 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3823 eval { qemu_objectdel($vmid, "mem-
$name"); };
3826 #update conf after each succesful module hotplug
3827 $conf->{memory} = $current_size;
3828 PVE::QemuConfig->write_config($vmid, $conf);
3833 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3834 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3836 return if $current_size >= $conf->{memory};
3837 print "try to unplug memory dimm
$name\n";
3841 eval { qemu_devicedel($vmid, $name) };
3843 my $dimm_list = qemu_dimm_list($vmid);
3844 last if !$dimm_list->{$name};
3845 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3849 #update conf after each succesful module unplug
3850 $conf->{memory} = $current_size;
3852 eval { qemu_objectdel($vmid, "mem-
$name"); };
3853 PVE::QemuConfig->write_config($vmid, $conf);
3858 sub qemu_dimm_list {
3861 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3864 foreach my $dimm (@$dimmarray) {
3866 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3867 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3868 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3869 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3870 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3875 sub qemu_block_set_io_throttle {
3876 my ($vmid, $deviceid,
3877 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3878 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3880 return if !check_running($vmid) ;
3882 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3884 bps_rd => int($bps_rd),
3885 bps_wr => int($bps_wr),
3887 iops_rd => int($iops_rd),
3888 iops_wr => int($iops_wr),
3889 bps_max => int($bps_max),
3890 bps_rd_max => int($bps_rd_max),
3891 bps_wr_max => int($bps_wr_max),
3892 iops_max => int($iops_max),
3893 iops_rd_max => int($iops_rd_max),
3894 iops_wr_max => int($iops_wr_max)
3899 # old code, only used to shutdown old VM after update
3901 my ($fh, $timeout) = @_;
3903 my $sel = new IO::Select;
3910 while (scalar (@ready = $sel->can_read($timeout))) {
3912 if ($count = $fh->sysread($buf, 8192)) {
3913 if ($buf =~ /^(.*)\(qemu\) $/s) {
3920 if (!defined($count)) {
3927 die "monitor
read timeout
\n" if !scalar(@ready);
3932 # old code, only used to shutdown old VM after update
3933 sub vm_monitor_command {
3934 my ($vmid, $cmdstr, $nocheck) = @_;
3939 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3941 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3943 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3944 die "unable to
connect to VM
$vmid socket - $!\n";
3948 # hack: migrate sometime blocks the monitor (when migrate_downtime
3950 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3951 $timeout = 60*60; # 1 hour
3955 my $data = __read_avail($sock, $timeout);
3957 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3958 die "got unexpected qemu monitor banner
\n";
3961 my $sel = new IO::Select;
3964 if (!scalar(my @ready = $sel->can_write($timeout))) {
3965 die "monitor
write error
- timeout
";
3968 my $fullcmd = "$cmdstr\r";
3970 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3973 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3974 die "monitor
write error
- $!";
3977 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3981 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3982 $timeout = 60*60; # 1 hour
3983 } elsif ($cmdstr =~ m/^(eject|change)/) {
3984 $timeout = 60; # note: cdrom mount command is slow
3986 if ($res = __read_avail($sock, $timeout)) {
3988 my @lines = split("\r?
\n", $res);
3990 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3992 $res = join("\n", @lines);
4000 syslog("err
", "VM
$vmid monitor command failed
- $err");
4007 sub qemu_block_resize {
4008 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4010 my $running = check_running($vmid);
4012 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4014 return if !$running;
4016 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4020 sub qemu_volume_snapshot {
4021 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4023 my $running = check_running($vmid);
4025 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4026 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4028 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4032 sub qemu_volume_snapshot_delete {
4033 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4035 my $running = check_running($vmid);
4037 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4039 return if !$running;
4041 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4044 sub set_migration_caps {
4050 "auto-converge
" => 1,
4052 "x-rdma-pin-all
" => 0,
4057 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4059 for my $supported_capability (@$supported_capabilities) {
4061 capability => $supported_capability->{capability},
4062 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4066 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4069 my $fast_plug_option = {
4078 # hotplug changes in [PENDING]
4079 # $selection hash can be used to only apply specified options, for
4080 # example: { cores => 1 } (only apply changed 'cores')
4081 # $errors ref is used to return error messages
4082 sub vmconfig_hotplug_pending {
4083 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4085 my $defaults = load_defaults();
4087 # commit values which do not have any impact on running VM first
4088 # Note: those option cannot raise errors, we we do not care about
4089 # $selection and always apply them.
4091 my $add_error = sub {
4092 my ($opt, $msg) = @_;
4093 $errors->{$opt} = "hotplug problem
- $msg";
4097 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4098 if ($fast_plug_option->{$opt}) {
4099 $conf->{$opt} = $conf->{pending}->{$opt};
4100 delete $conf->{pending}->{$opt};
4106 PVE::QemuConfig->write_config($vmid, $conf);
4107 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4110 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4112 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4113 while (my ($opt, $force) = each %$pending_delete_hash) {
4114 next if $selection && !$selection->{$opt};
4116 if ($opt eq 'hotplug') {
4117 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4118 } elsif ($opt eq 'tablet') {
4119 die "skip
\n" if !$hotplug_features->{usb};
4120 if ($defaults->{tablet}) {
4121 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4123 vm_deviceunplug($vmid, $conf, $opt);
4125 } elsif ($opt eq 'vcpus') {
4126 die "skip
\n" if !$hotplug_features->{cpu};
4127 qemu_cpu_hotplug($vmid, $conf, undef);
4128 } elsif ($opt eq 'balloon') {
4129 # enable balloon device is not hotpluggable
4130 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4131 } elsif ($fast_plug_option->{$opt}) {
4133 } elsif ($opt =~ m/^net(\d+)$/) {
4134 die "skip
\n" if !$hotplug_features->{network};
4135 vm_deviceunplug($vmid, $conf, $opt);
4136 } elsif (is_valid_drivename($opt)) {
4137 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4138 vm_deviceunplug($vmid, $conf, $opt);
4139 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4140 } elsif ($opt =~ m/^memory$/) {
4141 die "skip
\n" if !$hotplug_features->{memory};
4142 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4143 } elsif ($opt eq 'cpuunits') {
4144 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4145 } elsif ($opt eq 'cpulimit') {
4146 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4152 &$add_error($opt, $err) if $err ne "skip
\n";
4154 # save new config if hotplug was successful
4155 delete $conf->{$opt};
4156 vmconfig_undelete_pending_option($conf, $opt);
4157 PVE::QemuConfig->write_config($vmid, $conf);
4158 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4162 foreach my $opt (keys %{$conf->{pending}}) {
4163 next if $selection && !$selection->{$opt};
4164 my $value = $conf->{pending}->{$opt};
4166 if ($opt eq 'hotplug') {
4167 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4168 } elsif ($opt eq 'tablet') {
4169 die "skip
\n" if !$hotplug_features->{usb};
4171 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4172 } elsif ($value == 0) {
4173 vm_deviceunplug($vmid, $conf, $opt);
4175 } elsif ($opt eq 'vcpus') {
4176 die "skip
\n" if !$hotplug_features->{cpu};
4177 qemu_cpu_hotplug($vmid, $conf, $value);
4178 } elsif ($opt eq 'balloon') {
4179 # enable/disable balloning device is not hotpluggable
4180 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4181 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4182 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4184 # allow manual ballooning if shares is set to zero
4185 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4186 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4187 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4189 } elsif ($opt =~ m/^net(\d+)$/) {
4190 # some changes can be done without hotplug
4191 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4192 $vmid, $opt, $value);
4193 } elsif (is_valid_drivename($opt)) {
4194 # some changes can be done without hotplug
4195 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4196 $vmid, $opt, $value, 1);
4197 } elsif ($opt =~ m/^memory$/) { #dimms
4198 die "skip
\n" if !$hotplug_features->{memory};
4199 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4200 } elsif ($opt eq 'cpuunits') {
4201 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4202 } elsif ($opt eq 'cpulimit') {
4203 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4204 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4206 die "skip
\n"; # skip non-hot-pluggable options
4210 &$add_error($opt, $err) if $err ne "skip
\n";
4212 # save new config if hotplug was successful
4213 $conf->{$opt} = $value;
4214 delete $conf->{pending}->{$opt};
4215 PVE::QemuConfig->write_config($vmid, $conf);
4216 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4221 sub try_deallocate_drive {
4222 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4224 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4225 my $volid = $drive->{file};
4226 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4227 my $sid = PVE::Storage::parse_volume_id($volid);
4228 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4230 # check if the disk is really unused
4231 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4232 if is_volume_in_use($storecfg, $conf, $key, $volid);
4233 PVE::Storage::vdisk_free($storecfg, $volid);
4236 # If vm is not owner of this disk remove from config
4244 sub vmconfig_delete_or_detach_drive {
4245 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4247 my $drive = parse_drive($opt, $conf->{$opt});
4249 my $rpcenv = PVE::RPCEnvironment::get();
4250 my $authuser = $rpcenv->get_user();
4253 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4254 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4256 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4260 sub vmconfig_apply_pending {
4261 my ($vmid, $conf, $storecfg) = @_;
4265 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4266 while (my ($opt, $force) = each %$pending_delete_hash) {
4267 die "internal error
" if $opt =~ m/^unused/;
4268 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4269 if (!defined($conf->{$opt})) {
4270 vmconfig_undelete_pending_option($conf, $opt);
4271 PVE::QemuConfig->write_config($vmid, $conf);
4272 } elsif (is_valid_drivename($opt)) {
4273 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4274 vmconfig_undelete_pending_option($conf, $opt);
4275 delete $conf->{$opt};
4276 PVE::QemuConfig->write_config($vmid, $conf);
4278 vmconfig_undelete_pending_option($conf, $opt);
4279 delete $conf->{$opt};
4280 PVE::QemuConfig->write_config($vmid, $conf);
4284 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4286 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4287 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4289 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4290 # skip if nothing changed
4291 } elsif (is_valid_drivename($opt)) {
4292 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4293 if defined($conf->{$opt});
4294 $conf->{$opt} = $conf->{pending}->{$opt};
4296 $conf->{$opt} = $conf->{pending}->{$opt};
4299 delete $conf->{pending}->{$opt};
4300 PVE::QemuConfig->write_config($vmid, $conf);
4304 my $safe_num_ne = sub {
4307 return 0 if !defined($a) && !defined($b);
4308 return 1 if !defined($a);
4309 return 1 if !defined($b);
4314 my $safe_string_ne = sub {
4317 return 0 if !defined($a) && !defined($b);
4318 return 1 if !defined($a);
4319 return 1 if !defined($b);
4324 sub vmconfig_update_net {
4325 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4327 my $newnet = parse_net($value);
4329 if ($conf->{$opt}) {
4330 my $oldnet = parse_net($conf->{$opt});
4332 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4333 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4334 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4335 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4337 # for non online change, we try to hot-unplug
4338 die "skip
\n" if !$hotplug;
4339 vm_deviceunplug($vmid, $conf, $opt);
4342 die "internal error
" if $opt !~ m/net(\d+)/;
4343 my $iface = "tap
${vmid
}i
$1";
4345 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4346 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4347 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4348 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4349 PVE::Network::tap_unplug($iface);
4350 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4351 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4352 # Rate can be applied on its own but any change above needs to
4353 # include the rate in tap_plug since OVS resets everything.
4354 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4357 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4358 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4366 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4372 sub vmconfig_update_disk {
4373 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4375 # fixme: do we need force?
4377 my $drive = parse_drive($opt, $value);
4379 if ($conf->{$opt}) {
4381 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4383 my $media = $drive->{media} || 'disk';
4384 my $oldmedia = $old_drive->{media} || 'disk';
4385 die "unable to change media type
\n" if $media ne $oldmedia;
4387 if (!drive_is_cdrom($old_drive)) {
4389 if ($drive->{file} ne $old_drive->{file}) {
4391 die "skip
\n" if !$hotplug;
4393 # unplug and register as unused
4394 vm_deviceunplug($vmid, $conf, $opt);
4395 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4398 # update existing disk
4400 # skip non hotpluggable value
4401 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4402 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4403 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4404 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4409 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4410 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4411 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4412 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4413 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4414 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4415 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4416 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4417 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4418 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4419 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4420 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4422 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4423 ($drive->{mbps} || 0)*1024*1024,
4424 ($drive->{mbps_rd} || 0)*1024*1024,
4425 ($drive->{mbps_wr} || 0)*1024*1024,
4426 $drive->{iops} || 0,
4427 $drive->{iops_rd} || 0,
4428 $drive->{iops_wr} || 0,
4429 ($drive->{mbps_max} || 0)*1024*1024,
4430 ($drive->{mbps_rd_max} || 0)*1024*1024,
4431 ($drive->{mbps_wr_max} || 0)*1024*1024,
4432 $drive->{iops_max} || 0,
4433 $drive->{iops_rd_max} || 0,
4434 $drive->{iops_wr_max} || 0);
4443 if ($drive->{file} eq 'none') {
4444 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4446 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4447 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4448 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4456 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4458 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4459 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4463 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4464 $forcemachine, $spice_ticket) = @_;
4466 PVE::QemuConfig->lock_config($vmid, sub {
4467 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4469 die "you can
't start a vm if it's a template
\n" if PVE::QemuConfig->is_template($conf);
4471 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4473 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4475 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4476 vmconfig_apply_pending($vmid, $conf, $storecfg);
4477 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4480 my $defaults = load_defaults();
4482 # set environment variable useful inside network script
4483 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4485 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4487 my $migrate_port = 0;
4490 if ($statefile eq 'tcp') {
4491 my $localip = "localhost
";
4492 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4493 my $nodename = PVE::INotify::nodename();
4494 if ($datacenterconf->{migration_unsecure}) {
4495 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4496 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4498 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4499 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4500 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4501 push @$cmd, '-incoming', $migrate_uri;
4504 push @$cmd, '-loadstate', $statefile;
4511 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4512 my $d = parse_hostpci($conf->{"hostpci
$i"});
4514 my $pcidevices = $d->{pciid};
4515 foreach my $pcidevice (@$pcidevices) {
4516 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4518 my $info = pci_device_info("0000:$pciid");
4519 die "IOMMU
not present
\n" if !check_iommu_support();
4520 die "no pci device info
for device
'$pciid'\n" if !$info;
4521 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4522 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4526 PVE::Storage::activate_volumes($storecfg, $vollist);
4528 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4532 # deactivate volumes if start fails
4533 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4534 die "start failed
: $err";
4537 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4539 if ($statefile && $statefile ne 'tcp') {
4540 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4544 if ($migratedfrom) {
4547 set_migration_caps($vmid);
4552 print "spice listens on port
$spice_port\n";
4553 if ($spice_ticket) {
4554 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4555 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4561 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4562 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4563 if $conf->{balloon};
4566 foreach my $opt (keys %$conf) {
4567 next if $opt !~ m/^net\d+$/;
4568 my $nicconf = parse_net($conf->{$opt});
4569 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4573 vm_mon_cmd_nocheck($vmid, 'qom-set',
4574 path => "machine
/peripheral/balloon0
",
4575 property => "guest-stats-polling-interval
",
4576 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4582 my ($vmid, $execute, %params) = @_;
4584 my $cmd = { execute => $execute, arguments => \%params };
4585 vm_qmp_command($vmid, $cmd);
4588 sub vm_mon_cmd_nocheck {
4589 my ($vmid, $execute, %params) = @_;
4591 my $cmd = { execute => $execute, arguments => \%params };
4592 vm_qmp_command($vmid, $cmd, 1);
4595 sub vm_qmp_command {
4596 my ($vmid, $cmd, $nocheck) = @_;
4601 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4602 $timeout = $cmd->{arguments}->{timeout};
4603 delete $cmd->{arguments}->{timeout};
4607 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4608 my $sname = qmp_socket($vmid);
4609 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4610 my $qmpclient = PVE::QMPClient->new();
4612 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4613 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4614 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4615 if scalar(%{$cmd->{arguments}});
4616 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4618 die "unable to open monitor socket\n";
4622 syslog("err", "VM $vmid qmp command failed - $err");
4629 sub vm_human_monitor_command {
4630 my ($vmid, $cmdline) = @_;
4635 execute => 'human-monitor-command
',
4636 arguments => { 'command-line
' => $cmdline},
4639 return vm_qmp_command($vmid, $cmd);
4642 sub vm_commandline {
4643 my ($storecfg, $vmid) = @_;
4645 my $conf = PVE::QemuConfig->load_config($vmid);
4647 my $defaults = load_defaults();
4649 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4651 return join(' ', @$cmd);
4655 my ($vmid, $skiplock) = @_;
4657 PVE::QemuConfig->lock_config($vmid, sub {
4659 my $conf = PVE::QemuConfig->load_config($vmid);
4661 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4663 vm_mon_cmd($vmid, "system_reset");
4667 sub get_vm_volumes {
4671 foreach_volid($conf, sub {
4672 my ($volid, $is_cdrom) = @_;
4674 return if $volid =~ m|^/|;
4676 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4679 push @$vollist, $volid;
4685 sub vm_stop_cleanup {
4686 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4691 my $vollist = get_vm_volumes($conf);
4692 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4695 foreach my $ext (qw(mon qmp pid vnc qga)) {
4696 unlink "/var/run/qemu-server/${vmid}.$ext";
4699 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4701 warn $@ if $@; # avoid errors - just warn
4704 # Note: use $nockeck to skip tests if VM configuration file exists.
4705 # We need that when migration VMs to other nodes (files already moved)
4706 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4708 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4710 $force = 1 if !defined($force) && !$shutdown;
4713 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4714 kill 15, $pid if $pid;
4715 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4716 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4720 PVE
::QemuConfig-
>lock_config($vmid, sub {
4722 my $pid = check_running
($vmid, $nocheck);
4727 $conf = PVE
::QemuConfig-
>load_config($vmid);
4728 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4729 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4730 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4731 $timeout = $opts->{down
} if $opts->{down
};
4735 $timeout = 60 if !defined($timeout);
4739 if (defined($conf) && $conf->{agent
}) {
4740 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4742 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4745 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4752 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4757 if ($count >= $timeout) {
4759 warn "VM still running - terminating now with SIGTERM\n";
4762 die "VM quit/powerdown failed - got timeout\n";
4765 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4770 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4773 die "VM quit/powerdown failed\n";
4781 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4786 if ($count >= $timeout) {
4787 warn "VM still running - terminating now with SIGKILL\n";
4792 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4797 my ($vmid, $skiplock) = @_;
4799 PVE
::QemuConfig-
>lock_config($vmid, sub {
4801 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4803 PVE
::QemuConfig-
>check_lock($conf)
4804 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4806 vm_mon_cmd
($vmid, "stop");
4811 my ($vmid, $skiplock, $nocheck) = @_;
4813 PVE
::QemuConfig-
>lock_config($vmid, sub {
4817 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4819 PVE
::QemuConfig-
>check_lock($conf)
4820 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4822 vm_mon_cmd
($vmid, "cont");
4825 vm_mon_cmd_nocheck
($vmid, "cont");
4831 my ($vmid, $skiplock, $key) = @_;
4833 PVE
::QemuConfig-
>lock_config($vmid, sub {
4835 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4837 # there is no qmp command, so we use the human monitor command
4838 vm_human_monitor_command
($vmid, "sendkey $key");
4843 my ($storecfg, $vmid, $skiplock) = @_;
4845 PVE
::QemuConfig-
>lock_config($vmid, sub {
4847 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4849 if (!check_running
($vmid)) {
4850 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4852 die "VM $vmid is running - destroy failed\n";
4860 my ($filename, $buf) = @_;
4862 my $fh = IO
::File-
>new($filename, "w");
4863 return undef if !$fh;
4865 my $res = print $fh $buf;
4872 sub pci_device_info
{
4877 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4878 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4880 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4881 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4883 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4884 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4886 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4887 return undef if !defined($product) || $product !~ s/^0x//;
4892 product
=> $product,
4898 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4907 my $name = $dev->{name
};
4909 my $fn = "$pcisysfs/devices/$name/reset";
4911 return file_write
($fn, "1");
4914 sub pci_dev_bind_to_vfio
{
4917 my $name = $dev->{name
};
4919 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4921 if (!-d
$vfio_basedir) {
4922 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4924 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4926 my $testdir = "$vfio_basedir/$name";
4927 return 1 if -d
$testdir;
4929 my $data = "$dev->{vendor} $dev->{product}";
4930 return undef if !file_write
("$vfio_basedir/new_id", $data);
4932 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4933 if (!file_write
($fn, $name)) {
4934 return undef if -f
$fn;
4937 $fn = "$vfio_basedir/bind";
4938 if (! -d
$testdir) {
4939 return undef if !file_write
($fn, $name);
4945 sub pci_dev_group_bind_to_vfio
{
4948 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4950 if (!-d
$vfio_basedir) {
4951 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4953 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4955 # get IOMMU group devices
4956 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4957 my @devs = grep /^0000:/, readdir($D);
4960 foreach my $pciid (@devs) {
4961 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4963 # pci bridges, switches or root ports are not supported
4964 # they have a pci_bus subdirectory so skip them
4965 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4967 my $info = pci_device_info
($1);
4968 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4974 sub print_pci_addr
{
4975 my ($id, $bridges) = @_;
4979 piix3
=> { bus
=> 0, addr
=> 1 },
4980 #addr2 : first videocard
4981 balloon0
=> { bus
=> 0, addr
=> 3 },
4982 watchdog
=> { bus
=> 0, addr
=> 4 },
4983 scsihw0
=> { bus
=> 0, addr
=> 5 },
4984 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4985 scsihw1
=> { bus
=> 0, addr
=> 6 },
4986 ahci0
=> { bus
=> 0, addr
=> 7 },
4987 qga0
=> { bus
=> 0, addr
=> 8 },
4988 spice
=> { bus
=> 0, addr
=> 9 },
4989 virtio0
=> { bus
=> 0, addr
=> 10 },
4990 virtio1
=> { bus
=> 0, addr
=> 11 },
4991 virtio2
=> { bus
=> 0, addr
=> 12 },
4992 virtio3
=> { bus
=> 0, addr
=> 13 },
4993 virtio4
=> { bus
=> 0, addr
=> 14 },
4994 virtio5
=> { bus
=> 0, addr
=> 15 },
4995 hostpci0
=> { bus
=> 0, addr
=> 16 },
4996 hostpci1
=> { bus
=> 0, addr
=> 17 },
4997 net0
=> { bus
=> 0, addr
=> 18 },
4998 net1
=> { bus
=> 0, addr
=> 19 },
4999 net2
=> { bus
=> 0, addr
=> 20 },
5000 net3
=> { bus
=> 0, addr
=> 21 },
5001 net4
=> { bus
=> 0, addr
=> 22 },
5002 net5
=> { bus
=> 0, addr
=> 23 },
5003 vga1
=> { bus
=> 0, addr
=> 24 },
5004 vga2
=> { bus
=> 0, addr
=> 25 },
5005 vga3
=> { bus
=> 0, addr
=> 26 },
5006 hostpci2
=> { bus
=> 0, addr
=> 27 },
5007 hostpci3
=> { bus
=> 0, addr
=> 28 },
5008 #addr29 : usb-host (pve-usb.cfg)
5009 'pci.1' => { bus
=> 0, addr
=> 30 },
5010 'pci.2' => { bus
=> 0, addr
=> 31 },
5011 'net6' => { bus
=> 1, addr
=> 1 },
5012 'net7' => { bus
=> 1, addr
=> 2 },
5013 'net8' => { bus
=> 1, addr
=> 3 },
5014 'net9' => { bus
=> 1, addr
=> 4 },
5015 'net10' => { bus
=> 1, addr
=> 5 },
5016 'net11' => { bus
=> 1, addr
=> 6 },
5017 'net12' => { bus
=> 1, addr
=> 7 },
5018 'net13' => { bus
=> 1, addr
=> 8 },
5019 'net14' => { bus
=> 1, addr
=> 9 },
5020 'net15' => { bus
=> 1, addr
=> 10 },
5021 'net16' => { bus
=> 1, addr
=> 11 },
5022 'net17' => { bus
=> 1, addr
=> 12 },
5023 'net18' => { bus
=> 1, addr
=> 13 },
5024 'net19' => { bus
=> 1, addr
=> 14 },
5025 'net20' => { bus
=> 1, addr
=> 15 },
5026 'net21' => { bus
=> 1, addr
=> 16 },
5027 'net22' => { bus
=> 1, addr
=> 17 },
5028 'net23' => { bus
=> 1, addr
=> 18 },
5029 'net24' => { bus
=> 1, addr
=> 19 },
5030 'net25' => { bus
=> 1, addr
=> 20 },
5031 'net26' => { bus
=> 1, addr
=> 21 },
5032 'net27' => { bus
=> 1, addr
=> 22 },
5033 'net28' => { bus
=> 1, addr
=> 23 },
5034 'net29' => { bus
=> 1, addr
=> 24 },
5035 'net30' => { bus
=> 1, addr
=> 25 },
5036 'net31' => { bus
=> 1, addr
=> 26 },
5037 'xhci' => { bus
=> 1, addr
=> 27 },
5038 'virtio6' => { bus
=> 2, addr
=> 1 },
5039 'virtio7' => { bus
=> 2, addr
=> 2 },
5040 'virtio8' => { bus
=> 2, addr
=> 3 },
5041 'virtio9' => { bus
=> 2, addr
=> 4 },
5042 'virtio10' => { bus
=> 2, addr
=> 5 },
5043 'virtio11' => { bus
=> 2, addr
=> 6 },
5044 'virtio12' => { bus
=> 2, addr
=> 7 },
5045 'virtio13' => { bus
=> 2, addr
=> 8 },
5046 'virtio14' => { bus
=> 2, addr
=> 9 },
5047 'virtio15' => { bus
=> 2, addr
=> 10 },
5048 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5049 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5050 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5051 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5052 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5053 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5054 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5055 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5056 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5057 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5058 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5059 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5060 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5061 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5062 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5063 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5064 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5065 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5066 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5067 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5068 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5069 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5070 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5071 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5072 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5073 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5074 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5075 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5076 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5077 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5078 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5082 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5083 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5084 my $bus = $devices->{$id}->{bus
};
5085 $res = ",bus=pci.$bus,addr=$addr";
5086 $bridges->{$bus} = 1 if $bridges;
5092 sub print_pcie_addr
{
5097 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5098 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5099 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5100 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5103 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5104 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5105 my $bus = $devices->{$id}->{bus
};
5106 $res = ",bus=$bus,addr=$addr";
5112 # vzdump restore implementaion
5114 sub tar_archive_read_firstfile
{
5115 my $archive = shift;
5117 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5119 # try to detect archive type first
5120 my $pid = open (TMP
, "tar tf '$archive'|") ||
5121 die "unable to open file '$archive'\n";
5122 my $firstfile = <TMP
>;
5126 die "ERROR: archive contaions no data\n" if !$firstfile;
5132 sub tar_restore_cleanup
{
5133 my ($storecfg, $statfile) = @_;
5135 print STDERR
"starting cleanup\n";
5137 if (my $fd = IO
::File-
>new($statfile, "r")) {
5138 while (defined(my $line = <$fd>)) {
5139 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5142 if ($volid =~ m
|^/|) {
5143 unlink $volid || die 'unlink failed\n';
5145 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5147 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5149 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5151 print STDERR
"unable to parse line in statfile - $line";
5158 sub restore_archive
{
5159 my ($archive, $vmid, $user, $opts) = @_;
5161 my $format = $opts->{format
};
5164 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5165 $format = 'tar' if !$format;
5167 } elsif ($archive =~ m/\.tar$/) {
5168 $format = 'tar' if !$format;
5169 } elsif ($archive =~ m/.tar.lzo$/) {
5170 $format = 'tar' if !$format;
5172 } elsif ($archive =~ m/\.vma$/) {
5173 $format = 'vma' if !$format;
5174 } elsif ($archive =~ m/\.vma\.gz$/) {
5175 $format = 'vma' if !$format;
5177 } elsif ($archive =~ m/\.vma\.lzo$/) {
5178 $format = 'vma' if !$format;
5181 $format = 'vma' if !$format; # default
5184 # try to detect archive format
5185 if ($format eq 'tar') {
5186 return restore_tar_archive
($archive, $vmid, $user, $opts);
5188 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5192 sub restore_update_config_line
{
5193 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5195 return if $line =~ m/^\#qmdump\#/;
5196 return if $line =~ m/^\#vzdump\#/;
5197 return if $line =~ m/^lock:/;
5198 return if $line =~ m/^unused\d+:/;
5199 return if $line =~ m/^parent:/;
5200 return if $line =~ m/^template:/; # restored VM is never a template
5202 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5203 # try to convert old 1.X settings
5204 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5205 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5206 my ($model, $macaddr) = split(/\=/, $devconfig);
5207 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5210 bridge
=> "vmbr$ind",
5211 macaddr
=> $macaddr,
5213 my $netstr = print_net
($net);
5215 print $outfd "net$cookie->{netcount}: $netstr\n";
5216 $cookie->{netcount
}++;
5218 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5219 my ($id, $netstr) = ($1, $2);
5220 my $net = parse_net
($netstr);
5221 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5222 $netstr = print_net
($net);
5223 print $outfd "$id: $netstr\n";
5224 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5227 my $di = parse_drive
($virtdev, $value);
5228 if (defined($di->{backup
}) && !$di->{backup
}) {
5229 print $outfd "#$line";
5230 } elsif ($map->{$virtdev}) {
5231 delete $di->{format
}; # format can change on restore
5232 $di->{file
} = $map->{$virtdev};
5233 $value = print_drive
($vmid, $di);
5234 print $outfd "$virtdev: $value\n";
5244 my ($cfg, $vmid) = @_;
5246 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5248 my $volid_hash = {};
5249 foreach my $storeid (keys %$info) {
5250 foreach my $item (@{$info->{$storeid}}) {
5251 next if !($item->{volid
} && $item->{size
});
5252 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5253 $volid_hash->{$item->{volid
}} = $item;
5260 sub is_volume_in_use
{
5261 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5263 my $path = PVE
::Storage
::path
($storecfg, $volid);
5265 my $scan_config = sub {
5266 my ($cref, $snapname) = @_;
5268 foreach my $key (keys %$cref) {
5269 my $value = $cref->{$key};
5270 if (is_valid_drivename
($key)) {
5271 next if $skip_drive && $key eq $skip_drive;
5272 my $drive = parse_drive
($key, $value);
5273 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5274 return 1 if $volid eq $drive->{file
};
5275 if ($drive->{file
} =~ m!^/!) {
5276 return 1 if $drive->{file
} eq $path;
5278 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5280 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5282 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5290 return 1 if &$scan_config($conf);
5294 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5295 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5301 sub update_disksize
{
5302 my ($vmid, $conf, $volid_hash) = @_;
5308 # Note: it is allowed to define multiple storages with same path (alias), so
5309 # we need to check both 'volid' and real 'path' (two different volid can point
5310 # to the same path).
5315 foreach my $opt (keys %$conf) {
5316 if (is_valid_drivename
($opt)) {
5317 my $drive = parse_drive
($opt, $conf->{$opt});
5318 my $volid = $drive->{file
};
5321 $used->{$volid} = 1;
5322 if ($volid_hash->{$volid} &&
5323 (my $path = $volid_hash->{$volid}->{path
})) {
5324 $usedpath->{$path} = 1;
5327 next if drive_is_cdrom
($drive);
5328 next if !$volid_hash->{$volid};
5330 $drive->{size
} = $volid_hash->{$volid}->{size
};
5331 my $new = print_drive
($vmid, $drive);
5332 if ($new ne $conf->{$opt}) {
5334 $conf->{$opt} = $new;
5339 # remove 'unusedX' entry if volume is used
5340 foreach my $opt (keys %$conf) {
5341 next if $opt !~ m/^unused\d+$/;
5342 my $volid = $conf->{$opt};
5343 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5344 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5346 delete $conf->{$opt};
5350 foreach my $volid (sort keys %$volid_hash) {
5351 next if $volid =~ m/vm-$vmid-state-/;
5352 next if $used->{$volid};
5353 my $path = $volid_hash->{$volid}->{path
};
5354 next if !$path; # just to be sure
5355 next if $usedpath->{$path};
5357 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5358 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5365 my ($vmid, $nolock) = @_;
5367 my $cfg = PVE
::Storage
::config
();
5369 my $volid_hash = scan_volids
($cfg, $vmid);
5371 my $updatefn = sub {
5374 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5376 PVE
::QemuConfig-
>check_lock($conf);
5379 foreach my $volid (keys %$volid_hash) {
5380 my $info = $volid_hash->{$volid};
5381 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5384 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5386 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5389 if (defined($vmid)) {
5393 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5396 my $vmlist = config_list
();
5397 foreach my $vmid (keys %$vmlist) {
5401 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5407 sub restore_vma_archive
{
5408 my ($archive, $vmid, $user, $opts, $comp) = @_;
5410 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5411 my $readfrom = $archive;
5416 my $qarchive = PVE
::Tools
::shellquote
($archive);
5417 if ($comp eq 'gzip') {
5418 $uncomp = "zcat $qarchive|";
5419 } elsif ($comp eq 'lzop') {
5420 $uncomp = "lzop -d -c $qarchive|";
5422 die "unknown compression method '$comp'\n";
5427 my $tmpdir = "/var/tmp/vzdumptmp$$";
5430 # disable interrupts (always do cleanups)
5431 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5432 warn "got interrupt - ignored\n";
5435 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5436 POSIX
::mkfifo
($mapfifo, 0600);
5439 my $openfifo = sub {
5440 open($fifofh, '>', $mapfifo) || die $!;
5443 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5450 my $rpcenv = PVE
::RPCEnvironment
::get
();
5452 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5453 my $tmpfn = "$conffile.$$.tmp";
5455 # Note: $oldconf is undef if VM does not exists
5456 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5457 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5459 my $print_devmap = sub {
5460 my $virtdev_hash = {};
5462 my $cfgfn = "$tmpdir/qemu-server.conf";
5464 # we can read the config - that is already extracted
5465 my $fh = IO
::File-
>new($cfgfn, "r") ||
5466 "unable to read qemu-server.conf - $!\n";
5468 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5470 my $pve_firewall_dir = '/etc/pve/firewall';
5471 mkdir $pve_firewall_dir; # make sure the dir exists
5472 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5475 while (defined(my $line = <$fh>)) {
5476 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5477 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5478 die "archive does not contain data for drive '$virtdev'\n"
5479 if !$devinfo->{$devname};
5480 if (defined($opts->{storage
})) {
5481 $storeid = $opts->{storage
} || 'local';
5482 } elsif (!$storeid) {
5485 $format = 'raw' if !$format;
5486 $devinfo->{$devname}->{devname
} = $devname;
5487 $devinfo->{$devname}->{virtdev
} = $virtdev;
5488 $devinfo->{$devname}->{format
} = $format;
5489 $devinfo->{$devname}->{storeid
} = $storeid;
5491 # check permission on storage
5492 my $pool = $opts->{pool
}; # todo: do we need that?
5493 if ($user ne 'root@pam') {
5494 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5497 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5501 foreach my $devname (keys %$devinfo) {
5502 die "found no device mapping information for device '$devname'\n"
5503 if !$devinfo->{$devname}->{virtdev
};
5506 my $cfg = PVE
::Storage
::config
();
5508 # create empty/temp config
5510 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5511 foreach_drive
($oldconf, sub {
5512 my ($ds, $drive) = @_;
5514 return if drive_is_cdrom
($drive);
5516 my $volid = $drive->{file
};
5518 return if !$volid || $volid =~ m
|^/|;
5520 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5521 return if !$path || !$owner || ($owner != $vmid);
5523 # Note: only delete disk we want to restore
5524 # other volumes will become unused
5525 if ($virtdev_hash->{$ds}) {
5526 PVE
::Storage
::vdisk_free
($cfg, $volid);
5530 # delete vmstate files
5531 # since after the restore we have no snapshots anymore
5532 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5533 my $snap = $oldconf->{snapshots
}->{$snapname};
5534 if ($snap->{vmstate
}) {
5535 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5544 foreach my $virtdev (sort keys %$virtdev_hash) {
5545 my $d = $virtdev_hash->{$virtdev};
5546 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5547 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5549 # test if requested format is supported
5550 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5551 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5552 $d->{format
} = $defFormat if !$supported;
5554 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5555 $d->{format
}, undef, $alloc_size);
5556 print STDERR
"new volume ID is '$volid'\n";
5557 $d->{volid
} = $volid;
5558 my $path = PVE
::Storage
::path
($cfg, $volid);
5560 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5562 my $write_zeros = 1;
5563 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5567 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5569 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5570 $map->{$virtdev} = $volid;
5573 $fh->seek(0, 0) || die "seek failed - $!\n";
5575 my $outfd = new IO
::File
($tmpfn, "w") ||
5576 die "unable to write config for VM $vmid\n";
5578 my $cookie = { netcount
=> 0 };
5579 while (defined(my $line = <$fh>)) {
5580 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5589 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5590 die "interrupted by signal\n";
5592 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5594 $oldtimeout = alarm($timeout);
5601 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5602 my ($dev_id, $size, $devname) = ($1, $2, $3);
5603 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5604 } elsif ($line =~ m/^CTIME: /) {
5605 # we correctly received the vma config, so we can disable
5606 # the timeout now for disk allocation (set to 10 minutes, so
5607 # that we always timeout if something goes wrong)
5610 print $fifofh "done\n";
5611 my $tmp = $oldtimeout || 0;
5612 $oldtimeout = undef;
5618 print "restore vma archive: $cmd\n";
5619 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5623 alarm($oldtimeout) if $oldtimeout;
5626 foreach my $devname (keys %$devinfo) {
5627 my $volid = $devinfo->{$devname}->{volid
};
5628 push @$vollist, $volid if $volid;
5631 my $cfg = PVE
::Storage
::config
();
5632 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5640 foreach my $devname (keys %$devinfo) {
5641 my $volid = $devinfo->{$devname}->{volid
};
5644 if ($volid =~ m
|^/|) {
5645 unlink $volid || die 'unlink failed\n';
5647 PVE
::Storage
::vdisk_free
($cfg, $volid);
5649 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5651 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5658 rename($tmpfn, $conffile) ||
5659 die "unable to commit configuration file '$conffile'\n";
5661 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5663 eval { rescan
($vmid, 1); };
5667 sub restore_tar_archive
{
5668 my ($archive, $vmid, $user, $opts) = @_;
5670 if ($archive ne '-') {
5671 my $firstfile = tar_archive_read_firstfile
($archive);
5672 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5673 if $firstfile ne 'qemu-server.conf';
5676 my $storecfg = PVE
::Storage
::config
();
5678 # destroy existing data - keep empty config
5679 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5680 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5682 my $tocmd = "/usr/lib/qemu-server/qmextract";
5684 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5685 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5686 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5687 $tocmd .= ' --info' if $opts->{info
};
5689 # tar option "xf" does not autodetect compression when read from STDIN,
5690 # so we pipe to zcat
5691 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5692 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5694 my $tmpdir = "/var/tmp/vzdumptmp$$";
5697 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5698 local $ENV{VZDUMP_VMID
} = $vmid;
5699 local $ENV{VZDUMP_USER
} = $user;
5701 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5702 my $tmpfn = "$conffile.$$.tmp";
5704 # disable interrupts (always do cleanups)
5705 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5706 print STDERR
"got interrupt - ignored\n";
5711 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5712 die "interrupted by signal\n";
5715 if ($archive eq '-') {
5716 print "extracting archive from STDIN\n";
5717 run_command
($cmd, input
=> "<&STDIN");
5719 print "extracting archive '$archive'\n";
5723 return if $opts->{info
};
5727 my $statfile = "$tmpdir/qmrestore.stat";
5728 if (my $fd = IO
::File-
>new($statfile, "r")) {
5729 while (defined (my $line = <$fd>)) {
5730 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5731 $map->{$1} = $2 if $1;
5733 print STDERR
"unable to parse line in statfile - $line\n";
5739 my $confsrc = "$tmpdir/qemu-server.conf";
5741 my $srcfd = new IO
::File
($confsrc, "r") ||
5742 die "unable to open file '$confsrc'\n";
5744 my $outfd = new IO
::File
($tmpfn, "w") ||
5745 die "unable to write config for VM $vmid\n";
5747 my $cookie = { netcount
=> 0 };
5748 while (defined (my $line = <$srcfd>)) {
5749 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5761 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5768 rename $tmpfn, $conffile ||
5769 die "unable to commit configuration file '$conffile'\n";
5771 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5773 eval { rescan
($vmid, 1); };
5777 sub foreach_writable_storage
{
5778 my ($conf, $func) = @_;
5782 foreach my $ds (keys %$conf) {
5783 next if !is_valid_drivename
($ds);
5785 my $drive = parse_drive
($ds, $conf->{$ds});
5787 next if drive_is_cdrom
($drive);
5789 my $volid = $drive->{file
};
5791 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5792 $sidhash->{$sid} = $sid if $sid;
5795 foreach my $sid (sort keys %$sidhash) {
5800 sub do_snapshots_with_qemu
{
5801 my ($storecfg, $volid) = @_;
5803 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5805 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5806 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5810 if ($volid =~ m/\.(qcow2|qed)$/){
5817 sub qga_check_running
{
5820 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5822 warn "Qemu Guest Agent are not running - $@";
5828 sub template_create
{
5829 my ($vmid, $conf, $disk) = @_;
5831 my $storecfg = PVE
::Storage
::config
();
5833 foreach_drive
($conf, sub {
5834 my ($ds, $drive) = @_;
5836 return if drive_is_cdrom
($drive);
5837 return if $disk && $ds ne $disk;
5839 my $volid = $drive->{file
};
5840 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5842 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5843 $drive->{file
} = $voliddst;
5844 $conf->{$ds} = print_drive
($vmid, $drive);
5845 PVE
::QemuConfig-
>write_config($vmid, $conf);
5849 sub qemu_img_convert
{
5850 my ($src_volid, $dst_volid, $size, $snapname, $is_zero_initialized) = @_;
5852 my $storecfg = PVE
::Storage
::config
();
5853 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5854 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5856 if ($src_storeid && $dst_storeid) {
5858 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5860 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5861 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5863 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5864 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5866 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5867 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5870 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5871 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5872 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path;
5873 if ($is_zero_initialized) {
5874 push @$cmd, "zeroinit:$dst_path";
5876 push @$cmd, $dst_path;
5881 if($line =~ m/\((\S+)\/100\
%\)/){
5883 my $transferred = int($size * $percent / 100);
5884 my $remaining = $size - $transferred;
5886 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5891 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5893 die "copy failed: $err" if $err;
5897 sub qemu_img_format
{
5898 my ($scfg, $volname) = @_;
5900 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5907 sub qemu_drive_mirror
{
5908 my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized) = @_;
5910 my $storecfg = PVE
::Storage
::config
();
5911 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5913 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5915 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5917 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5919 my $qemu_target = $is_zero_initialized ?
"zeroinit:$dst_path" : $dst_path;
5921 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $qemu_target };
5922 $opts->{format
} = $format if $format;
5924 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5927 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5929 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5930 my $stat = @$stats[0];
5931 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5932 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5934 my $busy = $stat->{busy
};
5935 my $ready = $stat->{ready
};
5937 if (my $total = $stat->{len
}) {
5938 my $transferred = $stat->{offset
} || 0;
5939 my $remaining = $total - $transferred;
5940 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5942 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5946 if ($stat->{ready
} eq 'true') {
5948 last if $vmiddst != $vmid;
5950 # try to switch the disk if source and destination are on the same guest
5951 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5953 die $@ if $@ !~ m/cannot be completed/;
5962 my $cancel_job = sub {
5963 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5965 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5966 my $stat = @$stats[0];
5973 eval { &$cancel_job(); };
5974 die "mirroring error: $err";
5977 if ($vmiddst != $vmid) {
5978 # if we clone a disk for a new target vm, we don't switch the disk
5979 &$cancel_job(); # so we call block-job-cancel
5984 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5985 $newvmid, $storage, $format, $full, $newvollist) = @_;
5990 print "create linked clone of drive $drivename ($drive->{file})\n";
5991 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5992 push @$newvollist, $newvolid;
5994 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5995 $storeid = $storage if $storage;
5997 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5999 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6000 $format = qemu_img_format
($scfg, $volname);
6003 # test if requested format is supported - else use default
6004 my $supported = grep { $_ eq $format } @$validFormats;
6005 $format = $defFormat if !$supported;
6007 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6009 print "create full clone of drive $drivename ($drive->{file})\n";
6010 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6011 push @$newvollist, $newvolid;
6013 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6015 my $sparseinit = PVE
::Storage
::volume_has_feature
($storecfg, 'sparseinit', $newvolid);
6016 if (!$running || $snapname) {
6017 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname, $sparseinit);
6019 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid, $sparseinit);
6023 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6026 $disk->{format
} = undef;
6027 $disk->{file
} = $newvolid;
6028 $disk->{size
} = $size;
6033 # this only works if VM is running
6034 sub get_current_qemu_machine
{
6037 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6038 my $res = vm_qmp_command
($vmid, $cmd);
6040 my ($current, $default);
6041 foreach my $e (@$res) {
6042 $default = $e->{name
} if $e->{'is-default'};
6043 $current = $e->{name
} if $e->{'is-current'};
6046 # fallback to the default machine if current is not supported by qemu
6047 return $current || $default || 'pc';
6050 sub qemu_machine_feature_enabled
{
6051 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6056 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6058 $current_major = $3;
6059 $current_minor = $4;
6061 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6063 $current_major = $1;
6064 $current_minor = $2;
6067 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6072 sub qemu_machine_pxe
{
6073 my ($vmid, $conf, $machine) = @_;
6075 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6077 foreach my $opt (keys %$conf) {
6078 next if $opt !~ m/^net(\d+)$/;
6079 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6081 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6082 return $machine.".pxe" if $romfile =~ m/pxe/;
6089 sub qemu_use_old_bios_files
{
6090 my ($machine_type) = @_;
6092 return if !$machine_type;
6094 my $use_old_bios_files = undef;
6096 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6098 $use_old_bios_files = 1;
6100 my $kvmver = kvm_user_version
();
6101 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6102 # load new efi bios files on migration. So this hack is required to allow
6103 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6104 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6105 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6108 return ($use_old_bios_files, $machine_type);
6115 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6116 my (undef, $id, $function) = @_;
6117 my $res = { id
=> $id, function
=> $function};
6118 push @{$devices->{$id}}, $res;
6124 sub vm_iothreads_list
{
6127 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6130 foreach my $iothread (@$res) {
6131 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6138 my ($conf, $drive) = @_;
6142 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6144 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6150 my $controller = int($drive->{index} / $maxdev);
6151 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6153 return ($maxdev, $controller, $controller_prefix);
6156 # bash completion helper
6158 sub complete_backup_archives
{
6159 my ($cmdname, $pname, $cvalue) = @_;
6161 my $cfg = PVE
::Storage
::config
();
6165 if ($cvalue =~ m/^([^:]+):/) {
6169 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6172 foreach my $id (keys %$data) {
6173 foreach my $item (@{$data->{$id}}) {
6174 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6175 push @$res, $item->{volid
} if defined($item->{volid
});
6182 my $complete_vmid_full = sub {
6185 my $idlist = vmstatus
();
6189 foreach my $id (keys %$idlist) {
6190 my $d = $idlist->{$id};
6191 if (defined($running)) {
6192 next if $d->{template
};
6193 next if $running && $d->{status
} ne 'running';
6194 next if !$running && $d->{status
} eq 'running';
6203 return &$complete_vmid_full();
6206 sub complete_vmid_stopped
{
6207 return &$complete_vmid_full(0);
6210 sub complete_vmid_running
{
6211 return &$complete_vmid_full(1);
6214 sub complete_storage
{
6216 my $cfg = PVE
::Storage
::config
();
6217 my $ids = $cfg->{ids
};
6220 foreach my $sid (keys %$ids) {
6221 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6222 next if !$ids->{$sid}->{content
}->{images
};