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);
36 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
38 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
40 # Note about locking: we use flock on the config file protect
41 # against concurent actions.
42 # Aditionaly, we have a 'lock' setting in the config file. This
43 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
44 # allowed when such lock is set. But you can ignore this kind of
45 # lock with the --skiplock flag.
47 cfs_register_file
('/qemu-server/',
51 PVE
::JSONSchema
::register_standard_option
('skiplock', {
52 description
=> "Ignore locks - only root is allowed to use this option.",
57 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
58 description
=> "Some command save/restore state from this location.",
64 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
65 description
=> "The name of the snapshot.",
66 type
=> 'string', format
=> 'pve-configid',
70 #no warnings 'redefine';
73 my ($controller, $vmid, $option, $value) = @_;
75 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
76 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
80 my $nodename = PVE
::INotify
::nodename
();
82 mkdir "/etc/pve/nodes/$nodename";
83 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
86 my $var_run_tmpdir = "/var/run/qemu-server";
87 mkdir $var_run_tmpdir;
89 my $lock_dir = "/var/lock/qemu-server";
92 my $pcisysfs = "/sys/bus/pci";
96 description
=> "Emulated CPU type.",
98 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) ],
103 description
=> "Do not identify as a KVM virtual machine.",
114 description
=> "Specifies whether a VM will be started during system bootup.",
120 description
=> "Automatic restart after crash (currently ignored).",
125 type
=> 'string', format
=> 'pve-hotplug-features',
126 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'.",
127 default => 'network,disk,usb',
132 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
138 description
=> "Lock/unlock the VM.",
139 enum
=> [qw(migrate backup snapshot rollback)],
144 description
=> "Limit of CPU usage. Note if the computer has 2 CPUs, it has total of '2' CPU time. Value '0' indicates no CPU limit.",
152 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.",
160 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
167 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
173 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",
181 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
182 enum
=> PVE
::Tools
::kvmkeymaplist
(),
187 type
=> 'string', format
=> 'dns-name',
188 description
=> "Set a name for the VM. Only used on the configuration web interface.",
193 description
=> "scsi controller model",
194 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
200 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
205 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
206 description
=> <<EODESC,
207 Used to enable special optimization/features for specific
210 other => unspecified OS
211 wxp => Microsoft Windows XP
212 w2k => Microsoft Windows 2000
213 w2k3 => Microsoft Windows 2003
214 w2k8 => Microsoft Windows 2008
215 wvista => Microsoft Windows Vista
216 win7 => Microsoft Windows 7
217 win8 => Microsoft Windows 8/2012
218 l24 => Linux 2.4 Kernel
219 l26 => Linux 2.6/3.X Kernel
220 solaris => solaris/opensolaris/openindiania kernel
222 other|l24|l26|solaris ... no special behaviour
223 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
229 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
230 pattern
=> '[acdn]{1,4}',
235 type
=> 'string', format
=> 'pve-qm-bootdisk',
236 description
=> "Enable booting from specified disk.",
237 pattern
=> '(ide|sata|scsi|virtio)\d+',
242 description
=> "The number of CPUs. Please use option -sockets instead.",
249 description
=> "The number of CPU sockets.",
256 description
=> "The number of cores per socket.",
263 description
=> "Enable/disable Numa.",
269 description
=> "Number of hotplugged vcpus.",
276 description
=> "Enable/disable ACPI.",
282 description
=> "Enable/disable Qemu GuestAgent.",
288 description
=> "Enable/disable KVM hardware virtualization.",
294 description
=> "Enable/disable time drift fix.",
300 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
305 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
310 description
=> "Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and 'cirrur' for other OS types. Option 'qxl' enables the SPICE display sever. You can also run without any graphic card using a serial devive as terminal.",
311 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
315 type
=> 'string', format
=> 'pve-qm-watchdog',
316 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
317 description
=> "Create a virtual hardware watchdog device. Once enabled (by a guest action), the watchdog must be periodically polled by an agent inside the guest or else the guest will be restarted (or execute the action specified)",
322 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
323 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'.",
324 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
327 startup
=> get_standard_option
('pve-startup-order'),
331 description
=> "Enable/disable Template.",
337 description
=> <<EODESCR,
338 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
340 args: -no-reboot -no-hpet
347 description
=> "Enable/disable the usb tablet device. This device is usually needed to allow absolute mouse positioning with VNC. Else the mouse runs out of sync with normal VNC clients. If you're running lots of console-only guests on one host, you may consider disabling this to save some context switches. This is turned of by default if you use spice (vga=qxl).",
352 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
356 migrate_downtime
=> {
359 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
365 type
=> 'string', format
=> 'pve-qm-drive',
366 typetext
=> 'volume',
367 description
=> "This is an alias for option -ide2",
371 description
=> "Emulated CPU type.",
375 parent
=> get_standard_option
('pve-snapshot-name', {
377 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
381 description
=> "Timestamp for snapshots.",
387 type
=> 'string', format
=> 'pve-volume-id',
388 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
391 description
=> "Specific the Qemu machine type.",
393 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
398 description
=> "Specify SMBIOS type 1 fields.",
399 type
=> 'string', format
=> 'pve-qm-smbios1',
406 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
412 enum
=> [ qw(seabios ovmf) ],
413 description
=> "Select BIOS implementation.",
414 default => 'seabios',
418 # what about other qemu settings ?
420 #machine => 'string',
433 ##soundhw => 'string',
435 while (my ($k, $v) = each %$confdesc) {
436 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
439 my $MAX_IDE_DISKS = 4;
440 my $MAX_SCSI_DISKS = 14;
441 my $MAX_VIRTIO_DISKS = 16;
442 my $MAX_SATA_DISKS = 6;
443 my $MAX_USB_DEVICES = 5;
445 my $MAX_UNUSED_DISKS = 8;
446 my $MAX_HOSTPCI_DEVICES = 4;
447 my $MAX_SERIAL_PORTS = 4;
448 my $MAX_PARALLEL_PORTS = 3;
450 my $MAX_MEM = 4194304;
451 my $STATICMEM = 1024;
455 type
=> 'string', format
=> 'pve-qm-numanode',
456 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
457 description
=> "numa topology",
459 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
461 for (my $i = 0; $i < $MAX_NUMA; $i++) {
462 $confdesc->{"numa$i"} = $numadesc;
465 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
466 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
467 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
468 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
472 type
=> 'string', format
=> 'pve-qm-net',
473 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,trunks=<vlanid[;vlanid]>][,firewall=0|1],link_down=0|1]",
474 description
=> <<EODESCR,
475 Specify network devices.
477 MODEL is one of: $nic_model_list_txt
479 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
480 automatically generated if not specified.
482 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
484 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'.
486 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
492 The DHCP server assign addresses to the guest starting from 10.0.2.15.
496 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
498 for (my $i = 0; $i < $MAX_NETS; $i++) {
499 $confdesc->{"net$i"} = $netdesc;
504 my %drivedesc_base = (
505 volume
=> { alias
=> 'file' },
507 type
=> 'pve-volume-id',
509 format_description
=> 'volume',
510 description
=> "The drive's backing volume.",
514 format_description
=> 'cdrom|disk',
515 enum
=> [qw(cdrom disk)],
516 description
=> "The drive's media type.",
522 format_description
=> 'count',
523 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
528 format_description
=> 'count',
529 description
=> "Force the drive's physical geometry to have a specific head count.",
534 format_description
=> 'count',
535 description
=> "Force the drive's physical geometry to have a specific sector count.",
540 format_description
=> 'none|lba|auto',
541 enum
=> [qw(none lba auto)],
542 description
=> "Force disk geometry bios translation mode.",
547 format_description
=> 'on|off',
548 description
=> "Whether the drive should be included when making snapshots.",
553 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
554 enum
=> [qw(none writethrough writeback unsafe directsync)],
555 description
=> "The drive's cache mode",
560 format_description
=> 'drive format',
561 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
562 description
=> "The drive's backing file's data format.",
567 format
=> 'disk-size',
568 description
=> "Disk size. This is purely informational and has no effect.",
573 format_description
=> 'on|off',
574 description
=> "Whether the drive should be included when making backups.",
579 format_description
=> 'enospc|ignore|report|stop',
580 enum
=> [qw(enospc ignore report stop)],
581 description
=> 'Write error action.',
586 format_description
=> 'native|threads',
587 enum
=> [qw(native threads)],
588 description
=> 'AIO type to use.',
593 format_description
=> 'ignore|on',
594 enum
=> [qw(ignore on)],
595 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
600 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
605 format_description
=> 'serial',
606 description
=> "The drive's reported serial number.",
614 format_description
=> 'ignore|report|stop',
615 enum
=> [qw(ignore report stop)],
616 description
=> 'Read error action.',
621 my %iothread_fmt = ( iothread
=> {
623 format_description
=> 'off|on',
624 description
=> "Whether to use iothreads for this drive",
631 format_description
=> 'model',
632 description
=> "The drive's reported model name.",
640 format_description
=> 'nbqueues',
641 description
=> "Number of queues.",
647 my $add_throttle_desc = sub {
648 my ($key, $type, $what, $size, $longsize) = @_;
649 $drivedesc_base{$key} = {
651 format_description
=> $size,
652 description
=> "Maximum $what speed in $longsize per second.",
656 # throughput: (leaky bucket)
657 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
658 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
659 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
660 $add_throttle_desc->('mbps', 'float', 'r/w speed', 'mbps', 'megabytes');
661 $add_throttle_desc->('mbps_rd', 'float', 'read speed', 'mbps', 'megabytes');
662 $add_throttle_desc->('mbps_wr', 'float', 'write speed', 'mbps', 'megabytes');
663 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
664 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
665 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
667 # pools: (pool of IO before throttling starts taking effect)
668 $add_throttle_desc->('mbps_max', 'float', 'unthrottled r/w pool', 'mbps', 'megabytes');
669 $add_throttle_desc->('mbps_rd_max', 'float', 'unthrottled read pool', 'mbps', 'megabytes');
670 $add_throttle_desc->('mbps_wr_max', 'float', 'unthrottled write pool', 'mbps', 'megabytes');
671 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
672 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
673 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
683 type
=> 'string', format
=> $ide_fmt,
684 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
686 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
695 type
=> 'string', format
=> $scsi_fmt,
696 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
698 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
706 type
=> 'string', format
=> $sata_fmt,
707 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
709 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
718 type
=> 'string', format
=> $virtio_fmt,
719 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
721 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
734 type
=> 'string', format
=> 'pve-qm-usb-device',
735 format_description
=> 'HOSTUSBDEVICE|spice',
736 description
=> 'The Host USB device or port or the value spice',
741 format_description
=> 'yes|no',
742 description
=> 'Specifies whether if given host option is a USB3 device or port',
748 type
=> 'string', format
=> $usbformat,
749 description
=> <<EODESCR,
750 Configure an USB device (n is 0 to 4). This can be used to
751 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
753 'bus-port(.port)*' (decimal numbers) or
754 'vendor_id:product_id' (hexadeciaml numbers) or
757 You can use the 'lsusb -t' command to list existing usb devices.
759 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
761 The value 'spice' can be used to add a usb redirection devices for spice.
763 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).
767 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
771 type
=> 'string', format
=> 'pve-qm-hostpci',
772 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
773 description
=> <<EODESCR,
774 Map host pci devices. HOSTPCIDEVICE syntax is:
776 'bus:dev.func' (hexadecimal numbers)
778 You can us the 'lspci' command to list existing pci devices.
780 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
782 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
784 Experimental: user reported problems with this option.
787 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
792 pattern
=> '(/dev/.+|socket)',
793 description
=> <<EODESCR,
794 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).
796 Note: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
798 Experimental: user reported problems with this option.
805 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
806 description
=> <<EODESCR,
807 Map host parallel devices (n is 0 to 2).
809 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
811 Experimental: user reported problems with this option.
815 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
816 $confdesc->{"parallel$i"} = $paralleldesc;
819 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
820 $confdesc->{"serial$i"} = $serialdesc;
823 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
824 $confdesc->{"hostpci$i"} = $hostpcidesc;
827 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
828 $drivename_hash->{"ide$i"} = 1;
829 $confdesc->{"ide$i"} = $idedesc;
832 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
833 $drivename_hash->{"sata$i"} = 1;
834 $confdesc->{"sata$i"} = $satadesc;
837 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
838 $drivename_hash->{"scsi$i"} = 1;
839 $confdesc->{"scsi$i"} = $scsidesc ;
842 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
843 $drivename_hash->{"virtio$i"} = 1;
844 $confdesc->{"virtio$i"} = $virtiodesc;
847 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
848 $confdesc->{"usb$i"} = $usbdesc;
853 type
=> 'string', format
=> 'pve-volume-id',
854 description
=> "Reference to unused volumes.",
857 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
858 $confdesc->{"unused$i"} = $unuseddesc;
861 my $kvm_api_version = 0;
865 return $kvm_api_version if $kvm_api_version;
867 my $fh = IO
::File-
>new("</dev/kvm") ||
870 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
871 $kvm_api_version = $v;
876 return $kvm_api_version;
879 my $kvm_user_version;
881 sub kvm_user_version
{
883 return $kvm_user_version if $kvm_user_version;
885 $kvm_user_version = 'unknown';
889 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
890 $kvm_user_version = $2;
894 eval { run_command
("kvm -version", outfunc
=> $code); };
897 return $kvm_user_version;
901 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
903 sub valid_drive_names
{
904 # order is important - used to autoselect boot disk
905 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
906 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
907 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
908 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
911 sub is_valid_drivename
{
914 return defined($drivename_hash->{$dev});
919 return defined($confdesc->{$key});
923 return $nic_model_list;
926 sub os_list_description
{
931 w2k
=> 'Windows 2000',
932 w2k3
=>, 'Windows 2003',
933 w2k8
=> 'Windows 2008',
934 wvista
=> 'Windows Vista',
936 win8
=> 'Windows 8/2012',
946 return $cdrom_path if $cdrom_path;
948 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
949 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
950 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
954 my ($storecfg, $vmid, $cdrom) = @_;
956 if ($cdrom eq 'cdrom') {
957 return get_cdrom_path
();
958 } elsif ($cdrom eq 'none') {
960 } elsif ($cdrom =~ m
|^/|) {
963 return PVE
::Storage
::path
($storecfg, $cdrom);
967 # try to convert old style file names to volume IDs
968 sub filename_to_volume_id
{
969 my ($vmid, $file, $media) = @_;
971 if (!($file eq 'none' || $file eq 'cdrom' ||
972 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
974 return undef if $file =~ m
|/|;
976 if ($media && $media eq 'cdrom') {
977 $file = "local:iso/$file";
979 $file = "local:$vmid/$file";
986 sub verify_media_type
{
987 my ($opt, $vtype, $media) = @_;
992 if ($media eq 'disk') {
994 } elsif ($media eq 'cdrom') {
997 die "internal error";
1000 return if ($vtype eq $etype);
1002 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1005 sub cleanup_drive_path
{
1006 my ($opt, $storecfg, $drive) = @_;
1008 # try to convert filesystem paths to volume IDs
1010 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1011 ($drive->{file
} !~ m
|^/dev/.+|) &&
1012 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1013 ($drive->{file
} !~ m/^\d+$/)) {
1014 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1015 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1016 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1017 verify_media_type
($opt, $vtype, $drive->{media
});
1018 $drive->{file
} = $volid;
1021 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1024 sub parse_hotplug_features
{
1029 return $res if $data eq '0';
1031 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1033 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1034 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1037 warn "ignoring unknown hotplug feature '$feature'\n";
1043 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1044 sub pve_verify_hotplug_features
{
1045 my ($value, $noerr) = @_;
1047 return $value if parse_hotplug_features
($value);
1049 return undef if $noerr;
1051 die "unable to parse hotplug option\n";
1054 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1055 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1056 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1057 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1058 # [,iothread=on][,serial=serial][,model=model]
1061 my ($key, $data) = @_;
1063 my ($interface, $index);
1065 if ($key =~ m/^([^\d]+)(\d+)$/) {
1072 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1073 : $confdesc->{$key}->{format
};
1075 warn "invalid drive key: $key\n";
1078 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1079 return undef if !$res;
1080 $res->{interface
} = $interface;
1081 $res->{index} = $index;
1084 foreach my $opt (qw(bps bps_rd bps_wr)) {
1085 if (my $bps = defined(delete $res->{$opt})) {
1086 if (defined($res->{"m$opt"})) {
1087 warn "both $opt and m$opt specified\n";
1091 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1094 return undef if $error;
1096 return undef if $res->{mbps_rd
} && $res->{mbps
};
1097 return undef if $res->{mbps_wr
} && $res->{mbps
};
1098 return undef if $res->{iops_rd
} && $res->{iops
};
1099 return undef if $res->{iops_wr
} && $res->{iops
};
1101 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1102 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1103 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1104 return undef if $res->{interface
} eq 'virtio';
1107 if (my $size = $res->{size
}) {
1108 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1115 my ($vmid, $drive) = @_;
1116 my $data = { %$drive };
1117 delete $data->{$_} for qw(index interface);
1118 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1122 my($fh, $noerr) = @_;
1125 my $SG_GET_VERSION_NUM = 0x2282;
1127 my $versionbuf = "\x00" x
8;
1128 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1130 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1133 my $version = unpack("I", $versionbuf);
1134 if ($version < 30000) {
1135 die "scsi generic interface too old\n" if !$noerr;
1139 my $buf = "\x00" x
36;
1140 my $sensebuf = "\x00" x
8;
1141 my $cmd = pack("C x3 C x1", 0x12, 36);
1143 # see /usr/include/scsi/sg.h
1144 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";
1146 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1147 length($sensebuf), 0, length($buf), $buf,
1148 $cmd, $sensebuf, 6000);
1150 $ret = ioctl($fh, $SG_IO, $packet);
1152 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1156 my @res = unpack($sg_io_hdr_t, $packet);
1157 if ($res[17] || $res[18]) {
1158 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1163 (my $byte0, my $byte1, $res->{vendor
},
1164 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1166 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1167 $res->{type
} = $byte0 & 31;
1175 my $fh = IO
::File-
>new("+<$path") || return undef;
1176 my $res = scsi_inquiry
($fh, 1);
1182 sub machine_type_is_q35
{
1185 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1188 sub print_tabletdevice_full
{
1191 my $q35 = machine_type_is_q35
($conf);
1193 # we use uhci for old VMs because tablet driver was buggy in older qemu
1194 my $usbbus = $q35 ?
"ehci" : "uhci";
1196 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1199 sub print_drivedevice_full
{
1200 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1205 if ($drive->{interface
} eq 'virtio') {
1206 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1207 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1208 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1209 } elsif ($drive->{interface
} eq 'scsi') {
1211 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1212 my $unit = $drive->{index} % $maxdev;
1213 my $devicetype = 'hd';
1215 if (drive_is_cdrom
($drive)) {
1218 if ($drive->{file
} =~ m
|^/|) {
1219 $path = $drive->{file
};
1220 if (my $info = path_is_scsi
($path)) {
1221 if ($info->{type
} == 0) {
1222 $devicetype = 'block';
1223 } elsif ($info->{type
} == 1) { # tape
1224 $devicetype = 'generic';
1228 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1231 if($path =~ m/^iscsi\:\/\
//){
1232 $devicetype = 'generic';
1236 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1237 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1239 $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}";
1242 } elsif ($drive->{interface
} eq 'ide'){
1244 my $controller = int($drive->{index} / $maxdev);
1245 my $unit = $drive->{index} % $maxdev;
1246 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1248 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1249 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1250 $device .= ",model=$model";
1252 } elsif ($drive->{interface
} eq 'sata'){
1253 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1254 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1255 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1256 } elsif ($drive->{interface
} eq 'usb') {
1258 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1260 die "unsupported interface type";
1263 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1268 sub get_initiator_name
{
1271 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1272 while (defined(my $line = <$fh>)) {
1273 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1282 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 serial);
1283 sub print_drive_full
{
1284 my ($storecfg, $vmid, $drive) = @_;
1287 my $volid = $drive->{file
};
1290 if (drive_is_cdrom
($drive)) {
1291 $path = get_iso_path
($storecfg, $vmid, $volid);
1293 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1295 $path = PVE
::Storage
::path
($storecfg, $volid);
1296 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1297 $format = qemu_img_format
($scfg, $volname);
1305 foreach my $o (@qemu_drive_options) {
1306 next if $o eq 'bootindex';
1307 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1310 $opts .= ",format=$format" if $format && !$drive->{format
};
1312 foreach my $o (qw(bps bps_rd bps_wr)) {
1313 my $v = $drive->{"m$o"};
1314 $opts .= ",$o=" . int($v*1024*1024) if $v;
1317 my $cache_direct = 0;
1319 if (my $cache = $drive->{cache
}) {
1320 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1321 } elsif (!drive_is_cdrom
($drive)) {
1322 $opts .= ",cache=none";
1326 # aio native works only with O_DIRECT
1327 if (!$drive->{aio
}) {
1329 $opts .= ",aio=native";
1331 $opts .= ",aio=threads";
1335 if (!drive_is_cdrom
($drive)) {
1337 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1338 $detectzeroes = 'off';
1339 } elsif ($drive->{discard
}) {
1340 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1342 # This used to be our default with discard not being specified:
1343 $detectzeroes = 'on';
1345 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1348 my $pathinfo = $path ?
"file=$path," : '';
1350 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1353 sub print_netdevice_full
{
1354 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1356 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1358 my $device = $net->{model
};
1359 if ($net->{model
} eq 'virtio') {
1360 $device = 'virtio-net-pci';
1363 my $pciaddr = print_pci_addr
("$netid", $bridges);
1364 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1365 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1366 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1367 my $vectors = $net->{queues
} * 2 + 2;
1368 $tmpstr .= ",vectors=$vectors,mq=on";
1370 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1372 if ($use_old_bios_files) {
1374 if ($device eq 'virtio-net-pci') {
1375 $romfile = 'pxe-virtio.rom';
1376 } elsif ($device eq 'e1000') {
1377 $romfile = 'pxe-e1000.rom';
1378 } elsif ($device eq 'ne2k') {
1379 $romfile = 'pxe-ne2k_pci.rom';
1380 } elsif ($device eq 'pcnet') {
1381 $romfile = 'pxe-pcnet.rom';
1382 } elsif ($device eq 'rtl8139') {
1383 $romfile = 'pxe-rtl8139.rom';
1385 $tmpstr .= ",romfile=$romfile" if $romfile;
1391 sub print_netdev_full
{
1392 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1395 if ($netid =~ m/^net(\d+)$/) {
1399 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1401 my $ifname = "tap${vmid}i$i";
1403 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1404 die "interface name '$ifname' is too long (max 15 character)\n"
1405 if length($ifname) >= 16;
1407 my $vhostparam = '';
1408 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1410 my $vmname = $conf->{name
} || "vm$vmid";
1413 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1415 if ($net->{bridge
}) {
1416 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1418 $netdev = "type=user,id=$netid,hostname=$vmname";
1421 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1426 sub drive_is_cdrom
{
1429 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1438 foreach my $kvp (split(/,/, $data)) {
1440 if ($kvp =~ m/^memory=(\S+)$/) {
1441 $res->{memory
} = $1;
1442 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1443 $res->{policy
} = $1;
1444 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1445 $res->{cpus
}->{start
} = $1;
1446 $res->{cpus
}->{end
} = $3;
1447 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1448 $res->{hostnodes
}->{start
} = $1;
1449 $res->{hostnodes
}->{end
} = $3;
1461 return undef if !$value;
1464 my @list = split(/,/, $value);
1468 foreach my $kv (@list) {
1470 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1473 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1476 my $pcidevices = lspci
($2);
1477 $res->{pciid
} = $pcidevices->{$2};
1479 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1480 $res->{rombar
} = $1;
1481 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1482 $res->{'x-vga'} = $1;
1483 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1484 $res->{pcie
} = 1 if $1 == 1;
1486 warn "unknown hostpci setting '$kv'\n";
1490 return undef if !$found;
1495 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1501 foreach my $kvp (split(/,/, $data)) {
1503 if ($kvp =~ m/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er|vmxnet3)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i) {
1505 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1506 $res->{model
} = $model;
1507 $res->{macaddr
} = $mac;
1508 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1509 $res->{bridge
} = $1;
1510 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1511 $res->{queues
} = $1;
1512 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1514 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1516 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1517 $res->{trunks
} = $1;
1518 } elsif ($kvp =~ m/^firewall=([01])$/) {
1519 $res->{firewall
} = $1;
1520 } elsif ($kvp =~ m/^link_down=([01])$/) {
1521 $res->{link_down
} = $1;
1528 return undef if !$res->{model
};
1536 my $res = "$net->{model}";
1537 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1538 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1539 $res .= ",rate=$net->{rate}" if $net->{rate
};
1540 $res .= ",tag=$net->{tag}" if $net->{tag
};
1541 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1542 $res .= ",firewall=1" if $net->{firewall
};
1543 $res .= ",link_down=1" if $net->{link_down
};
1544 $res .= ",queues=$net->{queues}" if $net->{queues
};
1549 sub add_random_macs
{
1550 my ($settings) = @_;
1552 foreach my $opt (keys %$settings) {
1553 next if $opt !~ m/^net(\d+)$/;
1554 my $net = parse_net
($settings->{$opt});
1556 $settings->{$opt} = print_net
($net);
1560 sub vm_is_volid_owner
{
1561 my ($storecfg, $vmid, $volid) = @_;
1563 if ($volid !~ m
|^/|) {
1565 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1566 if ($owner && ($owner == $vmid)) {
1574 sub split_flagged_list
{
1575 my $text = shift || '';
1576 $text =~ s/[,;]/ /g;
1578 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1581 sub join_flagged_list
{
1582 my ($how, $lst) = @_;
1583 join $how, map { $lst->{$_} . $_ } keys %$lst;
1586 sub vmconfig_delete_pending_option
{
1587 my ($conf, $key, $force) = @_;
1589 delete $conf->{pending
}->{$key};
1590 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1591 $pending_delete_hash->{$key} = $force ?
'!' : '';
1592 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1595 sub vmconfig_undelete_pending_option
{
1596 my ($conf, $key) = @_;
1598 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1599 delete $pending_delete_hash->{$key};
1601 if (%$pending_delete_hash) {
1602 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1604 delete $conf->{pending
}->{delete};
1608 sub vmconfig_register_unused_drive
{
1609 my ($storecfg, $vmid, $conf, $drive) = @_;
1611 if (!drive_is_cdrom
($drive)) {
1612 my $volid = $drive->{file
};
1613 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1614 PVE
::QemuConfig-
>add_unused_volume($conf, $volid, $vmid);
1619 sub vmconfig_cleanup_pending
{
1622 # remove pending changes when nothing changed
1624 foreach my $opt (keys %{$conf->{pending
}}) {
1625 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1627 delete $conf->{pending
}->{$opt};
1631 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1632 my $pending_delete_hash = {};
1633 while (my ($opt, $force) = each %$current_delete_hash) {
1634 if (defined($conf->{$opt})) {
1635 $pending_delete_hash->{$opt} = $force;
1641 if (%$pending_delete_hash) {
1642 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1644 delete $conf->{pending
}->{delete};
1650 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1651 my $smbios1_desc = {
1654 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1655 format_description
=> 'UUID',
1661 format_description
=> 'str',
1667 format_description
=> 'str',
1673 format_description
=> 'name',
1679 format_description
=> 'name',
1685 format_description
=> 'str',
1691 format_description
=> 'str',
1699 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_desc, $data) };
1706 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_desc);
1709 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_desc);
1711 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1712 sub verify_bootdisk
{
1713 my ($value, $noerr) = @_;
1715 return $value if is_valid_drivename
($value);
1717 return undef if $noerr;
1719 die "invalid boot disk '$value'\n";
1722 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1724 my ($value, $noerr) = @_;
1726 return $value if parse_numa
($value);
1728 return undef if $noerr;
1730 die "unable to parse numa options\n";
1733 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1735 my ($value, $noerr) = @_;
1737 return $value if parse_net
($value);
1739 return undef if $noerr;
1741 die "unable to parse network options\n";
1744 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1745 sub verify_hostpci
{
1746 my ($value, $noerr) = @_;
1748 return $value if parse_hostpci
($value);
1750 return undef if $noerr;
1752 die "unable to parse pci id\n";
1755 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1756 sub verify_watchdog
{
1757 my ($value, $noerr) = @_;
1759 return $value if parse_watchdog
($value);
1761 return undef if $noerr;
1763 die "unable to parse watchdog options\n";
1766 sub parse_watchdog
{
1769 return undef if !$value;
1773 foreach my $p (split(/,/, $value)) {
1774 next if $p =~ m/^\s*$/;
1776 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1778 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1779 $res->{action
} = $2;
1788 sub parse_usb_device
{
1791 return undef if !$value;
1794 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1795 $res->{vendorid
} = $2;
1796 $res->{productid
} = $4;
1797 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1798 $res->{hostbus
} = $1;
1799 $res->{hostport
} = $2;
1800 } elsif ($value =~ m/^spice$/i) {
1809 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1810 sub verify_usb_device
{
1811 my ($value, $noerr) = @_;
1813 return $value if parse_usb_device
($value);
1815 return undef if $noerr;
1817 die "unable to parse usb device\n";
1820 # add JSON properties for create and set function
1821 sub json_config_properties
{
1824 foreach my $opt (keys %$confdesc) {
1825 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1826 $prop->{$opt} = $confdesc->{$opt};
1833 my ($key, $value) = @_;
1835 die "unknown setting '$key'\n" if !$confdesc->{$key};
1837 my $type = $confdesc->{$key}->{type
};
1839 if (!defined($value)) {
1840 die "got undefined value\n";
1843 if ($value =~ m/[\n\r]/) {
1844 die "property contains a line feed\n";
1847 if ($type eq 'boolean') {
1848 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1849 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1850 die "type check ('boolean') failed - got '$value'\n";
1851 } elsif ($type eq 'integer') {
1852 return int($1) if $value =~ m/^(\d+)$/;
1853 die "type check ('integer') failed - got '$value'\n";
1854 } elsif ($type eq 'number') {
1855 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1856 die "type check ('number') failed - got '$value'\n";
1857 } elsif ($type eq 'string') {
1858 if (my $fmt = $confdesc->{$key}->{format
}) {
1859 if ($fmt eq 'pve-qm-drive') {
1860 # special case - we need to pass $key to parse_drive()
1861 my $drive = parse_drive
($key, $value);
1862 return $value if $drive;
1863 die "unable to parse drive options\n";
1865 PVE
::JSONSchema
::check_format
($fmt, $value);
1868 $value =~ s/^\"(.*)\"$/$1/;
1871 die "internal error"
1875 sub check_iommu_support
{
1876 #fixme : need to check IOMMU support
1877 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1887 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1888 utime undef, undef, $conf;
1892 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1894 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1896 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1898 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1900 # only remove disks owned by this VM
1901 foreach_drive
($conf, sub {
1902 my ($ds, $drive) = @_;
1904 return if drive_is_cdrom
($drive);
1906 my $volid = $drive->{file
};
1908 return if !$volid || $volid =~ m
|^/|;
1910 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1911 return if !$path || !$owner || ($owner != $vmid);
1913 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1916 if ($keep_empty_config) {
1917 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1922 # also remove unused disk
1924 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1927 PVE
::Storage
::foreach_volid
($dl, sub {
1928 my ($volid, $sid, $volname, $d) = @_;
1929 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1938 sub parse_vm_config
{
1939 my ($filename, $raw) = @_;
1941 return undef if !defined($raw);
1944 digest
=> Digest
::SHA
::sha1_hex
($raw),
1949 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1950 || die "got strange filename '$filename'";
1958 my @lines = split(/\n/, $raw);
1959 foreach my $line (@lines) {
1960 next if $line =~ m/^\s*$/;
1962 if ($line =~ m/^\[PENDING\]\s*$/i) {
1963 $section = 'pending';
1964 if (defined($descr)) {
1966 $conf->{description
} = $descr;
1969 $conf = $res->{$section} = {};
1972 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1974 if (defined($descr)) {
1976 $conf->{description
} = $descr;
1979 $conf = $res->{snapshots
}->{$section} = {};
1983 if ($line =~ m/^\#(.*)\s*$/) {
1984 $descr = '' if !defined($descr);
1985 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1989 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1990 $descr = '' if !defined($descr);
1991 $descr .= PVE
::Tools
::decode_text
($2);
1992 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1993 $conf->{snapstate
} = $1;
1994 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1997 $conf->{$key} = $value;
1998 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2000 if ($section eq 'pending') {
2001 $conf->{delete} = $value; # we parse this later
2003 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2005 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2008 eval { $value = check_type
($key, $value); };
2010 warn "vm $vmid - unable to parse value of '$key' - $@";
2012 my $fmt = $confdesc->{$key}->{format
};
2013 if ($fmt && $fmt eq 'pve-qm-drive') {
2014 my $v = parse_drive
($key, $value);
2015 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2016 $v->{file
} = $volid;
2017 $value = print_drive
($vmid, $v);
2019 warn "vm $vmid - unable to parse value of '$key'\n";
2024 if ($key eq 'cdrom') {
2025 $conf->{ide2
} = $value;
2027 $conf->{$key} = $value;
2033 if (defined($descr)) {
2035 $conf->{description
} = $descr;
2037 delete $res->{snapstate
}; # just to be sure
2042 sub write_vm_config
{
2043 my ($filename, $conf) = @_;
2045 delete $conf->{snapstate
}; # just to be sure
2047 if ($conf->{cdrom
}) {
2048 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2049 $conf->{ide2
} = $conf->{cdrom
};
2050 delete $conf->{cdrom
};
2053 # we do not use 'smp' any longer
2054 if ($conf->{sockets
}) {
2055 delete $conf->{smp
};
2056 } elsif ($conf->{smp
}) {
2057 $conf->{sockets
} = $conf->{smp
};
2058 delete $conf->{cores
};
2059 delete $conf->{smp
};
2062 my $used_volids = {};
2064 my $cleanup_config = sub {
2065 my ($cref, $pending, $snapname) = @_;
2067 foreach my $key (keys %$cref) {
2068 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2069 $key eq 'snapstate' || $key eq 'pending';
2070 my $value = $cref->{$key};
2071 if ($key eq 'delete') {
2072 die "propertry 'delete' is only allowed in [PENDING]\n"
2074 # fixme: check syntax?
2077 eval { $value = check_type
($key, $value); };
2078 die "unable to parse value of '$key' - $@" if $@;
2080 $cref->{$key} = $value;
2082 if (!$snapname && is_valid_drivename
($key)) {
2083 my $drive = parse_drive
($key, $value);
2084 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2089 &$cleanup_config($conf);
2091 &$cleanup_config($conf->{pending
}, 1);
2093 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2094 die "internal error" if $snapname eq 'pending';
2095 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2098 # remove 'unusedX' settings if we re-add a volume
2099 foreach my $key (keys %$conf) {
2100 my $value = $conf->{$key};
2101 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2102 delete $conf->{$key};
2106 my $generate_raw_config = sub {
2107 my ($conf, $pending) = @_;
2111 # add description as comment to top of file
2112 if (defined(my $descr = $conf->{description
})) {
2114 foreach my $cl (split(/\n/, $descr)) {
2115 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2118 $raw .= "#\n" if $pending;
2122 foreach my $key (sort keys %$conf) {
2123 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2124 $raw .= "$key: $conf->{$key}\n";
2129 my $raw = &$generate_raw_config($conf);
2131 if (scalar(keys %{$conf->{pending
}})){
2132 $raw .= "\n[PENDING]\n";
2133 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2136 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2137 $raw .= "\n[$snapname]\n";
2138 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2148 # we use static defaults from our JSON schema configuration
2149 foreach my $key (keys %$confdesc) {
2150 if (defined(my $default = $confdesc->{$key}->{default})) {
2151 $res->{$key} = $default;
2155 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2156 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2162 my $vmlist = PVE
::Cluster
::get_vmlist
();
2164 return $res if !$vmlist || !$vmlist->{ids
};
2165 my $ids = $vmlist->{ids
};
2167 foreach my $vmid (keys %$ids) {
2168 my $d = $ids->{$vmid};
2169 next if !$d->{node
} || $d->{node
} ne $nodename;
2170 next if !$d->{type
} || $d->{type
} ne 'qemu';
2171 $res->{$vmid}->{exists} = 1;
2176 # test if VM uses local resources (to prevent migration)
2177 sub check_local_resources
{
2178 my ($conf, $noerr) = @_;
2182 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2183 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2185 foreach my $k (keys %$conf) {
2186 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2187 # sockets are safe: they will recreated be on the target side post-migrate
2188 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2189 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2192 die "VM uses local resources\n" if $loc_res && !$noerr;
2197 # check if used storages are available on all nodes (use by migrate)
2198 sub check_storage_availability
{
2199 my ($storecfg, $conf, $node) = @_;
2201 foreach_drive
($conf, sub {
2202 my ($ds, $drive) = @_;
2204 my $volid = $drive->{file
};
2207 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2210 # check if storage is available on both nodes
2211 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2212 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2216 # list nodes where all VM images are available (used by has_feature API)
2218 my ($conf, $storecfg) = @_;
2220 my $nodelist = PVE
::Cluster
::get_nodelist
();
2221 my $nodehash = { map { $_ => 1 } @$nodelist };
2222 my $nodename = PVE
::INotify
::nodename
();
2224 foreach_drive
($conf, sub {
2225 my ($ds, $drive) = @_;
2227 my $volid = $drive->{file
};
2230 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2232 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2233 if ($scfg->{disable
}) {
2235 } elsif (my $avail = $scfg->{nodes
}) {
2236 foreach my $node (keys %$nodehash) {
2237 delete $nodehash->{$node} if !$avail->{$node};
2239 } elsif (!$scfg->{shared
}) {
2240 foreach my $node (keys %$nodehash) {
2241 delete $nodehash->{$node} if $node ne $nodename
2251 my ($pidfile, $pid) = @_;
2253 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2257 return undef if !$line;
2258 my @param = split(/\0/, $line);
2260 my $cmd = $param[0];
2261 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2263 for (my $i = 0; $i < scalar (@param); $i++) {
2266 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2267 my $p = $param[$i+1];
2268 return 1 if $p && ($p eq $pidfile);
2277 my ($vmid, $nocheck, $node) = @_;
2279 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2281 die "unable to find configuration file for VM $vmid - no such machine\n"
2282 if !$nocheck && ! -f
$filename;
2284 my $pidfile = pidfile_name
($vmid);
2286 if (my $fd = IO
::File-
>new("<$pidfile")) {
2291 my $mtime = $st->mtime;
2292 if ($mtime > time()) {
2293 warn "file '$filename' modified in future\n";
2296 if ($line =~ m/^(\d+)$/) {
2298 if (check_cmdline
($pidfile, $pid)) {
2299 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2311 my $vzlist = config_list
();
2313 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2315 while (defined(my $de = $fd->read)) {
2316 next if $de !~ m/^(\d+)\.pid$/;
2318 next if !defined($vzlist->{$vmid});
2319 if (my $pid = check_running
($vmid)) {
2320 $vzlist->{$vmid}->{pid
} = $pid;
2328 my ($storecfg, $conf) = @_;
2330 my $bootdisk = $conf->{bootdisk
};
2331 return undef if !$bootdisk;
2332 return undef if !is_valid_drivename
($bootdisk);
2334 return undef if !$conf->{$bootdisk};
2336 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2337 return undef if !defined($drive);
2339 return undef if drive_is_cdrom
($drive);
2341 my $volid = $drive->{file
};
2342 return undef if !$volid;
2344 return $drive->{size
};
2347 my $last_proc_pid_stat;
2349 # get VM status information
2350 # This must be fast and should not block ($full == false)
2351 # We only query KVM using QMP if $full == true (this can be slow)
2353 my ($opt_vmid, $full) = @_;
2357 my $storecfg = PVE
::Storage
::config
();
2359 my $list = vzlist
();
2360 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2362 my $cpucount = $cpuinfo->{cpus
} || 1;
2364 foreach my $vmid (keys %$list) {
2365 next if $opt_vmid && ($vmid ne $opt_vmid);
2367 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2368 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2371 $d->{pid
} = $list->{$vmid}->{pid
};
2373 # fixme: better status?
2374 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2376 my $size = disksize
($storecfg, $conf);
2377 if (defined($size)) {
2378 $d->{disk
} = 0; # no info available
2379 $d->{maxdisk
} = $size;
2385 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2386 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2387 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2389 $d->{name
} = $conf->{name
} || "VM $vmid";
2390 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2392 if ($conf->{balloon
}) {
2393 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2394 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2405 $d->{diskwrite
} = 0;
2407 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2412 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2413 foreach my $dev (keys %$netdev) {
2414 next if $dev !~ m/^tap([1-9]\d*)i/;
2416 my $d = $res->{$vmid};
2419 $d->{netout
} += $netdev->{$dev}->{receive
};
2420 $d->{netin
} += $netdev->{$dev}->{transmit
};
2423 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2424 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2429 my $ctime = gettimeofday
;
2431 foreach my $vmid (keys %$list) {
2433 my $d = $res->{$vmid};
2434 my $pid = $d->{pid
};
2437 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2438 next if !$pstat; # not running
2440 my $used = $pstat->{utime} + $pstat->{stime
};
2442 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2444 if ($pstat->{vsize
}) {
2445 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2448 my $old = $last_proc_pid_stat->{$pid};
2450 $last_proc_pid_stat->{$pid} = {
2458 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2460 if ($dtime > 1000) {
2461 my $dutime = $used - $old->{used
};
2463 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2464 $last_proc_pid_stat->{$pid} = {
2470 $d->{cpu
} = $old->{cpu
};
2474 return $res if !$full;
2476 my $qmpclient = PVE
::QMPClient-
>new();
2478 my $ballooncb = sub {
2479 my ($vmid, $resp) = @_;
2481 my $info = $resp->{'return'};
2482 return if !$info->{max_mem
};
2484 my $d = $res->{$vmid};
2486 # use memory assigned to VM
2487 $d->{maxmem
} = $info->{max_mem
};
2488 $d->{balloon
} = $info->{actual
};
2490 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2491 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2492 $d->{freemem
} = $info->{free_mem
};
2495 $d->{ballooninfo
} = $info;
2498 my $blockstatscb = sub {
2499 my ($vmid, $resp) = @_;
2500 my $data = $resp->{'return'} || [];
2501 my $totalrdbytes = 0;
2502 my $totalwrbytes = 0;
2504 for my $blockstat (@$data) {
2505 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2506 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2508 $blockstat->{device
} =~ s/drive-//;
2509 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2511 $res->{$vmid}->{diskread
} = $totalrdbytes;
2512 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2515 my $statuscb = sub {
2516 my ($vmid, $resp) = @_;
2518 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2519 # this fails if ballon driver is not loaded, so this must be
2520 # the last commnand (following command are aborted if this fails).
2521 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2523 my $status = 'unknown';
2524 if (!defined($status = $resp->{'return'}->{status
})) {
2525 warn "unable to get VM status\n";
2529 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2532 foreach my $vmid (keys %$list) {
2533 next if $opt_vmid && ($vmid ne $opt_vmid);
2534 next if !$res->{$vmid}->{pid
}; # not running
2535 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2538 $qmpclient->queue_execute(undef, 1);
2540 foreach my $vmid (keys %$list) {
2541 next if $opt_vmid && ($vmid ne $opt_vmid);
2542 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2549 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2552 my $current_size = 1024;
2553 my $dimm_size = 512;
2554 return if $current_size == $memory;
2556 for (my $j = 0; $j < 8; $j++) {
2557 for (my $i = 0; $i < 32; $i++) {
2558 my $name = "dimm${dimm_id}";
2560 my $numanode = $i % $sockets;
2561 $current_size += $dimm_size;
2562 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2563 return $current_size if $current_size >= $memory;
2569 sub foreach_reverse_dimm
{
2570 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2573 my $current_size = 4177920;
2574 my $dimm_size = 65536;
2575 return if $current_size == $memory;
2577 for (my $j = 0; $j < 8; $j++) {
2578 for (my $i = 0; $i < 32; $i++) {
2579 my $name = "dimm${dimm_id}";
2581 my $numanode = $i % $sockets;
2582 $current_size -= $dimm_size;
2583 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2584 return $current_size if $current_size <= $memory;
2591 my ($conf, $func) = @_;
2593 foreach my $ds (valid_drive_names
()) {
2594 next if !defined($conf->{$ds});
2596 my $drive = parse_drive
($ds, $conf->{$ds});
2599 &$func($ds, $drive);
2604 my ($conf, $func) = @_;
2608 my $test_volid = sub {
2609 my ($volid, $is_cdrom) = @_;
2613 $volhash->{$volid} = $is_cdrom || 0;
2616 foreach_drive
($conf, sub {
2617 my ($ds, $drive) = @_;
2618 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2621 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2622 my $snap = $conf->{snapshots
}->{$snapname};
2623 &$test_volid($snap->{vmstate
}, 0);
2624 foreach_drive
($snap, sub {
2625 my ($ds, $drive) = @_;
2626 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2630 foreach my $volid (keys %$volhash) {
2631 &$func($volid, $volhash->{$volid});
2635 sub vga_conf_has_spice
{
2638 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2643 sub config_to_command
{
2644 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2647 my $globalFlags = [];
2648 my $machineFlags = [];
2654 my $kvmver = kvm_user_version
();
2655 my $vernum = 0; # unknown
2656 my $ostype = $conf->{ostype
};
2657 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2658 $vernum = $1*1000000+$2*1000;
2659 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2660 $vernum = $1*1000000+$2*1000+$3;
2663 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2665 my $have_ovz = -f
'/proc/vz/vestat';
2667 my $q35 = machine_type_is_q35
($conf);
2668 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2669 my $machine_type = $forcemachine || $conf->{machine
};
2670 my $use_old_bios_files = undef;
2671 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2673 my $cpuunits = defined($conf->{cpuunits
}) ?
2674 $conf->{cpuunits
} : $defaults->{cpuunits
};
2676 push @$cmd, '/usr/bin/systemd-run';
2677 push @$cmd, '--scope';
2678 push @$cmd, '--slice', "qemu";
2679 push @$cmd, '--unit', $vmid;
2680 # set KillMode=none, so that systemd don't kill those scopes
2681 # at shutdown (pve-manager service should stop the VMs instead)
2682 push @$cmd, '-p', "KillMode=none";
2683 push @$cmd, '-p', "CPUShares=$cpuunits";
2684 if ($conf->{cpulimit
}) {
2685 my $cpulimit = int($conf->{cpulimit
} * 100);
2686 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2689 push @$cmd, '/usr/bin/kvm';
2691 push @$cmd, '-id', $vmid;
2695 my $qmpsocket = qmp_socket
($vmid);
2696 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2697 push @$cmd, '-mon', "chardev=qmp,mode=control";
2700 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2702 push @$cmd, '-daemonize';
2704 if ($conf->{smbios1
}) {
2705 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2708 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2709 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2710 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2711 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2712 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2713 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2714 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2718 # the q35 chipset support native usb2, so we enable usb controller
2719 # by default for this machine type
2720 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2722 $pciaddr = print_pci_addr
("piix3", $bridges);
2723 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2726 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2727 next if !$conf->{"usb$i"};
2728 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2729 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2732 # include usb device config
2733 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2736 # add usb3 controller if needed
2739 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2740 next if !$conf->{"usb$i"};
2741 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2742 next if !$d || !$d->{usb3
};
2746 $pciaddr = print_pci_addr
("xhci", $bridges);
2747 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2749 my $vga = $conf->{vga
};
2751 my $qxlnum = vga_conf_has_spice
($vga);
2752 $vga = 'qxl' if $qxlnum;
2755 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2756 $conf->{ostype
} eq 'win7' ||
2757 $conf->{ostype
} eq 'w2k8')) {
2764 # enable absolute mouse coordinates (needed by vnc)
2766 if (defined($conf->{tablet
})) {
2767 $tablet = $conf->{tablet
};
2769 $tablet = $defaults->{tablet
};
2770 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2771 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2774 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2778 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2779 my $d = parse_hostpci
($conf->{"hostpci$i"});
2782 my $pcie = $d->{pcie
};
2784 die "q35 machine model is not enabled" if !$q35;
2785 $pciaddr = print_pcie_addr
("hostpci$i");
2787 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2790 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2791 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2792 if ($xvga && $xvga ne '') {
2795 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2796 push @$cpuFlags , 'hv_vendor_id=proxmox';
2798 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2802 my $pcidevices = $d->{pciid
};
2803 my $multifunction = 1 if @$pcidevices > 1;
2806 foreach my $pcidevice (@$pcidevices) {
2808 my $id = "hostpci$i";
2809 $id .= ".$j" if $multifunction;
2810 my $addr = $pciaddr;
2811 $addr .= ".$j" if $multifunction;
2812 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2815 $devicestr .= "$rombar$xvga";
2816 $devicestr .= ",multifunction=on" if $multifunction;
2819 push @$devices, '-device', $devicestr;
2825 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2826 next if !$conf->{"usb$i"};
2827 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2830 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2832 if (defined($d->{usb3
}) && $d->{usb3
}) {
2833 $usbbus = ',bus=xhci.0';
2836 if (defined($d->{host
})) {
2837 $d = parse_usb_device
($d->{host
});
2838 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2839 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2840 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2841 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2842 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2843 # usb redir support for spice, currently no usb3
2844 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2845 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2851 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2852 if (my $path = $conf->{"serial$i"}) {
2853 if ($path eq 'socket') {
2854 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2855 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2856 push @$devices, '-device', "isa-serial,chardev=serial$i";
2858 die "no such serial device\n" if ! -c
$path;
2859 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2860 push @$devices, '-device', "isa-serial,chardev=serial$i";
2866 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2867 if (my $path = $conf->{"parallel$i"}) {
2868 die "no such parallel device\n" if ! -c
$path;
2869 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2870 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2871 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2875 my $vmname = $conf->{name
} || "vm$vmid";
2877 push @$cmd, '-name', $vmname;
2880 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2881 $sockets = $conf->{sockets
} if $conf->{sockets
};
2883 my $cores = $conf->{cores
} || 1;
2885 my $maxcpus = $sockets * $cores;
2887 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2889 my $allowed_vcpus = $cpuinfo->{cpus
};
2891 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2892 if ($allowed_vcpus < $maxcpus);
2894 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2896 push @$cmd, '-nodefaults';
2898 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2900 my $bootindex_hash = {};
2902 foreach my $o (split(//, $bootorder)) {
2903 $bootindex_hash->{$o} = $i*100;
2907 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2909 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2911 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2913 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2915 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2916 my $socket = vnc_socket
($vmid);
2917 push @$cmd, '-vnc', "unix:$socket,x509,password";
2919 push @$cmd, '-nographic';
2923 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2925 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2926 my $useLocaltime = $conf->{localtime};
2929 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2931 if ($ostype =~ m/^w/) { # windows
2932 $useLocaltime = 1 if !defined($conf->{localtime});
2934 # use time drift fix when acpi is enabled
2935 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2936 $tdf = 1 if !defined($conf->{tdf
});
2940 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2941 $ostype eq 'wvista') {
2942 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2943 push @$cmd, '-no-hpet';
2944 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2945 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2946 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2947 push @$cpuFlags , 'hv_time' if !$nokvm;
2950 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2954 if ($ostype eq 'win7' || $ostype eq 'win8') {
2955 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2959 push @$rtcFlags, 'driftfix=slew' if $tdf;
2962 push @$machineFlags, 'accel=tcg';
2964 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2967 if ($machine_type) {
2968 push @$machineFlags, "type=${machine_type}";
2971 if ($conf->{startdate
}) {
2972 push @$rtcFlags, "base=$conf->{startdate}";
2973 } elsif ($useLocaltime) {
2974 push @$rtcFlags, 'base=localtime';
2977 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2978 if (my $cputype = $conf->{cpu
}) {
2979 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpudesc, $cputype)
2980 or die "Cannot parse cpu description: $cputype\n";
2981 $cpu = $cpuconf->{cputype
};
2982 $kvm_off = 1 if $cpuconf->{hidden
};
2985 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2987 push @$cpuFlags , '-x2apic'
2988 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
2990 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2992 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2994 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2996 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2997 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3000 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3002 push @$cpuFlags, 'kvm=off' if $kvm_off;
3004 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3006 push @$cmd, '-cpu', $cpu;
3008 my $memory = $conf->{memory
} || $defaults->{memory
};
3009 my $static_memory = 0;
3010 my $dimm_memory = 0;
3012 if ($hotplug_features->{memory
}) {
3013 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3014 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3015 $static_memory = $STATICMEM;
3016 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3017 $dimm_memory = $memory - $static_memory;
3018 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3022 $static_memory = $memory;
3023 push @$cmd, '-m', $static_memory;
3026 if ($conf->{numa
}) {
3028 my $numa_totalmemory = undef;
3029 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3030 next if !$conf->{"numa$i"};
3031 my $numa = parse_numa
($conf->{"numa$i"});
3034 die "missing numa node$i memory value\n" if !$numa->{memory
};
3035 my $numa_memory = $numa->{memory
};
3036 $numa_totalmemory += $numa_memory;
3037 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3040 my $cpus_start = $numa->{cpus
}->{start
};
3041 die "missing numa node$i cpus\n" if !defined($cpus_start);
3042 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3043 my $cpus = $cpus_start;
3044 if (defined($cpus_end)) {
3045 $cpus .= "-$cpus_end";
3046 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3050 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3051 if (defined($hostnodes_start)) {
3052 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3053 my $hostnodes = $hostnodes_start;
3054 if (defined($hostnodes_end)) {
3055 $hostnodes .= "-$hostnodes_end";
3056 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3059 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3060 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3061 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3065 my $policy = $numa->{policy
};
3066 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3067 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3070 push @$cmd, '-object', $numa_object;
3071 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3074 die "total memory for NUMA nodes must be equal to vm static memory\n"
3075 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3077 #if no custom tology, we split memory and cores across numa nodes
3078 if(!$numa_totalmemory) {
3080 my $numa_memory = ($static_memory / $sockets) . "M";
3082 for (my $i = 0; $i < $sockets; $i++) {
3084 my $cpustart = ($cores * $i);
3085 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3086 my $cpus = $cpustart;
3087 $cpus .= "-$cpuend" if $cpuend;
3089 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3090 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3095 if ($hotplug_features->{memory
}) {
3096 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3097 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3098 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3099 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3101 #if dimm_memory is not aligned to dimm map
3102 if($current_size > $memory) {
3103 $conf->{memory
} = $current_size;
3104 PVE
::QemuConfig-
>write_config($vmid, $conf);
3109 push @$cmd, '-S' if $conf->{freeze
};
3111 # set keyboard layout
3112 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3113 push @$cmd, '-k', $kb if $kb;
3116 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3117 #push @$cmd, '-soundhw', 'es1370';
3118 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3120 if($conf->{agent
}) {
3121 my $qgasocket = qmp_socket
($vmid, 1);
3122 my $pciaddr = print_pci_addr
("qga0", $bridges);
3123 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3124 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3125 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3132 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3133 for(my $i = 1; $i < $qxlnum; $i++){
3134 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3135 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3138 # assume other OS works like Linux
3139 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3140 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3144 my $pciaddr = print_pci_addr
("spice", $bridges);
3146 my $nodename = PVE
::INotify
::nodename
();
3147 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3148 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3150 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3152 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3153 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3154 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3157 # enable balloon by default, unless explicitly disabled
3158 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3159 $pciaddr = print_pci_addr
("balloon0", $bridges);
3160 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3163 if ($conf->{watchdog
}) {
3164 my $wdopts = parse_watchdog
($conf->{watchdog
});
3165 $pciaddr = print_pci_addr
("watchdog", $bridges);
3166 my $watchdog = $wdopts->{model
} || 'i6300esb';
3167 push @$devices, '-device', "$watchdog$pciaddr";
3168 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3172 my $scsicontroller = {};
3173 my $ahcicontroller = {};
3174 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3176 # Add iscsi initiator name if available
3177 if (my $initiator = get_initiator_name
()) {
3178 push @$devices, '-iscsi', "initiator-name=$initiator";
3181 foreach_drive
($conf, sub {
3182 my ($ds, $drive) = @_;
3184 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3185 push @$vollist, $drive->{file
};
3188 $use_virtio = 1 if $ds =~ m/^virtio/;
3190 if (drive_is_cdrom
($drive)) {
3191 if ($bootindex_hash->{d
}) {
3192 $drive->{bootindex
} = $bootindex_hash->{d
};
3193 $bootindex_hash->{d
} += 1;
3196 if ($bootindex_hash->{c
}) {
3197 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3198 $bootindex_hash->{c
} += 1;
3202 if($drive->{interface
} eq 'virtio'){
3203 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3206 if ($drive->{interface
} eq 'scsi') {
3208 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3210 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3211 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3214 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3215 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3216 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3220 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3221 $queues = ",num_queues=$drive->{queues}";
3224 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3225 $scsicontroller->{$controller}=1;
3228 if ($drive->{interface
} eq 'sata') {
3229 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3230 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3231 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3232 $ahcicontroller->{$controller}=1;
3235 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3236 push @$devices, '-drive',$drive_cmd;
3237 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3240 for (my $i = 0; $i < $MAX_NETS; $i++) {
3241 next if !$conf->{"net$i"};
3242 my $d = parse_net
($conf->{"net$i"});
3245 $use_virtio = 1 if $d->{model
} eq 'virtio';
3247 if ($bootindex_hash->{n
}) {
3248 $d->{bootindex
} = $bootindex_hash->{n
};
3249 $bootindex_hash->{n
} += 1;
3252 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3253 push @$devices, '-netdev', $netdevfull;
3255 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3256 push @$devices, '-device', $netdevicefull;
3261 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3266 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3268 while (my ($k, $v) = each %$bridges) {
3269 $pciaddr = print_pci_addr
("pci.$k");
3270 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3275 if ($conf->{args
}) {
3276 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3280 push @$cmd, @$devices;
3281 push @$cmd, '-rtc', join(',', @$rtcFlags)
3282 if scalar(@$rtcFlags);
3283 push @$cmd, '-machine', join(',', @$machineFlags)
3284 if scalar(@$machineFlags);
3285 push @$cmd, '-global', join(',', @$globalFlags)
3286 if scalar(@$globalFlags);
3288 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3293 return "${var_run_tmpdir}/$vmid.vnc";
3299 my $res = vm_mon_cmd
($vmid, 'query-spice');
3301 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3305 my ($vmid, $qga) = @_;
3306 my $sockettype = $qga ?
'qga' : 'qmp';
3307 return "${var_run_tmpdir}/$vmid.$sockettype";
3312 return "${var_run_tmpdir}/$vmid.pid";
3315 sub vm_devices_list
{
3318 my $res = vm_mon_cmd
($vmid, 'query-pci');
3320 foreach my $pcibus (@$res) {
3321 foreach my $device (@{$pcibus->{devices
}}) {
3322 next if !$device->{'qdev_id'};
3323 if ($device->{'pci_bridge'}) {
3324 $devices->{$device->{'qdev_id'}} = 1;
3325 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3326 next if !$bridge_device->{'qdev_id'};
3327 $devices->{$bridge_device->{'qdev_id'}} = 1;
3328 $devices->{$device->{'qdev_id'}}++;
3331 $devices->{$device->{'qdev_id'}} = 1;
3336 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3337 foreach my $block (@$resblock) {
3338 if($block->{device
} =~ m/^drive-(\S+)/){
3343 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3344 foreach my $mice (@$resmice) {
3345 if ($mice->{name
} eq 'QEMU HID Tablet') {
3346 $devices->{tablet
} = 1;
3355 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3357 my $q35 = machine_type_is_q35
($conf);
3359 my $devices_list = vm_devices_list
($vmid);
3360 return 1 if defined($devices_list->{$deviceid});
3362 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3364 if ($deviceid eq 'tablet') {
3366 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3368 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3370 qemu_iothread_add
($vmid, $deviceid, $device);
3372 qemu_driveadd
($storecfg, $vmid, $device);
3373 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3375 qemu_deviceadd
($vmid, $devicefull);
3376 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3378 eval { qemu_drivedel
($vmid, $deviceid); };
3383 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3386 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3387 my $pciaddr = print_pci_addr
($deviceid);
3388 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3390 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3392 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3393 qemu_iothread_add
($vmid, $deviceid, $device);
3394 $devicefull .= ",iothread=iothread-$deviceid";
3397 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3398 $devicefull .= ",num_queues=$device->{queues}";
3401 qemu_deviceadd
($vmid, $devicefull);
3402 qemu_deviceaddverify
($vmid, $deviceid);
3404 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3406 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3407 qemu_driveadd
($storecfg, $vmid, $device);
3409 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3410 eval { qemu_deviceadd
($vmid, $devicefull); };
3412 eval { qemu_drivedel
($vmid, $deviceid); };
3417 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3419 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3421 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3422 my $use_old_bios_files = undef;
3423 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3425 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3426 qemu_deviceadd
($vmid, $netdevicefull);
3427 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3429 eval { qemu_netdevdel
($vmid, $deviceid); };
3434 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3437 my $pciaddr = print_pci_addr
($deviceid);
3438 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3440 qemu_deviceadd
($vmid, $devicefull);
3441 qemu_deviceaddverify
($vmid, $deviceid);
3444 die "can't hotplug device '$deviceid'\n";
3450 # fixme: this should raise exceptions on error!
3451 sub vm_deviceunplug
{
3452 my ($vmid, $conf, $deviceid) = @_;
3454 my $devices_list = vm_devices_list
($vmid);
3455 return 1 if !defined($devices_list->{$deviceid});
3457 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3459 if ($deviceid eq 'tablet') {
3461 qemu_devicedel
($vmid, $deviceid);
3463 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3465 qemu_devicedel
($vmid, $deviceid);
3466 qemu_devicedelverify
($vmid, $deviceid);
3467 qemu_drivedel
($vmid, $deviceid);
3468 qemu_iothread_del
($conf, $vmid, $deviceid);
3470 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3472 qemu_devicedel
($vmid, $deviceid);
3473 qemu_devicedelverify
($vmid, $deviceid);
3474 qemu_iothread_del
($conf, $vmid, $deviceid);
3476 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3478 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3479 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3480 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3482 qemu_devicedel
($vmid, $deviceid);
3483 qemu_drivedel
($vmid, $deviceid);
3484 qemu_deletescsihw
($conf, $vmid, $deviceid);
3486 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3488 qemu_devicedel
($vmid, $deviceid);
3489 qemu_devicedelverify
($vmid, $deviceid);
3490 qemu_netdevdel
($vmid, $deviceid);
3493 die "can't unplug device '$deviceid'\n";
3499 sub qemu_deviceadd
{
3500 my ($vmid, $devicefull) = @_;
3502 $devicefull = "driver=".$devicefull;
3503 my %options = split(/[=,]/, $devicefull);
3505 vm_mon_cmd
($vmid, "device_add" , %options);
3508 sub qemu_devicedel
{
3509 my ($vmid, $deviceid) = @_;
3511 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3514 sub qemu_iothread_add
{
3515 my($vmid, $deviceid, $device) = @_;
3517 if ($device->{iothread
}) {
3518 my $iothreads = vm_iothreads_list
($vmid);
3519 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3523 sub qemu_iothread_del
{
3524 my($conf, $vmid, $deviceid) = @_;
3526 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3527 if ($device->{iothread
}) {
3528 my $iothreads = vm_iothreads_list
($vmid);
3529 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3533 sub qemu_objectadd
{
3534 my($vmid, $objectid, $qomtype) = @_;
3536 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3541 sub qemu_objectdel
{
3542 my($vmid, $objectid) = @_;
3544 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3550 my ($storecfg, $vmid, $device) = @_;
3552 my $drive = print_drive_full
($storecfg, $vmid, $device);
3553 $drive =~ s/\\/\\\\/g;
3554 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3556 # If the command succeeds qemu prints: "OK
"
3557 return 1 if $ret =~ m/OK/s;
3559 die "adding drive failed
: $ret\n";
3563 my($vmid, $deviceid) = @_;
3565 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3568 return 1 if $ret eq "";
3570 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3571 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3573 die "deleting drive
$deviceid failed
: $ret\n";
3576 sub qemu_deviceaddverify {
3577 my ($vmid, $deviceid) = @_;
3579 for (my $i = 0; $i <= 5; $i++) {
3580 my $devices_list = vm_devices_list($vmid);
3581 return 1 if defined($devices_list->{$deviceid});
3585 die "error on hotplug device
'$deviceid'\n";
3589 sub qemu_devicedelverify {
3590 my ($vmid, $deviceid) = @_;
3592 # need to verify that the device is correctly removed as device_del
3593 # is async and empty return is not reliable
3595 for (my $i = 0; $i <= 5; $i++) {
3596 my $devices_list = vm_devices_list($vmid);
3597 return 1 if !defined($devices_list->{$deviceid});
3601 die "error on hot-unplugging device
'$deviceid'\n";
3604 sub qemu_findorcreatescsihw {
3605 my ($storecfg, $conf, $vmid, $device) = @_;
3607 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3609 my $scsihwid="$controller_prefix$controller";
3610 my $devices_list = vm_devices_list($vmid);
3612 if(!defined($devices_list->{$scsihwid})) {
3613 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3619 sub qemu_deletescsihw {
3620 my ($conf, $vmid, $opt) = @_;
3622 my $device = parse_drive($opt, $conf->{$opt});
3624 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3625 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3629 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3631 my $devices_list = vm_devices_list($vmid);
3632 foreach my $opt (keys %{$devices_list}) {
3633 if (PVE::QemuServer::is_valid_drivename($opt)) {
3634 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3635 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3641 my $scsihwid="scsihw
$controller";
3643 vm_deviceunplug($vmid, $conf, $scsihwid);
3648 sub qemu_add_pci_bridge {
3649 my ($storecfg, $conf, $vmid, $device) = @_;
3655 print_pci_addr($device, $bridges);
3657 while (my ($k, $v) = each %$bridges) {
3660 return 1 if !defined($bridgeid) || $bridgeid < 1;
3662 my $bridge = "pci
.$bridgeid";
3663 my $devices_list = vm_devices_list($vmid);
3665 if (!defined($devices_list->{$bridge})) {
3666 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3672 sub qemu_set_link_status {
3673 my ($vmid, $device, $up) = @_;
3675 vm_mon_cmd($vmid, "set_link
", name => $device,
3676 up => $up ? JSON::true : JSON::false);
3679 sub qemu_netdevadd {
3680 my ($vmid, $conf, $device, $deviceid) = @_;
3682 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3683 my %options = split(/[=,]/, $netdev);
3685 vm_mon_cmd($vmid, "netdev_add
", %options);
3689 sub qemu_netdevdel {
3690 my ($vmid, $deviceid) = @_;
3692 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3695 sub qemu_cpu_hotplug {
3696 my ($vmid, $conf, $vcpus) = @_;
3699 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3700 $sockets = $conf->{sockets} if $conf->{sockets};
3701 my $cores = $conf->{cores} || 1;
3702 my $maxcpus = $sockets * $cores;
3704 $vcpus = $maxcpus if !$vcpus;
3706 die "you can
't add more vcpus than maxcpus\n"
3707 if $vcpus > $maxcpus;
3709 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3710 die "online cpu unplug is not yet possible\n"
3711 if $vcpus < $currentvcpus;
3713 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3714 die "vcpus in running vm is different than configuration\n"
3715 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3717 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3718 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3722 sub qemu_memory_hotplug {
3723 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3725 return $value if !check_running($vmid);
3727 my $memory = $conf->{memory} || $defaults->{memory};
3728 $value = $defaults->{memory} if !$value;
3729 return $value if $value == $memory;
3731 my $static_memory = $STATICMEM;
3732 my $dimm_memory = $memory - $static_memory;
3734 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3735 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3739 $sockets = $conf->{sockets} if $conf->{sockets};
3741 if($value > $memory) {
3743 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3744 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3746 return if $current_size <= $conf->{memory};
3748 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3750 eval { qemu_objectdel($vmid, "mem-
$name"); };
3754 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3756 eval { qemu_objectdel($vmid, "mem-
$name"); };
3759 #update conf after each succesful module hotplug
3760 $conf->{memory} = $current_size;
3761 PVE::QemuConfig->write_config($vmid, $conf);
3766 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3767 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3769 return if $current_size >= $conf->{memory};
3770 print "try to unplug memory dimm
$name\n";
3774 eval { qemu_devicedel($vmid, $name) };
3776 my $dimm_list = qemu_dimm_list($vmid);
3777 last if !$dimm_list->{$name};
3778 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3782 #update conf after each succesful module unplug
3783 $conf->{memory} = $current_size;
3785 eval { qemu_objectdel($vmid, "mem-
$name"); };
3786 PVE::QemuConfig->write_config($vmid, $conf);
3791 sub qemu_dimm_list {
3794 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3797 foreach my $dimm (@$dimmarray) {
3799 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3800 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3801 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3802 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3803 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3808 sub qemu_block_set_io_throttle {
3809 my ($vmid, $deviceid,
3810 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3811 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3813 return if !check_running($vmid) ;
3815 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3817 bps_rd => int($bps_rd),
3818 bps_wr => int($bps_wr),
3820 iops_rd => int($iops_rd),
3821 iops_wr => int($iops_wr),
3822 bps_max => int($bps_max),
3823 bps_rd_max => int($bps_rd_max),
3824 bps_wr_max => int($bps_wr_max),
3825 iops_max => int($iops_max),
3826 iops_rd_max => int($iops_rd_max),
3827 iops_wr_max => int($iops_wr_max)
3832 # old code, only used to shutdown old VM after update
3834 my ($fh, $timeout) = @_;
3836 my $sel = new IO::Select;
3843 while (scalar (@ready = $sel->can_read($timeout))) {
3845 if ($count = $fh->sysread($buf, 8192)) {
3846 if ($buf =~ /^(.*)\(qemu\) $/s) {
3853 if (!defined($count)) {
3860 die "monitor
read timeout
\n" if !scalar(@ready);
3865 # old code, only used to shutdown old VM after update
3866 sub vm_monitor_command {
3867 my ($vmid, $cmdstr, $nocheck) = @_;
3872 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3874 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3876 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3877 die "unable to
connect to VM
$vmid socket - $!\n";
3881 # hack: migrate sometime blocks the monitor (when migrate_downtime
3883 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3884 $timeout = 60*60; # 1 hour
3888 my $data = __read_avail($sock, $timeout);
3890 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3891 die "got unexpected qemu monitor banner
\n";
3894 my $sel = new IO::Select;
3897 if (!scalar(my @ready = $sel->can_write($timeout))) {
3898 die "monitor
write error
- timeout
";
3901 my $fullcmd = "$cmdstr\r";
3903 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3906 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3907 die "monitor
write error
- $!";
3910 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3914 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3915 $timeout = 60*60; # 1 hour
3916 } elsif ($cmdstr =~ m/^(eject|change)/) {
3917 $timeout = 60; # note: cdrom mount command is slow
3919 if ($res = __read_avail($sock, $timeout)) {
3921 my @lines = split("\r?
\n", $res);
3923 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3925 $res = join("\n", @lines);
3933 syslog("err
", "VM
$vmid monitor command failed
- $err");
3940 sub qemu_block_resize {
3941 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3943 my $running = check_running($vmid);
3945 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3947 return if !$running;
3949 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3953 sub qemu_volume_snapshot {
3954 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3956 my $running = check_running($vmid);
3958 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3959 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3961 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3965 sub qemu_volume_snapshot_delete {
3966 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3968 my $running = check_running($vmid);
3970 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3972 return if !$running;
3974 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3977 sub set_migration_caps {
3983 "auto-converge
" => 1,
3985 "x-rdma-pin-all
" => 0,
3990 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3992 for my $supported_capability (@$supported_capabilities) {
3994 capability => $supported_capability->{capability},
3995 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3999 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4002 my $fast_plug_option = {
4011 # hotplug changes in [PENDING]
4012 # $selection hash can be used to only apply specified options, for
4013 # example: { cores => 1 } (only apply changed 'cores')
4014 # $errors ref is used to return error messages
4015 sub vmconfig_hotplug_pending {
4016 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4018 my $defaults = load_defaults();
4020 # commit values which do not have any impact on running VM first
4021 # Note: those option cannot raise errors, we we do not care about
4022 # $selection and always apply them.
4024 my $add_error = sub {
4025 my ($opt, $msg) = @_;
4026 $errors->{$opt} = "hotplug problem
- $msg";
4030 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4031 if ($fast_plug_option->{$opt}) {
4032 $conf->{$opt} = $conf->{pending}->{$opt};
4033 delete $conf->{pending}->{$opt};
4039 PVE::QemuConfig->write_config($vmid, $conf);
4040 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4043 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4045 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4046 while (my ($opt, $force) = each %$pending_delete_hash) {
4047 next if $selection && !$selection->{$opt};
4049 if ($opt eq 'hotplug') {
4050 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4051 } elsif ($opt eq 'tablet') {
4052 die "skip
\n" if !$hotplug_features->{usb};
4053 if ($defaults->{tablet}) {
4054 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4056 vm_deviceunplug($vmid, $conf, $opt);
4058 } elsif ($opt eq 'vcpus') {
4059 die "skip
\n" if !$hotplug_features->{cpu};
4060 qemu_cpu_hotplug($vmid, $conf, undef);
4061 } elsif ($opt eq 'balloon') {
4062 # enable balloon device is not hotpluggable
4063 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4064 } elsif ($fast_plug_option->{$opt}) {
4066 } elsif ($opt =~ m/^net(\d+)$/) {
4067 die "skip
\n" if !$hotplug_features->{network};
4068 vm_deviceunplug($vmid, $conf, $opt);
4069 } elsif (is_valid_drivename($opt)) {
4070 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4071 vm_deviceunplug($vmid, $conf, $opt);
4072 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4073 } elsif ($opt =~ m/^memory$/) {
4074 die "skip
\n" if !$hotplug_features->{memory};
4075 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4076 } elsif ($opt eq 'cpuunits') {
4077 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4078 } elsif ($opt eq 'cpulimit') {
4079 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4085 &$add_error($opt, $err) if $err ne "skip
\n";
4087 # save new config if hotplug was successful
4088 delete $conf->{$opt};
4089 vmconfig_undelete_pending_option($conf, $opt);
4090 PVE::QemuConfig->write_config($vmid, $conf);
4091 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4095 foreach my $opt (keys %{$conf->{pending}}) {
4096 next if $selection && !$selection->{$opt};
4097 my $value = $conf->{pending}->{$opt};
4099 if ($opt eq 'hotplug') {
4100 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4101 } elsif ($opt eq 'tablet') {
4102 die "skip
\n" if !$hotplug_features->{usb};
4104 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4105 } elsif ($value == 0) {
4106 vm_deviceunplug($vmid, $conf, $opt);
4108 } elsif ($opt eq 'vcpus') {
4109 die "skip
\n" if !$hotplug_features->{cpu};
4110 qemu_cpu_hotplug($vmid, $conf, $value);
4111 } elsif ($opt eq 'balloon') {
4112 # enable/disable balloning device is not hotpluggable
4113 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4114 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4115 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4117 # allow manual ballooning if shares is set to zero
4118 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4119 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4120 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4122 } elsif ($opt =~ m/^net(\d+)$/) {
4123 # some changes can be done without hotplug
4124 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4125 $vmid, $opt, $value);
4126 } elsif (is_valid_drivename($opt)) {
4127 # some changes can be done without hotplug
4128 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4129 $vmid, $opt, $value, 1);
4130 } elsif ($opt =~ m/^memory$/) { #dimms
4131 die "skip
\n" if !$hotplug_features->{memory};
4132 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4133 } elsif ($opt eq 'cpuunits') {
4134 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4135 } elsif ($opt eq 'cpulimit') {
4136 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4137 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4139 die "skip
\n"; # skip non-hot-pluggable options
4143 &$add_error($opt, $err) if $err ne "skip
\n";
4145 # save new config if hotplug was successful
4146 $conf->{$opt} = $value;
4147 delete $conf->{pending}->{$opt};
4148 PVE::QemuConfig->write_config($vmid, $conf);
4149 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4154 sub try_deallocate_drive {
4155 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4157 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4158 my $volid = $drive->{file};
4159 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4160 my $sid = PVE::Storage::parse_volume_id($volid);
4161 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4163 # check if the disk is really unused
4164 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4165 if is_volume_in_use($storecfg, $conf, $key, $volid);
4166 PVE::Storage::vdisk_free($storecfg, $volid);
4169 # If vm is not owner of this disk remove from config
4177 sub vmconfig_delete_or_detach_drive {
4178 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4180 my $drive = parse_drive($opt, $conf->{$opt});
4182 my $rpcenv = PVE::RPCEnvironment::get();
4183 my $authuser = $rpcenv->get_user();
4186 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4187 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4189 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4193 sub vmconfig_apply_pending {
4194 my ($vmid, $conf, $storecfg) = @_;
4198 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4199 while (my ($opt, $force) = each %$pending_delete_hash) {
4200 die "internal error
" if $opt =~ m/^unused/;
4201 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4202 if (!defined($conf->{$opt})) {
4203 vmconfig_undelete_pending_option($conf, $opt);
4204 PVE::QemuConfig->write_config($vmid, $conf);
4205 } elsif (is_valid_drivename($opt)) {
4206 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4207 vmconfig_undelete_pending_option($conf, $opt);
4208 delete $conf->{$opt};
4209 PVE::QemuConfig->write_config($vmid, $conf);
4211 vmconfig_undelete_pending_option($conf, $opt);
4212 delete $conf->{$opt};
4213 PVE::QemuConfig->write_config($vmid, $conf);
4217 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4219 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4220 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4222 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4223 # skip if nothing changed
4224 } elsif (is_valid_drivename($opt)) {
4225 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4226 if defined($conf->{$opt});
4227 $conf->{$opt} = $conf->{pending}->{$opt};
4229 $conf->{$opt} = $conf->{pending}->{$opt};
4232 delete $conf->{pending}->{$opt};
4233 PVE::QemuConfig->write_config($vmid, $conf);
4237 my $safe_num_ne = sub {
4240 return 0 if !defined($a) && !defined($b);
4241 return 1 if !defined($a);
4242 return 1 if !defined($b);
4247 my $safe_string_ne = sub {
4250 return 0 if !defined($a) && !defined($b);
4251 return 1 if !defined($a);
4252 return 1 if !defined($b);
4257 sub vmconfig_update_net {
4258 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4260 my $newnet = parse_net($value);
4262 if ($conf->{$opt}) {
4263 my $oldnet = parse_net($conf->{$opt});
4265 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4266 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4267 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4268 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4270 # for non online change, we try to hot-unplug
4271 die "skip
\n" if !$hotplug;
4272 vm_deviceunplug($vmid, $conf, $opt);
4275 die "internal error
" if $opt !~ m/net(\d+)/;
4276 my $iface = "tap
${vmid
}i
$1";
4278 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4279 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4282 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4283 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4284 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4285 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4286 PVE::Network::tap_unplug($iface);
4287 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks});
4290 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4291 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4299 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4305 sub vmconfig_update_disk {
4306 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4308 # fixme: do we need force?
4310 my $drive = parse_drive($opt, $value);
4312 if ($conf->{$opt}) {
4314 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4316 my $media = $drive->{media} || 'disk';
4317 my $oldmedia = $old_drive->{media} || 'disk';
4318 die "unable to change media type
\n" if $media ne $oldmedia;
4320 if (!drive_is_cdrom($old_drive)) {
4322 if ($drive->{file} ne $old_drive->{file}) {
4324 die "skip
\n" if !$hotplug;
4326 # unplug and register as unused
4327 vm_deviceunplug($vmid, $conf, $opt);
4328 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4331 # update existing disk
4333 # skip non hotpluggable value
4334 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4335 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4336 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4337 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4342 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4343 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4344 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4345 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4346 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4347 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4348 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4349 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4350 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4351 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4352 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4353 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4355 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4356 ($drive->{mbps} || 0)*1024*1024,
4357 ($drive->{mbps_rd} || 0)*1024*1024,
4358 ($drive->{mbps_wr} || 0)*1024*1024,
4359 $drive->{iops} || 0,
4360 $drive->{iops_rd} || 0,
4361 $drive->{iops_wr} || 0,
4362 ($drive->{mbps_max} || 0)*1024*1024,
4363 ($drive->{mbps_rd_max} || 0)*1024*1024,
4364 ($drive->{mbps_wr_max} || 0)*1024*1024,
4365 $drive->{iops_max} || 0,
4366 $drive->{iops_rd_max} || 0,
4367 $drive->{iops_wr_max} || 0);
4376 if ($drive->{file} eq 'none') {
4377 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4379 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4380 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4381 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4389 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4391 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4392 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4396 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4397 $forcemachine, $spice_ticket) = @_;
4399 PVE::QemuConfig->lock_config($vmid, sub {
4400 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4402 die "you can
't start a vm if it's a template
\n" if PVE::QemuConfig->is_template($conf);
4404 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4406 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4408 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4409 vmconfig_apply_pending($vmid, $conf, $storecfg);
4410 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4413 my $defaults = load_defaults();
4415 # set environment variable useful inside network script
4416 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4418 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4420 my $migrate_port = 0;
4423 if ($statefile eq 'tcp') {
4424 my $localip = "localhost
";
4425 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4426 my $nodename = PVE::INotify::nodename();
4427 if ($datacenterconf->{migration_unsecure}) {
4428 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4429 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4431 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4432 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4433 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4434 push @$cmd, '-incoming', $migrate_uri;
4437 push @$cmd, '-loadstate', $statefile;
4444 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4445 my $d = parse_hostpci($conf->{"hostpci
$i"});
4447 my $pcidevices = $d->{pciid};
4448 foreach my $pcidevice (@$pcidevices) {
4449 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4451 my $info = pci_device_info("0000:$pciid");
4452 die "IOMMU
not present
\n" if !check_iommu_support();
4453 die "no pci device info
for device
'$pciid'\n" if !$info;
4454 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4455 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4459 PVE::Storage::activate_volumes($storecfg, $vollist);
4461 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4465 # deactivate volumes if start fails
4466 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4467 die "start failed
: $err";
4470 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4472 if ($statefile && $statefile ne 'tcp') {
4473 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4477 if ($migratedfrom) {
4480 set_migration_caps($vmid);
4485 print "spice listens on port
$spice_port\n";
4486 if ($spice_ticket) {
4487 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4488 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4494 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4495 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4496 if $conf->{balloon};
4499 foreach my $opt (keys %$conf) {
4500 next if $opt !~ m/^net\d+$/;
4501 my $nicconf = parse_net($conf->{$opt});
4502 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4506 vm_mon_cmd_nocheck($vmid, 'qom-set',
4507 path => "machine
/peripheral/balloon0
",
4508 property => "guest-stats-polling-interval
",
4509 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4515 my ($vmid, $execute, %params) = @_;
4517 my $cmd = { execute => $execute, arguments => \%params };
4518 vm_qmp_command($vmid, $cmd);
4521 sub vm_mon_cmd_nocheck {
4522 my ($vmid, $execute, %params) = @_;
4524 my $cmd = { execute => $execute, arguments => \%params };
4525 vm_qmp_command($vmid, $cmd, 1);
4528 sub vm_qmp_command {
4529 my ($vmid, $cmd, $nocheck) = @_;
4534 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4535 $timeout = $cmd->{arguments}->{timeout};
4536 delete $cmd->{arguments}->{timeout};
4540 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4541 my $sname = qmp_socket($vmid);
4542 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4543 my $qmpclient = PVE::QMPClient->new();
4545 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4546 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4547 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4548 if scalar(%{$cmd->{arguments}});
4549 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4551 die "unable to open monitor socket\n";
4555 syslog("err", "VM $vmid qmp command failed - $err");
4562 sub vm_human_monitor_command {
4563 my ($vmid, $cmdline) = @_;
4568 execute => 'human-monitor-command
',
4569 arguments => { 'command-line
' => $cmdline},
4572 return vm_qmp_command($vmid, $cmd);
4575 sub vm_commandline {
4576 my ($storecfg, $vmid) = @_;
4578 my $conf = PVE::QemuConfig->load_config($vmid);
4580 my $defaults = load_defaults();
4582 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4584 return join(' ', @$cmd);
4588 my ($vmid, $skiplock) = @_;
4590 PVE::QemuConfig->lock_config($vmid, sub {
4592 my $conf = PVE::QemuConfig->load_config($vmid);
4594 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4596 vm_mon_cmd($vmid, "system_reset");
4600 sub get_vm_volumes {
4604 foreach_volid($conf, sub {
4605 my ($volid, $is_cdrom) = @_;
4607 return if $volid =~ m|^/|;
4609 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4612 push @$vollist, $volid;
4618 sub vm_stop_cleanup {
4619 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4624 my $vollist = get_vm_volumes($conf);
4625 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4628 foreach my $ext (qw(mon qmp pid vnc qga)) {
4629 unlink "/var/run/qemu-server/${vmid}.$ext";
4632 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4634 warn $@ if $@; # avoid errors - just warn
4637 # Note: use $nockeck to skip tests if VM configuration file exists.
4638 # We need that when migration VMs to other nodes (files already moved)
4639 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4641 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4643 $force = 1 if !defined($force) && !$shutdown;
4646 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4647 kill 15, $pid if $pid;
4648 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4649 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4653 PVE
::QemuConfig-
>lock_config($vmid, sub {
4655 my $pid = check_running
($vmid, $nocheck);
4660 $conf = PVE
::QemuConfig-
>load_config($vmid);
4661 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4662 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4663 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4664 $timeout = $opts->{down
} if $opts->{down
};
4668 $timeout = 60 if !defined($timeout);
4672 if (defined($conf) && $conf->{agent
}) {
4673 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4675 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4678 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4685 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4690 if ($count >= $timeout) {
4692 warn "VM still running - terminating now with SIGTERM\n";
4695 die "VM quit/powerdown failed - got timeout\n";
4698 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4703 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4706 die "VM quit/powerdown failed\n";
4714 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4719 if ($count >= $timeout) {
4720 warn "VM still running - terminating now with SIGKILL\n";
4725 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4730 my ($vmid, $skiplock) = @_;
4732 PVE
::QemuConfig-
>lock_config($vmid, sub {
4734 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4736 PVE
::QemuConfig-
>check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4738 vm_mon_cmd
($vmid, "stop");
4743 my ($vmid, $skiplock, $nocheck) = @_;
4745 PVE
::QemuConfig-
>lock_config($vmid, sub {
4749 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4751 PVE
::QemuConfig-
>check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4753 vm_mon_cmd
($vmid, "cont");
4756 vm_mon_cmd_nocheck
($vmid, "cont");
4762 my ($vmid, $skiplock, $key) = @_;
4764 PVE
::QemuConfig-
>lock_config($vmid, sub {
4766 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4768 # there is no qmp command, so we use the human monitor command
4769 vm_human_monitor_command
($vmid, "sendkey $key");
4774 my ($storecfg, $vmid, $skiplock) = @_;
4776 PVE
::QemuConfig-
>lock_config($vmid, sub {
4778 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4780 if (!check_running
($vmid)) {
4781 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4783 die "VM $vmid is running - destroy failed\n";
4791 my ($filename, $buf) = @_;
4793 my $fh = IO
::File-
>new($filename, "w");
4794 return undef if !$fh;
4796 my $res = print $fh $buf;
4803 sub pci_device_info
{
4808 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4809 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4811 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4812 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4814 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4815 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4817 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4818 return undef if !defined($product) || $product !~ s/^0x//;
4823 product
=> $product,
4829 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4838 my $name = $dev->{name
};
4840 my $fn = "$pcisysfs/devices/$name/reset";
4842 return file_write
($fn, "1");
4845 sub pci_dev_bind_to_vfio
{
4848 my $name = $dev->{name
};
4850 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4852 if (!-d
$vfio_basedir) {
4853 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4855 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4857 my $testdir = "$vfio_basedir/$name";
4858 return 1 if -d
$testdir;
4860 my $data = "$dev->{vendor} $dev->{product}";
4861 return undef if !file_write
("$vfio_basedir/new_id", $data);
4863 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4864 if (!file_write
($fn, $name)) {
4865 return undef if -f
$fn;
4868 $fn = "$vfio_basedir/bind";
4869 if (! -d
$testdir) {
4870 return undef if !file_write
($fn, $name);
4876 sub pci_dev_group_bind_to_vfio
{
4879 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4881 if (!-d
$vfio_basedir) {
4882 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4884 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4886 # get IOMMU group devices
4887 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4888 my @devs = grep /^0000:/, readdir($D);
4891 foreach my $pciid (@devs) {
4892 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4894 # pci bridges, switches or root ports are not supported
4895 # they have a pci_bus subdirectory so skip them
4896 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4898 my $info = pci_device_info
($1);
4899 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4905 sub print_pci_addr
{
4906 my ($id, $bridges) = @_;
4910 piix3
=> { bus
=> 0, addr
=> 1 },
4911 #addr2 : first videocard
4912 balloon0
=> { bus
=> 0, addr
=> 3 },
4913 watchdog
=> { bus
=> 0, addr
=> 4 },
4914 scsihw0
=> { bus
=> 0, addr
=> 5 },
4915 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4916 scsihw1
=> { bus
=> 0, addr
=> 6 },
4917 ahci0
=> { bus
=> 0, addr
=> 7 },
4918 qga0
=> { bus
=> 0, addr
=> 8 },
4919 spice
=> { bus
=> 0, addr
=> 9 },
4920 virtio0
=> { bus
=> 0, addr
=> 10 },
4921 virtio1
=> { bus
=> 0, addr
=> 11 },
4922 virtio2
=> { bus
=> 0, addr
=> 12 },
4923 virtio3
=> { bus
=> 0, addr
=> 13 },
4924 virtio4
=> { bus
=> 0, addr
=> 14 },
4925 virtio5
=> { bus
=> 0, addr
=> 15 },
4926 hostpci0
=> { bus
=> 0, addr
=> 16 },
4927 hostpci1
=> { bus
=> 0, addr
=> 17 },
4928 net0
=> { bus
=> 0, addr
=> 18 },
4929 net1
=> { bus
=> 0, addr
=> 19 },
4930 net2
=> { bus
=> 0, addr
=> 20 },
4931 net3
=> { bus
=> 0, addr
=> 21 },
4932 net4
=> { bus
=> 0, addr
=> 22 },
4933 net5
=> { bus
=> 0, addr
=> 23 },
4934 vga1
=> { bus
=> 0, addr
=> 24 },
4935 vga2
=> { bus
=> 0, addr
=> 25 },
4936 vga3
=> { bus
=> 0, addr
=> 26 },
4937 hostpci2
=> { bus
=> 0, addr
=> 27 },
4938 hostpci3
=> { bus
=> 0, addr
=> 28 },
4939 #addr29 : usb-host (pve-usb.cfg)
4940 'pci.1' => { bus
=> 0, addr
=> 30 },
4941 'pci.2' => { bus
=> 0, addr
=> 31 },
4942 'net6' => { bus
=> 1, addr
=> 1 },
4943 'net7' => { bus
=> 1, addr
=> 2 },
4944 'net8' => { bus
=> 1, addr
=> 3 },
4945 'net9' => { bus
=> 1, addr
=> 4 },
4946 'net10' => { bus
=> 1, addr
=> 5 },
4947 'net11' => { bus
=> 1, addr
=> 6 },
4948 'net12' => { bus
=> 1, addr
=> 7 },
4949 'net13' => { bus
=> 1, addr
=> 8 },
4950 'net14' => { bus
=> 1, addr
=> 9 },
4951 'net15' => { bus
=> 1, addr
=> 10 },
4952 'net16' => { bus
=> 1, addr
=> 11 },
4953 'net17' => { bus
=> 1, addr
=> 12 },
4954 'net18' => { bus
=> 1, addr
=> 13 },
4955 'net19' => { bus
=> 1, addr
=> 14 },
4956 'net20' => { bus
=> 1, addr
=> 15 },
4957 'net21' => { bus
=> 1, addr
=> 16 },
4958 'net22' => { bus
=> 1, addr
=> 17 },
4959 'net23' => { bus
=> 1, addr
=> 18 },
4960 'net24' => { bus
=> 1, addr
=> 19 },
4961 'net25' => { bus
=> 1, addr
=> 20 },
4962 'net26' => { bus
=> 1, addr
=> 21 },
4963 'net27' => { bus
=> 1, addr
=> 22 },
4964 'net28' => { bus
=> 1, addr
=> 23 },
4965 'net29' => { bus
=> 1, addr
=> 24 },
4966 'net30' => { bus
=> 1, addr
=> 25 },
4967 'net31' => { bus
=> 1, addr
=> 26 },
4968 'xhci' => { bus
=> 1, addr
=> 27 },
4969 'virtio6' => { bus
=> 2, addr
=> 1 },
4970 'virtio7' => { bus
=> 2, addr
=> 2 },
4971 'virtio8' => { bus
=> 2, addr
=> 3 },
4972 'virtio9' => { bus
=> 2, addr
=> 4 },
4973 'virtio10' => { bus
=> 2, addr
=> 5 },
4974 'virtio11' => { bus
=> 2, addr
=> 6 },
4975 'virtio12' => { bus
=> 2, addr
=> 7 },
4976 'virtio13' => { bus
=> 2, addr
=> 8 },
4977 'virtio14' => { bus
=> 2, addr
=> 9 },
4978 'virtio15' => { bus
=> 2, addr
=> 10 },
4979 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4980 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4981 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4982 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4983 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4984 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4985 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4986 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4987 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4988 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4989 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4990 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4991 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4992 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4993 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4994 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4995 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4996 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4997 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4998 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4999 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5000 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5001 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5002 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5003 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5004 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5005 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5006 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5007 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5008 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5009 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5013 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5014 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5015 my $bus = $devices->{$id}->{bus
};
5016 $res = ",bus=pci.$bus,addr=$addr";
5017 $bridges->{$bus} = 1 if $bridges;
5023 sub print_pcie_addr
{
5028 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5029 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5030 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5031 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5034 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5035 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5036 my $bus = $devices->{$id}->{bus
};
5037 $res = ",bus=$bus,addr=$addr";
5043 # vzdump restore implementaion
5045 sub tar_archive_read_firstfile
{
5046 my $archive = shift;
5048 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5050 # try to detect archive type first
5051 my $pid = open (TMP
, "tar tf '$archive'|") ||
5052 die "unable to open file '$archive'\n";
5053 my $firstfile = <TMP
>;
5057 die "ERROR: archive contaions no data\n" if !$firstfile;
5063 sub tar_restore_cleanup
{
5064 my ($storecfg, $statfile) = @_;
5066 print STDERR
"starting cleanup\n";
5068 if (my $fd = IO
::File-
>new($statfile, "r")) {
5069 while (defined(my $line = <$fd>)) {
5070 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5073 if ($volid =~ m
|^/|) {
5074 unlink $volid || die 'unlink failed\n';
5076 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5078 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5080 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5082 print STDERR
"unable to parse line in statfile - $line";
5089 sub restore_archive
{
5090 my ($archive, $vmid, $user, $opts) = @_;
5092 my $format = $opts->{format
};
5095 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5096 $format = 'tar' if !$format;
5098 } elsif ($archive =~ m/\.tar$/) {
5099 $format = 'tar' if !$format;
5100 } elsif ($archive =~ m/.tar.lzo$/) {
5101 $format = 'tar' if !$format;
5103 } elsif ($archive =~ m/\.vma$/) {
5104 $format = 'vma' if !$format;
5105 } elsif ($archive =~ m/\.vma\.gz$/) {
5106 $format = 'vma' if !$format;
5108 } elsif ($archive =~ m/\.vma\.lzo$/) {
5109 $format = 'vma' if !$format;
5112 $format = 'vma' if !$format; # default
5115 # try to detect archive format
5116 if ($format eq 'tar') {
5117 return restore_tar_archive
($archive, $vmid, $user, $opts);
5119 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5123 sub restore_update_config_line
{
5124 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5126 return if $line =~ m/^\#qmdump\#/;
5127 return if $line =~ m/^\#vzdump\#/;
5128 return if $line =~ m/^lock:/;
5129 return if $line =~ m/^unused\d+:/;
5130 return if $line =~ m/^parent:/;
5131 return if $line =~ m/^template:/; # restored VM is never a template
5133 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5134 # try to convert old 1.X settings
5135 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5136 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5137 my ($model, $macaddr) = split(/\=/, $devconfig);
5138 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5141 bridge
=> "vmbr$ind",
5142 macaddr
=> $macaddr,
5144 my $netstr = print_net
($net);
5146 print $outfd "net$cookie->{netcount}: $netstr\n";
5147 $cookie->{netcount
}++;
5149 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5150 my ($id, $netstr) = ($1, $2);
5151 my $net = parse_net
($netstr);
5152 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5153 $netstr = print_net
($net);
5154 print $outfd "$id: $netstr\n";
5155 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5158 my $di = parse_drive
($virtdev, $value);
5159 if (defined($di->{backup
}) && !$di->{backup
}) {
5160 print $outfd "#$line";
5161 } elsif ($map->{$virtdev}) {
5162 delete $di->{format
}; # format can change on restore
5163 $di->{file
} = $map->{$virtdev};
5164 $value = print_drive
($vmid, $di);
5165 print $outfd "$virtdev: $value\n";
5175 my ($cfg, $vmid) = @_;
5177 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5179 my $volid_hash = {};
5180 foreach my $storeid (keys %$info) {
5181 foreach my $item (@{$info->{$storeid}}) {
5182 next if !($item->{volid
} && $item->{size
});
5183 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5184 $volid_hash->{$item->{volid
}} = $item;
5191 sub is_volume_in_use
{
5192 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5194 my $path = PVE
::Storage
::path
($storecfg, $volid);
5196 my $scan_config = sub {
5197 my ($cref, $snapname) = @_;
5199 foreach my $key (keys %$cref) {
5200 my $value = $cref->{$key};
5201 if (is_valid_drivename
($key)) {
5202 next if $skip_drive && $key eq $skip_drive;
5203 my $drive = parse_drive
($key, $value);
5204 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5205 return 1 if $volid eq $drive->{file
};
5206 if ($drive->{file
} =~ m!^/!) {
5207 return 1 if $drive->{file
} eq $path;
5209 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5211 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5213 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5221 return 1 if &$scan_config($conf);
5225 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5226 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5232 sub update_disksize
{
5233 my ($vmid, $conf, $volid_hash) = @_;
5239 # Note: it is allowed to define multiple storages with same path (alias), so
5240 # we need to check both 'volid' and real 'path' (two different volid can point
5241 # to the same path).
5246 foreach my $opt (keys %$conf) {
5247 if (is_valid_drivename
($opt)) {
5248 my $drive = parse_drive
($opt, $conf->{$opt});
5249 my $volid = $drive->{file
};
5252 $used->{$volid} = 1;
5253 if ($volid_hash->{$volid} &&
5254 (my $path = $volid_hash->{$volid}->{path
})) {
5255 $usedpath->{$path} = 1;
5258 next if drive_is_cdrom
($drive);
5259 next if !$volid_hash->{$volid};
5261 $drive->{size
} = $volid_hash->{$volid}->{size
};
5262 my $new = print_drive
($vmid, $drive);
5263 if ($new ne $conf->{$opt}) {
5265 $conf->{$opt} = $new;
5270 # remove 'unusedX' entry if volume is used
5271 foreach my $opt (keys %$conf) {
5272 next if $opt !~ m/^unused\d+$/;
5273 my $volid = $conf->{$opt};
5274 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5275 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5277 delete $conf->{$opt};
5281 foreach my $volid (sort keys %$volid_hash) {
5282 next if $volid =~ m/vm-$vmid-state-/;
5283 next if $used->{$volid};
5284 my $path = $volid_hash->{$volid}->{path
};
5285 next if !$path; # just to be sure
5286 next if $usedpath->{$path};
5288 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5289 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5296 my ($vmid, $nolock) = @_;
5298 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5300 my $volid_hash = scan_volids
($cfg, $vmid);
5302 my $updatefn = sub {
5305 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5307 PVE
::QemuConfig-
>check_lock($conf);
5310 foreach my $volid (keys %$volid_hash) {
5311 my $info = $volid_hash->{$volid};
5312 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5315 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5317 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5320 if (defined($vmid)) {
5324 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5327 my $vmlist = config_list
();
5328 foreach my $vmid (keys %$vmlist) {
5332 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5338 sub restore_vma_archive
{
5339 my ($archive, $vmid, $user, $opts, $comp) = @_;
5341 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5342 my $readfrom = $archive;
5347 my $qarchive = PVE
::Tools
::shellquote
($archive);
5348 if ($comp eq 'gzip') {
5349 $uncomp = "zcat $qarchive|";
5350 } elsif ($comp eq 'lzop') {
5351 $uncomp = "lzop -d -c $qarchive|";
5353 die "unknown compression method '$comp'\n";
5358 my $tmpdir = "/var/tmp/vzdumptmp$$";
5361 # disable interrupts (always do cleanups)
5362 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5363 warn "got interrupt - ignored\n";
5366 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5367 POSIX
::mkfifo
($mapfifo, 0600);
5370 my $openfifo = sub {
5371 open($fifofh, '>', $mapfifo) || die $!;
5374 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5381 my $rpcenv = PVE
::RPCEnvironment
::get
();
5383 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5384 my $tmpfn = "$conffile.$$.tmp";
5386 # Note: $oldconf is undef if VM does not exists
5387 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5388 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5390 my $print_devmap = sub {
5391 my $virtdev_hash = {};
5393 my $cfgfn = "$tmpdir/qemu-server.conf";
5395 # we can read the config - that is already extracted
5396 my $fh = IO
::File-
>new($cfgfn, "r") ||
5397 "unable to read qemu-server.conf - $!\n";
5399 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5401 my $pve_firewall_dir = '/etc/pve/firewall';
5402 mkdir $pve_firewall_dir; # make sure the dir exists
5403 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5406 while (defined(my $line = <$fh>)) {
5407 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5408 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5409 die "archive does not contain data for drive '$virtdev'\n"
5410 if !$devinfo->{$devname};
5411 if (defined($opts->{storage
})) {
5412 $storeid = $opts->{storage
} || 'local';
5413 } elsif (!$storeid) {
5416 $format = 'raw' if !$format;
5417 $devinfo->{$devname}->{devname
} = $devname;
5418 $devinfo->{$devname}->{virtdev
} = $virtdev;
5419 $devinfo->{$devname}->{format
} = $format;
5420 $devinfo->{$devname}->{storeid
} = $storeid;
5422 # check permission on storage
5423 my $pool = $opts->{pool
}; # todo: do we need that?
5424 if ($user ne 'root@pam') {
5425 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5428 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5432 foreach my $devname (keys %$devinfo) {
5433 die "found no device mapping information for device '$devname'\n"
5434 if !$devinfo->{$devname}->{virtdev
};
5437 my $cfg = cfs_read_file
('storage.cfg');
5439 # create empty/temp config
5441 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5442 foreach_drive
($oldconf, sub {
5443 my ($ds, $drive) = @_;
5445 return if drive_is_cdrom
($drive);
5447 my $volid = $drive->{file
};
5449 return if !$volid || $volid =~ m
|^/|;
5451 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5452 return if !$path || !$owner || ($owner != $vmid);
5454 # Note: only delete disk we want to restore
5455 # other volumes will become unused
5456 if ($virtdev_hash->{$ds}) {
5457 PVE
::Storage
::vdisk_free
($cfg, $volid);
5461 # delete vmstate files
5462 # since after the restore we have no snapshots anymore
5463 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5464 my $snap = $oldconf->{snapshots
}->{$snapname};
5465 if ($snap->{vmstate
}) {
5466 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5475 foreach my $virtdev (sort keys %$virtdev_hash) {
5476 my $d = $virtdev_hash->{$virtdev};
5477 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5478 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5480 # test if requested format is supported
5481 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5482 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5483 $d->{format
} = $defFormat if !$supported;
5485 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5486 $d->{format
}, undef, $alloc_size);
5487 print STDERR
"new volume ID is '$volid'\n";
5488 $d->{volid
} = $volid;
5489 my $path = PVE
::Storage
::path
($cfg, $volid);
5491 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5493 my $write_zeros = 1;
5494 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5498 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5500 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5501 $map->{$virtdev} = $volid;
5504 $fh->seek(0, 0) || die "seek failed - $!\n";
5506 my $outfd = new IO
::File
($tmpfn, "w") ||
5507 die "unable to write config for VM $vmid\n";
5509 my $cookie = { netcount
=> 0 };
5510 while (defined(my $line = <$fh>)) {
5511 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5520 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5521 die "interrupted by signal\n";
5523 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5525 $oldtimeout = alarm($timeout);
5532 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5533 my ($dev_id, $size, $devname) = ($1, $2, $3);
5534 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5535 } elsif ($line =~ m/^CTIME: /) {
5536 # we correctly received the vma config, so we can disable
5537 # the timeout now for disk allocation (set to 10 minutes, so
5538 # that we always timeout if something goes wrong)
5541 print $fifofh "done\n";
5542 my $tmp = $oldtimeout || 0;
5543 $oldtimeout = undef;
5549 print "restore vma archive: $cmd\n";
5550 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5554 alarm($oldtimeout) if $oldtimeout;
5557 foreach my $devname (keys %$devinfo) {
5558 my $volid = $devinfo->{$devname}->{volid
};
5559 push @$vollist, $volid if $volid;
5562 my $cfg = cfs_read_file
('storage.cfg');
5563 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5571 foreach my $devname (keys %$devinfo) {
5572 my $volid = $devinfo->{$devname}->{volid
};
5575 if ($volid =~ m
|^/|) {
5576 unlink $volid || die 'unlink failed\n';
5578 PVE
::Storage
::vdisk_free
($cfg, $volid);
5580 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5582 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5589 rename($tmpfn, $conffile) ||
5590 die "unable to commit configuration file '$conffile'\n";
5592 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5594 eval { rescan
($vmid, 1); };
5598 sub restore_tar_archive
{
5599 my ($archive, $vmid, $user, $opts) = @_;
5601 if ($archive ne '-') {
5602 my $firstfile = tar_archive_read_firstfile
($archive);
5603 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5604 if $firstfile ne 'qemu-server.conf';
5607 my $storecfg = cfs_read_file
('storage.cfg');
5609 # destroy existing data - keep empty config
5610 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5611 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5613 my $tocmd = "/usr/lib/qemu-server/qmextract";
5615 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5616 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5617 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5618 $tocmd .= ' --info' if $opts->{info
};
5620 # tar option "xf" does not autodetect compression when read from STDIN,
5621 # so we pipe to zcat
5622 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5623 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5625 my $tmpdir = "/var/tmp/vzdumptmp$$";
5628 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5629 local $ENV{VZDUMP_VMID
} = $vmid;
5630 local $ENV{VZDUMP_USER
} = $user;
5632 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5633 my $tmpfn = "$conffile.$$.tmp";
5635 # disable interrupts (always do cleanups)
5636 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5637 print STDERR
"got interrupt - ignored\n";
5642 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5643 die "interrupted by signal\n";
5646 if ($archive eq '-') {
5647 print "extracting archive from STDIN\n";
5648 run_command
($cmd, input
=> "<&STDIN");
5650 print "extracting archive '$archive'\n";
5654 return if $opts->{info
};
5658 my $statfile = "$tmpdir/qmrestore.stat";
5659 if (my $fd = IO
::File-
>new($statfile, "r")) {
5660 while (defined (my $line = <$fd>)) {
5661 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5662 $map->{$1} = $2 if $1;
5664 print STDERR
"unable to parse line in statfile - $line\n";
5670 my $confsrc = "$tmpdir/qemu-server.conf";
5672 my $srcfd = new IO
::File
($confsrc, "r") ||
5673 die "unable to open file '$confsrc'\n";
5675 my $outfd = new IO
::File
($tmpfn, "w") ||
5676 die "unable to write config for VM $vmid\n";
5678 my $cookie = { netcount
=> 0 };
5679 while (defined (my $line = <$srcfd>)) {
5680 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5692 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5699 rename $tmpfn, $conffile ||
5700 die "unable to commit configuration file '$conffile'\n";
5702 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5704 eval { rescan
($vmid, 1); };
5708 sub foreach_writable_storage
{
5709 my ($conf, $func) = @_;
5713 foreach my $ds (keys %$conf) {
5714 next if !is_valid_drivename
($ds);
5716 my $drive = parse_drive
($ds, $conf->{$ds});
5718 next if drive_is_cdrom
($drive);
5720 my $volid = $drive->{file
};
5722 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5723 $sidhash->{$sid} = $sid if $sid;
5726 foreach my $sid (sort keys %$sidhash) {
5731 sub do_snapshots_with_qemu
{
5732 my ($storecfg, $volid) = @_;
5734 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5736 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5737 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5741 if ($volid =~ m/\.(qcow2|qed)$/){
5748 sub qga_check_running
{
5751 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5753 warn "Qemu Guest Agent are not running - $@";
5759 sub template_create
{
5760 my ($vmid, $conf, $disk) = @_;
5762 my $storecfg = PVE
::Storage
::config
();
5764 foreach_drive
($conf, sub {
5765 my ($ds, $drive) = @_;
5767 return if drive_is_cdrom
($drive);
5768 return if $disk && $ds ne $disk;
5770 my $volid = $drive->{file
};
5771 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5773 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5774 $drive->{file
} = $voliddst;
5775 $conf->{$ds} = print_drive
($vmid, $drive);
5776 PVE
::QemuConfig-
>write_config($vmid, $conf);
5780 sub qemu_img_convert
{
5781 my ($src_volid, $dst_volid, $size, $snapname) = @_;
5783 my $storecfg = PVE
::Storage
::config
();
5784 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5785 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5787 if ($src_storeid && $dst_storeid) {
5789 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5791 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5792 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5794 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5795 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5797 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5798 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5801 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5802 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5803 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
5807 if($line =~ m/\((\S+)\/100\
%\)/){
5809 my $transferred = int($size * $percent / 100);
5810 my $remaining = $size - $transferred;
5812 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5817 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5819 die "copy failed: $err" if $err;
5823 sub qemu_img_format
{
5824 my ($scfg, $volname) = @_;
5826 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5833 sub qemu_drive_mirror
{
5834 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
5836 my $storecfg = PVE
::Storage
::config
();
5837 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5839 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5841 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5843 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5845 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
5846 $opts->{format
} = $format if $format;
5848 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5851 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5853 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5854 my $stat = @$stats[0];
5855 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5856 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5858 my $busy = $stat->{busy
};
5859 my $ready = $stat->{ready
};
5861 if (my $total = $stat->{len
}) {
5862 my $transferred = $stat->{offset
} || 0;
5863 my $remaining = $total - $transferred;
5864 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5866 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5870 if ($stat->{ready
} eq 'true') {
5872 last if $vmiddst != $vmid;
5874 # try to switch the disk if source and destination are on the same guest
5875 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5877 die $@ if $@ !~ m/cannot be completed/;
5886 my $cancel_job = sub {
5887 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5889 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5890 my $stat = @$stats[0];
5897 eval { &$cancel_job(); };
5898 die "mirroring error: $err";
5901 if ($vmiddst != $vmid) {
5902 # if we clone a disk for a new target vm, we don't switch the disk
5903 &$cancel_job(); # so we call block-job-cancel
5908 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5909 $newvmid, $storage, $format, $full, $newvollist) = @_;
5914 print "create linked clone of drive $drivename ($drive->{file})\n";
5915 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5916 push @$newvollist, $newvolid;
5918 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5919 $storeid = $storage if $storage;
5921 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5923 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5924 $format = qemu_img_format
($scfg, $volname);
5927 # test if requested format is supported - else use default
5928 my $supported = grep { $_ eq $format } @$validFormats;
5929 $format = $defFormat if !$supported;
5931 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5933 print "create full clone of drive $drivename ($drive->{file})\n";
5934 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5935 push @$newvollist, $newvolid;
5937 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5939 if (!$running || $snapname) {
5940 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
5942 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
5946 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5949 $disk->{format
} = undef;
5950 $disk->{file
} = $newvolid;
5951 $disk->{size
} = $size;
5956 # this only works if VM is running
5957 sub get_current_qemu_machine
{
5960 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5961 my $res = vm_qmp_command
($vmid, $cmd);
5963 my ($current, $default);
5964 foreach my $e (@$res) {
5965 $default = $e->{name
} if $e->{'is-default'};
5966 $current = $e->{name
} if $e->{'is-current'};
5969 # fallback to the default machine if current is not supported by qemu
5970 return $current || $default || 'pc';
5973 sub qemu_machine_feature_enabled
{
5974 my ($machine, $kvmver, $version_major, $version_minor) = @_;
5979 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
5981 $current_major = $3;
5982 $current_minor = $4;
5984 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
5986 $current_major = $1;
5987 $current_minor = $2;
5990 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
5995 sub qemu_machine_pxe
{
5996 my ($vmid, $conf, $machine) = @_;
5998 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6000 foreach my $opt (keys %$conf) {
6001 next if $opt !~ m/^net(\d+)$/;
6002 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6004 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6005 return $machine.".pxe" if $romfile =~ m/pxe/;
6012 sub qemu_use_old_bios_files
{
6013 my ($machine_type) = @_;
6015 return if !$machine_type;
6017 my $use_old_bios_files = undef;
6019 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6021 $use_old_bios_files = 1;
6023 my $kvmver = kvm_user_version
();
6024 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6025 # load new efi bios files on migration. So this hack is required to allow
6026 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6027 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6028 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6031 return ($use_old_bios_files, $machine_type);
6038 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6039 my (undef, $id, $function) = @_;
6040 my $res = { id
=> $id, function
=> $function};
6041 push @{$devices->{$id}}, $res;
6047 sub vm_iothreads_list
{
6050 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6053 foreach my $iothread (@$res) {
6054 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6061 my ($conf, $drive) = @_;
6065 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6067 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6073 my $controller = int($drive->{index} / $maxdev);
6074 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6076 return ($maxdev, $controller, $controller_prefix);
6079 # bash completion helper
6081 sub complete_backup_archives
{
6082 my ($cmdname, $pname, $cvalue) = @_;
6084 my $cfg = PVE
::Storage
::config
();
6088 if ($cvalue =~ m/^([^:]+):/) {
6092 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6095 foreach my $id (keys %$data) {
6096 foreach my $item (@{$data->{$id}}) {
6097 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6098 push @$res, $item->{volid
} if defined($item->{volid
});
6105 my $complete_vmid_full = sub {
6108 my $idlist = vmstatus
();
6112 foreach my $id (keys %$idlist) {
6113 my $d = $idlist->{$id};
6114 if (defined($running)) {
6115 next if $d->{template
};
6116 next if $running && $d->{status
} ne 'running';
6117 next if !$running && $d->{status
} eq 'running';
6126 return &$complete_vmid_full();
6129 sub complete_vmid_stopped
{
6130 return &$complete_vmid_full(0);
6133 sub complete_vmid_running
{
6134 return &$complete_vmid_full(1);
6137 sub complete_storage
{
6139 my $cfg = PVE
::Storage
::config
();
6140 my $ids = $cfg->{ids
};
6143 foreach my $sid (keys %$ids) {
6144 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6145 next if !$ids->{$sid}->{content
}->{images
};