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 add_unused_volume
{
1561 my ($config, $volid) = @_;
1564 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1565 my $test = "unused$ind";
1566 if (my $vid = $config->{$test}) {
1567 return if $vid eq $volid; # do not add duplicates
1573 die "To many unused volume - please delete them first.\n" if !$key;
1575 $config->{$key} = $volid;
1580 sub vm_is_volid_owner
{
1581 my ($storecfg, $vmid, $volid) = @_;
1583 if ($volid !~ m
|^/|) {
1585 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1586 if ($owner && ($owner == $vmid)) {
1594 sub split_flagged_list
{
1595 my $text = shift || '';
1596 $text =~ s/[,;]/ /g;
1598 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1601 sub join_flagged_list
{
1602 my ($how, $lst) = @_;
1603 join $how, map { $lst->{$_} . $_ } keys %$lst;
1606 sub vmconfig_delete_pending_option
{
1607 my ($conf, $key, $force) = @_;
1609 delete $conf->{pending
}->{$key};
1610 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1611 $pending_delete_hash->{$key} = $force ?
'!' : '';
1612 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1615 sub vmconfig_undelete_pending_option
{
1616 my ($conf, $key) = @_;
1618 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1619 delete $pending_delete_hash->{$key};
1621 if (%$pending_delete_hash) {
1622 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1624 delete $conf->{pending
}->{delete};
1628 sub vmconfig_register_unused_drive
{
1629 my ($storecfg, $vmid, $conf, $drive) = @_;
1631 if (!drive_is_cdrom
($drive)) {
1632 my $volid = $drive->{file
};
1633 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1634 add_unused_volume
($conf, $volid, $vmid);
1639 sub vmconfig_cleanup_pending
{
1642 # remove pending changes when nothing changed
1644 foreach my $opt (keys %{$conf->{pending
}}) {
1645 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1647 delete $conf->{pending
}->{$opt};
1651 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1652 my $pending_delete_hash = {};
1653 while (my ($opt, $force) = each %$current_delete_hash) {
1654 if (defined($conf->{$opt})) {
1655 $pending_delete_hash->{$opt} = $force;
1661 if (%$pending_delete_hash) {
1662 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1664 delete $conf->{pending
}->{delete};
1670 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1671 my $smbios1_desc = {
1674 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1675 format_description
=> 'UUID',
1681 format_description
=> 'str',
1687 format_description
=> 'str',
1693 format_description
=> 'name',
1699 format_description
=> 'name',
1705 format_description
=> 'str',
1711 format_description
=> 'str',
1719 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_desc, $data) };
1726 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_desc);
1729 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_desc);
1731 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1732 sub verify_bootdisk
{
1733 my ($value, $noerr) = @_;
1735 return $value if is_valid_drivename
($value);
1737 return undef if $noerr;
1739 die "invalid boot disk '$value'\n";
1742 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1744 my ($value, $noerr) = @_;
1746 return $value if parse_numa
($value);
1748 return undef if $noerr;
1750 die "unable to parse numa options\n";
1753 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1755 my ($value, $noerr) = @_;
1757 return $value if parse_net
($value);
1759 return undef if $noerr;
1761 die "unable to parse network options\n";
1764 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1765 sub verify_hostpci
{
1766 my ($value, $noerr) = @_;
1768 return $value if parse_hostpci
($value);
1770 return undef if $noerr;
1772 die "unable to parse pci id\n";
1775 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1776 sub verify_watchdog
{
1777 my ($value, $noerr) = @_;
1779 return $value if parse_watchdog
($value);
1781 return undef if $noerr;
1783 die "unable to parse watchdog options\n";
1786 sub parse_watchdog
{
1789 return undef if !$value;
1793 foreach my $p (split(/,/, $value)) {
1794 next if $p =~ m/^\s*$/;
1796 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1798 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1799 $res->{action
} = $2;
1808 sub parse_usb_device
{
1811 return undef if !$value;
1814 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1815 $res->{vendorid
} = $2;
1816 $res->{productid
} = $4;
1817 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1818 $res->{hostbus
} = $1;
1819 $res->{hostport
} = $2;
1820 } elsif ($value =~ m/^spice$/i) {
1829 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1830 sub verify_usb_device
{
1831 my ($value, $noerr) = @_;
1833 return $value if parse_usb_device
($value);
1835 return undef if $noerr;
1837 die "unable to parse usb device\n";
1840 # add JSON properties for create and set function
1841 sub json_config_properties
{
1844 foreach my $opt (keys %$confdesc) {
1845 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1846 $prop->{$opt} = $confdesc->{$opt};
1853 my ($key, $value) = @_;
1855 die "unknown setting '$key'\n" if !$confdesc->{$key};
1857 my $type = $confdesc->{$key}->{type
};
1859 if (!defined($value)) {
1860 die "got undefined value\n";
1863 if ($value =~ m/[\n\r]/) {
1864 die "property contains a line feed\n";
1867 if ($type eq 'boolean') {
1868 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1869 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1870 die "type check ('boolean') failed - got '$value'\n";
1871 } elsif ($type eq 'integer') {
1872 return int($1) if $value =~ m/^(\d+)$/;
1873 die "type check ('integer') failed - got '$value'\n";
1874 } elsif ($type eq 'number') {
1875 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1876 die "type check ('number') failed - got '$value'\n";
1877 } elsif ($type eq 'string') {
1878 if (my $fmt = $confdesc->{$key}->{format
}) {
1879 if ($fmt eq 'pve-qm-drive') {
1880 # special case - we need to pass $key to parse_drive()
1881 my $drive = parse_drive
($key, $value);
1882 return $value if $drive;
1883 die "unable to parse drive options\n";
1885 PVE
::JSONSchema
::check_format
($fmt, $value);
1888 $value =~ s/^\"(.*)\"$/$1/;
1891 die "internal error"
1895 sub check_iommu_support
{
1896 #fixme : need to check IOMMU support
1897 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1907 my $conf = PVE
::QemuConfig-
>config_file($vmid);
1908 utime undef, undef, $conf;
1912 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1914 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
1916 my $conf = PVE
::QemuConfig-
>load_config($vmid);
1918 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
1920 # only remove disks owned by this VM
1921 foreach_drive
($conf, sub {
1922 my ($ds, $drive) = @_;
1924 return if drive_is_cdrom
($drive);
1926 my $volid = $drive->{file
};
1928 return if !$volid || $volid =~ m
|^/|;
1930 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1931 return if !$path || !$owner || ($owner != $vmid);
1933 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1936 if ($keep_empty_config) {
1937 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1942 # also remove unused disk
1944 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1947 PVE
::Storage
::foreach_volid
($dl, sub {
1948 my ($volid, $sid, $volname, $d) = @_;
1949 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1958 sub parse_vm_config
{
1959 my ($filename, $raw) = @_;
1961 return undef if !defined($raw);
1964 digest
=> Digest
::SHA
::sha1_hex
($raw),
1969 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1970 || die "got strange filename '$filename'";
1978 my @lines = split(/\n/, $raw);
1979 foreach my $line (@lines) {
1980 next if $line =~ m/^\s*$/;
1982 if ($line =~ m/^\[PENDING\]\s*$/i) {
1983 $section = 'pending';
1984 if (defined($descr)) {
1986 $conf->{description
} = $descr;
1989 $conf = $res->{$section} = {};
1992 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1994 if (defined($descr)) {
1996 $conf->{description
} = $descr;
1999 $conf = $res->{snapshots
}->{$section} = {};
2003 if ($line =~ m/^\#(.*)\s*$/) {
2004 $descr = '' if !defined($descr);
2005 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2009 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2010 $descr = '' if !defined($descr);
2011 $descr .= PVE
::Tools
::decode_text
($2);
2012 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2013 $conf->{snapstate
} = $1;
2014 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2017 $conf->{$key} = $value;
2018 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2020 if ($section eq 'pending') {
2021 $conf->{delete} = $value; # we parse this later
2023 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2025 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2028 eval { $value = check_type
($key, $value); };
2030 warn "vm $vmid - unable to parse value of '$key' - $@";
2032 my $fmt = $confdesc->{$key}->{format
};
2033 if ($fmt && $fmt eq 'pve-qm-drive') {
2034 my $v = parse_drive
($key, $value);
2035 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2036 $v->{file
} = $volid;
2037 $value = print_drive
($vmid, $v);
2039 warn "vm $vmid - unable to parse value of '$key'\n";
2044 if ($key eq 'cdrom') {
2045 $conf->{ide2
} = $value;
2047 $conf->{$key} = $value;
2053 if (defined($descr)) {
2055 $conf->{description
} = $descr;
2057 delete $res->{snapstate
}; # just to be sure
2062 sub write_vm_config
{
2063 my ($filename, $conf) = @_;
2065 delete $conf->{snapstate
}; # just to be sure
2067 if ($conf->{cdrom
}) {
2068 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2069 $conf->{ide2
} = $conf->{cdrom
};
2070 delete $conf->{cdrom
};
2073 # we do not use 'smp' any longer
2074 if ($conf->{sockets
}) {
2075 delete $conf->{smp
};
2076 } elsif ($conf->{smp
}) {
2077 $conf->{sockets
} = $conf->{smp
};
2078 delete $conf->{cores
};
2079 delete $conf->{smp
};
2082 my $used_volids = {};
2084 my $cleanup_config = sub {
2085 my ($cref, $pending, $snapname) = @_;
2087 foreach my $key (keys %$cref) {
2088 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2089 $key eq 'snapstate' || $key eq 'pending';
2090 my $value = $cref->{$key};
2091 if ($key eq 'delete') {
2092 die "propertry 'delete' is only allowed in [PENDING]\n"
2094 # fixme: check syntax?
2097 eval { $value = check_type
($key, $value); };
2098 die "unable to parse value of '$key' - $@" if $@;
2100 $cref->{$key} = $value;
2102 if (!$snapname && is_valid_drivename
($key)) {
2103 my $drive = parse_drive
($key, $value);
2104 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2109 &$cleanup_config($conf);
2111 &$cleanup_config($conf->{pending
}, 1);
2113 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2114 die "internal error" if $snapname eq 'pending';
2115 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2118 # remove 'unusedX' settings if we re-add a volume
2119 foreach my $key (keys %$conf) {
2120 my $value = $conf->{$key};
2121 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2122 delete $conf->{$key};
2126 my $generate_raw_config = sub {
2127 my ($conf, $pending) = @_;
2131 # add description as comment to top of file
2132 if (defined(my $descr = $conf->{description
})) {
2134 foreach my $cl (split(/\n/, $descr)) {
2135 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2138 $raw .= "#\n" if $pending;
2142 foreach my $key (sort keys %$conf) {
2143 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2144 $raw .= "$key: $conf->{$key}\n";
2149 my $raw = &$generate_raw_config($conf);
2151 if (scalar(keys %{$conf->{pending
}})){
2152 $raw .= "\n[PENDING]\n";
2153 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2156 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2157 $raw .= "\n[$snapname]\n";
2158 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2168 # we use static defaults from our JSON schema configuration
2169 foreach my $key (keys %$confdesc) {
2170 if (defined(my $default = $confdesc->{$key}->{default})) {
2171 $res->{$key} = $default;
2175 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2176 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2182 my $vmlist = PVE
::Cluster
::get_vmlist
();
2184 return $res if !$vmlist || !$vmlist->{ids
};
2185 my $ids = $vmlist->{ids
};
2187 foreach my $vmid (keys %$ids) {
2188 my $d = $ids->{$vmid};
2189 next if !$d->{node
} || $d->{node
} ne $nodename;
2190 next if !$d->{type
} || $d->{type
} ne 'qemu';
2191 $res->{$vmid}->{exists} = 1;
2196 # test if VM uses local resources (to prevent migration)
2197 sub check_local_resources
{
2198 my ($conf, $noerr) = @_;
2202 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2203 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2205 foreach my $k (keys %$conf) {
2206 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2207 # sockets are safe: they will recreated be on the target side post-migrate
2208 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2209 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2212 die "VM uses local resources\n" if $loc_res && !$noerr;
2217 # check if used storages are available on all nodes (use by migrate)
2218 sub check_storage_availability
{
2219 my ($storecfg, $conf, $node) = @_;
2221 foreach_drive
($conf, sub {
2222 my ($ds, $drive) = @_;
2224 my $volid = $drive->{file
};
2227 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2230 # check if storage is available on both nodes
2231 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2232 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2236 # list nodes where all VM images are available (used by has_feature API)
2238 my ($conf, $storecfg) = @_;
2240 my $nodelist = PVE
::Cluster
::get_nodelist
();
2241 my $nodehash = { map { $_ => 1 } @$nodelist };
2242 my $nodename = PVE
::INotify
::nodename
();
2244 foreach_drive
($conf, sub {
2245 my ($ds, $drive) = @_;
2247 my $volid = $drive->{file
};
2250 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2252 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2253 if ($scfg->{disable
}) {
2255 } elsif (my $avail = $scfg->{nodes
}) {
2256 foreach my $node (keys %$nodehash) {
2257 delete $nodehash->{$node} if !$avail->{$node};
2259 } elsif (!$scfg->{shared
}) {
2260 foreach my $node (keys %$nodehash) {
2261 delete $nodehash->{$node} if $node ne $nodename
2271 my ($pidfile, $pid) = @_;
2273 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2277 return undef if !$line;
2278 my @param = split(/\0/, $line);
2280 my $cmd = $param[0];
2281 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2283 for (my $i = 0; $i < scalar (@param); $i++) {
2286 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2287 my $p = $param[$i+1];
2288 return 1 if $p && ($p eq $pidfile);
2297 my ($vmid, $nocheck, $node) = @_;
2299 my $filename = PVE
::QemuConfig-
>config_file($vmid, $node);
2301 die "unable to find configuration file for VM $vmid - no such machine\n"
2302 if !$nocheck && ! -f
$filename;
2304 my $pidfile = pidfile_name
($vmid);
2306 if (my $fd = IO
::File-
>new("<$pidfile")) {
2311 my $mtime = $st->mtime;
2312 if ($mtime > time()) {
2313 warn "file '$filename' modified in future\n";
2316 if ($line =~ m/^(\d+)$/) {
2318 if (check_cmdline
($pidfile, $pid)) {
2319 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2331 my $vzlist = config_list
();
2333 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2335 while (defined(my $de = $fd->read)) {
2336 next if $de !~ m/^(\d+)\.pid$/;
2338 next if !defined($vzlist->{$vmid});
2339 if (my $pid = check_running
($vmid)) {
2340 $vzlist->{$vmid}->{pid
} = $pid;
2348 my ($storecfg, $conf) = @_;
2350 my $bootdisk = $conf->{bootdisk
};
2351 return undef if !$bootdisk;
2352 return undef if !is_valid_drivename
($bootdisk);
2354 return undef if !$conf->{$bootdisk};
2356 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2357 return undef if !defined($drive);
2359 return undef if drive_is_cdrom
($drive);
2361 my $volid = $drive->{file
};
2362 return undef if !$volid;
2364 return $drive->{size
};
2367 my $last_proc_pid_stat;
2369 # get VM status information
2370 # This must be fast and should not block ($full == false)
2371 # We only query KVM using QMP if $full == true (this can be slow)
2373 my ($opt_vmid, $full) = @_;
2377 my $storecfg = PVE
::Storage
::config
();
2379 my $list = vzlist
();
2380 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2382 my $cpucount = $cpuinfo->{cpus
} || 1;
2384 foreach my $vmid (keys %$list) {
2385 next if $opt_vmid && ($vmid ne $opt_vmid);
2387 my $cfspath = PVE
::QemuConfig-
>cfs_config_path($vmid);
2388 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2391 $d->{pid
} = $list->{$vmid}->{pid
};
2393 # fixme: better status?
2394 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2396 my $size = disksize
($storecfg, $conf);
2397 if (defined($size)) {
2398 $d->{disk
} = 0; # no info available
2399 $d->{maxdisk
} = $size;
2405 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2406 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2407 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2409 $d->{name
} = $conf->{name
} || "VM $vmid";
2410 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2412 if ($conf->{balloon
}) {
2413 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2414 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2425 $d->{diskwrite
} = 0;
2427 $d->{template
} = PVE
::QemuConfig-
>is_template($conf);
2432 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2433 foreach my $dev (keys %$netdev) {
2434 next if $dev !~ m/^tap([1-9]\d*)i/;
2436 my $d = $res->{$vmid};
2439 $d->{netout
} += $netdev->{$dev}->{receive
};
2440 $d->{netin
} += $netdev->{$dev}->{transmit
};
2443 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2444 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2449 my $ctime = gettimeofday
;
2451 foreach my $vmid (keys %$list) {
2453 my $d = $res->{$vmid};
2454 my $pid = $d->{pid
};
2457 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2458 next if !$pstat; # not running
2460 my $used = $pstat->{utime} + $pstat->{stime
};
2462 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2464 if ($pstat->{vsize
}) {
2465 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2468 my $old = $last_proc_pid_stat->{$pid};
2470 $last_proc_pid_stat->{$pid} = {
2478 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2480 if ($dtime > 1000) {
2481 my $dutime = $used - $old->{used
};
2483 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2484 $last_proc_pid_stat->{$pid} = {
2490 $d->{cpu
} = $old->{cpu
};
2494 return $res if !$full;
2496 my $qmpclient = PVE
::QMPClient-
>new();
2498 my $ballooncb = sub {
2499 my ($vmid, $resp) = @_;
2501 my $info = $resp->{'return'};
2502 return if !$info->{max_mem
};
2504 my $d = $res->{$vmid};
2506 # use memory assigned to VM
2507 $d->{maxmem
} = $info->{max_mem
};
2508 $d->{balloon
} = $info->{actual
};
2510 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2511 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2512 $d->{freemem
} = $info->{free_mem
};
2515 $d->{ballooninfo
} = $info;
2518 my $blockstatscb = sub {
2519 my ($vmid, $resp) = @_;
2520 my $data = $resp->{'return'} || [];
2521 my $totalrdbytes = 0;
2522 my $totalwrbytes = 0;
2524 for my $blockstat (@$data) {
2525 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2526 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2528 $blockstat->{device
} =~ s/drive-//;
2529 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2531 $res->{$vmid}->{diskread
} = $totalrdbytes;
2532 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2535 my $statuscb = sub {
2536 my ($vmid, $resp) = @_;
2538 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2539 # this fails if ballon driver is not loaded, so this must be
2540 # the last commnand (following command are aborted if this fails).
2541 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2543 my $status = 'unknown';
2544 if (!defined($status = $resp->{'return'}->{status
})) {
2545 warn "unable to get VM status\n";
2549 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2552 foreach my $vmid (keys %$list) {
2553 next if $opt_vmid && ($vmid ne $opt_vmid);
2554 next if !$res->{$vmid}->{pid
}; # not running
2555 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2558 $qmpclient->queue_execute(undef, 1);
2560 foreach my $vmid (keys %$list) {
2561 next if $opt_vmid && ($vmid ne $opt_vmid);
2562 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2569 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2572 my $current_size = 1024;
2573 my $dimm_size = 512;
2574 return if $current_size == $memory;
2576 for (my $j = 0; $j < 8; $j++) {
2577 for (my $i = 0; $i < 32; $i++) {
2578 my $name = "dimm${dimm_id}";
2580 my $numanode = $i % $sockets;
2581 $current_size += $dimm_size;
2582 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2583 return $current_size if $current_size >= $memory;
2589 sub foreach_reverse_dimm
{
2590 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2593 my $current_size = 4177920;
2594 my $dimm_size = 65536;
2595 return if $current_size == $memory;
2597 for (my $j = 0; $j < 8; $j++) {
2598 for (my $i = 0; $i < 32; $i++) {
2599 my $name = "dimm${dimm_id}";
2601 my $numanode = $i % $sockets;
2602 $current_size -= $dimm_size;
2603 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2604 return $current_size if $current_size <= $memory;
2611 my ($conf, $func) = @_;
2613 foreach my $ds (valid_drive_names
()) {
2614 next if !defined($conf->{$ds});
2616 my $drive = parse_drive
($ds, $conf->{$ds});
2619 &$func($ds, $drive);
2624 my ($conf, $func) = @_;
2628 my $test_volid = sub {
2629 my ($volid, $is_cdrom) = @_;
2633 $volhash->{$volid} = $is_cdrom || 0;
2636 foreach_drive
($conf, sub {
2637 my ($ds, $drive) = @_;
2638 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2641 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2642 my $snap = $conf->{snapshots
}->{$snapname};
2643 &$test_volid($snap->{vmstate
}, 0);
2644 foreach_drive
($snap, sub {
2645 my ($ds, $drive) = @_;
2646 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2650 foreach my $volid (keys %$volhash) {
2651 &$func($volid, $volhash->{$volid});
2655 sub vga_conf_has_spice
{
2658 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2663 sub config_to_command
{
2664 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2667 my $globalFlags = [];
2668 my $machineFlags = [];
2674 my $kvmver = kvm_user_version
();
2675 my $vernum = 0; # unknown
2676 my $ostype = $conf->{ostype
};
2677 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2678 $vernum = $1*1000000+$2*1000;
2679 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2680 $vernum = $1*1000000+$2*1000+$3;
2683 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2685 my $have_ovz = -f
'/proc/vz/vestat';
2687 my $q35 = machine_type_is_q35
($conf);
2688 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2689 my $machine_type = $forcemachine || $conf->{machine
};
2690 my $use_old_bios_files = undef;
2691 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2693 my $cpuunits = defined($conf->{cpuunits
}) ?
2694 $conf->{cpuunits
} : $defaults->{cpuunits
};
2696 push @$cmd, '/usr/bin/systemd-run';
2697 push @$cmd, '--scope';
2698 push @$cmd, '--slice', "qemu";
2699 push @$cmd, '--unit', $vmid;
2700 # set KillMode=none, so that systemd don't kill those scopes
2701 # at shutdown (pve-manager service should stop the VMs instead)
2702 push @$cmd, '-p', "KillMode=none";
2703 push @$cmd, '-p', "CPUShares=$cpuunits";
2704 if ($conf->{cpulimit
}) {
2705 my $cpulimit = int($conf->{cpulimit
} * 100);
2706 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2709 push @$cmd, '/usr/bin/kvm';
2711 push @$cmd, '-id', $vmid;
2715 my $qmpsocket = qmp_socket
($vmid);
2716 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2717 push @$cmd, '-mon', "chardev=qmp,mode=control";
2720 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2722 push @$cmd, '-daemonize';
2724 if ($conf->{smbios1
}) {
2725 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2728 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2729 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2730 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2731 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2732 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2733 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2734 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2738 # the q35 chipset support native usb2, so we enable usb controller
2739 # by default for this machine type
2740 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2742 $pciaddr = print_pci_addr
("piix3", $bridges);
2743 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2746 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2747 next if !$conf->{"usb$i"};
2748 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2749 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2752 # include usb device config
2753 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2756 # add usb3 controller if needed
2759 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2760 next if !$conf->{"usb$i"};
2761 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2762 next if !$d || !$d->{usb3
};
2766 $pciaddr = print_pci_addr
("xhci", $bridges);
2767 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2769 my $vga = $conf->{vga
};
2771 my $qxlnum = vga_conf_has_spice
($vga);
2772 $vga = 'qxl' if $qxlnum;
2775 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2776 $conf->{ostype
} eq 'win7' ||
2777 $conf->{ostype
} eq 'w2k8')) {
2784 # enable absolute mouse coordinates (needed by vnc)
2786 if (defined($conf->{tablet
})) {
2787 $tablet = $conf->{tablet
};
2789 $tablet = $defaults->{tablet
};
2790 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2791 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2794 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2798 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2799 my $d = parse_hostpci
($conf->{"hostpci$i"});
2802 my $pcie = $d->{pcie
};
2804 die "q35 machine model is not enabled" if !$q35;
2805 $pciaddr = print_pcie_addr
("hostpci$i");
2807 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2810 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2811 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2812 if ($xvga && $xvga ne '') {
2815 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2816 push @$cpuFlags , 'hv_vendor_id=proxmox';
2818 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2822 my $pcidevices = $d->{pciid
};
2823 my $multifunction = 1 if @$pcidevices > 1;
2826 foreach my $pcidevice (@$pcidevices) {
2828 my $id = "hostpci$i";
2829 $id .= ".$j" if $multifunction;
2830 my $addr = $pciaddr;
2831 $addr .= ".$j" if $multifunction;
2832 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2835 $devicestr .= "$rombar$xvga";
2836 $devicestr .= ",multifunction=on" if $multifunction;
2839 push @$devices, '-device', $devicestr;
2845 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2846 next if !$conf->{"usb$i"};
2847 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2850 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2852 if (defined($d->{usb3
}) && $d->{usb3
}) {
2853 $usbbus = ',bus=xhci.0';
2856 if (defined($d->{host
})) {
2857 $d = parse_usb_device
($d->{host
});
2858 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2859 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2860 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2861 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2862 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2863 # usb redir support for spice, currently no usb3
2864 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2865 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2871 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2872 if (my $path = $conf->{"serial$i"}) {
2873 if ($path eq 'socket') {
2874 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2875 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2876 push @$devices, '-device', "isa-serial,chardev=serial$i";
2878 die "no such serial device\n" if ! -c
$path;
2879 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2880 push @$devices, '-device', "isa-serial,chardev=serial$i";
2886 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2887 if (my $path = $conf->{"parallel$i"}) {
2888 die "no such parallel device\n" if ! -c
$path;
2889 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2890 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2891 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2895 my $vmname = $conf->{name
} || "vm$vmid";
2897 push @$cmd, '-name', $vmname;
2900 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2901 $sockets = $conf->{sockets
} if $conf->{sockets
};
2903 my $cores = $conf->{cores
} || 1;
2905 my $maxcpus = $sockets * $cores;
2907 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2909 my $allowed_vcpus = $cpuinfo->{cpus
};
2911 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2912 if ($allowed_vcpus < $maxcpus);
2914 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2916 push @$cmd, '-nodefaults';
2918 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2920 my $bootindex_hash = {};
2922 foreach my $o (split(//, $bootorder)) {
2923 $bootindex_hash->{$o} = $i*100;
2927 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2929 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2931 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2933 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2935 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
2936 my $socket = vnc_socket
($vmid);
2937 push @$cmd, '-vnc', "unix:$socket,x509,password";
2939 push @$cmd, '-nographic';
2943 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2945 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2946 my $useLocaltime = $conf->{localtime};
2949 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2951 if ($ostype =~ m/^w/) { # windows
2952 $useLocaltime = 1 if !defined($conf->{localtime});
2954 # use time drift fix when acpi is enabled
2955 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2956 $tdf = 1 if !defined($conf->{tdf
});
2960 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
2961 $ostype eq 'wvista') {
2962 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2963 push @$cmd, '-no-hpet';
2964 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2965 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2966 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2967 push @$cpuFlags , 'hv_time' if !$nokvm;
2970 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2974 if ($ostype eq 'win7' || $ostype eq 'win8') {
2975 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2979 push @$rtcFlags, 'driftfix=slew' if $tdf;
2982 push @$machineFlags, 'accel=tcg';
2984 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2987 if ($machine_type) {
2988 push @$machineFlags, "type=${machine_type}";
2991 if ($conf->{startdate
}) {
2992 push @$rtcFlags, "base=$conf->{startdate}";
2993 } elsif ($useLocaltime) {
2994 push @$rtcFlags, 'base=localtime';
2997 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2998 if (my $cputype = $conf->{cpu
}) {
2999 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpudesc, $cputype)
3000 or die "Cannot parse cpu description: $cputype\n";
3001 $cpu = $cpuconf->{cputype
};
3002 $kvm_off = 1 if $cpuconf->{hidden
};
3005 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3007 push @$cpuFlags , '-x2apic'
3008 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3010 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3012 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3014 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3016 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3017 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3020 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3022 push @$cpuFlags, 'kvm=off' if $kvm_off;
3024 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3026 push @$cmd, '-cpu', $cpu;
3028 my $memory = $conf->{memory
} || $defaults->{memory
};
3029 my $static_memory = 0;
3030 my $dimm_memory = 0;
3032 if ($hotplug_features->{memory
}) {
3033 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3034 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3035 $static_memory = $STATICMEM;
3036 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3037 $dimm_memory = $memory - $static_memory;
3038 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3042 $static_memory = $memory;
3043 push @$cmd, '-m', $static_memory;
3046 if ($conf->{numa
}) {
3048 my $numa_totalmemory = undef;
3049 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3050 next if !$conf->{"numa$i"};
3051 my $numa = parse_numa
($conf->{"numa$i"});
3054 die "missing numa node$i memory value\n" if !$numa->{memory
};
3055 my $numa_memory = $numa->{memory
};
3056 $numa_totalmemory += $numa_memory;
3057 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3060 my $cpus_start = $numa->{cpus
}->{start
};
3061 die "missing numa node$i cpus\n" if !defined($cpus_start);
3062 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3063 my $cpus = $cpus_start;
3064 if (defined($cpus_end)) {
3065 $cpus .= "-$cpus_end";
3066 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3070 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3071 if (defined($hostnodes_start)) {
3072 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3073 my $hostnodes = $hostnodes_start;
3074 if (defined($hostnodes_end)) {
3075 $hostnodes .= "-$hostnodes_end";
3076 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3079 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3080 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3081 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3085 my $policy = $numa->{policy
};
3086 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3087 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3090 push @$cmd, '-object', $numa_object;
3091 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3094 die "total memory for NUMA nodes must be equal to vm static memory\n"
3095 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3097 #if no custom tology, we split memory and cores across numa nodes
3098 if(!$numa_totalmemory) {
3100 my $numa_memory = ($static_memory / $sockets) . "M";
3102 for (my $i = 0; $i < $sockets; $i++) {
3104 my $cpustart = ($cores * $i);
3105 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3106 my $cpus = $cpustart;
3107 $cpus .= "-$cpuend" if $cpuend;
3109 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3110 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3115 if ($hotplug_features->{memory
}) {
3116 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3117 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3118 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3119 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3121 #if dimm_memory is not aligned to dimm map
3122 if($current_size > $memory) {
3123 $conf->{memory
} = $current_size;
3124 PVE
::QemuConfig-
>write_config($vmid, $conf);
3129 push @$cmd, '-S' if $conf->{freeze
};
3131 # set keyboard layout
3132 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3133 push @$cmd, '-k', $kb if $kb;
3136 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3137 #push @$cmd, '-soundhw', 'es1370';
3138 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3140 if($conf->{agent
}) {
3141 my $qgasocket = qmp_socket
($vmid, 1);
3142 my $pciaddr = print_pci_addr
("qga0", $bridges);
3143 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3144 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3145 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3152 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3153 for(my $i = 1; $i < $qxlnum; $i++){
3154 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3155 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3158 # assume other OS works like Linux
3159 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3160 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3164 my $pciaddr = print_pci_addr
("spice", $bridges);
3166 my $nodename = PVE
::INotify
::nodename
();
3167 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3168 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3170 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3172 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3173 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3174 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3177 # enable balloon by default, unless explicitly disabled
3178 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3179 $pciaddr = print_pci_addr
("balloon0", $bridges);
3180 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3183 if ($conf->{watchdog
}) {
3184 my $wdopts = parse_watchdog
($conf->{watchdog
});
3185 $pciaddr = print_pci_addr
("watchdog", $bridges);
3186 my $watchdog = $wdopts->{model
} || 'i6300esb';
3187 push @$devices, '-device', "$watchdog$pciaddr";
3188 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3192 my $scsicontroller = {};
3193 my $ahcicontroller = {};
3194 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3196 # Add iscsi initiator name if available
3197 if (my $initiator = get_initiator_name
()) {
3198 push @$devices, '-iscsi', "initiator-name=$initiator";
3201 foreach_drive
($conf, sub {
3202 my ($ds, $drive) = @_;
3204 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3205 push @$vollist, $drive->{file
};
3208 $use_virtio = 1 if $ds =~ m/^virtio/;
3210 if (drive_is_cdrom
($drive)) {
3211 if ($bootindex_hash->{d
}) {
3212 $drive->{bootindex
} = $bootindex_hash->{d
};
3213 $bootindex_hash->{d
} += 1;
3216 if ($bootindex_hash->{c
}) {
3217 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3218 $bootindex_hash->{c
} += 1;
3222 if($drive->{interface
} eq 'virtio'){
3223 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3226 if ($drive->{interface
} eq 'scsi') {
3228 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3230 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3231 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3234 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3235 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3236 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3240 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3241 $queues = ",num_queues=$drive->{queues}";
3244 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3245 $scsicontroller->{$controller}=1;
3248 if ($drive->{interface
} eq 'sata') {
3249 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3250 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3251 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3252 $ahcicontroller->{$controller}=1;
3255 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3256 push @$devices, '-drive',$drive_cmd;
3257 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3260 for (my $i = 0; $i < $MAX_NETS; $i++) {
3261 next if !$conf->{"net$i"};
3262 my $d = parse_net
($conf->{"net$i"});
3265 $use_virtio = 1 if $d->{model
} eq 'virtio';
3267 if ($bootindex_hash->{n
}) {
3268 $d->{bootindex
} = $bootindex_hash->{n
};
3269 $bootindex_hash->{n
} += 1;
3272 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3273 push @$devices, '-netdev', $netdevfull;
3275 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3276 push @$devices, '-device', $netdevicefull;
3281 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3286 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3288 while (my ($k, $v) = each %$bridges) {
3289 $pciaddr = print_pci_addr
("pci.$k");
3290 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3295 if ($conf->{args
}) {
3296 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3300 push @$cmd, @$devices;
3301 push @$cmd, '-rtc', join(',', @$rtcFlags)
3302 if scalar(@$rtcFlags);
3303 push @$cmd, '-machine', join(',', @$machineFlags)
3304 if scalar(@$machineFlags);
3305 push @$cmd, '-global', join(',', @$globalFlags)
3306 if scalar(@$globalFlags);
3308 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3313 return "${var_run_tmpdir}/$vmid.vnc";
3319 my $res = vm_mon_cmd
($vmid, 'query-spice');
3321 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3325 my ($vmid, $qga) = @_;
3326 my $sockettype = $qga ?
'qga' : 'qmp';
3327 return "${var_run_tmpdir}/$vmid.$sockettype";
3332 return "${var_run_tmpdir}/$vmid.pid";
3335 sub vm_devices_list
{
3338 my $res = vm_mon_cmd
($vmid, 'query-pci');
3340 foreach my $pcibus (@$res) {
3341 foreach my $device (@{$pcibus->{devices
}}) {
3342 next if !$device->{'qdev_id'};
3343 if ($device->{'pci_bridge'}) {
3344 $devices->{$device->{'qdev_id'}} = 1;
3345 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3346 next if !$bridge_device->{'qdev_id'};
3347 $devices->{$bridge_device->{'qdev_id'}} = 1;
3348 $devices->{$device->{'qdev_id'}}++;
3351 $devices->{$device->{'qdev_id'}} = 1;
3356 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3357 foreach my $block (@$resblock) {
3358 if($block->{device
} =~ m/^drive-(\S+)/){
3363 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3364 foreach my $mice (@$resmice) {
3365 if ($mice->{name
} eq 'QEMU HID Tablet') {
3366 $devices->{tablet
} = 1;
3375 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3377 my $q35 = machine_type_is_q35
($conf);
3379 my $devices_list = vm_devices_list
($vmid);
3380 return 1 if defined($devices_list->{$deviceid});
3382 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3384 if ($deviceid eq 'tablet') {
3386 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3388 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3390 qemu_iothread_add
($vmid, $deviceid, $device);
3392 qemu_driveadd
($storecfg, $vmid, $device);
3393 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3395 qemu_deviceadd
($vmid, $devicefull);
3396 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3398 eval { qemu_drivedel
($vmid, $deviceid); };
3403 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3406 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3407 my $pciaddr = print_pci_addr
($deviceid);
3408 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3410 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3412 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3413 qemu_iothread_add
($vmid, $deviceid, $device);
3414 $devicefull .= ",iothread=iothread-$deviceid";
3417 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3418 $devicefull .= ",num_queues=$device->{queues}";
3421 qemu_deviceadd
($vmid, $devicefull);
3422 qemu_deviceaddverify
($vmid, $deviceid);
3424 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3426 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3427 qemu_driveadd
($storecfg, $vmid, $device);
3429 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3430 eval { qemu_deviceadd
($vmid, $devicefull); };
3432 eval { qemu_drivedel
($vmid, $deviceid); };
3437 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3439 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3441 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3442 my $use_old_bios_files = undef;
3443 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3445 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3446 qemu_deviceadd
($vmid, $netdevicefull);
3447 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3449 eval { qemu_netdevdel
($vmid, $deviceid); };
3454 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3457 my $pciaddr = print_pci_addr
($deviceid);
3458 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3460 qemu_deviceadd
($vmid, $devicefull);
3461 qemu_deviceaddverify
($vmid, $deviceid);
3464 die "can't hotplug device '$deviceid'\n";
3470 # fixme: this should raise exceptions on error!
3471 sub vm_deviceunplug
{
3472 my ($vmid, $conf, $deviceid) = @_;
3474 my $devices_list = vm_devices_list
($vmid);
3475 return 1 if !defined($devices_list->{$deviceid});
3477 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3479 if ($deviceid eq 'tablet') {
3481 qemu_devicedel
($vmid, $deviceid);
3483 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3485 qemu_devicedel
($vmid, $deviceid);
3486 qemu_devicedelverify
($vmid, $deviceid);
3487 qemu_drivedel
($vmid, $deviceid);
3488 qemu_iothread_del
($conf, $vmid, $deviceid);
3490 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3492 qemu_devicedel
($vmid, $deviceid);
3493 qemu_devicedelverify
($vmid, $deviceid);
3494 qemu_iothread_del
($conf, $vmid, $deviceid);
3496 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3498 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3499 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3500 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3502 qemu_devicedel
($vmid, $deviceid);
3503 qemu_drivedel
($vmid, $deviceid);
3504 qemu_deletescsihw
($conf, $vmid, $deviceid);
3506 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3508 qemu_devicedel
($vmid, $deviceid);
3509 qemu_devicedelverify
($vmid, $deviceid);
3510 qemu_netdevdel
($vmid, $deviceid);
3513 die "can't unplug device '$deviceid'\n";
3519 sub qemu_deviceadd
{
3520 my ($vmid, $devicefull) = @_;
3522 $devicefull = "driver=".$devicefull;
3523 my %options = split(/[=,]/, $devicefull);
3525 vm_mon_cmd
($vmid, "device_add" , %options);
3528 sub qemu_devicedel
{
3529 my ($vmid, $deviceid) = @_;
3531 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3534 sub qemu_iothread_add
{
3535 my($vmid, $deviceid, $device) = @_;
3537 if ($device->{iothread
}) {
3538 my $iothreads = vm_iothreads_list
($vmid);
3539 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3543 sub qemu_iothread_del
{
3544 my($conf, $vmid, $deviceid) = @_;
3546 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3547 if ($device->{iothread
}) {
3548 my $iothreads = vm_iothreads_list
($vmid);
3549 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3553 sub qemu_objectadd
{
3554 my($vmid, $objectid, $qomtype) = @_;
3556 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3561 sub qemu_objectdel
{
3562 my($vmid, $objectid) = @_;
3564 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3570 my ($storecfg, $vmid, $device) = @_;
3572 my $drive = print_drive_full
($storecfg, $vmid, $device);
3573 $drive =~ s/\\/\\\\/g;
3574 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3576 # If the command succeeds qemu prints: "OK
"
3577 return 1 if $ret =~ m/OK/s;
3579 die "adding drive failed
: $ret\n";
3583 my($vmid, $deviceid) = @_;
3585 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3588 return 1 if $ret eq "";
3590 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3591 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3593 die "deleting drive
$deviceid failed
: $ret\n";
3596 sub qemu_deviceaddverify {
3597 my ($vmid, $deviceid) = @_;
3599 for (my $i = 0; $i <= 5; $i++) {
3600 my $devices_list = vm_devices_list($vmid);
3601 return 1 if defined($devices_list->{$deviceid});
3605 die "error on hotplug device
'$deviceid'\n";
3609 sub qemu_devicedelverify {
3610 my ($vmid, $deviceid) = @_;
3612 # need to verify that the device is correctly removed as device_del
3613 # is async and empty return is not reliable
3615 for (my $i = 0; $i <= 5; $i++) {
3616 my $devices_list = vm_devices_list($vmid);
3617 return 1 if !defined($devices_list->{$deviceid});
3621 die "error on hot-unplugging device
'$deviceid'\n";
3624 sub qemu_findorcreatescsihw {
3625 my ($storecfg, $conf, $vmid, $device) = @_;
3627 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3629 my $scsihwid="$controller_prefix$controller";
3630 my $devices_list = vm_devices_list($vmid);
3632 if(!defined($devices_list->{$scsihwid})) {
3633 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3639 sub qemu_deletescsihw {
3640 my ($conf, $vmid, $opt) = @_;
3642 my $device = parse_drive($opt, $conf->{$opt});
3644 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3645 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3649 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3651 my $devices_list = vm_devices_list($vmid);
3652 foreach my $opt (keys %{$devices_list}) {
3653 if (PVE::QemuServer::is_valid_drivename($opt)) {
3654 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3655 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3661 my $scsihwid="scsihw
$controller";
3663 vm_deviceunplug($vmid, $conf, $scsihwid);
3668 sub qemu_add_pci_bridge {
3669 my ($storecfg, $conf, $vmid, $device) = @_;
3675 print_pci_addr($device, $bridges);
3677 while (my ($k, $v) = each %$bridges) {
3680 return 1 if !defined($bridgeid) || $bridgeid < 1;
3682 my $bridge = "pci
.$bridgeid";
3683 my $devices_list = vm_devices_list($vmid);
3685 if (!defined($devices_list->{$bridge})) {
3686 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3692 sub qemu_set_link_status {
3693 my ($vmid, $device, $up) = @_;
3695 vm_mon_cmd($vmid, "set_link
", name => $device,
3696 up => $up ? JSON::true : JSON::false);
3699 sub qemu_netdevadd {
3700 my ($vmid, $conf, $device, $deviceid) = @_;
3702 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3703 my %options = split(/[=,]/, $netdev);
3705 vm_mon_cmd($vmid, "netdev_add
", %options);
3709 sub qemu_netdevdel {
3710 my ($vmid, $deviceid) = @_;
3712 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3715 sub qemu_cpu_hotplug {
3716 my ($vmid, $conf, $vcpus) = @_;
3719 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3720 $sockets = $conf->{sockets} if $conf->{sockets};
3721 my $cores = $conf->{cores} || 1;
3722 my $maxcpus = $sockets * $cores;
3724 $vcpus = $maxcpus if !$vcpus;
3726 die "you can
't add more vcpus than maxcpus\n"
3727 if $vcpus > $maxcpus;
3729 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3730 die "online cpu unplug is not yet possible\n"
3731 if $vcpus < $currentvcpus;
3733 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3734 die "vcpus in running vm is different than configuration\n"
3735 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3737 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3738 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3742 sub qemu_memory_hotplug {
3743 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3745 return $value if !check_running($vmid);
3747 my $memory = $conf->{memory} || $defaults->{memory};
3748 $value = $defaults->{memory} if !$value;
3749 return $value if $value == $memory;
3751 my $static_memory = $STATICMEM;
3752 my $dimm_memory = $memory - $static_memory;
3754 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3755 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3759 $sockets = $conf->{sockets} if $conf->{sockets};
3761 if($value > $memory) {
3763 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3764 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3766 return if $current_size <= $conf->{memory};
3768 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3770 eval { qemu_objectdel($vmid, "mem-
$name"); };
3774 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3776 eval { qemu_objectdel($vmid, "mem-
$name"); };
3779 #update conf after each succesful module hotplug
3780 $conf->{memory} = $current_size;
3781 PVE::QemuConfig->write_config($vmid, $conf);
3786 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3787 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3789 return if $current_size >= $conf->{memory};
3790 print "try to unplug memory dimm
$name\n";
3794 eval { qemu_devicedel($vmid, $name) };
3796 my $dimm_list = qemu_dimm_list($vmid);
3797 last if !$dimm_list->{$name};
3798 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3802 #update conf after each succesful module unplug
3803 $conf->{memory} = $current_size;
3805 eval { qemu_objectdel($vmid, "mem-
$name"); };
3806 PVE::QemuConfig->write_config($vmid, $conf);
3811 sub qemu_dimm_list {
3814 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3817 foreach my $dimm (@$dimmarray) {
3819 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3820 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3821 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3822 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3823 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3828 sub qemu_block_set_io_throttle {
3829 my ($vmid, $deviceid,
3830 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3831 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3833 return if !check_running($vmid) ;
3835 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3837 bps_rd => int($bps_rd),
3838 bps_wr => int($bps_wr),
3840 iops_rd => int($iops_rd),
3841 iops_wr => int($iops_wr),
3842 bps_max => int($bps_max),
3843 bps_rd_max => int($bps_rd_max),
3844 bps_wr_max => int($bps_wr_max),
3845 iops_max => int($iops_max),
3846 iops_rd_max => int($iops_rd_max),
3847 iops_wr_max => int($iops_wr_max)
3852 # old code, only used to shutdown old VM after update
3854 my ($fh, $timeout) = @_;
3856 my $sel = new IO::Select;
3863 while (scalar (@ready = $sel->can_read($timeout))) {
3865 if ($count = $fh->sysread($buf, 8192)) {
3866 if ($buf =~ /^(.*)\(qemu\) $/s) {
3873 if (!defined($count)) {
3880 die "monitor
read timeout
\n" if !scalar(@ready);
3885 # old code, only used to shutdown old VM after update
3886 sub vm_monitor_command {
3887 my ($vmid, $cmdstr, $nocheck) = @_;
3892 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3894 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3896 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3897 die "unable to
connect to VM
$vmid socket - $!\n";
3901 # hack: migrate sometime blocks the monitor (when migrate_downtime
3903 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3904 $timeout = 60*60; # 1 hour
3908 my $data = __read_avail($sock, $timeout);
3910 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3911 die "got unexpected qemu monitor banner
\n";
3914 my $sel = new IO::Select;
3917 if (!scalar(my @ready = $sel->can_write($timeout))) {
3918 die "monitor
write error
- timeout
";
3921 my $fullcmd = "$cmdstr\r";
3923 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3926 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3927 die "monitor
write error
- $!";
3930 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3934 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3935 $timeout = 60*60; # 1 hour
3936 } elsif ($cmdstr =~ m/^(eject|change)/) {
3937 $timeout = 60; # note: cdrom mount command is slow
3939 if ($res = __read_avail($sock, $timeout)) {
3941 my @lines = split("\r?
\n", $res);
3943 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3945 $res = join("\n", @lines);
3953 syslog("err
", "VM
$vmid monitor command failed
- $err");
3960 sub qemu_block_resize {
3961 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3963 my $running = check_running($vmid);
3965 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3967 return if !$running;
3969 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3973 sub qemu_volume_snapshot {
3974 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3976 my $running = check_running($vmid);
3978 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3979 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3981 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3985 sub qemu_volume_snapshot_delete {
3986 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3988 my $running = check_running($vmid);
3990 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3992 return if !$running;
3994 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3997 sub set_migration_caps {
4003 "auto-converge
" => 1,
4005 "x-rdma-pin-all
" => 0,
4010 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4012 for my $supported_capability (@$supported_capabilities) {
4014 capability => $supported_capability->{capability},
4015 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4019 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4022 my $fast_plug_option = {
4031 # hotplug changes in [PENDING]
4032 # $selection hash can be used to only apply specified options, for
4033 # example: { cores => 1 } (only apply changed 'cores')
4034 # $errors ref is used to return error messages
4035 sub vmconfig_hotplug_pending {
4036 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4038 my $defaults = load_defaults();
4040 # commit values which do not have any impact on running VM first
4041 # Note: those option cannot raise errors, we we do not care about
4042 # $selection and always apply them.
4044 my $add_error = sub {
4045 my ($opt, $msg) = @_;
4046 $errors->{$opt} = "hotplug problem
- $msg";
4050 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4051 if ($fast_plug_option->{$opt}) {
4052 $conf->{$opt} = $conf->{pending}->{$opt};
4053 delete $conf->{pending}->{$opt};
4059 PVE::QemuConfig->write_config($vmid, $conf);
4060 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4063 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4065 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4066 while (my ($opt, $force) = each %$pending_delete_hash) {
4067 next if $selection && !$selection->{$opt};
4069 if ($opt eq 'hotplug') {
4070 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4071 } elsif ($opt eq 'tablet') {
4072 die "skip
\n" if !$hotplug_features->{usb};
4073 if ($defaults->{tablet}) {
4074 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4076 vm_deviceunplug($vmid, $conf, $opt);
4078 } elsif ($opt eq 'vcpus') {
4079 die "skip
\n" if !$hotplug_features->{cpu};
4080 qemu_cpu_hotplug($vmid, $conf, undef);
4081 } elsif ($opt eq 'balloon') {
4082 # enable balloon device is not hotpluggable
4083 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4084 } elsif ($fast_plug_option->{$opt}) {
4086 } elsif ($opt =~ m/^net(\d+)$/) {
4087 die "skip
\n" if !$hotplug_features->{network};
4088 vm_deviceunplug($vmid, $conf, $opt);
4089 } elsif (is_valid_drivename($opt)) {
4090 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4091 vm_deviceunplug($vmid, $conf, $opt);
4092 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4093 } elsif ($opt =~ m/^memory$/) {
4094 die "skip
\n" if !$hotplug_features->{memory};
4095 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4096 } elsif ($opt eq 'cpuunits') {
4097 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4098 } elsif ($opt eq 'cpulimit') {
4099 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4105 &$add_error($opt, $err) if $err ne "skip
\n";
4107 # save new config if hotplug was successful
4108 delete $conf->{$opt};
4109 vmconfig_undelete_pending_option($conf, $opt);
4110 PVE::QemuConfig->write_config($vmid, $conf);
4111 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4115 foreach my $opt (keys %{$conf->{pending}}) {
4116 next if $selection && !$selection->{$opt};
4117 my $value = $conf->{pending}->{$opt};
4119 if ($opt eq 'hotplug') {
4120 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4121 } elsif ($opt eq 'tablet') {
4122 die "skip
\n" if !$hotplug_features->{usb};
4124 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4125 } elsif ($value == 0) {
4126 vm_deviceunplug($vmid, $conf, $opt);
4128 } elsif ($opt eq 'vcpus') {
4129 die "skip
\n" if !$hotplug_features->{cpu};
4130 qemu_cpu_hotplug($vmid, $conf, $value);
4131 } elsif ($opt eq 'balloon') {
4132 # enable/disable balloning device is not hotpluggable
4133 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4134 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4135 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4137 # allow manual ballooning if shares is set to zero
4138 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4139 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4140 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4142 } elsif ($opt =~ m/^net(\d+)$/) {
4143 # some changes can be done without hotplug
4144 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4145 $vmid, $opt, $value);
4146 } elsif (is_valid_drivename($opt)) {
4147 # some changes can be done without hotplug
4148 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4149 $vmid, $opt, $value, 1);
4150 } elsif ($opt =~ m/^memory$/) { #dimms
4151 die "skip
\n" if !$hotplug_features->{memory};
4152 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4153 } elsif ($opt eq 'cpuunits') {
4154 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4155 } elsif ($opt eq 'cpulimit') {
4156 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4157 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4159 die "skip
\n"; # skip non-hot-pluggable options
4163 &$add_error($opt, $err) if $err ne "skip
\n";
4165 # save new config if hotplug was successful
4166 $conf->{$opt} = $value;
4167 delete $conf->{pending}->{$opt};
4168 PVE::QemuConfig->write_config($vmid, $conf);
4169 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4174 sub try_deallocate_drive {
4175 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4177 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4178 my $volid = $drive->{file};
4179 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4180 my $sid = PVE::Storage::parse_volume_id($volid);
4181 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4183 # check if the disk is really unused
4184 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4185 if is_volume_in_use($storecfg, $conf, $key, $volid);
4186 PVE::Storage::vdisk_free($storecfg, $volid);
4189 # If vm is not owner of this disk remove from config
4197 sub vmconfig_delete_or_detach_drive {
4198 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4200 my $drive = parse_drive($opt, $conf->{$opt});
4202 my $rpcenv = PVE::RPCEnvironment::get();
4203 my $authuser = $rpcenv->get_user();
4206 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4207 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4209 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4213 sub vmconfig_apply_pending {
4214 my ($vmid, $conf, $storecfg) = @_;
4218 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4219 while (my ($opt, $force) = each %$pending_delete_hash) {
4220 die "internal error
" if $opt =~ m/^unused/;
4221 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4222 if (!defined($conf->{$opt})) {
4223 vmconfig_undelete_pending_option($conf, $opt);
4224 PVE::QemuConfig->write_config($vmid, $conf);
4225 } elsif (is_valid_drivename($opt)) {
4226 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4227 vmconfig_undelete_pending_option($conf, $opt);
4228 delete $conf->{$opt};
4229 PVE::QemuConfig->write_config($vmid, $conf);
4231 vmconfig_undelete_pending_option($conf, $opt);
4232 delete $conf->{$opt};
4233 PVE::QemuConfig->write_config($vmid, $conf);
4237 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4239 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4240 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4242 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4243 # skip if nothing changed
4244 } elsif (is_valid_drivename($opt)) {
4245 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4246 if defined($conf->{$opt});
4247 $conf->{$opt} = $conf->{pending}->{$opt};
4249 $conf->{$opt} = $conf->{pending}->{$opt};
4252 delete $conf->{pending}->{$opt};
4253 PVE::QemuConfig->write_config($vmid, $conf);
4257 my $safe_num_ne = sub {
4260 return 0 if !defined($a) && !defined($b);
4261 return 1 if !defined($a);
4262 return 1 if !defined($b);
4267 my $safe_string_ne = sub {
4270 return 0 if !defined($a) && !defined($b);
4271 return 1 if !defined($a);
4272 return 1 if !defined($b);
4277 sub vmconfig_update_net {
4278 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4280 my $newnet = parse_net($value);
4282 if ($conf->{$opt}) {
4283 my $oldnet = parse_net($conf->{$opt});
4285 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4286 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4287 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4288 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4290 # for non online change, we try to hot-unplug
4291 die "skip
\n" if !$hotplug;
4292 vm_deviceunplug($vmid, $conf, $opt);
4295 die "internal error
" if $opt !~ m/net(\d+)/;
4296 my $iface = "tap
${vmid
}i
$1";
4298 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4299 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4302 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4303 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4304 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4305 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4306 PVE::Network::tap_unplug($iface);
4307 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks});
4310 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4311 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4319 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4325 sub vmconfig_update_disk {
4326 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4328 # fixme: do we need force?
4330 my $drive = parse_drive($opt, $value);
4332 if ($conf->{$opt}) {
4334 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4336 my $media = $drive->{media} || 'disk';
4337 my $oldmedia = $old_drive->{media} || 'disk';
4338 die "unable to change media type
\n" if $media ne $oldmedia;
4340 if (!drive_is_cdrom($old_drive)) {
4342 if ($drive->{file} ne $old_drive->{file}) {
4344 die "skip
\n" if !$hotplug;
4346 # unplug and register as unused
4347 vm_deviceunplug($vmid, $conf, $opt);
4348 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4351 # update existing disk
4353 # skip non hotpluggable value
4354 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4355 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4356 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4357 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4362 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4363 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4364 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4365 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4366 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4367 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4368 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4369 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4370 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4371 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4372 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4373 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4375 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4376 ($drive->{mbps} || 0)*1024*1024,
4377 ($drive->{mbps_rd} || 0)*1024*1024,
4378 ($drive->{mbps_wr} || 0)*1024*1024,
4379 $drive->{iops} || 0,
4380 $drive->{iops_rd} || 0,
4381 $drive->{iops_wr} || 0,
4382 ($drive->{mbps_max} || 0)*1024*1024,
4383 ($drive->{mbps_rd_max} || 0)*1024*1024,
4384 ($drive->{mbps_wr_max} || 0)*1024*1024,
4385 $drive->{iops_max} || 0,
4386 $drive->{iops_rd_max} || 0,
4387 $drive->{iops_wr_max} || 0);
4396 if ($drive->{file} eq 'none') {
4397 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4399 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4400 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4401 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4409 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4411 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4412 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4416 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4417 $forcemachine, $spice_ticket) = @_;
4419 PVE::QemuConfig->lock_config($vmid, sub {
4420 my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
4422 die "you can
't start a vm if it's a template
\n" if PVE::QemuConfig->is_template($conf);
4424 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4426 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4428 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4429 vmconfig_apply_pending($vmid, $conf, $storecfg);
4430 $conf = PVE::QemuConfig->load_config($vmid); # update/reload
4433 my $defaults = load_defaults();
4435 # set environment variable useful inside network script
4436 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4438 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4440 my $migrate_port = 0;
4443 if ($statefile eq 'tcp') {
4444 my $localip = "localhost
";
4445 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4446 my $nodename = PVE::INotify::nodename();
4447 if ($datacenterconf->{migration_unsecure}) {
4448 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4449 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4451 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4452 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4453 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4454 push @$cmd, '-incoming', $migrate_uri;
4457 push @$cmd, '-loadstate', $statefile;
4464 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4465 my $d = parse_hostpci($conf->{"hostpci
$i"});
4467 my $pcidevices = $d->{pciid};
4468 foreach my $pcidevice (@$pcidevices) {
4469 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4471 my $info = pci_device_info("0000:$pciid");
4472 die "IOMMU
not present
\n" if !check_iommu_support();
4473 die "no pci device info
for device
'$pciid'\n" if !$info;
4474 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4475 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4479 PVE::Storage::activate_volumes($storecfg, $vollist);
4481 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4485 # deactivate volumes if start fails
4486 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4487 die "start failed
: $err";
4490 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4492 if ($statefile && $statefile ne 'tcp') {
4493 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4497 if ($migratedfrom) {
4500 set_migration_caps($vmid);
4505 print "spice listens on port
$spice_port\n";
4506 if ($spice_ticket) {
4507 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4508 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4514 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4515 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4516 if $conf->{balloon};
4519 foreach my $opt (keys %$conf) {
4520 next if $opt !~ m/^net\d+$/;
4521 my $nicconf = parse_net($conf->{$opt});
4522 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4526 vm_mon_cmd_nocheck($vmid, 'qom-set',
4527 path => "machine
/peripheral/balloon0
",
4528 property => "guest-stats-polling-interval
",
4529 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4535 my ($vmid, $execute, %params) = @_;
4537 my $cmd = { execute => $execute, arguments => \%params };
4538 vm_qmp_command($vmid, $cmd);
4541 sub vm_mon_cmd_nocheck {
4542 my ($vmid, $execute, %params) = @_;
4544 my $cmd = { execute => $execute, arguments => \%params };
4545 vm_qmp_command($vmid, $cmd, 1);
4548 sub vm_qmp_command {
4549 my ($vmid, $cmd, $nocheck) = @_;
4554 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4555 $timeout = $cmd->{arguments}->{timeout};
4556 delete $cmd->{arguments}->{timeout};
4560 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4561 my $sname = qmp_socket($vmid);
4562 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4563 my $qmpclient = PVE::QMPClient->new();
4565 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4566 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4567 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4568 if scalar(%{$cmd->{arguments}});
4569 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4571 die "unable to open monitor socket\n";
4575 syslog("err", "VM $vmid qmp command failed - $err");
4582 sub vm_human_monitor_command {
4583 my ($vmid, $cmdline) = @_;
4588 execute => 'human-monitor-command
',
4589 arguments => { 'command-line
' => $cmdline},
4592 return vm_qmp_command($vmid, $cmd);
4595 sub vm_commandline {
4596 my ($storecfg, $vmid) = @_;
4598 my $conf = PVE::QemuConfig->load_config($vmid);
4600 my $defaults = load_defaults();
4602 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4604 return join(' ', @$cmd);
4608 my ($vmid, $skiplock) = @_;
4610 PVE::QemuConfig->lock_config($vmid, sub {
4612 my $conf = PVE::QemuConfig->load_config($vmid);
4614 PVE::QemuConfig->check_lock($conf) if !$skiplock;
4616 vm_mon_cmd($vmid, "system_reset");
4620 sub get_vm_volumes {
4624 foreach_volid($conf, sub {
4625 my ($volid, $is_cdrom) = @_;
4627 return if $volid =~ m|^/|;
4629 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4632 push @$vollist, $volid;
4638 sub vm_stop_cleanup {
4639 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4644 my $vollist = get_vm_volumes($conf);
4645 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4648 foreach my $ext (qw(mon qmp pid vnc qga)) {
4649 unlink "/var/run/qemu-server/${vmid}.$ext";
4652 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4654 warn $@ if $@; # avoid errors - just warn
4657 # Note: use $nockeck to skip tests if VM configuration file exists.
4658 # We need that when migration VMs to other nodes (files already moved)
4659 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4661 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4663 $force = 1 if !defined($force) && !$shutdown;
4666 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4667 kill 15, $pid if $pid;
4668 my $conf = PVE
::QemuConfig-
>load_config($vmid, $migratedfrom);
4669 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4673 PVE
::QemuConfig-
>lock_config($vmid, sub {
4675 my $pid = check_running
($vmid, $nocheck);
4680 $conf = PVE
::QemuConfig-
>load_config($vmid);
4681 PVE
::QemuConfig-
>check_lock($conf) if !$skiplock;
4682 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4683 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4684 $timeout = $opts->{down
} if $opts->{down
};
4688 $timeout = 60 if !defined($timeout);
4692 if (defined($conf) && $conf->{agent
}) {
4693 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4695 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4698 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4705 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4710 if ($count >= $timeout) {
4712 warn "VM still running - terminating now with SIGTERM\n";
4715 die "VM quit/powerdown failed - got timeout\n";
4718 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4723 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4726 die "VM quit/powerdown failed\n";
4734 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4739 if ($count >= $timeout) {
4740 warn "VM still running - terminating now with SIGKILL\n";
4745 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4750 my ($vmid, $skiplock) = @_;
4752 PVE
::QemuConfig-
>lock_config($vmid, sub {
4754 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4756 PVE
::QemuConfig-
>check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4758 vm_mon_cmd
($vmid, "stop");
4763 my ($vmid, $skiplock, $nocheck) = @_;
4765 PVE
::QemuConfig-
>lock_config($vmid, sub {
4769 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4771 PVE
::QemuConfig-
>check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4773 vm_mon_cmd
($vmid, "cont");
4776 vm_mon_cmd_nocheck
($vmid, "cont");
4782 my ($vmid, $skiplock, $key) = @_;
4784 PVE
::QemuConfig-
>lock_config($vmid, sub {
4786 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4788 # there is no qmp command, so we use the human monitor command
4789 vm_human_monitor_command
($vmid, "sendkey $key");
4794 my ($storecfg, $vmid, $skiplock) = @_;
4796 PVE
::QemuConfig-
>lock_config($vmid, sub {
4798 my $conf = PVE
::QemuConfig-
>load_config($vmid);
4800 if (!check_running
($vmid)) {
4801 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4803 die "VM $vmid is running - destroy failed\n";
4811 my ($filename, $buf) = @_;
4813 my $fh = IO
::File-
>new($filename, "w");
4814 return undef if !$fh;
4816 my $res = print $fh $buf;
4823 sub pci_device_info
{
4828 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4829 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4831 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4832 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4834 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4835 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4837 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4838 return undef if !defined($product) || $product !~ s/^0x//;
4843 product
=> $product,
4849 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4858 my $name = $dev->{name
};
4860 my $fn = "$pcisysfs/devices/$name/reset";
4862 return file_write
($fn, "1");
4865 sub pci_dev_bind_to_vfio
{
4868 my $name = $dev->{name
};
4870 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4872 if (!-d
$vfio_basedir) {
4873 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4875 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4877 my $testdir = "$vfio_basedir/$name";
4878 return 1 if -d
$testdir;
4880 my $data = "$dev->{vendor} $dev->{product}";
4881 return undef if !file_write
("$vfio_basedir/new_id", $data);
4883 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4884 if (!file_write
($fn, $name)) {
4885 return undef if -f
$fn;
4888 $fn = "$vfio_basedir/bind";
4889 if (! -d
$testdir) {
4890 return undef if !file_write
($fn, $name);
4896 sub pci_dev_group_bind_to_vfio
{
4899 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4901 if (!-d
$vfio_basedir) {
4902 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4904 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4906 # get IOMMU group devices
4907 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4908 my @devs = grep /^0000:/, readdir($D);
4911 foreach my $pciid (@devs) {
4912 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4914 # pci bridges, switches or root ports are not supported
4915 # they have a pci_bus subdirectory so skip them
4916 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4918 my $info = pci_device_info
($1);
4919 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4925 sub print_pci_addr
{
4926 my ($id, $bridges) = @_;
4930 piix3
=> { bus
=> 0, addr
=> 1 },
4931 #addr2 : first videocard
4932 balloon0
=> { bus
=> 0, addr
=> 3 },
4933 watchdog
=> { bus
=> 0, addr
=> 4 },
4934 scsihw0
=> { bus
=> 0, addr
=> 5 },
4935 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4936 scsihw1
=> { bus
=> 0, addr
=> 6 },
4937 ahci0
=> { bus
=> 0, addr
=> 7 },
4938 qga0
=> { bus
=> 0, addr
=> 8 },
4939 spice
=> { bus
=> 0, addr
=> 9 },
4940 virtio0
=> { bus
=> 0, addr
=> 10 },
4941 virtio1
=> { bus
=> 0, addr
=> 11 },
4942 virtio2
=> { bus
=> 0, addr
=> 12 },
4943 virtio3
=> { bus
=> 0, addr
=> 13 },
4944 virtio4
=> { bus
=> 0, addr
=> 14 },
4945 virtio5
=> { bus
=> 0, addr
=> 15 },
4946 hostpci0
=> { bus
=> 0, addr
=> 16 },
4947 hostpci1
=> { bus
=> 0, addr
=> 17 },
4948 net0
=> { bus
=> 0, addr
=> 18 },
4949 net1
=> { bus
=> 0, addr
=> 19 },
4950 net2
=> { bus
=> 0, addr
=> 20 },
4951 net3
=> { bus
=> 0, addr
=> 21 },
4952 net4
=> { bus
=> 0, addr
=> 22 },
4953 net5
=> { bus
=> 0, addr
=> 23 },
4954 vga1
=> { bus
=> 0, addr
=> 24 },
4955 vga2
=> { bus
=> 0, addr
=> 25 },
4956 vga3
=> { bus
=> 0, addr
=> 26 },
4957 hostpci2
=> { bus
=> 0, addr
=> 27 },
4958 hostpci3
=> { bus
=> 0, addr
=> 28 },
4959 #addr29 : usb-host (pve-usb.cfg)
4960 'pci.1' => { bus
=> 0, addr
=> 30 },
4961 'pci.2' => { bus
=> 0, addr
=> 31 },
4962 'net6' => { bus
=> 1, addr
=> 1 },
4963 'net7' => { bus
=> 1, addr
=> 2 },
4964 'net8' => { bus
=> 1, addr
=> 3 },
4965 'net9' => { bus
=> 1, addr
=> 4 },
4966 'net10' => { bus
=> 1, addr
=> 5 },
4967 'net11' => { bus
=> 1, addr
=> 6 },
4968 'net12' => { bus
=> 1, addr
=> 7 },
4969 'net13' => { bus
=> 1, addr
=> 8 },
4970 'net14' => { bus
=> 1, addr
=> 9 },
4971 'net15' => { bus
=> 1, addr
=> 10 },
4972 'net16' => { bus
=> 1, addr
=> 11 },
4973 'net17' => { bus
=> 1, addr
=> 12 },
4974 'net18' => { bus
=> 1, addr
=> 13 },
4975 'net19' => { bus
=> 1, addr
=> 14 },
4976 'net20' => { bus
=> 1, addr
=> 15 },
4977 'net21' => { bus
=> 1, addr
=> 16 },
4978 'net22' => { bus
=> 1, addr
=> 17 },
4979 'net23' => { bus
=> 1, addr
=> 18 },
4980 'net24' => { bus
=> 1, addr
=> 19 },
4981 'net25' => { bus
=> 1, addr
=> 20 },
4982 'net26' => { bus
=> 1, addr
=> 21 },
4983 'net27' => { bus
=> 1, addr
=> 22 },
4984 'net28' => { bus
=> 1, addr
=> 23 },
4985 'net29' => { bus
=> 1, addr
=> 24 },
4986 'net30' => { bus
=> 1, addr
=> 25 },
4987 'net31' => { bus
=> 1, addr
=> 26 },
4988 'xhci' => { bus
=> 1, addr
=> 27 },
4989 'virtio6' => { bus
=> 2, addr
=> 1 },
4990 'virtio7' => { bus
=> 2, addr
=> 2 },
4991 'virtio8' => { bus
=> 2, addr
=> 3 },
4992 'virtio9' => { bus
=> 2, addr
=> 4 },
4993 'virtio10' => { bus
=> 2, addr
=> 5 },
4994 'virtio11' => { bus
=> 2, addr
=> 6 },
4995 'virtio12' => { bus
=> 2, addr
=> 7 },
4996 'virtio13' => { bus
=> 2, addr
=> 8 },
4997 'virtio14' => { bus
=> 2, addr
=> 9 },
4998 'virtio15' => { bus
=> 2, addr
=> 10 },
4999 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5000 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5001 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5002 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5003 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5004 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5005 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5006 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5007 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5008 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5009 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5010 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5011 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5012 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5013 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5014 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5015 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5016 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5017 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5018 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5019 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5020 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5021 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5022 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5023 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5024 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5025 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5026 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5027 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5028 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5029 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5033 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5034 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5035 my $bus = $devices->{$id}->{bus
};
5036 $res = ",bus=pci.$bus,addr=$addr";
5037 $bridges->{$bus} = 1 if $bridges;
5043 sub print_pcie_addr
{
5048 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5049 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5050 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5051 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5054 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5055 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5056 my $bus = $devices->{$id}->{bus
};
5057 $res = ",bus=$bus,addr=$addr";
5063 # vzdump restore implementaion
5065 sub tar_archive_read_firstfile
{
5066 my $archive = shift;
5068 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5070 # try to detect archive type first
5071 my $pid = open (TMP
, "tar tf '$archive'|") ||
5072 die "unable to open file '$archive'\n";
5073 my $firstfile = <TMP
>;
5077 die "ERROR: archive contaions no data\n" if !$firstfile;
5083 sub tar_restore_cleanup
{
5084 my ($storecfg, $statfile) = @_;
5086 print STDERR
"starting cleanup\n";
5088 if (my $fd = IO
::File-
>new($statfile, "r")) {
5089 while (defined(my $line = <$fd>)) {
5090 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5093 if ($volid =~ m
|^/|) {
5094 unlink $volid || die 'unlink failed\n';
5096 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5098 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5100 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5102 print STDERR
"unable to parse line in statfile - $line";
5109 sub restore_archive
{
5110 my ($archive, $vmid, $user, $opts) = @_;
5112 my $format = $opts->{format
};
5115 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5116 $format = 'tar' if !$format;
5118 } elsif ($archive =~ m/\.tar$/) {
5119 $format = 'tar' if !$format;
5120 } elsif ($archive =~ m/.tar.lzo$/) {
5121 $format = 'tar' if !$format;
5123 } elsif ($archive =~ m/\.vma$/) {
5124 $format = 'vma' if !$format;
5125 } elsif ($archive =~ m/\.vma\.gz$/) {
5126 $format = 'vma' if !$format;
5128 } elsif ($archive =~ m/\.vma\.lzo$/) {
5129 $format = 'vma' if !$format;
5132 $format = 'vma' if !$format; # default
5135 # try to detect archive format
5136 if ($format eq 'tar') {
5137 return restore_tar_archive
($archive, $vmid, $user, $opts);
5139 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5143 sub restore_update_config_line
{
5144 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5146 return if $line =~ m/^\#qmdump\#/;
5147 return if $line =~ m/^\#vzdump\#/;
5148 return if $line =~ m/^lock:/;
5149 return if $line =~ m/^unused\d+:/;
5150 return if $line =~ m/^parent:/;
5151 return if $line =~ m/^template:/; # restored VM is never a template
5153 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5154 # try to convert old 1.X settings
5155 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5156 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5157 my ($model, $macaddr) = split(/\=/, $devconfig);
5158 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5161 bridge
=> "vmbr$ind",
5162 macaddr
=> $macaddr,
5164 my $netstr = print_net
($net);
5166 print $outfd "net$cookie->{netcount}: $netstr\n";
5167 $cookie->{netcount
}++;
5169 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5170 my ($id, $netstr) = ($1, $2);
5171 my $net = parse_net
($netstr);
5172 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5173 $netstr = print_net
($net);
5174 print $outfd "$id: $netstr\n";
5175 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5178 my $di = parse_drive
($virtdev, $value);
5179 if (defined($di->{backup
}) && !$di->{backup
}) {
5180 print $outfd "#$line";
5181 } elsif ($map->{$virtdev}) {
5182 delete $di->{format
}; # format can change on restore
5183 $di->{file
} = $map->{$virtdev};
5184 $value = print_drive
($vmid, $di);
5185 print $outfd "$virtdev: $value\n";
5195 my ($cfg, $vmid) = @_;
5197 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5199 my $volid_hash = {};
5200 foreach my $storeid (keys %$info) {
5201 foreach my $item (@{$info->{$storeid}}) {
5202 next if !($item->{volid
} && $item->{size
});
5203 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5204 $volid_hash->{$item->{volid
}} = $item;
5211 sub is_volume_in_use
{
5212 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5214 my $path = PVE
::Storage
::path
($storecfg, $volid);
5216 my $scan_config = sub {
5217 my ($cref, $snapname) = @_;
5219 foreach my $key (keys %$cref) {
5220 my $value = $cref->{$key};
5221 if (is_valid_drivename
($key)) {
5222 next if $skip_drive && $key eq $skip_drive;
5223 my $drive = parse_drive
($key, $value);
5224 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5225 return 1 if $volid eq $drive->{file
};
5226 if ($drive->{file
} =~ m!^/!) {
5227 return 1 if $drive->{file
} eq $path;
5229 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5231 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5233 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5241 return 1 if &$scan_config($conf);
5245 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5246 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5252 sub update_disksize
{
5253 my ($vmid, $conf, $volid_hash) = @_;
5259 # Note: it is allowed to define multiple storages with same path (alias), so
5260 # we need to check both 'volid' and real 'path' (two different volid can point
5261 # to the same path).
5266 foreach my $opt (keys %$conf) {
5267 if (is_valid_drivename
($opt)) {
5268 my $drive = parse_drive
($opt, $conf->{$opt});
5269 my $volid = $drive->{file
};
5272 $used->{$volid} = 1;
5273 if ($volid_hash->{$volid} &&
5274 (my $path = $volid_hash->{$volid}->{path
})) {
5275 $usedpath->{$path} = 1;
5278 next if drive_is_cdrom
($drive);
5279 next if !$volid_hash->{$volid};
5281 $drive->{size
} = $volid_hash->{$volid}->{size
};
5282 my $new = print_drive
($vmid, $drive);
5283 if ($new ne $conf->{$opt}) {
5285 $conf->{$opt} = $new;
5290 # remove 'unusedX' entry if volume is used
5291 foreach my $opt (keys %$conf) {
5292 next if $opt !~ m/^unused\d+$/;
5293 my $volid = $conf->{$opt};
5294 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5295 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5297 delete $conf->{$opt};
5301 foreach my $volid (sort keys %$volid_hash) {
5302 next if $volid =~ m/vm-$vmid-state-/;
5303 next if $used->{$volid};
5304 my $path = $volid_hash->{$volid}->{path
};
5305 next if !$path; # just to be sure
5306 next if $usedpath->{$path};
5308 add_unused_volume
($conf, $volid);
5309 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5316 my ($vmid, $nolock) = @_;
5318 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5320 my $volid_hash = scan_volids
($cfg, $vmid);
5322 my $updatefn = sub {
5325 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5327 PVE
::QemuConfig-
>check_lock($conf);
5330 foreach my $volid (keys %$volid_hash) {
5331 my $info = $volid_hash->{$volid};
5332 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5335 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5337 PVE
::QemuConfig-
>write_config($vmid, $conf) if $changes;
5340 if (defined($vmid)) {
5344 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5347 my $vmlist = config_list
();
5348 foreach my $vmid (keys %$vmlist) {
5352 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $vmid);
5358 sub restore_vma_archive
{
5359 my ($archive, $vmid, $user, $opts, $comp) = @_;
5361 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5362 my $readfrom = $archive;
5367 my $qarchive = PVE
::Tools
::shellquote
($archive);
5368 if ($comp eq 'gzip') {
5369 $uncomp = "zcat $qarchive|";
5370 } elsif ($comp eq 'lzop') {
5371 $uncomp = "lzop -d -c $qarchive|";
5373 die "unknown compression method '$comp'\n";
5378 my $tmpdir = "/var/tmp/vzdumptmp$$";
5381 # disable interrupts (always do cleanups)
5382 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5383 warn "got interrupt - ignored\n";
5386 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5387 POSIX
::mkfifo
($mapfifo, 0600);
5390 my $openfifo = sub {
5391 open($fifofh, '>', $mapfifo) || die $!;
5394 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5401 my $rpcenv = PVE
::RPCEnvironment
::get
();
5403 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5404 my $tmpfn = "$conffile.$$.tmp";
5406 # Note: $oldconf is undef if VM does not exists
5407 my $cfs_path = PVE
::QemuConfig-
>cfs_config_path($vmid);
5408 my $oldconf = PVE
::Cluster
::cfs_read_file
($cfs_path);
5410 my $print_devmap = sub {
5411 my $virtdev_hash = {};
5413 my $cfgfn = "$tmpdir/qemu-server.conf";
5415 # we can read the config - that is already extracted
5416 my $fh = IO
::File-
>new($cfgfn, "r") ||
5417 "unable to read qemu-server.conf - $!\n";
5419 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5421 my $pve_firewall_dir = '/etc/pve/firewall';
5422 mkdir $pve_firewall_dir; # make sure the dir exists
5423 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5426 while (defined(my $line = <$fh>)) {
5427 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5428 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5429 die "archive does not contain data for drive '$virtdev'\n"
5430 if !$devinfo->{$devname};
5431 if (defined($opts->{storage
})) {
5432 $storeid = $opts->{storage
} || 'local';
5433 } elsif (!$storeid) {
5436 $format = 'raw' if !$format;
5437 $devinfo->{$devname}->{devname
} = $devname;
5438 $devinfo->{$devname}->{virtdev
} = $virtdev;
5439 $devinfo->{$devname}->{format
} = $format;
5440 $devinfo->{$devname}->{storeid
} = $storeid;
5442 # check permission on storage
5443 my $pool = $opts->{pool
}; # todo: do we need that?
5444 if ($user ne 'root@pam') {
5445 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5448 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5452 foreach my $devname (keys %$devinfo) {
5453 die "found no device mapping information for device '$devname'\n"
5454 if !$devinfo->{$devname}->{virtdev
};
5457 my $cfg = cfs_read_file
('storage.cfg');
5459 # create empty/temp config
5461 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5462 foreach_drive
($oldconf, sub {
5463 my ($ds, $drive) = @_;
5465 return if drive_is_cdrom
($drive);
5467 my $volid = $drive->{file
};
5469 return if !$volid || $volid =~ m
|^/|;
5471 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5472 return if !$path || !$owner || ($owner != $vmid);
5474 # Note: only delete disk we want to restore
5475 # other volumes will become unused
5476 if ($virtdev_hash->{$ds}) {
5477 PVE
::Storage
::vdisk_free
($cfg, $volid);
5481 # delete vmstate files
5482 # since after the restore we have no snapshots anymore
5483 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5484 my $snap = $oldconf->{snapshots
}->{$snapname};
5485 if ($snap->{vmstate
}) {
5486 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5495 foreach my $virtdev (sort keys %$virtdev_hash) {
5496 my $d = $virtdev_hash->{$virtdev};
5497 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5498 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5500 # test if requested format is supported
5501 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5502 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5503 $d->{format
} = $defFormat if !$supported;
5505 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5506 $d->{format
}, undef, $alloc_size);
5507 print STDERR
"new volume ID is '$volid'\n";
5508 $d->{volid
} = $volid;
5509 my $path = PVE
::Storage
::path
($cfg, $volid);
5511 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5513 my $write_zeros = 1;
5514 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5518 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5520 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5521 $map->{$virtdev} = $volid;
5524 $fh->seek(0, 0) || die "seek failed - $!\n";
5526 my $outfd = new IO
::File
($tmpfn, "w") ||
5527 die "unable to write config for VM $vmid\n";
5529 my $cookie = { netcount
=> 0 };
5530 while (defined(my $line = <$fh>)) {
5531 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5540 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5541 die "interrupted by signal\n";
5543 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5545 $oldtimeout = alarm($timeout);
5552 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5553 my ($dev_id, $size, $devname) = ($1, $2, $3);
5554 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5555 } elsif ($line =~ m/^CTIME: /) {
5556 # we correctly received the vma config, so we can disable
5557 # the timeout now for disk allocation (set to 10 minutes, so
5558 # that we always timeout if something goes wrong)
5561 print $fifofh "done\n";
5562 my $tmp = $oldtimeout || 0;
5563 $oldtimeout = undef;
5569 print "restore vma archive: $cmd\n";
5570 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5574 alarm($oldtimeout) if $oldtimeout;
5577 foreach my $devname (keys %$devinfo) {
5578 my $volid = $devinfo->{$devname}->{volid
};
5579 push @$vollist, $volid if $volid;
5582 my $cfg = cfs_read_file
('storage.cfg');
5583 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5591 foreach my $devname (keys %$devinfo) {
5592 my $volid = $devinfo->{$devname}->{volid
};
5595 if ($volid =~ m
|^/|) {
5596 unlink $volid || die 'unlink failed\n';
5598 PVE
::Storage
::vdisk_free
($cfg, $volid);
5600 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5602 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5609 rename($tmpfn, $conffile) ||
5610 die "unable to commit configuration file '$conffile'\n";
5612 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5614 eval { rescan
($vmid, 1); };
5618 sub restore_tar_archive
{
5619 my ($archive, $vmid, $user, $opts) = @_;
5621 if ($archive ne '-') {
5622 my $firstfile = tar_archive_read_firstfile
($archive);
5623 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5624 if $firstfile ne 'qemu-server.conf';
5627 my $storecfg = cfs_read_file
('storage.cfg');
5629 # destroy existing data - keep empty config
5630 my $vmcfgfn = PVE
::QemuConfig-
>config_file($vmid);
5631 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5633 my $tocmd = "/usr/lib/qemu-server/qmextract";
5635 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5636 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5637 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5638 $tocmd .= ' --info' if $opts->{info
};
5640 # tar option "xf" does not autodetect compression when read from STDIN,
5641 # so we pipe to zcat
5642 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5643 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5645 my $tmpdir = "/var/tmp/vzdumptmp$$";
5648 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5649 local $ENV{VZDUMP_VMID
} = $vmid;
5650 local $ENV{VZDUMP_USER
} = $user;
5652 my $conffile = PVE
::QemuConfig-
>config_file($vmid);
5653 my $tmpfn = "$conffile.$$.tmp";
5655 # disable interrupts (always do cleanups)
5656 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5657 print STDERR
"got interrupt - ignored\n";
5662 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5663 die "interrupted by signal\n";
5666 if ($archive eq '-') {
5667 print "extracting archive from STDIN\n";
5668 run_command
($cmd, input
=> "<&STDIN");
5670 print "extracting archive '$archive'\n";
5674 return if $opts->{info
};
5678 my $statfile = "$tmpdir/qmrestore.stat";
5679 if (my $fd = IO
::File-
>new($statfile, "r")) {
5680 while (defined (my $line = <$fd>)) {
5681 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5682 $map->{$1} = $2 if $1;
5684 print STDERR
"unable to parse line in statfile - $line\n";
5690 my $confsrc = "$tmpdir/qemu-server.conf";
5692 my $srcfd = new IO
::File
($confsrc, "r") ||
5693 die "unable to open file '$confsrc'\n";
5695 my $outfd = new IO
::File
($tmpfn, "w") ||
5696 die "unable to write config for VM $vmid\n";
5698 my $cookie = { netcount
=> 0 };
5699 while (defined (my $line = <$srcfd>)) {
5700 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5712 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5719 rename $tmpfn, $conffile ||
5720 die "unable to commit configuration file '$conffile'\n";
5722 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5724 eval { rescan
($vmid, 1); };
5729 # Internal snapshots
5731 # NOTE: Snapshot create/delete involves several non-atomic
5732 # action, and can take a long time.
5733 # So we try to avoid locking the file and use 'lock' variable
5734 # inside the config file instead.
5736 my $snapshot_copy_config = sub {
5737 my ($source, $dest) = @_;
5739 foreach my $k (keys %$source) {
5740 next if $k eq 'snapshots';
5741 next if $k eq 'snapstate';
5742 next if $k eq 'snaptime';
5743 next if $k eq 'vmstate';
5744 next if $k eq 'lock';
5745 next if $k eq 'digest';
5746 next if $k eq 'description';
5747 next if $k =~ m/^unused\d+$/;
5749 $dest->{$k} = $source->{$k};
5753 my $snapshot_apply_config = sub {
5754 my ($conf, $snap) = @_;
5756 # copy snapshot list
5758 snapshots
=> $conf->{snapshots
},
5761 # keep description and list of unused disks
5762 foreach my $k (keys %$conf) {
5763 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5764 $newconf->{$k} = $conf->{$k};
5767 &$snapshot_copy_config($snap, $newconf);
5772 sub foreach_writable_storage
{
5773 my ($conf, $func) = @_;
5777 foreach my $ds (keys %$conf) {
5778 next if !is_valid_drivename
($ds);
5780 my $drive = parse_drive
($ds, $conf->{$ds});
5782 next if drive_is_cdrom
($drive);
5784 my $volid = $drive->{file
};
5786 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5787 $sidhash->{$sid} = $sid if $sid;
5790 foreach my $sid (sort keys %$sidhash) {
5795 my $alloc_vmstate_volid = sub {
5796 my ($storecfg, $vmid, $conf, $snapname) = @_;
5798 # Note: we try to be smart when selecting a $target storage
5802 # search shared storage first
5803 foreach_writable_storage
($conf, sub {
5805 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5806 return if !$scfg->{shared
};
5808 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5812 # now search local storage
5813 foreach_writable_storage
($conf, sub {
5815 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5816 return if $scfg->{shared
};
5818 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5822 $target = 'local' if !$target;
5824 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5825 # we abort live save after $conf->{memory}, so we need at max twice that space
5826 my $size = $conf->{memory
}*2 + $driver_state_size;
5828 my $name = "vm-$vmid-state-$snapname";
5829 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5830 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5831 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5836 sub snapshot_save_vmstate
{
5837 my ($vmid, $conf, $snapname, $storecfg) = @_;
5839 my $snap = $conf->{snapshots
}->{$snapname};
5841 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5842 # always overwrite machine if we save vmstate. This makes sure we
5843 # can restore it later using correct machine type
5844 $snap->{machine
} = get_current_qemu_machine
($vmid);
5847 sub snapshot_prepare
{
5848 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5852 my $updatefn = sub {
5854 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5856 die "you can't take a snapshot if it's a template\n"
5857 if PVE
::QemuConfig-
>is_template($conf);
5859 PVE
::QemuConfig-
>check_lock($conf);
5861 $conf->{lock} = 'snapshot';
5863 die "snapshot name '$snapname' already used\n"
5864 if defined($conf->{snapshots
}->{$snapname});
5866 my $storecfg = PVE
::Storage
::config
();
5867 die "snapshot feature is not available\n"
5868 if !has_feature
('snapshot', $conf, $storecfg, undef, undef, $snapname eq 'vzdump');
5870 $snap = $conf->{snapshots
}->{$snapname} = {};
5872 if ($save_vmstate && check_running
($vmid)) {
5873 snapshot_save_vmstate
($vmid, $conf, $snapname, $storecfg);
5876 &$snapshot_copy_config($conf, $snap);
5878 $snap->{snapstate
} = "prepare";
5879 $snap->{snaptime
} = time();
5880 $snap->{description
} = $comment if $comment;
5882 PVE
::QemuConfig-
>write_config($vmid, $conf);
5885 PVE
::QemuConfig-
>lock_config($vmid, $updatefn);
5890 sub snapshot_commit
{
5891 my ($vmid, $snapname) = @_;
5893 my $updatefn = sub {
5895 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5897 die "missing snapshot lock\n"
5898 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5900 my $snap = $conf->{snapshots
}->{$snapname};
5902 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5904 die "wrong snapshot state\n"
5905 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5907 delete $snap->{snapstate
};
5908 delete $conf->{lock};
5910 $conf->{parent
} = $snapname;
5912 PVE
::QemuConfig-
>write_config($vmid, $conf);
5915 PVE
::QemuConfig-
>lock_config($vmid, $updatefn);
5918 sub snapshot_rollback
{
5919 my ($vmid, $snapname) = @_;
5923 my $storecfg = PVE
::Storage
::config
();
5925 my $conf = PVE
::QemuConfig-
>load_config($vmid);
5927 my $get_snapshot_config = sub {
5929 die "you can't rollback if vm is a template\n" if PVE
::QemuConfig-
>is_template($conf);
5931 my $res = $conf->{snapshots
}->{$snapname};
5933 die "snapshot '$snapname' does not exist\n" if !defined($res);
5938 my $snap = &$get_snapshot_config();
5940 foreach_drive
($snap, sub {
5941 my ($ds, $drive) = @_;
5943 return if drive_is_cdrom
($drive);
5945 my $volid = $drive->{file
};
5947 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5950 my $updatefn = sub {
5952 $conf = PVE
::QemuConfig-
>load_config($vmid);
5954 $snap = &$get_snapshot_config();
5956 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5957 if $snap->{snapstate
};
5960 PVE
::QemuConfig-
>check_lock($conf);
5961 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5964 die "unable to rollback vm $vmid: vm is running\n"
5965 if check_running
($vmid);
5968 $conf->{lock} = 'rollback';
5970 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5971 delete $conf->{lock};
5977 my $has_machine_config = defined($conf->{machine
});
5979 # copy snapshot config to current config
5980 $conf = &$snapshot_apply_config($conf, $snap);
5981 $conf->{parent
} = $snapname;
5983 # Note: old code did not store 'machine', so we try to be smart
5984 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5985 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5986 # we remove the 'machine' configuration if not explicitly specified
5987 # in the original config.
5988 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5991 PVE
::QemuConfig-
>write_config($vmid, $conf);
5993 if (!$prepare && $snap->{vmstate
}) {
5994 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5995 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5999 PVE
::QemuConfig-
>lock_config($vmid, $updatefn);
6001 foreach_drive
($snap, sub {
6002 my ($ds, $drive) = @_;
6004 return if drive_is_cdrom
($drive);
6006 my $volid = $drive->{file
};
6007 my $device = "drive-$ds";
6009 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
6013 PVE
::QemuConfig-
>lock_config($vmid, $updatefn);
6016 my $savevm_wait = sub {
6020 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6021 if (!$stat->{status
}) {
6022 die "savevm not active\n";
6023 } elsif ($stat->{status
} eq 'active') {
6026 } elsif ($stat->{status
} eq 'completed') {
6029 die "query-savevm returned status '$stat->{status}'\n";
6034 sub do_snapshots_with_qemu
{
6035 my ($storecfg, $volid) = @_;
6037 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
6039 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
6040 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
6044 if ($volid =~ m/\.(qcow2|qed)$/){
6051 sub qga_check_running
{
6054 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
6056 warn "Qemu Guest Agent are not running - $@";
6062 sub check_freeze_needed
{
6063 my ($vmid, $config, $save_vmstate) = @_;
6065 my $running = check_running
($vmid);
6066 if ($save_vmstate) {
6067 return ($running, $running && $config->{agent
} && qga_check_running
($vmid));
6069 return ($running, 0);
6073 sub snapshot_create
{
6074 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
6076 my $snap = snapshot_prepare
($vmid, $snapname, $save_vmstate, $comment);
6078 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
6080 my $config = PVE
::QemuConfig-
>load_config($vmid);
6082 my ($running, $freezefs) = check_freeze_needed
($vmid, $config, $snap->{vmstate
});
6088 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6089 warn "guest-fsfreeze-freeze problems - $@" if $@;
6092 # create internal snapshots of all drives
6094 my $storecfg = PVE
::Storage
::config
();
6097 if ($snap->{vmstate
}) {
6098 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6099 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
6100 &$savevm_wait($vmid);
6102 vm_mon_cmd
($vmid, "savevm-start");
6106 foreach_drive
($snap, sub {
6107 my ($ds, $drive) = @_;
6109 return if drive_is_cdrom
($drive);
6111 my $volid = $drive->{file
};
6112 my $device = "drive-$ds";
6114 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
6115 $drivehash->{$ds} = 1;
6121 eval { vm_mon_cmd
($vmid, "savevm-end") };
6125 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6126 warn "guest-fsfreeze-thaw problems - $@" if $@;
6129 # savevm-end is async, we need to wait
6131 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6132 if (!$stat->{bytes
}) {
6135 print "savevm not yet finished\n";
6143 warn "snapshot create failed: starting cleanup\n";
6144 eval { snapshot_delete
($vmid, $snapname, 1, $drivehash); };
6149 snapshot_commit
($vmid, $snapname);
6152 # Note: $drivehash is only set when called from snapshot_create.
6153 sub snapshot_delete
{
6154 my ($vmid, $snapname, $force, $drivehash) = @_;
6161 my $unlink_parent = sub {
6162 my ($confref, $new_parent) = @_;
6164 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6166 $confref->{parent
} = $new_parent;
6168 delete $confref->{parent
};
6173 my $updatefn = sub {
6174 my ($remove_drive) = @_;
6176 my $conf = PVE
::QemuConfig-
>load_config($vmid);
6179 PVE
::QemuConfig-
>check_lock($conf);
6180 die "you can't delete a snapshot if vm is a template\n"
6181 if PVE
::QemuConfig-
>is_template($conf);
6184 $snap = $conf->{snapshots
}->{$snapname};
6186 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6188 # remove parent refs
6190 &$unlink_parent($conf, $snap->{parent
});
6191 foreach my $sn (keys %{$conf->{snapshots
}}) {
6192 next if $sn eq $snapname;
6193 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6197 if ($remove_drive) {
6198 if ($remove_drive eq 'vmstate') {
6199 delete $snap->{$remove_drive};
6201 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6202 my $volid = $drive->{file
};
6203 delete $snap->{$remove_drive};
6204 add_unused_volume
($conf, $volid);
6209 $snap->{snapstate
} = 'delete';
6211 delete $conf->{snapshots
}->{$snapname};
6212 delete $conf->{lock} if $drivehash;
6213 foreach my $volid (@$unused) {
6214 add_unused_volume
($conf, $volid);
6218 PVE
::QemuConfig-
>write_config($vmid, $conf);
6221 PVE
::QemuConfig-
>lock_config($vmid, $updatefn);
6223 # now remove vmstate file
6225 my $storecfg = PVE
::Storage
::config
();
6227 if ($snap->{vmstate
}) {
6228 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6230 die $err if !$force;
6233 # save changes (remove vmstate from snapshot)
6234 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, 'vmstate') if !$force;
6237 # now remove all internal snapshots
6238 foreach_drive
($snap, sub {
6239 my ($ds, $drive) = @_;
6241 return if drive_is_cdrom
($drive);
6243 my $volid = $drive->{file
};
6244 my $device = "drive-$ds";
6246 if (!$drivehash || $drivehash->{$ds}) {
6247 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6249 die $err if !$force;
6254 # save changes (remove drive fron snapshot)
6255 PVE
::QemuConfig-
>lock_config($vmid, $updatefn, $ds) if !$force;
6256 push @$unused, $volid;
6259 # now cleanup config
6261 PVE
::QemuConfig-
>lock_config($vmid, $updatefn);
6265 my ($feature, $conf, $storecfg, $snapname, $running, $backup_only) = @_;
6268 foreach_drive
($conf, sub {
6269 my ($ds, $drive) = @_;
6271 return if drive_is_cdrom
($drive);
6272 return if $backup_only && !$drive->{backup
};
6273 my $volid = $drive->{file
};
6274 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6277 return $err ?
0 : 1;
6280 sub template_create
{
6281 my ($vmid, $conf, $disk) = @_;
6283 my $storecfg = PVE
::Storage
::config
();
6285 foreach_drive
($conf, sub {
6286 my ($ds, $drive) = @_;
6288 return if drive_is_cdrom
($drive);
6289 return if $disk && $ds ne $disk;
6291 my $volid = $drive->{file
};
6292 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6294 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6295 $drive->{file
} = $voliddst;
6296 $conf->{$ds} = print_drive
($vmid, $drive);
6297 PVE
::QemuConfig-
>write_config($vmid, $conf);
6301 sub qemu_img_convert
{
6302 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6304 my $storecfg = PVE
::Storage
::config
();
6305 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6306 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6308 if ($src_storeid && $dst_storeid) {
6310 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6312 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6313 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6315 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6316 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6318 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6319 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6322 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6323 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6324 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6328 if($line =~ m/\((\S+)\/100\
%\)/){
6330 my $transferred = int($size * $percent / 100);
6331 my $remaining = $size - $transferred;
6333 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6338 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6340 die "copy failed: $err" if $err;
6344 sub qemu_img_format
{
6345 my ($scfg, $volname) = @_;
6347 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6354 sub qemu_drive_mirror
{
6355 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6357 my $storecfg = PVE
::Storage
::config
();
6358 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6360 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6362 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6364 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6366 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6367 $opts->{format
} = $format if $format;
6369 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6372 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6374 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6375 my $stat = @$stats[0];
6376 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6377 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6379 my $busy = $stat->{busy
};
6380 my $ready = $stat->{ready
};
6382 if (my $total = $stat->{len
}) {
6383 my $transferred = $stat->{offset
} || 0;
6384 my $remaining = $total - $transferred;
6385 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6387 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6391 if ($stat->{ready
} eq 'true') {
6393 last if $vmiddst != $vmid;
6395 # try to switch the disk if source and destination are on the same guest
6396 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6398 die $@ if $@ !~ m/cannot be completed/;
6407 my $cancel_job = sub {
6408 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6410 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6411 my $stat = @$stats[0];
6418 eval { &$cancel_job(); };
6419 die "mirroring error: $err";
6422 if ($vmiddst != $vmid) {
6423 # if we clone a disk for a new target vm, we don't switch the disk
6424 &$cancel_job(); # so we call block-job-cancel
6429 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6430 $newvmid, $storage, $format, $full, $newvollist) = @_;
6435 print "create linked clone of drive $drivename ($drive->{file})\n";
6436 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6437 push @$newvollist, $newvolid;
6439 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6440 $storeid = $storage if $storage;
6442 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6444 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6445 $format = qemu_img_format
($scfg, $volname);
6448 # test if requested format is supported - else use default
6449 my $supported = grep { $_ eq $format } @$validFormats;
6450 $format = $defFormat if !$supported;
6452 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6454 print "create full clone of drive $drivename ($drive->{file})\n";
6455 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6456 push @$newvollist, $newvolid;
6458 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6460 if (!$running || $snapname) {
6461 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6463 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6467 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6470 $disk->{format
} = undef;
6471 $disk->{file
} = $newvolid;
6472 $disk->{size
} = $size;
6477 # this only works if VM is running
6478 sub get_current_qemu_machine
{
6481 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6482 my $res = vm_qmp_command
($vmid, $cmd);
6484 my ($current, $default);
6485 foreach my $e (@$res) {
6486 $default = $e->{name
} if $e->{'is-default'};
6487 $current = $e->{name
} if $e->{'is-current'};
6490 # fallback to the default machine if current is not supported by qemu
6491 return $current || $default || 'pc';
6494 sub qemu_machine_feature_enabled
{
6495 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6500 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6502 $current_major = $3;
6503 $current_minor = $4;
6505 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6507 $current_major = $1;
6508 $current_minor = $2;
6511 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6516 sub qemu_machine_pxe
{
6517 my ($vmid, $conf, $machine) = @_;
6519 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6521 foreach my $opt (keys %$conf) {
6522 next if $opt !~ m/^net(\d+)$/;
6523 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6525 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6526 return $machine.".pxe" if $romfile =~ m/pxe/;
6533 sub qemu_use_old_bios_files
{
6534 my ($machine_type) = @_;
6536 return if !$machine_type;
6538 my $use_old_bios_files = undef;
6540 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6542 $use_old_bios_files = 1;
6544 my $kvmver = kvm_user_version
();
6545 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6546 # load new efi bios files on migration. So this hack is required to allow
6547 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6548 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6549 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6552 return ($use_old_bios_files, $machine_type);
6559 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6560 my (undef, $id, $function) = @_;
6561 my $res = { id
=> $id, function
=> $function};
6562 push @{$devices->{$id}}, $res;
6568 sub vm_iothreads_list
{
6571 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6574 foreach my $iothread (@$res) {
6575 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6582 my ($conf, $drive) = @_;
6586 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6588 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6594 my $controller = int($drive->{index} / $maxdev);
6595 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6597 return ($maxdev, $controller, $controller_prefix);
6600 # bash completion helper
6602 sub complete_backup_archives
{
6603 my ($cmdname, $pname, $cvalue) = @_;
6605 my $cfg = PVE
::Storage
::config
();
6609 if ($cvalue =~ m/^([^:]+):/) {
6613 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6616 foreach my $id (keys %$data) {
6617 foreach my $item (@{$data->{$id}}) {
6618 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6619 push @$res, $item->{volid
} if defined($item->{volid
});
6626 my $complete_vmid_full = sub {
6629 my $idlist = vmstatus
();
6633 foreach my $id (keys %$idlist) {
6634 my $d = $idlist->{$id};
6635 if (defined($running)) {
6636 next if $d->{template
};
6637 next if $running && $d->{status
} ne 'running';
6638 next if !$running && $d->{status
} eq 'running';
6647 return &$complete_vmid_full();
6650 sub complete_vmid_stopped
{
6651 return &$complete_vmid_full(0);
6654 sub complete_vmid_running
{
6655 return &$complete_vmid_full(1);
6658 sub complete_storage
{
6660 my $cfg = PVE
::Storage
::config
();
6661 my $ids = $cfg->{ids
};
6664 foreach my $sid (keys %$ids) {
6665 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6666 next if !$ids->{$sid}->{content
}->{images
};