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_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4279 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4280 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4281 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4282 PVE::Network::tap_unplug($iface);
4283 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
4284 } elsif (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4285 # Rate can be applied on its own but any change above needs to
4286 # include the rate in tap_plug since OVS resets everything.
4287 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
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)
4737 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4739 vm_mon_cmd
($vmid, "stop");
4744 my ($vmid, $skiplock, $nocheck) = @_;
4746 PVE
::QemuConfig-
>lock_config($vmid, sub {
4750 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4752 PVE
::QemuConfig-
>check_lock($conf)
4753 if !($skiplock || PVE
::QemuConfig-
>has_lock($conf, 'backup'));
4755 vm_mon_cmd
($vmid, "cont");
4758 vm_mon_cmd_nocheck
($vmid, "cont");
4764 my ($vmid, $skiplock, $key) = @_;
4766 PVE
::QemuConfig-
>lock_config($vmid, sub {
4768 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4770 # there is no qmp command, so we use the human monitor command
4771 vm_human_monitor_command
($vmid, "sendkey $key");
4776 my ($storecfg, $vmid, $skiplock) = @_;
4778 PVE
::QemuConfig-
>lock_config($vmid, sub {
4780 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4782 if (!check_running
($vmid)) {
4783 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4785 die "VM $vmid is running - destroy failed\n";
4793 my ($filename, $buf) = @_;
4795 my $fh = IO
::File-
>new($filename, "w");
4796 return undef if !$fh;
4798 my $res = print $fh $buf;
4805 sub pci_device_info
{
4810 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4811 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4813 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4814 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4816 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4817 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4819 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4820 return undef if !defined($product) || $product !~ s/^0x//;
4825 product
=> $product,
4831 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4840 my $name = $dev->{name
};
4842 my $fn = "$pcisysfs/devices/$name/reset";
4844 return file_write
($fn, "1");
4847 sub pci_dev_bind_to_vfio
{
4850 my $name = $dev->{name
};
4852 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4854 if (!-d
$vfio_basedir) {
4855 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4857 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4859 my $testdir = "$vfio_basedir/$name";
4860 return 1 if -d
$testdir;
4862 my $data = "$dev->{vendor} $dev->{product}";
4863 return undef if !file_write
("$vfio_basedir/new_id", $data);
4865 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4866 if (!file_write
($fn, $name)) {
4867 return undef if -f
$fn;
4870 $fn = "$vfio_basedir/bind";
4871 if (! -d
$testdir) {
4872 return undef if !file_write
($fn, $name);
4878 sub pci_dev_group_bind_to_vfio
{
4881 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4883 if (!-d
$vfio_basedir) {
4884 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4886 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4888 # get IOMMU group devices
4889 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4890 my @devs = grep /^0000:/, readdir($D);
4893 foreach my $pciid (@devs) {
4894 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4896 # pci bridges, switches or root ports are not supported
4897 # they have a pci_bus subdirectory so skip them
4898 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4900 my $info = pci_device_info
($1);
4901 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4907 sub print_pci_addr
{
4908 my ($id, $bridges) = @_;
4912 piix3
=> { bus
=> 0, addr
=> 1 },
4913 #addr2 : first videocard
4914 balloon0
=> { bus
=> 0, addr
=> 3 },
4915 watchdog
=> { bus
=> 0, addr
=> 4 },
4916 scsihw0
=> { bus
=> 0, addr
=> 5 },
4917 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4918 scsihw1
=> { bus
=> 0, addr
=> 6 },
4919 ahci0
=> { bus
=> 0, addr
=> 7 },
4920 qga0
=> { bus
=> 0, addr
=> 8 },
4921 spice
=> { bus
=> 0, addr
=> 9 },
4922 virtio0
=> { bus
=> 0, addr
=> 10 },
4923 virtio1
=> { bus
=> 0, addr
=> 11 },
4924 virtio2
=> { bus
=> 0, addr
=> 12 },
4925 virtio3
=> { bus
=> 0, addr
=> 13 },
4926 virtio4
=> { bus
=> 0, addr
=> 14 },
4927 virtio5
=> { bus
=> 0, addr
=> 15 },
4928 hostpci0
=> { bus
=> 0, addr
=> 16 },
4929 hostpci1
=> { bus
=> 0, addr
=> 17 },
4930 net0
=> { bus
=> 0, addr
=> 18 },
4931 net1
=> { bus
=> 0, addr
=> 19 },
4932 net2
=> { bus
=> 0, addr
=> 20 },
4933 net3
=> { bus
=> 0, addr
=> 21 },
4934 net4
=> { bus
=> 0, addr
=> 22 },
4935 net5
=> { bus
=> 0, addr
=> 23 },
4936 vga1
=> { bus
=> 0, addr
=> 24 },
4937 vga2
=> { bus
=> 0, addr
=> 25 },
4938 vga3
=> { bus
=> 0, addr
=> 26 },
4939 hostpci2
=> { bus
=> 0, addr
=> 27 },
4940 hostpci3
=> { bus
=> 0, addr
=> 28 },
4941 #addr29 : usb-host (pve-usb.cfg)
4942 'pci.1' => { bus
=> 0, addr
=> 30 },
4943 'pci.2' => { bus
=> 0, addr
=> 31 },
4944 'net6' => { bus
=> 1, addr
=> 1 },
4945 'net7' => { bus
=> 1, addr
=> 2 },
4946 'net8' => { bus
=> 1, addr
=> 3 },
4947 'net9' => { bus
=> 1, addr
=> 4 },
4948 'net10' => { bus
=> 1, addr
=> 5 },
4949 'net11' => { bus
=> 1, addr
=> 6 },
4950 'net12' => { bus
=> 1, addr
=> 7 },
4951 'net13' => { bus
=> 1, addr
=> 8 },
4952 'net14' => { bus
=> 1, addr
=> 9 },
4953 'net15' => { bus
=> 1, addr
=> 10 },
4954 'net16' => { bus
=> 1, addr
=> 11 },
4955 'net17' => { bus
=> 1, addr
=> 12 },
4956 'net18' => { bus
=> 1, addr
=> 13 },
4957 'net19' => { bus
=> 1, addr
=> 14 },
4958 'net20' => { bus
=> 1, addr
=> 15 },
4959 'net21' => { bus
=> 1, addr
=> 16 },
4960 'net22' => { bus
=> 1, addr
=> 17 },
4961 'net23' => { bus
=> 1, addr
=> 18 },
4962 'net24' => { bus
=> 1, addr
=> 19 },
4963 'net25' => { bus
=> 1, addr
=> 20 },
4964 'net26' => { bus
=> 1, addr
=> 21 },
4965 'net27' => { bus
=> 1, addr
=> 22 },
4966 'net28' => { bus
=> 1, addr
=> 23 },
4967 'net29' => { bus
=> 1, addr
=> 24 },
4968 'net30' => { bus
=> 1, addr
=> 25 },
4969 'net31' => { bus
=> 1, addr
=> 26 },
4970 'xhci' => { bus
=> 1, addr
=> 27 },
4971 'virtio6' => { bus
=> 2, addr
=> 1 },
4972 'virtio7' => { bus
=> 2, addr
=> 2 },
4973 'virtio8' => { bus
=> 2, addr
=> 3 },
4974 'virtio9' => { bus
=> 2, addr
=> 4 },
4975 'virtio10' => { bus
=> 2, addr
=> 5 },
4976 'virtio11' => { bus
=> 2, addr
=> 6 },
4977 'virtio12' => { bus
=> 2, addr
=> 7 },
4978 'virtio13' => { bus
=> 2, addr
=> 8 },
4979 'virtio14' => { bus
=> 2, addr
=> 9 },
4980 'virtio15' => { bus
=> 2, addr
=> 10 },
4981 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4982 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4983 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4984 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4985 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4986 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4987 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4988 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4989 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4990 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4991 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4992 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4993 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4994 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4995 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4996 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4997 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4998 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4999 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5000 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5001 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5002 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5003 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5004 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5005 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5006 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5007 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5008 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5009 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5010 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5011 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5015 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5016 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5017 my $bus = $devices->{$id}->{bus
};
5018 $res = ",bus=pci.$bus,addr=$addr";
5019 $bridges->{$bus} = 1 if $bridges;
5025 sub print_pcie_addr
{
5030 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5031 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5032 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5033 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5036 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5037 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5038 my $bus = $devices->{$id}->{bus
};
5039 $res = ",bus=$bus,addr=$addr";
5045 # vzdump restore implementaion
5047 sub tar_archive_read_firstfile
{
5048 my $archive = shift;
5050 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5052 # try to detect archive type first
5053 my $pid = open (TMP
, "tar tf '$archive'|") ||
5054 die "unable to open file '$archive'\n";
5055 my $firstfile = <TMP
>;
5059 die "ERROR: archive contaions no data\n" if !$firstfile;
5065 sub tar_restore_cleanup
{
5066 my ($storecfg, $statfile) = @_;
5068 print STDERR
"starting cleanup\n";
5070 if (my $fd = IO
::File-
>new($statfile, "r")) {
5071 while (defined(my $line = <$fd>)) {
5072 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5075 if ($volid =~ m
|^/|) {
5076 unlink $volid || die 'unlink failed\n';
5078 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5080 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5082 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5084 print STDERR
"unable to parse line in statfile - $line";
5091 sub restore_archive
{
5092 my ($archive, $vmid, $user, $opts) = @_;
5094 my $format = $opts->{format
};
5097 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5098 $format = 'tar' if !$format;
5100 } elsif ($archive =~ m/\.tar$/) {
5101 $format = 'tar' if !$format;
5102 } elsif ($archive =~ m/.tar.lzo$/) {
5103 $format = 'tar' if !$format;
5105 } elsif ($archive =~ m/\.vma$/) {
5106 $format = 'vma' if !$format;
5107 } elsif ($archive =~ m/\.vma\.gz$/) {
5108 $format = 'vma' if !$format;
5110 } elsif ($archive =~ m/\.vma\.lzo$/) {
5111 $format = 'vma' if !$format;
5114 $format = 'vma' if !$format; # default
5117 # try to detect archive format
5118 if ($format eq 'tar') {
5119 return restore_tar_archive
($archive, $vmid, $user, $opts);
5121 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5125 sub restore_update_config_line
{
5126 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5128 return if $line =~ m/^\#qmdump\#/;
5129 return if $line =~ m/^\#vzdump\#/;
5130 return if $line =~ m/^lock:/;
5131 return if $line =~ m/^unused\d+:/;
5132 return if $line =~ m/^parent:/;
5133 return if $line =~ m/^template:/; # restored VM is never a template
5135 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5136 # try to convert old 1.X settings
5137 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5138 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5139 my ($model, $macaddr) = split(/\=/, $devconfig);
5140 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5143 bridge
=> "vmbr$ind",
5144 macaddr
=> $macaddr,
5146 my $netstr = print_net
($net);
5148 print $outfd "net$cookie->{netcount}: $netstr\n";
5149 $cookie->{netcount
}++;
5151 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5152 my ($id, $netstr) = ($1, $2);
5153 my $net = parse_net
($netstr);
5154 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5155 $netstr = print_net
($net);
5156 print $outfd "$id: $netstr\n";
5157 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5160 my $di = parse_drive
($virtdev, $value);
5161 if (defined($di->{backup
}) && !$di->{backup
}) {
5162 print $outfd "#$line";
5163 } elsif ($map->{$virtdev}) {
5164 delete $di->{format
}; # format can change on restore
5165 $di->{file
} = $map->{$virtdev};
5166 $value = print_drive
($vmid, $di);
5167 print $outfd "$virtdev: $value\n";
5177 my ($cfg, $vmid) = @_;
5179 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5181 my $volid_hash = {};
5182 foreach my $storeid (keys %$info) {
5183 foreach my $item (@{$info->{$storeid}}) {
5184 next if !($item->{volid
} && $item->{size
});
5185 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5186 $volid_hash->{$item->{volid
}} = $item;
5193 sub is_volume_in_use
{
5194 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5196 my $path = PVE
::Storage
::path
($storecfg, $volid);
5198 my $scan_config = sub {
5199 my ($cref, $snapname) = @_;
5201 foreach my $key (keys %$cref) {
5202 my $value = $cref->{$key};
5203 if (is_valid_drivename
($key)) {
5204 next if $skip_drive && $key eq $skip_drive;
5205 my $drive = parse_drive
($key, $value);
5206 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5207 return 1 if $volid eq $drive->{file
};
5208 if ($drive->{file
} =~ m!^/!) {
5209 return 1 if $drive->{file
} eq $path;
5211 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5213 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5215 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5223 return 1 if &$scan_config($conf);
5227 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5228 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5234 sub update_disksize
{
5235 my ($vmid, $conf, $volid_hash) = @_;
5241 # Note: it is allowed to define multiple storages with same path (alias), so
5242 # we need to check both 'volid' and real 'path' (two different volid can point
5243 # to the same path).
5248 foreach my $opt (keys %$conf) {
5249 if (is_valid_drivename
($opt)) {
5250 my $drive = parse_drive
($opt, $conf->{$opt});
5251 my $volid = $drive->{file
};
5254 $used->{$volid} = 1;
5255 if ($volid_hash->{$volid} &&
5256 (my $path = $volid_hash->{$volid}->{path
})) {
5257 $usedpath->{$path} = 1;
5260 next if drive_is_cdrom
($drive);
5261 next if !$volid_hash->{$volid};
5263 $drive->{size
} = $volid_hash->{$volid}->{size
};
5264 my $new = print_drive
($vmid, $drive);
5265 if ($new ne $conf->{$opt}) {
5267 $conf->{$opt} = $new;
5272 # remove 'unusedX' entry if volume is used
5273 foreach my $opt (keys %$conf) {
5274 next if $opt !~ m/^unused\d+$/;
5275 my $volid = $conf->{$opt};
5276 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5277 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5279 delete $conf->{$opt};
5283 foreach my $volid (sort keys %$volid_hash) {
5284 next if $volid =~ m/vm-$vmid-state-/;
5285 next if $used->{$volid};
5286 my $path = $volid_hash->{$volid}->{path
};
5287 next if !$path; # just to be sure
5288 next if $usedpath->{$path};
5290 PVE
::QemuConfig-
>add_unused_volume($conf, $volid);
5291 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5298 my ($vmid, $nolock) = @_;
5300 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5302 my $volid_hash = scan_volids
($cfg, $vmid);
5304 my $updatefn = sub {
5307 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5309 PVE
::QemuConfig-
>check_lock($conf);
5312 foreach my $volid (keys %$volid_hash) {
5313 my $info = $volid_hash->{$volid};
5314 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5317 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5319 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5322 if (defined($vmid)) {
5326 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5329 my $vmlist = config_list
();
5330 foreach my $vmid (keys %$vmlist) {
5334 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5340 sub restore_vma_archive
{
5341 my ($archive, $vmid, $user, $opts, $comp) = @_;
5343 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5344 my $readfrom = $archive;
5349 my $qarchive = PVE
::Tools
::shellquote
($archive);
5350 if ($comp eq 'gzip') {
5351 $uncomp = "zcat $qarchive|";
5352 } elsif ($comp eq 'lzop') {
5353 $uncomp = "lzop -d -c $qarchive|";
5355 die "unknown compression method '$comp'\n";
5360 my $tmpdir = "/var/tmp/vzdumptmp$$";
5363 # disable interrupts (always do cleanups)
5364 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5365 warn "got interrupt - ignored\n";
5368 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5369 POSIX
::mkfifo
($mapfifo, 0600);
5372 my $openfifo = sub {
5373 open($fifofh, '>', $mapfifo) || die $!;
5376 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5383 my $rpcenv = PVE
::RPCEnvironment
::get
();
5385 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5386 my $tmpfn = "$conffile.$$.tmp";
5388 # Note: $oldconf is undef if VM does not exists
5389 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5390 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5392 my $print_devmap = sub {
5393 my $virtdev_hash = {};
5395 my $cfgfn = "$tmpdir/qemu-server.conf";
5397 # we can read the config - that is already extracted
5398 my $fh = IO
::File-
>new($cfgfn, "r") ||
5399 "unable to read qemu-server.conf - $!\n";
5401 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5403 my $pve_firewall_dir = '/etc/pve/firewall';
5404 mkdir $pve_firewall_dir; # make sure the dir exists
5405 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5408 while (defined(my $line = <$fh>)) {
5409 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5410 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5411 die "archive does not contain data for drive '$virtdev'\n"
5412 if !$devinfo->{$devname};
5413 if (defined($opts->{storage
})) {
5414 $storeid = $opts->{storage
} || 'local';
5415 } elsif (!$storeid) {
5418 $format = 'raw' if !$format;
5419 $devinfo->{$devname}->{devname
} = $devname;
5420 $devinfo->{$devname}->{virtdev
} = $virtdev;
5421 $devinfo->{$devname}->{format
} = $format;
5422 $devinfo->{$devname}->{storeid
} = $storeid;
5424 # check permission on storage
5425 my $pool = $opts->{pool
}; # todo: do we need that?
5426 if ($user ne 'root@pam') {
5427 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5430 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5434 foreach my $devname (keys %$devinfo) {
5435 die "found no device mapping information for device '$devname'\n"
5436 if !$devinfo->{$devname}->{virtdev
};
5439 my $cfg = cfs_read_file
('storage.cfg');
5441 # create empty/temp config
5443 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5444 foreach_drive
($oldconf, sub {
5445 my ($ds, $drive) = @_;
5447 return if drive_is_cdrom
($drive);
5449 my $volid = $drive->{file
};
5451 return if !$volid || $volid =~ m
|^/|;
5453 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5454 return if !$path || !$owner || ($owner != $vmid);
5456 # Note: only delete disk we want to restore
5457 # other volumes will become unused
5458 if ($virtdev_hash->{$ds}) {
5459 PVE
::Storage
::vdisk_free
($cfg, $volid);
5463 # delete vmstate files
5464 # since after the restore we have no snapshots anymore
5465 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5466 my $snap = $oldconf->{snapshots
}->{$snapname};
5467 if ($snap->{vmstate
}) {
5468 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5477 foreach my $virtdev (sort keys %$virtdev_hash) {
5478 my $d = $virtdev_hash->{$virtdev};
5479 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5480 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5482 # test if requested format is supported
5483 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5484 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5485 $d->{format
} = $defFormat if !$supported;
5487 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5488 $d->{format
}, undef, $alloc_size);
5489 print STDERR
"new volume ID is '$volid'\n";
5490 $d->{volid
} = $volid;
5491 my $path = PVE
::Storage
::path
($cfg, $volid);
5493 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5495 my $write_zeros = 1;
5496 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5500 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5502 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5503 $map->{$virtdev} = $volid;
5506 $fh->seek(0, 0) || die "seek failed - $!\n";
5508 my $outfd = new IO
::File
($tmpfn, "w") ||
5509 die "unable to write config for VM $vmid\n";
5511 my $cookie = { netcount
=> 0 };
5512 while (defined(my $line = <$fh>)) {
5513 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5522 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5523 die "interrupted by signal\n";
5525 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5527 $oldtimeout = alarm($timeout);
5534 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5535 my ($dev_id, $size, $devname) = ($1, $2, $3);
5536 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5537 } elsif ($line =~ m/^CTIME: /) {
5538 # we correctly received the vma config, so we can disable
5539 # the timeout now for disk allocation (set to 10 minutes, so
5540 # that we always timeout if something goes wrong)
5543 print $fifofh "done\n";
5544 my $tmp = $oldtimeout || 0;
5545 $oldtimeout = undef;
5551 print "restore vma archive: $cmd\n";
5552 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5556 alarm($oldtimeout) if $oldtimeout;
5559 foreach my $devname (keys %$devinfo) {
5560 my $volid = $devinfo->{$devname}->{volid
};
5561 push @$vollist, $volid if $volid;
5564 my $cfg = cfs_read_file
('storage.cfg');
5565 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5573 foreach my $devname (keys %$devinfo) {
5574 my $volid = $devinfo->{$devname}->{volid
};
5577 if ($volid =~ m
|^/|) {
5578 unlink $volid || die 'unlink failed\n';
5580 PVE
::Storage
::vdisk_free
($cfg, $volid);
5582 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5584 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5591 rename($tmpfn, $conffile) ||
5592 die "unable to commit configuration file '$conffile'\n";
5594 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5596 eval { rescan
($vmid, 1); };
5600 sub restore_tar_archive
{
5601 my ($archive, $vmid, $user, $opts) = @_;
5603 if ($archive ne '-') {
5604 my $firstfile = tar_archive_read_firstfile
($archive);
5605 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5606 if $firstfile ne 'qemu-server.conf';
5609 my $storecfg = cfs_read_file
('storage.cfg');
5611 # destroy existing data - keep empty config
5612 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5613 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5615 my $tocmd = "/usr/lib/qemu-server/qmextract";
5617 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5618 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5619 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5620 $tocmd .= ' --info' if $opts->{info
};
5622 # tar option "xf" does not autodetect compression when read from STDIN,
5623 # so we pipe to zcat
5624 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5625 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5627 my $tmpdir = "/var/tmp/vzdumptmp$$";
5630 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5631 local $ENV{VZDUMP_VMID
} = $vmid;
5632 local $ENV{VZDUMP_USER
} = $user;
5634 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5635 my $tmpfn = "$conffile.$$.tmp";
5637 # disable interrupts (always do cleanups)
5638 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5639 print STDERR
"got interrupt - ignored\n";
5644 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5645 die "interrupted by signal\n";
5648 if ($archive eq '-') {
5649 print "extracting archive from STDIN\n";
5650 run_command
($cmd, input
=> "<&STDIN");
5652 print "extracting archive '$archive'\n";
5656 return if $opts->{info
};
5660 my $statfile = "$tmpdir/qmrestore.stat";
5661 if (my $fd = IO
::File-
>new($statfile, "r")) {
5662 while (defined (my $line = <$fd>)) {
5663 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5664 $map->{$1} = $2 if $1;
5666 print STDERR
"unable to parse line in statfile - $line\n";
5672 my $confsrc = "$tmpdir/qemu-server.conf";
5674 my $srcfd = new IO
::File
($confsrc, "r") ||
5675 die "unable to open file '$confsrc'\n";
5677 my $outfd = new IO
::File
($tmpfn, "w") ||
5678 die "unable to write config for VM $vmid\n";
5680 my $cookie = { netcount
=> 0 };
5681 while (defined (my $line = <$srcfd>)) {
5682 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5694 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5701 rename $tmpfn, $conffile ||
5702 die "unable to commit configuration file '$conffile'\n";
5704 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5706 eval { rescan
($vmid, 1); };
5710 sub foreach_writable_storage
{
5711 my ($conf, $func) = @_;
5715 foreach my $ds (keys %$conf) {
5716 next if !is_valid_drivename
($ds);
5718 my $drive = parse_drive
($ds, $conf->{$ds});
5720 next if drive_is_cdrom
($drive);
5722 my $volid = $drive->{file
};
5724 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5725 $sidhash->{$sid} = $sid if $sid;
5728 foreach my $sid (sort keys %$sidhash) {
5733 sub do_snapshots_with_qemu
{
5734 my ($storecfg, $volid) = @_;
5736 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5738 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
5739 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
5743 if ($volid =~ m/\.(qcow2|qed)$/){
5750 sub qga_check_running
{
5753 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
5755 warn "Qemu Guest Agent are not running - $@";
5761 sub template_create
{
5762 my ($vmid, $conf, $disk) = @_;
5764 my $storecfg = PVE
::Storage
::config
();
5766 foreach_drive
($conf, sub {
5767 my ($ds, $drive) = @_;
5769 return if drive_is_cdrom
($drive);
5770 return if $disk && $ds ne $disk;
5772 my $volid = $drive->{file
};
5773 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
5775 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
5776 $drive->{file
} = $voliddst;
5777 $conf->{$ds} = print_drive
($vmid, $drive);
5778 PVE
::QemuConfig-
>write_config($vmid, $conf);
5782 sub qemu_img_convert
{
5783 my ($src_volid, $dst_volid, $size, $snapname) = @_;
5785 my $storecfg = PVE
::Storage
::config
();
5786 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
5787 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
5789 if ($src_storeid && $dst_storeid) {
5791 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
5793 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
5794 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5796 my $src_format = qemu_img_format
($src_scfg, $src_volname);
5797 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
5799 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
5800 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5803 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
5804 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
5805 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
5809 if($line =~ m/\((\S+)\/100\
%\)/){
5811 my $transferred = int($size * $percent / 100);
5812 my $remaining = $size - $transferred;
5814 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
5819 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
5821 die "copy failed: $err" if $err;
5825 sub qemu_img_format
{
5826 my ($scfg, $volname) = @_;
5828 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
5835 sub qemu_drive_mirror
{
5836 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
5838 my $storecfg = PVE
::Storage
::config
();
5839 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
5841 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
5843 my $format = qemu_img_format
($dst_scfg, $dst_volname);
5845 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
5847 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
5848 $opts->{format
} = $format if $format;
5850 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
5853 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
5855 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5856 my $stat = @$stats[0];
5857 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
5858 die "error job is not mirroring" if $stat->{type
} ne "mirror";
5860 my $busy = $stat->{busy
};
5861 my $ready = $stat->{ready
};
5863 if (my $total = $stat->{len
}) {
5864 my $transferred = $stat->{offset
} || 0;
5865 my $remaining = $total - $transferred;
5866 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
5868 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
5872 if ($stat->{ready
} eq 'true') {
5874 last if $vmiddst != $vmid;
5876 # try to switch the disk if source and destination are on the same guest
5877 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
5879 die $@ if $@ !~ m/cannot be completed/;
5888 my $cancel_job = sub {
5889 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
5891 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
5892 my $stat = @$stats[0];
5899 eval { &$cancel_job(); };
5900 die "mirroring error: $err";
5903 if ($vmiddst != $vmid) {
5904 # if we clone a disk for a new target vm, we don't switch the disk
5905 &$cancel_job(); # so we call block-job-cancel
5910 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
5911 $newvmid, $storage, $format, $full, $newvollist) = @_;
5916 print "create linked clone of drive $drivename ($drive->{file})\n";
5917 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
5918 push @$newvollist, $newvolid;
5920 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
5921 $storeid = $storage if $storage;
5923 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
5925 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
5926 $format = qemu_img_format
($scfg, $volname);
5929 # test if requested format is supported - else use default
5930 my $supported = grep { $_ eq $format } @$validFormats;
5931 $format = $defFormat if !$supported;
5933 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
5935 print "create full clone of drive $drivename ($drive->{file})\n";
5936 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
5937 push @$newvollist, $newvolid;
5939 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
5941 if (!$running || $snapname) {
5942 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
5944 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
5948 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
5951 $disk->{format
} = undef;
5952 $disk->{file
} = $newvolid;
5953 $disk->{size
} = $size;
5958 # this only works if VM is running
5959 sub get_current_qemu_machine
{
5962 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
5963 my $res = vm_qmp_command
($vmid, $cmd);
5965 my ($current, $default);
5966 foreach my $e (@$res) {
5967 $default = $e->{name
} if $e->{'is-default'};
5968 $current = $e->{name
} if $e->{'is-current'};
5971 # fallback to the default machine if current is not supported by qemu
5972 return $current || $default || 'pc';
5975 sub qemu_machine_feature_enabled
{
5976 my ($machine, $kvmver, $version_major, $version_minor) = @_;
5981 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
5983 $current_major = $3;
5984 $current_minor = $4;
5986 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
5988 $current_major = $1;
5989 $current_minor = $2;
5992 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
5997 sub qemu_machine_pxe
{
5998 my ($vmid, $conf, $machine) = @_;
6000 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6002 foreach my $opt (keys %$conf) {
6003 next if $opt !~ m/^net(\d+)$/;
6004 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6006 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6007 return $machine.".pxe" if $romfile =~ m/pxe/;
6014 sub qemu_use_old_bios_files
{
6015 my ($machine_type) = @_;
6017 return if !$machine_type;
6019 my $use_old_bios_files = undef;
6021 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6023 $use_old_bios_files = 1;
6025 my $kvmver = kvm_user_version
();
6026 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6027 # load new efi bios files on migration. So this hack is required to allow
6028 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6029 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6030 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6033 return ($use_old_bios_files, $machine_type);
6040 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6041 my (undef, $id, $function) = @_;
6042 my $res = { id
=> $id, function
=> $function};
6043 push @{$devices->{$id}}, $res;
6049 sub vm_iothreads_list
{
6052 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6055 foreach my $iothread (@$res) {
6056 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6063 my ($conf, $drive) = @_;
6067 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6069 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6075 my $controller = int($drive->{index} / $maxdev);
6076 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6078 return ($maxdev, $controller, $controller_prefix);
6081 # bash completion helper
6083 sub complete_backup_archives
{
6084 my ($cmdname, $pname, $cvalue) = @_;
6086 my $cfg = PVE
::Storage
::config
();
6090 if ($cvalue =~ m/^([^:]+):/) {
6094 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6097 foreach my $id (keys %$data) {
6098 foreach my $item (@{$data->{$id}}) {
6099 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6100 push @$res, $item->{volid
} if defined($item->{volid
});
6107 my $complete_vmid_full = sub {
6110 my $idlist = vmstatus
();
6114 foreach my $id (keys %$idlist) {
6115 my $d = $idlist->{$id};
6116 if (defined($running)) {
6117 next if $d->{template
};
6118 next if $running && $d->{status
} ne 'running';
6119 next if !$running && $d->{status
} eq 'running';
6128 return &$complete_vmid_full();
6131 sub complete_vmid_stopped
{
6132 return &$complete_vmid_full(0);
6135 sub complete_vmid_running
{
6136 return &$complete_vmid_full(1);
6139 sub complete_storage
{
6141 my $cfg = PVE
::Storage
::config
();
6142 my $ids = $cfg->{ids
};
6145 foreach my $sid (keys %$ids) {
6146 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6147 next if !$ids->{$sid}->{content
}->{images
};