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);
31 use PVE
::RPCEnvironment
;
32 use Time
::HiRes
qw(gettimeofday);
33 use File
::Copy
qw(copy);
35 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
37 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
39 # Note about locking: we use flock on the config file protect
40 # against concurent actions.
41 # Aditionaly, we have a 'lock' setting in the config file. This
42 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
43 # allowed when such lock is set. But you can ignore this kind of
44 # lock with the --skiplock flag.
46 cfs_register_file
('/qemu-server/',
50 PVE
::JSONSchema
::register_standard_option
('skiplock', {
51 description
=> "Ignore locks - only root is allowed to use this option.",
56 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
57 description
=> "Some command save/restore state from this location.",
63 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
64 description
=> "The name of the snapshot.",
65 type
=> 'string', format
=> 'pve-configid',
69 #no warnings 'redefine';
72 my ($controller, $vmid, $option, $value) = @_;
74 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
75 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
79 my $nodename = PVE
::INotify
::nodename
();
81 mkdir "/etc/pve/nodes/$nodename";
82 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
85 my $var_run_tmpdir = "/var/run/qemu-server";
86 mkdir $var_run_tmpdir;
88 my $lock_dir = "/var/lock/qemu-server";
91 my $pcisysfs = "/sys/bus/pci";
95 description
=> "Emulated CPU type.",
97 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) ],
102 description
=> "Do not identify as a KVM virtual machine.",
113 description
=> "Specifies whether a VM will be started during system bootup.",
119 description
=> "Automatic restart after crash (currently ignored).",
124 type
=> 'string', format
=> 'pve-hotplug-features',
125 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'.",
126 default => 'network,disk,usb',
131 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
137 description
=> "Lock/unlock the VM.",
138 enum
=> [qw(migrate backup snapshot rollback)],
143 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.",
151 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.",
159 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
166 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
172 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",
180 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
181 enum
=> PVE
::Tools
::kvmkeymaplist
(),
186 type
=> 'string', format
=> 'dns-name',
187 description
=> "Set a name for the VM. Only used on the configuration web interface.",
192 description
=> "scsi controller model",
193 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
199 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
204 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
205 description
=> <<EODESC,
206 Used to enable special optimization/features for specific
209 other => unspecified OS
210 wxp => Microsoft Windows XP
211 w2k => Microsoft Windows 2000
212 w2k3 => Microsoft Windows 2003
213 w2k8 => Microsoft Windows 2008
214 wvista => Microsoft Windows Vista
215 win7 => Microsoft Windows 7
216 win8 => Microsoft Windows 8/2012
217 l24 => Linux 2.4 Kernel
218 l26 => Linux 2.6/3.X Kernel
219 solaris => solaris/opensolaris/openindiania kernel
221 other|l24|l26|solaris ... no special behaviour
222 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
228 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
229 pattern
=> '[acdn]{1,4}',
234 type
=> 'string', format
=> 'pve-qm-bootdisk',
235 description
=> "Enable booting from specified disk.",
236 pattern
=> '(ide|sata|scsi|virtio)\d+',
241 description
=> "The number of CPUs. Please use option -sockets instead.",
248 description
=> "The number of CPU sockets.",
255 description
=> "The number of cores per socket.",
262 description
=> "Enable/disable Numa.",
268 description
=> "Number of hotplugged vcpus.",
275 description
=> "Enable/disable ACPI.",
281 description
=> "Enable/disable Qemu GuestAgent.",
287 description
=> "Enable/disable KVM hardware virtualization.",
293 description
=> "Enable/disable time drift fix.",
299 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
304 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
309 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.",
310 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
314 type
=> 'string', format
=> 'pve-qm-watchdog',
315 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
316 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)",
321 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
322 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'.",
323 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
326 startup
=> get_standard_option
('pve-startup-order'),
330 description
=> "Enable/disable Template.",
336 description
=> <<EODESCR,
337 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
339 args: -no-reboot -no-hpet
346 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).",
351 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
355 migrate_downtime
=> {
358 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
364 type
=> 'string', format
=> 'pve-qm-drive',
365 typetext
=> 'volume',
366 description
=> "This is an alias for option -ide2",
370 description
=> "Emulated CPU type.",
374 parent
=> get_standard_option
('pve-snapshot-name', {
376 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
380 description
=> "Timestamp for snapshots.",
386 type
=> 'string', format
=> 'pve-volume-id',
387 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
390 description
=> "Specific the Qemu machine type.",
392 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
397 description
=> "Specify SMBIOS type 1 fields.",
398 type
=> 'string', format
=> 'pve-qm-smbios1',
405 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
411 enum
=> [ qw(seabios ovmf) ],
412 description
=> "Select BIOS implementation.",
413 default => 'seabios',
417 # what about other qemu settings ?
419 #machine => 'string',
432 ##soundhw => 'string',
434 while (my ($k, $v) = each %$confdesc) {
435 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
438 my $MAX_IDE_DISKS = 4;
439 my $MAX_SCSI_DISKS = 14;
440 my $MAX_VIRTIO_DISKS = 16;
441 my $MAX_SATA_DISKS = 6;
442 my $MAX_USB_DEVICES = 5;
444 my $MAX_UNUSED_DISKS = 8;
445 my $MAX_HOSTPCI_DEVICES = 4;
446 my $MAX_SERIAL_PORTS = 4;
447 my $MAX_PARALLEL_PORTS = 3;
449 my $MAX_MEM = 4194304;
450 my $STATICMEM = 1024;
454 type
=> 'string', format
=> 'pve-qm-numanode',
455 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
456 description
=> "numa topology",
458 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
460 for (my $i = 0; $i < $MAX_NUMA; $i++) {
461 $confdesc->{"numa$i"} = $numadesc;
464 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
465 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
466 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
467 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
471 type
=> 'string', format
=> 'pve-qm-net',
472 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]",
473 description
=> <<EODESCR,
474 Specify network devices.
476 MODEL is one of: $nic_model_list_txt
478 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
479 automatically generated if not specified.
481 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
483 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'.
485 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
491 The DHCP server assign addresses to the guest starting from 10.0.2.15.
495 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
497 for (my $i = 0; $i < $MAX_NETS; $i++) {
498 $confdesc->{"net$i"} = $netdesc;
503 my %drivedesc_base = (
504 volume
=> { alias
=> 'file' },
506 type
=> 'pve-volume-id',
508 format_description
=> 'volume',
509 description
=> "The drive's backing volume.",
513 format_description
=> 'cdrom|disk',
514 enum
=> [qw(cdrom disk)],
515 description
=> "The drive's media type.",
521 format_description
=> 'count',
522 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
527 format_description
=> 'count',
528 description
=> "Force the drive's physical geometry to have a specific head count.",
533 format_description
=> 'count',
534 description
=> "Force the drive's physical geometry to have a specific sector count.",
539 format_description
=> 'none|lba|auto',
540 enum
=> [qw(none lba auto)],
541 description
=> "Force disk geometry bios translation mode.",
546 format_description
=> 'on|off',
547 description
=> "Whether the drive should be included when making snapshots.",
552 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
553 enum
=> [qw(none writethrough writeback unsafe directsync)],
554 description
=> "The drive's cache mode",
559 format_description
=> 'drive format',
560 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
561 description
=> "The drive's backing file's data format.",
566 format
=> 'disk-size',
567 description
=> "Disk size. This is purely informational and has no effect.",
572 format_description
=> 'on|off',
573 description
=> "Whether the drive should be included when making backups.",
578 format_description
=> 'enospc|ignore|report|stop',
579 enum
=> [qw(enospc ignore report stop)],
580 description
=> 'Write error action.',
585 format_description
=> 'native|threads',
586 enum
=> [qw(native threads)],
587 description
=> 'AIO type to use.',
592 format_description
=> 'ignore|on',
593 enum
=> [qw(ignore on)],
594 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
599 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
604 format_description
=> 'serial',
605 description
=> "The drive's reported serial number.",
613 format_description
=> 'ignore|report|stop',
614 enum
=> [qw(ignore report stop)],
615 description
=> 'Read error action.',
620 my %iothread_fmt = ( iothread
=> {
622 format_description
=> 'off|on',
623 description
=> "Whether to use iothreads for this drive",
630 format_description
=> 'model',
631 description
=> "The drive's reported model name.",
639 format_description
=> 'nbqueues',
640 description
=> "Number of queues.",
646 my $add_throttle_desc = sub {
647 my ($key, $type, $what, $size, $longsize) = @_;
648 $drivedesc_base{$key} = {
650 format_description
=> $size,
651 description
=> "Maximum $what speed in $longsize per second.",
655 # throughput: (leaky bucket)
656 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
657 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
658 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
659 $add_throttle_desc->('mbps', 'float', 'r/w speed', 'mbps', 'megabytes');
660 $add_throttle_desc->('mbps_rd', 'float', 'read speed', 'mbps', 'megabytes');
661 $add_throttle_desc->('mbps_wr', 'float', 'write speed', 'mbps', 'megabytes');
662 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
663 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
664 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
666 # pools: (pool of IO before throttling starts taking effect)
667 $add_throttle_desc->('mbps_max', 'float', 'unthrottled r/w pool', 'mbps', 'megabytes');
668 $add_throttle_desc->('mbps_rd_max', 'float', 'unthrottled read pool', 'mbps', 'megabytes');
669 $add_throttle_desc->('mbps_wr_max', 'float', 'unthrottled write pool', 'mbps', 'megabytes');
670 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
671 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
672 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
682 type
=> 'string', format
=> $ide_fmt,
683 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
685 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
694 type
=> 'string', format
=> $scsi_fmt,
695 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
697 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
705 type
=> 'string', format
=> $sata_fmt,
706 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
708 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
717 type
=> 'string', format
=> $virtio_fmt,
718 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
720 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
733 type
=> 'string', format
=> 'pve-qm-usb-device',
734 format_description
=> 'HOSTUSBDEVICE|spice',
735 description
=> 'The Host USB device or port or the value spice',
740 format_description
=> 'yes|no',
741 description
=> 'Specifies whether if given host option is a USB3 device or port',
747 type
=> 'string', format
=> $usbformat,
748 description
=> <<EODESCR,
749 Configure an USB device (n is 0 to 4). This can be used to
750 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
752 'bus-port(.port)*' (decimal numbers) or
753 'vendor_id:product_id' (hexadeciaml numbers) or
756 You can use the 'lsusb -t' command to list existing usb devices.
758 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
760 The value 'spice' can be used to add a usb redirection devices for spice.
762 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).
766 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
770 type
=> 'string', format
=> 'pve-qm-hostpci',
771 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
772 description
=> <<EODESCR,
773 Map host pci devices. HOSTPCIDEVICE syntax is:
775 'bus:dev.func' (hexadecimal numbers)
777 You can us the 'lspci' command to list existing pci devices.
779 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
781 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
783 Experimental: user reported problems with this option.
786 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
791 pattern
=> '(/dev/.+|socket)',
792 description
=> <<EODESCR,
793 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).
795 Note: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
797 Experimental: user reported problems with this option.
804 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
805 description
=> <<EODESCR,
806 Map host parallel devices (n is 0 to 2).
808 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
810 Experimental: user reported problems with this option.
814 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
815 $confdesc->{"parallel$i"} = $paralleldesc;
818 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
819 $confdesc->{"serial$i"} = $serialdesc;
822 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
823 $confdesc->{"hostpci$i"} = $hostpcidesc;
826 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
827 $drivename_hash->{"ide$i"} = 1;
828 $confdesc->{"ide$i"} = $idedesc;
831 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
832 $drivename_hash->{"sata$i"} = 1;
833 $confdesc->{"sata$i"} = $satadesc;
836 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
837 $drivename_hash->{"scsi$i"} = 1;
838 $confdesc->{"scsi$i"} = $scsidesc ;
841 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
842 $drivename_hash->{"virtio$i"} = 1;
843 $confdesc->{"virtio$i"} = $virtiodesc;
846 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
847 $confdesc->{"usb$i"} = $usbdesc;
852 type
=> 'string', format
=> 'pve-volume-id',
853 description
=> "Reference to unused volumes.",
856 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
857 $confdesc->{"unused$i"} = $unuseddesc;
860 my $kvm_api_version = 0;
864 return $kvm_api_version if $kvm_api_version;
866 my $fh = IO
::File-
>new("</dev/kvm") ||
869 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
870 $kvm_api_version = $v;
875 return $kvm_api_version;
878 my $kvm_user_version;
880 sub kvm_user_version
{
882 return $kvm_user_version if $kvm_user_version;
884 $kvm_user_version = 'unknown';
888 if ($line =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
889 $kvm_user_version = $2;
893 eval { run_command
("kvm -version", outfunc
=> $code); };
896 return $kvm_user_version;
900 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
903 # order is important - used to autoselect boot disk
904 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
905 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
906 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
907 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
910 sub valid_drivename
{
913 return defined($drivename_hash->{$dev});
918 return defined($confdesc->{$key});
922 return $nic_model_list;
925 sub os_list_description
{
930 w2k
=> 'Windows 2000',
931 w2k3
=>, 'Windows 2003',
932 w2k8
=> 'Windows 2008',
933 wvista
=> 'Windows Vista',
935 win8
=> 'Windows 8/2012',
945 return $cdrom_path if $cdrom_path;
947 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
948 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
949 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
953 my ($storecfg, $vmid, $cdrom) = @_;
955 if ($cdrom eq 'cdrom') {
956 return get_cdrom_path
();
957 } elsif ($cdrom eq 'none') {
959 } elsif ($cdrom =~ m
|^/|) {
962 return PVE
::Storage
::path
($storecfg, $cdrom);
966 # try to convert old style file names to volume IDs
967 sub filename_to_volume_id
{
968 my ($vmid, $file, $media) = @_;
970 if (!($file eq 'none' || $file eq 'cdrom' ||
971 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
973 return undef if $file =~ m
|/|;
975 if ($media && $media eq 'cdrom') {
976 $file = "local:iso/$file";
978 $file = "local:$vmid/$file";
985 sub verify_media_type
{
986 my ($opt, $vtype, $media) = @_;
991 if ($media eq 'disk') {
993 } elsif ($media eq 'cdrom') {
996 die "internal error";
999 return if ($vtype eq $etype);
1001 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1004 sub cleanup_drive_path
{
1005 my ($opt, $storecfg, $drive) = @_;
1007 # try to convert filesystem paths to volume IDs
1009 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1010 ($drive->{file
} !~ m
|^/dev/.+|) &&
1011 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1012 ($drive->{file
} !~ m/^\d+$/)) {
1013 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1014 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1015 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1016 verify_media_type
($opt, $vtype, $drive->{media
});
1017 $drive->{file
} = $volid;
1020 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1023 sub create_conf_nolock
{
1024 my ($vmid, $settings) = @_;
1026 my $filename = config_file
($vmid);
1028 die "configuration file '$filename' already exists\n" if -f
$filename;
1030 my $defaults = load_defaults
();
1032 $settings->{name
} = "vm$vmid" if !$settings->{name
};
1033 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
1036 foreach my $opt (keys %$settings) {
1037 next if !$confdesc->{$opt};
1039 my $value = $settings->{$opt};
1042 $data .= "$opt: $value\n";
1045 PVE
::Tools
::file_set_contents
($filename, $data);
1048 sub parse_hotplug_features
{
1053 return $res if $data eq '0';
1055 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1057 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1058 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1061 warn "ignoring unknown hotplug feature '$feature'\n";
1067 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1068 sub pve_verify_hotplug_features
{
1069 my ($value, $noerr) = @_;
1071 return $value if parse_hotplug_features
($value);
1073 return undef if $noerr;
1075 die "unable to parse hotplug option\n";
1078 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1079 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1080 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1081 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1082 # [,iothread=on][,serial=serial][,model=model]
1085 my ($key, $data) = @_;
1087 my ($interface, $index);
1089 if ($key =~ m/^([^\d]+)(\d+)$/) {
1096 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1097 : $confdesc->{$key}->{format
};
1099 warn "invalid drive key: $key\n";
1102 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1103 return undef if !$res;
1104 $res->{interface
} = $interface;
1105 $res->{index} = $index;
1108 foreach my $opt (qw(bps bps_rd bps_wr)) {
1109 if (my $bps = defined(delete $res->{$opt})) {
1110 if (defined($res->{"m$opt"})) {
1111 warn "both $opt and m$opt specified\n";
1115 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1118 return undef if $error;
1120 return undef if $res->{mbps_rd
} && $res->{mbps
};
1121 return undef if $res->{mbps_wr
} && $res->{mbps
};
1122 return undef if $res->{iops_rd
} && $res->{iops
};
1123 return undef if $res->{iops_wr
} && $res->{iops
};
1125 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1126 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1127 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1128 return undef if $res->{interface
} eq 'virtio';
1131 if (my $size = $res->{size
}) {
1132 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1139 my ($vmid, $drive) = @_;
1140 my $data = { %$drive };
1141 delete $data->{$_} for qw(index interface);
1142 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1146 my($fh, $noerr) = @_;
1149 my $SG_GET_VERSION_NUM = 0x2282;
1151 my $versionbuf = "\x00" x
8;
1152 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1154 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1157 my $version = unpack("I", $versionbuf);
1158 if ($version < 30000) {
1159 die "scsi generic interface too old\n" if !$noerr;
1163 my $buf = "\x00" x
36;
1164 my $sensebuf = "\x00" x
8;
1165 my $cmd = pack("C x3 C x1", 0x12, 36);
1167 # see /usr/include/scsi/sg.h
1168 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";
1170 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1171 length($sensebuf), 0, length($buf), $buf,
1172 $cmd, $sensebuf, 6000);
1174 $ret = ioctl($fh, $SG_IO, $packet);
1176 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1180 my @res = unpack($sg_io_hdr_t, $packet);
1181 if ($res[17] || $res[18]) {
1182 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1187 (my $byte0, my $byte1, $res->{vendor
},
1188 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1190 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1191 $res->{type
} = $byte0 & 31;
1199 my $fh = IO
::File-
>new("+<$path") || return undef;
1200 my $res = scsi_inquiry
($fh, 1);
1206 sub machine_type_is_q35
{
1209 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1212 sub print_tabletdevice_full
{
1215 my $q35 = machine_type_is_q35
($conf);
1217 # we use uhci for old VMs because tablet driver was buggy in older qemu
1218 my $usbbus = $q35 ?
"ehci" : "uhci";
1220 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1223 sub print_drivedevice_full
{
1224 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1229 if ($drive->{interface
} eq 'virtio') {
1230 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1231 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1232 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1233 } elsif ($drive->{interface
} eq 'scsi') {
1235 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1236 my $unit = $drive->{index} % $maxdev;
1237 my $devicetype = 'hd';
1239 if (drive_is_cdrom
($drive)) {
1242 if ($drive->{file
} =~ m
|^/|) {
1243 $path = $drive->{file
};
1245 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1248 if($path =~ m/^iscsi\:\/\
//){
1249 $devicetype = 'generic';
1251 if (my $info = path_is_scsi
($path)) {
1252 if ($info->{type
} == 0) {
1253 $devicetype = 'block';
1254 } elsif ($info->{type
} == 1) { # tape
1255 $devicetype = 'generic';
1261 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1262 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1264 $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}";
1267 } elsif ($drive->{interface
} eq 'ide'){
1269 my $controller = int($drive->{index} / $maxdev);
1270 my $unit = $drive->{index} % $maxdev;
1271 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1273 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1274 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1275 $device .= ",model=$model";
1277 } elsif ($drive->{interface
} eq 'sata'){
1278 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1279 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1280 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1281 } elsif ($drive->{interface
} eq 'usb') {
1283 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1285 die "unsupported interface type";
1288 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1293 sub get_initiator_name
{
1296 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1297 while (defined(my $line = <$fh>)) {
1298 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1307 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);
1308 sub print_drive_full
{
1309 my ($storecfg, $vmid, $drive) = @_;
1312 my $volid = $drive->{file
};
1315 if (drive_is_cdrom
($drive)) {
1316 $path = get_iso_path
($storecfg, $vmid, $volid);
1318 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1320 $path = PVE
::Storage
::path
($storecfg, $volid);
1321 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1322 $format = qemu_img_format
($scfg, $volname);
1330 foreach my $o (@qemu_drive_options) {
1331 next if $o eq 'bootindex';
1332 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1335 $opts .= ",format=$format" if $format && !$drive->{format
};
1337 foreach my $o (qw(bps bps_rd bps_wr)) {
1338 my $v = $drive->{"m$o"};
1339 $opts .= ",$o=" . int($v*1024*1024) if $v;
1342 my $cache_direct = 0;
1344 if (my $cache = $drive->{cache
}) {
1345 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1346 } elsif (!drive_is_cdrom
($drive)) {
1347 $opts .= ",cache=none";
1351 # aio native works only with O_DIRECT
1352 if (!$drive->{aio
}) {
1354 $opts .= ",aio=native";
1356 $opts .= ",aio=threads";
1360 if (!drive_is_cdrom
($drive)) {
1362 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1363 $detectzeroes = 'off';
1364 } elsif ($drive->{discard
}) {
1365 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1367 # This used to be our default with discard not being specified:
1368 $detectzeroes = 'on';
1370 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1373 my $pathinfo = $path ?
"file=$path," : '';
1375 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1378 sub print_netdevice_full
{
1379 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1381 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1383 my $device = $net->{model
};
1384 if ($net->{model
} eq 'virtio') {
1385 $device = 'virtio-net-pci';
1388 my $pciaddr = print_pci_addr
("$netid", $bridges);
1389 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1390 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1391 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1392 my $vectors = $net->{queues
} * 2 + 2;
1393 $tmpstr .= ",vectors=$vectors,mq=on";
1395 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1397 if ($use_old_bios_files) {
1399 if ($device eq 'virtio-net-pci') {
1400 $romfile = 'pxe-virtio.rom';
1401 } elsif ($device eq 'e1000') {
1402 $romfile = 'pxe-e1000.rom';
1403 } elsif ($device eq 'ne2k') {
1404 $romfile = 'pxe-ne2k_pci.rom';
1405 } elsif ($device eq 'pcnet') {
1406 $romfile = 'pxe-pcnet.rom';
1407 } elsif ($device eq 'rtl8139') {
1408 $romfile = 'pxe-rtl8139.rom';
1410 $tmpstr .= ",romfile=$romfile" if $romfile;
1416 sub print_netdev_full
{
1417 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1420 if ($netid =~ m/^net(\d+)$/) {
1424 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1426 my $ifname = "tap${vmid}i$i";
1428 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1429 die "interface name '$ifname' is too long (max 15 character)\n"
1430 if length($ifname) >= 16;
1432 my $vhostparam = '';
1433 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1435 my $vmname = $conf->{name
} || "vm$vmid";
1438 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1440 if ($net->{bridge
}) {
1441 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1443 $netdev = "type=user,id=$netid,hostname=$vmname";
1446 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1451 sub drive_is_cdrom
{
1454 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1463 foreach my $kvp (split(/,/, $data)) {
1465 if ($kvp =~ m/^memory=(\S+)$/) {
1466 $res->{memory
} = $1;
1467 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1468 $res->{policy
} = $1;
1469 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1470 $res->{cpus
}->{start
} = $1;
1471 $res->{cpus
}->{end
} = $3;
1472 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1473 $res->{hostnodes
}->{start
} = $1;
1474 $res->{hostnodes
}->{end
} = $3;
1486 return undef if !$value;
1489 my @list = split(/,/, $value);
1493 foreach my $kv (@list) {
1495 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1498 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1501 my $pcidevices = lspci
($2);
1502 $res->{pciid
} = $pcidevices->{$2};
1504 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1505 $res->{rombar
} = $1;
1506 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1507 $res->{'x-vga'} = $1;
1508 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1509 $res->{pcie
} = 1 if $1 == 1;
1511 warn "unknown hostpci setting '$kv'\n";
1515 return undef if !$found;
1520 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1526 foreach my $kvp (split(/,/, $data)) {
1528 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) {
1530 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1531 $res->{model
} = $model;
1532 $res->{macaddr
} = $mac;
1533 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1534 $res->{bridge
} = $1;
1535 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1536 $res->{queues
} = $1;
1537 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1539 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1541 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1542 $res->{trunks
} = $1;
1543 } elsif ($kvp =~ m/^firewall=([01])$/) {
1544 $res->{firewall
} = $1;
1545 } elsif ($kvp =~ m/^link_down=([01])$/) {
1546 $res->{link_down
} = $1;
1553 return undef if !$res->{model
};
1561 my $res = "$net->{model}";
1562 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1563 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1564 $res .= ",rate=$net->{rate}" if $net->{rate
};
1565 $res .= ",tag=$net->{tag}" if $net->{tag
};
1566 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1567 $res .= ",firewall=1" if $net->{firewall
};
1568 $res .= ",link_down=1" if $net->{link_down
};
1569 $res .= ",queues=$net->{queues}" if $net->{queues
};
1574 sub add_random_macs
{
1575 my ($settings) = @_;
1577 foreach my $opt (keys %$settings) {
1578 next if $opt !~ m/^net(\d+)$/;
1579 my $net = parse_net
($settings->{$opt});
1581 $settings->{$opt} = print_net
($net);
1585 sub add_unused_volume
{
1586 my ($config, $volid) = @_;
1589 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1590 my $test = "unused$ind";
1591 if (my $vid = $config->{$test}) {
1592 return if $vid eq $volid; # do not add duplicates
1598 die "To many unused volume - please delete them first.\n" if !$key;
1600 $config->{$key} = $volid;
1605 sub vm_is_volid_owner
{
1606 my ($storecfg, $vmid, $volid) = @_;
1608 if ($volid !~ m
|^/|) {
1610 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1611 if ($owner && ($owner == $vmid)) {
1619 sub split_flagged_list
{
1620 my $text = shift || '';
1621 $text =~ s/[,;]/ /g;
1623 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1626 sub join_flagged_list
{
1627 my ($how, $lst) = @_;
1628 join $how, map { $lst->{$_} . $_ } keys %$lst;
1631 sub vmconfig_delete_pending_option
{
1632 my ($conf, $key, $force) = @_;
1634 delete $conf->{pending
}->{$key};
1635 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1636 $pending_delete_hash->{$key} = $force ?
'!' : '';
1637 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1640 sub vmconfig_undelete_pending_option
{
1641 my ($conf, $key) = @_;
1643 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1644 delete $pending_delete_hash->{$key};
1646 if (%$pending_delete_hash) {
1647 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1649 delete $conf->{pending
}->{delete};
1653 sub vmconfig_register_unused_drive
{
1654 my ($storecfg, $vmid, $conf, $drive) = @_;
1656 if (!drive_is_cdrom
($drive)) {
1657 my $volid = $drive->{file
};
1658 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1659 add_unused_volume
($conf, $volid, $vmid);
1664 sub vmconfig_cleanup_pending
{
1667 # remove pending changes when nothing changed
1669 foreach my $opt (keys %{$conf->{pending
}}) {
1670 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1672 delete $conf->{pending
}->{$opt};
1676 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1677 my $pending_delete_hash = {};
1678 while (my ($opt, $force) = each %$current_delete_hash) {
1679 if (defined($conf->{$opt})) {
1680 $pending_delete_hash->{$opt} = $force;
1686 if (%$pending_delete_hash) {
1687 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1689 delete $conf->{pending
}->{delete};
1695 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1696 my $smbios1_desc = {
1699 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1700 format_description
=> 'UUID',
1706 format_description
=> 'str',
1712 format_description
=> 'str',
1718 format_description
=> 'name',
1724 format_description
=> 'name',
1730 format_description
=> 'str',
1736 format_description
=> 'str',
1744 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_desc, $data) };
1751 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_desc);
1754 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_desc);
1756 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1757 sub verify_bootdisk
{
1758 my ($value, $noerr) = @_;
1760 return $value if valid_drivename
($value);
1762 return undef if $noerr;
1764 die "invalid boot disk '$value'\n";
1767 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1769 my ($value, $noerr) = @_;
1771 return $value if parse_numa
($value);
1773 return undef if $noerr;
1775 die "unable to parse numa options\n";
1778 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1780 my ($value, $noerr) = @_;
1782 return $value if parse_net
($value);
1784 return undef if $noerr;
1786 die "unable to parse network options\n";
1789 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1790 sub verify_hostpci
{
1791 my ($value, $noerr) = @_;
1793 return $value if parse_hostpci
($value);
1795 return undef if $noerr;
1797 die "unable to parse pci id\n";
1800 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1801 sub verify_watchdog
{
1802 my ($value, $noerr) = @_;
1804 return $value if parse_watchdog
($value);
1806 return undef if $noerr;
1808 die "unable to parse watchdog options\n";
1811 sub parse_watchdog
{
1814 return undef if !$value;
1818 foreach my $p (split(/,/, $value)) {
1819 next if $p =~ m/^\s*$/;
1821 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1823 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1824 $res->{action
} = $2;
1833 sub parse_usb_device
{
1836 return undef if !$value;
1839 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1840 $res->{vendorid
} = $2;
1841 $res->{productid
} = $4;
1842 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1843 $res->{hostbus
} = $1;
1844 $res->{hostport
} = $2;
1845 } elsif ($value =~ m/^spice$/i) {
1854 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1855 sub verify_usb_device
{
1856 my ($value, $noerr) = @_;
1858 return $value if parse_usb_device
($value);
1860 return undef if $noerr;
1862 die "unable to parse usb device\n";
1865 # add JSON properties for create and set function
1866 sub json_config_properties
{
1869 foreach my $opt (keys %$confdesc) {
1870 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1871 $prop->{$opt} = $confdesc->{$opt};
1878 my ($key, $value) = @_;
1880 die "unknown setting '$key'\n" if !$confdesc->{$key};
1882 my $type = $confdesc->{$key}->{type
};
1884 if (!defined($value)) {
1885 die "got undefined value\n";
1888 if ($value =~ m/[\n\r]/) {
1889 die "property contains a line feed\n";
1892 if ($type eq 'boolean') {
1893 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1894 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1895 die "type check ('boolean') failed - got '$value'\n";
1896 } elsif ($type eq 'integer') {
1897 return int($1) if $value =~ m/^(\d+)$/;
1898 die "type check ('integer') failed - got '$value'\n";
1899 } elsif ($type eq 'number') {
1900 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1901 die "type check ('number') failed - got '$value'\n";
1902 } elsif ($type eq 'string') {
1903 if (my $fmt = $confdesc->{$key}->{format
}) {
1904 if ($fmt eq 'pve-qm-drive') {
1905 # special case - we need to pass $key to parse_drive()
1906 my $drive = parse_drive
($key, $value);
1907 return $value if $drive;
1908 die "unable to parse drive options\n";
1910 PVE
::JSONSchema
::check_format
($fmt, $value);
1913 $value =~ s/^\"(.*)\"$/$1/;
1916 die "internal error"
1920 sub lock_config_full
{
1921 my ($vmid, $timeout, $code, @param) = @_;
1923 my $filename = config_file_lock
($vmid);
1925 my $res = lock_file
($filename, $timeout, $code, @param);
1932 sub lock_config_mode
{
1933 my ($vmid, $timeout, $shared, $code, @param) = @_;
1935 my $filename = config_file_lock
($vmid);
1937 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1945 my ($vmid, $code, @param) = @_;
1947 return lock_config_full
($vmid, 10, $code, @param);
1950 sub cfs_config_path
{
1951 my ($vmid, $node) = @_;
1953 $node = $nodename if !$node;
1954 return "nodes/$node/qemu-server/$vmid.conf";
1957 sub check_iommu_support
{
1958 #fixme : need to check IOMMU support
1959 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1967 my ($vmid, $node) = @_;
1969 my $cfspath = cfs_config_path
($vmid, $node);
1970 return "/etc/pve/$cfspath";
1973 sub config_file_lock
{
1976 return "$lock_dir/lock-$vmid.conf";
1982 my $conf = config_file
($vmid);
1983 utime undef, undef, $conf;
1987 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1989 my $conffile = config_file
($vmid);
1991 my $conf = load_config
($vmid);
1993 check_lock
($conf) if !$skiplock;
1995 # only remove disks owned by this VM
1996 foreach_drive
($conf, sub {
1997 my ($ds, $drive) = @_;
1999 return if drive_is_cdrom
($drive);
2001 my $volid = $drive->{file
};
2003 return if !$volid || $volid =~ m
|^/|;
2005 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2006 return if !$path || !$owner || ($owner != $vmid);
2008 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2011 if ($keep_empty_config) {
2012 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2017 # also remove unused disk
2019 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2022 PVE
::Storage
::foreach_volid
($dl, sub {
2023 my ($volid, $sid, $volname, $d) = @_;
2024 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2034 my ($vmid, $node) = @_;
2036 my $cfspath = cfs_config_path
($vmid, $node);
2038 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
2040 die "no such VM ('$vmid')\n" if !defined($conf);
2045 sub parse_vm_config
{
2046 my ($filename, $raw) = @_;
2048 return undef if !defined($raw);
2051 digest
=> Digest
::SHA
::sha1_hex
($raw),
2056 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2057 || die "got strange filename '$filename'";
2065 my @lines = split(/\n/, $raw);
2066 foreach my $line (@lines) {
2067 next if $line =~ m/^\s*$/;
2069 if ($line =~ m/^\[PENDING\]\s*$/i) {
2070 $section = 'pending';
2071 if (defined($descr)) {
2073 $conf->{description
} = $descr;
2076 $conf = $res->{$section} = {};
2079 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2081 if (defined($descr)) {
2083 $conf->{description
} = $descr;
2086 $conf = $res->{snapshots
}->{$section} = {};
2090 if ($line =~ m/^\#(.*)\s*$/) {
2091 $descr = '' if !defined($descr);
2092 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2096 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2097 $descr = '' if !defined($descr);
2098 $descr .= PVE
::Tools
::decode_text
($2);
2099 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2100 $conf->{snapstate
} = $1;
2101 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2104 $conf->{$key} = $value;
2105 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2107 if ($section eq 'pending') {
2108 $conf->{delete} = $value; # we parse this later
2110 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2112 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2115 eval { $value = check_type
($key, $value); };
2117 warn "vm $vmid - unable to parse value of '$key' - $@";
2119 my $fmt = $confdesc->{$key}->{format
};
2120 if ($fmt && $fmt eq 'pve-qm-drive') {
2121 my $v = parse_drive
($key, $value);
2122 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2123 $v->{file
} = $volid;
2124 $value = print_drive
($vmid, $v);
2126 warn "vm $vmid - unable to parse value of '$key'\n";
2131 if ($key eq 'cdrom') {
2132 $conf->{ide2
} = $value;
2134 $conf->{$key} = $value;
2140 if (defined($descr)) {
2142 $conf->{description
} = $descr;
2144 delete $res->{snapstate
}; # just to be sure
2149 sub write_vm_config
{
2150 my ($filename, $conf) = @_;
2152 delete $conf->{snapstate
}; # just to be sure
2154 if ($conf->{cdrom
}) {
2155 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2156 $conf->{ide2
} = $conf->{cdrom
};
2157 delete $conf->{cdrom
};
2160 # we do not use 'smp' any longer
2161 if ($conf->{sockets
}) {
2162 delete $conf->{smp
};
2163 } elsif ($conf->{smp
}) {
2164 $conf->{sockets
} = $conf->{smp
};
2165 delete $conf->{cores
};
2166 delete $conf->{smp
};
2169 my $used_volids = {};
2171 my $cleanup_config = sub {
2172 my ($cref, $pending, $snapname) = @_;
2174 foreach my $key (keys %$cref) {
2175 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2176 $key eq 'snapstate' || $key eq 'pending';
2177 my $value = $cref->{$key};
2178 if ($key eq 'delete') {
2179 die "propertry 'delete' is only allowed in [PENDING]\n"
2181 # fixme: check syntax?
2184 eval { $value = check_type
($key, $value); };
2185 die "unable to parse value of '$key' - $@" if $@;
2187 $cref->{$key} = $value;
2189 if (!$snapname && valid_drivename
($key)) {
2190 my $drive = parse_drive
($key, $value);
2191 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2196 &$cleanup_config($conf);
2198 &$cleanup_config($conf->{pending
}, 1);
2200 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2201 die "internal error" if $snapname eq 'pending';
2202 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2205 # remove 'unusedX' settings if we re-add a volume
2206 foreach my $key (keys %$conf) {
2207 my $value = $conf->{$key};
2208 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2209 delete $conf->{$key};
2213 my $generate_raw_config = sub {
2214 my ($conf, $pending) = @_;
2218 # add description as comment to top of file
2219 if (defined(my $descr = $conf->{description
})) {
2221 foreach my $cl (split(/\n/, $descr)) {
2222 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2225 $raw .= "#\n" if $pending;
2229 foreach my $key (sort keys %$conf) {
2230 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2231 $raw .= "$key: $conf->{$key}\n";
2236 my $raw = &$generate_raw_config($conf);
2238 if (scalar(keys %{$conf->{pending
}})){
2239 $raw .= "\n[PENDING]\n";
2240 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2243 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2244 $raw .= "\n[$snapname]\n";
2245 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2252 my ($vmid, $conf) = @_;
2254 my $cfspath = cfs_config_path
($vmid);
2256 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2263 # we use static defaults from our JSON schema configuration
2264 foreach my $key (keys %$confdesc) {
2265 if (defined(my $default = $confdesc->{$key}->{default})) {
2266 $res->{$key} = $default;
2270 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2271 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2277 my $vmlist = PVE
::Cluster
::get_vmlist
();
2279 return $res if !$vmlist || !$vmlist->{ids
};
2280 my $ids = $vmlist->{ids
};
2282 foreach my $vmid (keys %$ids) {
2283 my $d = $ids->{$vmid};
2284 next if !$d->{node
} || $d->{node
} ne $nodename;
2285 next if !$d->{type
} || $d->{type
} ne 'qemu';
2286 $res->{$vmid}->{exists} = 1;
2291 # test if VM uses local resources (to prevent migration)
2292 sub check_local_resources
{
2293 my ($conf, $noerr) = @_;
2297 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2298 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2300 foreach my $k (keys %$conf) {
2301 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2302 # sockets are safe: they will recreated be on the target side post-migrate
2303 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2304 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2307 die "VM uses local resources\n" if $loc_res && !$noerr;
2312 # check if used storages are available on all nodes (use by migrate)
2313 sub check_storage_availability
{
2314 my ($storecfg, $conf, $node) = @_;
2316 foreach_drive
($conf, sub {
2317 my ($ds, $drive) = @_;
2319 my $volid = $drive->{file
};
2322 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2325 # check if storage is available on both nodes
2326 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2327 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2331 # list nodes where all VM images are available (used by has_feature API)
2333 my ($conf, $storecfg) = @_;
2335 my $nodelist = PVE
::Cluster
::get_nodelist
();
2336 my $nodehash = { map { $_ => 1 } @$nodelist };
2337 my $nodename = PVE
::INotify
::nodename
();
2339 foreach_drive
($conf, sub {
2340 my ($ds, $drive) = @_;
2342 my $volid = $drive->{file
};
2345 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2347 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2348 if ($scfg->{disable
}) {
2350 } elsif (my $avail = $scfg->{nodes
}) {
2351 foreach my $node (keys %$nodehash) {
2352 delete $nodehash->{$node} if !$avail->{$node};
2354 } elsif (!$scfg->{shared
}) {
2355 foreach my $node (keys %$nodehash) {
2356 delete $nodehash->{$node} if $node ne $nodename
2368 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2372 my ($pidfile, $pid) = @_;
2374 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2378 return undef if !$line;
2379 my @param = split(/\0/, $line);
2381 my $cmd = $param[0];
2382 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2384 for (my $i = 0; $i < scalar (@param); $i++) {
2387 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2388 my $p = $param[$i+1];
2389 return 1 if $p && ($p eq $pidfile);
2398 my ($vmid, $nocheck, $node) = @_;
2400 my $filename = config_file
($vmid, $node);
2402 die "unable to find configuration file for VM $vmid - no such machine\n"
2403 if !$nocheck && ! -f
$filename;
2405 my $pidfile = pidfile_name
($vmid);
2407 if (my $fd = IO
::File-
>new("<$pidfile")) {
2412 my $mtime = $st->mtime;
2413 if ($mtime > time()) {
2414 warn "file '$filename' modified in future\n";
2417 if ($line =~ m/^(\d+)$/) {
2419 if (check_cmdline
($pidfile, $pid)) {
2420 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2432 my $vzlist = config_list
();
2434 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2436 while (defined(my $de = $fd->read)) {
2437 next if $de !~ m/^(\d+)\.pid$/;
2439 next if !defined($vzlist->{$vmid});
2440 if (my $pid = check_running
($vmid)) {
2441 $vzlist->{$vmid}->{pid
} = $pid;
2449 my ($storecfg, $conf) = @_;
2451 my $bootdisk = $conf->{bootdisk
};
2452 return undef if !$bootdisk;
2453 return undef if !valid_drivename
($bootdisk);
2455 return undef if !$conf->{$bootdisk};
2457 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2458 return undef if !defined($drive);
2460 return undef if drive_is_cdrom
($drive);
2462 my $volid = $drive->{file
};
2463 return undef if !$volid;
2465 return $drive->{size
};
2468 my $last_proc_pid_stat;
2470 # get VM status information
2471 # This must be fast and should not block ($full == false)
2472 # We only query KVM using QMP if $full == true (this can be slow)
2474 my ($opt_vmid, $full) = @_;
2478 my $storecfg = PVE
::Storage
::config
();
2480 my $list = vzlist
();
2481 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2483 my $cpucount = $cpuinfo->{cpus
} || 1;
2485 foreach my $vmid (keys %$list) {
2486 next if $opt_vmid && ($vmid ne $opt_vmid);
2488 my $cfspath = cfs_config_path
($vmid);
2489 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2492 $d->{pid
} = $list->{$vmid}->{pid
};
2494 # fixme: better status?
2495 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2497 my $size = disksize
($storecfg, $conf);
2498 if (defined($size)) {
2499 $d->{disk
} = 0; # no info available
2500 $d->{maxdisk
} = $size;
2506 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2507 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2508 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2510 $d->{name
} = $conf->{name
} || "VM $vmid";
2511 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2513 if ($conf->{balloon
}) {
2514 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2515 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2526 $d->{diskwrite
} = 0;
2528 $d->{template
} = is_template
($conf);
2533 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2534 foreach my $dev (keys %$netdev) {
2535 next if $dev !~ m/^tap([1-9]\d*)i/;
2537 my $d = $res->{$vmid};
2540 $d->{netout
} += $netdev->{$dev}->{receive
};
2541 $d->{netin
} += $netdev->{$dev}->{transmit
};
2544 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2545 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2550 my $ctime = gettimeofday
;
2552 foreach my $vmid (keys %$list) {
2554 my $d = $res->{$vmid};
2555 my $pid = $d->{pid
};
2558 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2559 next if !$pstat; # not running
2561 my $used = $pstat->{utime} + $pstat->{stime
};
2563 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2565 if ($pstat->{vsize
}) {
2566 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2569 my $old = $last_proc_pid_stat->{$pid};
2571 $last_proc_pid_stat->{$pid} = {
2579 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2581 if ($dtime > 1000) {
2582 my $dutime = $used - $old->{used
};
2584 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2585 $last_proc_pid_stat->{$pid} = {
2591 $d->{cpu
} = $old->{cpu
};
2595 return $res if !$full;
2597 my $qmpclient = PVE
::QMPClient-
>new();
2599 my $ballooncb = sub {
2600 my ($vmid, $resp) = @_;
2602 my $info = $resp->{'return'};
2603 return if !$info->{max_mem
};
2605 my $d = $res->{$vmid};
2607 # use memory assigned to VM
2608 $d->{maxmem
} = $info->{max_mem
};
2609 $d->{balloon
} = $info->{actual
};
2611 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2612 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2613 $d->{freemem
} = $info->{free_mem
};
2616 $d->{ballooninfo
} = $info;
2619 my $blockstatscb = sub {
2620 my ($vmid, $resp) = @_;
2621 my $data = $resp->{'return'} || [];
2622 my $totalrdbytes = 0;
2623 my $totalwrbytes = 0;
2625 for my $blockstat (@$data) {
2626 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2627 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2629 $blockstat->{device
} =~ s/drive-//;
2630 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2632 $res->{$vmid}->{diskread
} = $totalrdbytes;
2633 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2636 my $statuscb = sub {
2637 my ($vmid, $resp) = @_;
2639 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2640 # this fails if ballon driver is not loaded, so this must be
2641 # the last commnand (following command are aborted if this fails).
2642 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2644 my $status = 'unknown';
2645 if (!defined($status = $resp->{'return'}->{status
})) {
2646 warn "unable to get VM status\n";
2650 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2653 foreach my $vmid (keys %$list) {
2654 next if $opt_vmid && ($vmid ne $opt_vmid);
2655 next if !$res->{$vmid}->{pid
}; # not running
2656 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2659 $qmpclient->queue_execute(undef, 1);
2661 foreach my $vmid (keys %$list) {
2662 next if $opt_vmid && ($vmid ne $opt_vmid);
2663 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2670 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2673 my $current_size = 1024;
2674 my $dimm_size = 512;
2675 return if $current_size == $memory;
2677 for (my $j = 0; $j < 8; $j++) {
2678 for (my $i = 0; $i < 32; $i++) {
2679 my $name = "dimm${dimm_id}";
2681 my $numanode = $i % $sockets;
2682 $current_size += $dimm_size;
2683 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2684 return $current_size if $current_size >= $memory;
2690 sub foreach_reverse_dimm
{
2691 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2694 my $current_size = 4177920;
2695 my $dimm_size = 65536;
2696 return if $current_size == $memory;
2698 for (my $j = 0; $j < 8; $j++) {
2699 for (my $i = 0; $i < 32; $i++) {
2700 my $name = "dimm${dimm_id}";
2702 my $numanode = $i % $sockets;
2703 $current_size -= $dimm_size;
2704 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2705 return $current_size if $current_size <= $memory;
2712 my ($conf, $func) = @_;
2714 foreach my $ds (keys %$conf) {
2715 next if !valid_drivename
($ds);
2717 my $drive = parse_drive
($ds, $conf->{$ds});
2720 &$func($ds, $drive);
2725 my ($conf, $func) = @_;
2729 my $test_volid = sub {
2730 my ($volid, $is_cdrom) = @_;
2734 $volhash->{$volid} = $is_cdrom || 0;
2737 foreach_drive
($conf, sub {
2738 my ($ds, $drive) = @_;
2739 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2742 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2743 my $snap = $conf->{snapshots
}->{$snapname};
2744 &$test_volid($snap->{vmstate
}, 0);
2745 foreach_drive
($snap, sub {
2746 my ($ds, $drive) = @_;
2747 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2751 foreach my $volid (keys %$volhash) {
2752 &$func($volid, $volhash->{$volid});
2756 sub vga_conf_has_spice
{
2759 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2764 sub config_to_command
{
2765 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2768 my $globalFlags = [];
2769 my $machineFlags = [];
2775 my $kvmver = kvm_user_version
();
2776 my $vernum = 0; # unknown
2777 my $ostype = $conf->{ostype
};
2778 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2779 $vernum = $1*1000000+$2*1000;
2780 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2781 $vernum = $1*1000000+$2*1000+$3;
2784 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2786 my $have_ovz = -f
'/proc/vz/vestat';
2788 my $q35 = machine_type_is_q35
($conf);
2789 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2790 my $machine_type = $forcemachine || $conf->{machine
};
2791 my $use_old_bios_files = undef;
2792 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2794 my $cpuunits = defined($conf->{cpuunits
}) ?
2795 $conf->{cpuunits
} : $defaults->{cpuunits
};
2797 push @$cmd, '/usr/bin/systemd-run';
2798 push @$cmd, '--scope';
2799 push @$cmd, '--slice', "qemu";
2800 push @$cmd, '--unit', $vmid;
2801 # set KillMode=none, so that systemd don't kill those scopes
2802 # at shutdown (pve-manager service should stop the VMs instead)
2803 push @$cmd, '-p', "KillMode=none";
2804 push @$cmd, '-p', "CPUShares=$cpuunits";
2805 if ($conf->{cpulimit
}) {
2806 my $cpulimit = int($conf->{cpulimit
} * 100);
2807 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2810 push @$cmd, '/usr/bin/kvm';
2812 push @$cmd, '-id', $vmid;
2816 my $qmpsocket = qmp_socket
($vmid);
2817 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2818 push @$cmd, '-mon', "chardev=qmp,mode=control";
2821 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2823 push @$cmd, '-daemonize';
2825 if ($conf->{smbios1
}) {
2826 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2829 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2830 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2831 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2832 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2833 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2834 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2835 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2839 # the q35 chipset support native usb2, so we enable usb controller
2840 # by default for this machine type
2841 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2843 $pciaddr = print_pci_addr
("piix3", $bridges);
2844 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2847 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2848 next if !$conf->{"usb$i"};
2849 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2850 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2853 # include usb device config
2854 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2857 # add usb3 controller if needed
2860 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2861 next if !$conf->{"usb$i"};
2862 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2863 next if !$d || !$d->{usb3
};
2867 $pciaddr = print_pci_addr
("xhci", $bridges);
2868 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2870 my $vga = $conf->{vga
};
2872 my $qxlnum = vga_conf_has_spice
($vga);
2873 $vga = 'qxl' if $qxlnum;
2876 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2877 $conf->{ostype
} eq 'win7' ||
2878 $conf->{ostype
} eq 'w2k8')) {
2885 # enable absolute mouse coordinates (needed by vnc)
2887 if (defined($conf->{tablet
})) {
2888 $tablet = $conf->{tablet
};
2890 $tablet = $defaults->{tablet
};
2891 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2892 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2895 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2899 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2900 my $d = parse_hostpci
($conf->{"hostpci$i"});
2903 my $pcie = $d->{pcie
};
2905 die "q35 machine model is not enabled" if !$q35;
2906 $pciaddr = print_pcie_addr
("hostpci$i");
2908 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2911 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2912 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2913 if ($xvga && $xvga ne '') {
2916 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2917 push @$cpuFlags , 'hv_vendor_id=proxmox';
2919 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2923 my $pcidevices = $d->{pciid
};
2924 my $multifunction = 1 if @$pcidevices > 1;
2927 foreach my $pcidevice (@$pcidevices) {
2929 my $id = "hostpci$i";
2930 $id .= ".$j" if $multifunction;
2931 my $addr = $pciaddr;
2932 $addr .= ".$j" if $multifunction;
2933 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2936 $devicestr .= "$rombar$xvga";
2937 $devicestr .= ",multifunction=on" if $multifunction;
2940 push @$devices, '-device', $devicestr;
2946 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2947 next if !$conf->{"usb$i"};
2948 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2951 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2953 if (defined($d->{usb3
}) && $d->{usb3
}) {
2954 $usbbus = ',bus=xhci.0';
2957 if (defined($d->{host
})) {
2958 $d = parse_usb_device
($d->{host
});
2959 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2960 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2961 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2962 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2963 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2964 # usb redir support for spice, currently no usb3
2965 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2966 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2972 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2973 if (my $path = $conf->{"serial$i"}) {
2974 if ($path eq 'socket') {
2975 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2976 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2977 push @$devices, '-device', "isa-serial,chardev=serial$i";
2979 die "no such serial device\n" if ! -c
$path;
2980 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2981 push @$devices, '-device', "isa-serial,chardev=serial$i";
2987 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2988 if (my $path = $conf->{"parallel$i"}) {
2989 die "no such parallel device\n" if ! -c
$path;
2990 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2991 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2992 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2996 my $vmname = $conf->{name
} || "vm$vmid";
2998 push @$cmd, '-name', $vmname;
3001 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
3002 $sockets = $conf->{sockets
} if $conf->{sockets
};
3004 my $cores = $conf->{cores
} || 1;
3006 my $maxcpus = $sockets * $cores;
3008 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3010 my $allowed_vcpus = $cpuinfo->{cpus
};
3012 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3013 if ($allowed_vcpus < $maxcpus);
3015 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3017 push @$cmd, '-nodefaults';
3019 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3021 my $bootindex_hash = {};
3023 foreach my $o (split(//, $bootorder)) {
3024 $bootindex_hash->{$o} = $i*100;
3028 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
3030 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3032 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3034 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3036 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3037 my $socket = vnc_socket
($vmid);
3038 push @$cmd, '-vnc', "unix:$socket,x509,password";
3040 push @$cmd, '-nographic';
3044 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3046 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3047 my $useLocaltime = $conf->{localtime};
3050 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3052 if ($ostype =~ m/^w/) { # windows
3053 $useLocaltime = 1 if !defined($conf->{localtime});
3055 # use time drift fix when acpi is enabled
3056 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3057 $tdf = 1 if !defined($conf->{tdf
});
3061 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3062 $ostype eq 'wvista') {
3063 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3064 push @$cmd, '-no-hpet';
3065 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3066 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3067 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3068 push @$cpuFlags , 'hv_time' if !$nokvm;
3071 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3075 if ($ostype eq 'win7' || $ostype eq 'win8') {
3076 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3080 push @$rtcFlags, 'driftfix=slew' if $tdf;
3083 push @$machineFlags, 'accel=tcg';
3085 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3088 if ($machine_type) {
3089 push @$machineFlags, "type=${machine_type}";
3092 if ($conf->{startdate
}) {
3093 push @$rtcFlags, "base=$conf->{startdate}";
3094 } elsif ($useLocaltime) {
3095 push @$rtcFlags, 'base=localtime';
3098 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3099 if (my $cputype = $conf->{cpu
}) {
3100 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpudesc, $cputype)
3101 or die "Cannot parse cpu description: $cputype\n";
3102 $cpu = $cpuconf->{cputype
};
3103 $kvm_off = 1 if $cpuconf->{hidden
};
3106 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3108 push @$cpuFlags , '-x2apic'
3109 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3111 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3113 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3115 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3117 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3118 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3121 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3123 push @$cpuFlags, 'kvm=off' if $kvm_off;
3125 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3127 push @$cmd, '-cpu', $cpu;
3129 my $memory = $conf->{memory
} || $defaults->{memory
};
3130 my $static_memory = 0;
3131 my $dimm_memory = 0;
3133 if ($hotplug_features->{memory
}) {
3134 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3135 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3136 $static_memory = $STATICMEM;
3137 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3138 $dimm_memory = $memory - $static_memory;
3139 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3143 $static_memory = $memory;
3144 push @$cmd, '-m', $static_memory;
3147 if ($conf->{numa
}) {
3149 my $numa_totalmemory = undef;
3150 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3151 next if !$conf->{"numa$i"};
3152 my $numa = parse_numa
($conf->{"numa$i"});
3155 die "missing numa node$i memory value\n" if !$numa->{memory
};
3156 my $numa_memory = $numa->{memory
};
3157 $numa_totalmemory += $numa_memory;
3158 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3161 my $cpus_start = $numa->{cpus
}->{start
};
3162 die "missing numa node$i cpus\n" if !defined($cpus_start);
3163 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3164 my $cpus = $cpus_start;
3165 if (defined($cpus_end)) {
3166 $cpus .= "-$cpus_end";
3167 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3171 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3172 if (defined($hostnodes_start)) {
3173 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3174 my $hostnodes = $hostnodes_start;
3175 if (defined($hostnodes_end)) {
3176 $hostnodes .= "-$hostnodes_end";
3177 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3180 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3181 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3182 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3186 my $policy = $numa->{policy
};
3187 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3188 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3191 push @$cmd, '-object', $numa_object;
3192 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3195 die "total memory for NUMA nodes must be equal to vm static memory\n"
3196 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3198 #if no custom tology, we split memory and cores across numa nodes
3199 if(!$numa_totalmemory) {
3201 my $numa_memory = ($static_memory / $sockets) . "M";
3203 for (my $i = 0; $i < $sockets; $i++) {
3205 my $cpustart = ($cores * $i);
3206 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3207 my $cpus = $cpustart;
3208 $cpus .= "-$cpuend" if $cpuend;
3210 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3211 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3216 if ($hotplug_features->{memory
}) {
3217 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3218 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3219 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3220 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3222 #if dimm_memory is not aligned to dimm map
3223 if($current_size > $memory) {
3224 $conf->{memory
} = $current_size;
3225 write_config
($vmid, $conf);
3230 push @$cmd, '-S' if $conf->{freeze
};
3232 # set keyboard layout
3233 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3234 push @$cmd, '-k', $kb if $kb;
3237 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3238 #push @$cmd, '-soundhw', 'es1370';
3239 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3241 if($conf->{agent
}) {
3242 my $qgasocket = qmp_socket
($vmid, 1);
3243 my $pciaddr = print_pci_addr
("qga0", $bridges);
3244 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3245 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3246 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3253 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3254 for(my $i = 1; $i < $qxlnum; $i++){
3255 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3256 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3259 # assume other OS works like Linux
3260 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3261 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3265 my $pciaddr = print_pci_addr
("spice", $bridges);
3267 my $nodename = PVE
::INotify
::nodename
();
3268 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3269 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3271 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3273 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3274 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3275 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3278 # enable balloon by default, unless explicitly disabled
3279 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3280 $pciaddr = print_pci_addr
("balloon0", $bridges);
3281 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3284 if ($conf->{watchdog
}) {
3285 my $wdopts = parse_watchdog
($conf->{watchdog
});
3286 $pciaddr = print_pci_addr
("watchdog", $bridges);
3287 my $watchdog = $wdopts->{model
} || 'i6300esb';
3288 push @$devices, '-device', "$watchdog$pciaddr";
3289 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3293 my $scsicontroller = {};
3294 my $ahcicontroller = {};
3295 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3297 # Add iscsi initiator name if available
3298 if (my $initiator = get_initiator_name
()) {
3299 push @$devices, '-iscsi', "initiator-name=$initiator";
3302 foreach_drive
($conf, sub {
3303 my ($ds, $drive) = @_;
3305 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3306 push @$vollist, $drive->{file
};
3309 $use_virtio = 1 if $ds =~ m/^virtio/;
3311 if (drive_is_cdrom
($drive)) {
3312 if ($bootindex_hash->{d
}) {
3313 $drive->{bootindex
} = $bootindex_hash->{d
};
3314 $bootindex_hash->{d
} += 1;
3317 if ($bootindex_hash->{c
}) {
3318 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3319 $bootindex_hash->{c
} += 1;
3323 if($drive->{interface
} eq 'virtio'){
3324 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3327 if ($drive->{interface
} eq 'scsi') {
3329 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3331 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3332 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3335 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3336 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3337 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3341 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3342 $queues = ",num_queues=$drive->{queues}";
3345 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3346 $scsicontroller->{$controller}=1;
3349 if ($drive->{interface
} eq 'sata') {
3350 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3351 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3352 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3353 $ahcicontroller->{$controller}=1;
3356 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3357 push @$devices, '-drive',$drive_cmd;
3358 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3361 for (my $i = 0; $i < $MAX_NETS; $i++) {
3362 next if !$conf->{"net$i"};
3363 my $d = parse_net
($conf->{"net$i"});
3366 $use_virtio = 1 if $d->{model
} eq 'virtio';
3368 if ($bootindex_hash->{n
}) {
3369 $d->{bootindex
} = $bootindex_hash->{n
};
3370 $bootindex_hash->{n
} += 1;
3373 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3374 push @$devices, '-netdev', $netdevfull;
3376 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3377 push @$devices, '-device', $netdevicefull;
3382 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3387 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3389 while (my ($k, $v) = each %$bridges) {
3390 $pciaddr = print_pci_addr
("pci.$k");
3391 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3396 if ($conf->{args
}) {
3397 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3401 push @$cmd, @$devices;
3402 push @$cmd, '-rtc', join(',', @$rtcFlags)
3403 if scalar(@$rtcFlags);
3404 push @$cmd, '-machine', join(',', @$machineFlags)
3405 if scalar(@$machineFlags);
3406 push @$cmd, '-global', join(',', @$globalFlags)
3407 if scalar(@$globalFlags);
3409 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3414 return "${var_run_tmpdir}/$vmid.vnc";
3420 my $res = vm_mon_cmd
($vmid, 'query-spice');
3422 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3426 my ($vmid, $qga) = @_;
3427 my $sockettype = $qga ?
'qga' : 'qmp';
3428 return "${var_run_tmpdir}/$vmid.$sockettype";
3433 return "${var_run_tmpdir}/$vmid.pid";
3436 sub vm_devices_list
{
3439 my $res = vm_mon_cmd
($vmid, 'query-pci');
3441 foreach my $pcibus (@$res) {
3442 foreach my $device (@{$pcibus->{devices
}}) {
3443 next if !$device->{'qdev_id'};
3444 if ($device->{'pci_bridge'}) {
3445 $devices->{$device->{'qdev_id'}} = 1;
3446 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3447 next if !$bridge_device->{'qdev_id'};
3448 $devices->{$bridge_device->{'qdev_id'}} = 1;
3449 $devices->{$device->{'qdev_id'}}++;
3452 $devices->{$device->{'qdev_id'}} = 1;
3457 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3458 foreach my $block (@$resblock) {
3459 if($block->{device
} =~ m/^drive-(\S+)/){
3464 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3465 foreach my $mice (@$resmice) {
3466 if ($mice->{name
} eq 'QEMU HID Tablet') {
3467 $devices->{tablet
} = 1;
3476 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3478 my $q35 = machine_type_is_q35
($conf);
3480 my $devices_list = vm_devices_list
($vmid);
3481 return 1 if defined($devices_list->{$deviceid});
3483 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3485 if ($deviceid eq 'tablet') {
3487 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3489 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3491 qemu_iothread_add
($vmid, $deviceid, $device);
3493 qemu_driveadd
($storecfg, $vmid, $device);
3494 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3496 qemu_deviceadd
($vmid, $devicefull);
3497 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3499 eval { qemu_drivedel
($vmid, $deviceid); };
3504 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3507 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3508 my $pciaddr = print_pci_addr
($deviceid);
3509 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3511 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3513 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3514 qemu_iothread_add
($vmid, $deviceid, $device);
3515 $devicefull .= ",iothread=iothread-$deviceid";
3518 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3519 $devicefull .= ",num_queues=$device->{queues}";
3522 qemu_deviceadd
($vmid, $devicefull);
3523 qemu_deviceaddverify
($vmid, $deviceid);
3525 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3527 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3528 qemu_driveadd
($storecfg, $vmid, $device);
3530 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3531 eval { qemu_deviceadd
($vmid, $devicefull); };
3533 eval { qemu_drivedel
($vmid, $deviceid); };
3538 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3540 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3542 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3543 my $use_old_bios_files = undef;
3544 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3546 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3547 qemu_deviceadd
($vmid, $netdevicefull);
3548 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3550 eval { qemu_netdevdel
($vmid, $deviceid); };
3555 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3558 my $pciaddr = print_pci_addr
($deviceid);
3559 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3561 qemu_deviceadd
($vmid, $devicefull);
3562 qemu_deviceaddverify
($vmid, $deviceid);
3565 die "can't hotplug device '$deviceid'\n";
3571 # fixme: this should raise exceptions on error!
3572 sub vm_deviceunplug
{
3573 my ($vmid, $conf, $deviceid) = @_;
3575 my $devices_list = vm_devices_list
($vmid);
3576 return 1 if !defined($devices_list->{$deviceid});
3578 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3580 if ($deviceid eq 'tablet') {
3582 qemu_devicedel
($vmid, $deviceid);
3584 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3586 qemu_devicedel
($vmid, $deviceid);
3587 qemu_devicedelverify
($vmid, $deviceid);
3588 qemu_drivedel
($vmid, $deviceid);
3589 qemu_iothread_del
($conf, $vmid, $deviceid);
3591 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3593 qemu_devicedel
($vmid, $deviceid);
3594 qemu_devicedelverify
($vmid, $deviceid);
3595 qemu_iothread_del
($conf, $vmid, $deviceid);
3597 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3599 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3600 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3601 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3603 qemu_devicedel
($vmid, $deviceid);
3604 qemu_drivedel
($vmid, $deviceid);
3605 qemu_deletescsihw
($conf, $vmid, $deviceid);
3607 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3609 qemu_devicedel
($vmid, $deviceid);
3610 qemu_devicedelverify
($vmid, $deviceid);
3611 qemu_netdevdel
($vmid, $deviceid);
3614 die "can't unplug device '$deviceid'\n";
3620 sub qemu_deviceadd
{
3621 my ($vmid, $devicefull) = @_;
3623 $devicefull = "driver=".$devicefull;
3624 my %options = split(/[=,]/, $devicefull);
3626 vm_mon_cmd
($vmid, "device_add" , %options);
3629 sub qemu_devicedel
{
3630 my ($vmid, $deviceid) = @_;
3632 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3635 sub qemu_iothread_add
{
3636 my($vmid, $deviceid, $device) = @_;
3638 if ($device->{iothread
}) {
3639 my $iothreads = vm_iothreads_list
($vmid);
3640 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3644 sub qemu_iothread_del
{
3645 my($conf, $vmid, $deviceid) = @_;
3647 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3648 if ($device->{iothread
}) {
3649 my $iothreads = vm_iothreads_list
($vmid);
3650 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3654 sub qemu_objectadd
{
3655 my($vmid, $objectid, $qomtype) = @_;
3657 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3662 sub qemu_objectdel
{
3663 my($vmid, $objectid) = @_;
3665 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3671 my ($storecfg, $vmid, $device) = @_;
3673 my $drive = print_drive_full
($storecfg, $vmid, $device);
3674 $drive =~ s/\\/\\\\/g;
3675 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3677 # If the command succeeds qemu prints: "OK
"
3678 return 1 if $ret =~ m/OK/s;
3680 die "adding drive failed
: $ret\n";
3684 my($vmid, $deviceid) = @_;
3686 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3689 return 1 if $ret eq "";
3691 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3692 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3694 die "deleting drive
$deviceid failed
: $ret\n";
3697 sub qemu_deviceaddverify {
3698 my ($vmid, $deviceid) = @_;
3700 for (my $i = 0; $i <= 5; $i++) {
3701 my $devices_list = vm_devices_list($vmid);
3702 return 1 if defined($devices_list->{$deviceid});
3706 die "error on hotplug device
'$deviceid'\n";
3710 sub qemu_devicedelverify {
3711 my ($vmid, $deviceid) = @_;
3713 # need to verify that the device is correctly removed as device_del
3714 # is async and empty return is not reliable
3716 for (my $i = 0; $i <= 5; $i++) {
3717 my $devices_list = vm_devices_list($vmid);
3718 return 1 if !defined($devices_list->{$deviceid});
3722 die "error on hot-unplugging device
'$deviceid'\n";
3725 sub qemu_findorcreatescsihw {
3726 my ($storecfg, $conf, $vmid, $device) = @_;
3728 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3730 my $scsihwid="$controller_prefix$controller";
3731 my $devices_list = vm_devices_list($vmid);
3733 if(!defined($devices_list->{$scsihwid})) {
3734 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3740 sub qemu_deletescsihw {
3741 my ($conf, $vmid, $opt) = @_;
3743 my $device = parse_drive($opt, $conf->{$opt});
3745 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3746 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3750 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3752 my $devices_list = vm_devices_list($vmid);
3753 foreach my $opt (keys %{$devices_list}) {
3754 if (PVE::QemuServer::valid_drivename($opt)) {
3755 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3756 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3762 my $scsihwid="scsihw
$controller";
3764 vm_deviceunplug($vmid, $conf, $scsihwid);
3769 sub qemu_add_pci_bridge {
3770 my ($storecfg, $conf, $vmid, $device) = @_;
3776 print_pci_addr($device, $bridges);
3778 while (my ($k, $v) = each %$bridges) {
3781 return 1 if !defined($bridgeid) || $bridgeid < 1;
3783 my $bridge = "pci
.$bridgeid";
3784 my $devices_list = vm_devices_list($vmid);
3786 if (!defined($devices_list->{$bridge})) {
3787 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3793 sub qemu_set_link_status {
3794 my ($vmid, $device, $up) = @_;
3796 vm_mon_cmd($vmid, "set_link
", name => $device,
3797 up => $up ? JSON::true : JSON::false);
3800 sub qemu_netdevadd {
3801 my ($vmid, $conf, $device, $deviceid) = @_;
3803 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3804 my %options = split(/[=,]/, $netdev);
3806 vm_mon_cmd($vmid, "netdev_add
", %options);
3810 sub qemu_netdevdel {
3811 my ($vmid, $deviceid) = @_;
3813 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3816 sub qemu_cpu_hotplug {
3817 my ($vmid, $conf, $vcpus) = @_;
3820 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3821 $sockets = $conf->{sockets} if $conf->{sockets};
3822 my $cores = $conf->{cores} || 1;
3823 my $maxcpus = $sockets * $cores;
3825 $vcpus = $maxcpus if !$vcpus;
3827 die "you can
't add more vcpus than maxcpus\n"
3828 if $vcpus > $maxcpus;
3830 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3831 die "online cpu unplug is not yet possible\n"
3832 if $vcpus < $currentvcpus;
3834 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3835 die "vcpus in running vm is different than configuration\n"
3836 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3838 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3839 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3843 sub qemu_memory_hotplug {
3844 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3846 return $value if !check_running($vmid);
3848 my $memory = $conf->{memory} || $defaults->{memory};
3849 $value = $defaults->{memory} if !$value;
3850 return $value if $value == $memory;
3852 my $static_memory = $STATICMEM;
3853 my $dimm_memory = $memory - $static_memory;
3855 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3856 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3860 $sockets = $conf->{sockets} if $conf->{sockets};
3862 if($value > $memory) {
3864 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3865 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3867 return if $current_size <= $conf->{memory};
3869 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3871 eval { qemu_objectdel($vmid, "mem-
$name"); };
3875 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3877 eval { qemu_objectdel($vmid, "mem-
$name"); };
3880 #update conf after each succesful module hotplug
3881 $conf->{memory} = $current_size;
3882 write_config($vmid, $conf);
3887 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3888 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3890 return if $current_size >= $conf->{memory};
3891 print "try to unplug memory dimm
$name\n";
3895 eval { qemu_devicedel($vmid, $name) };
3897 my $dimm_list = qemu_dimm_list($vmid);
3898 last if !$dimm_list->{$name};
3899 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3903 #update conf after each succesful module unplug
3904 $conf->{memory} = $current_size;
3906 eval { qemu_objectdel($vmid, "mem-
$name"); };
3907 write_config($vmid, $conf);
3912 sub qemu_dimm_list {
3915 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3918 foreach my $dimm (@$dimmarray) {
3920 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3921 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3922 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3923 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3924 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3929 sub qemu_block_set_io_throttle {
3930 my ($vmid, $deviceid,
3931 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3932 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3934 return if !check_running($vmid) ;
3936 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3938 bps_rd => int($bps_rd),
3939 bps_wr => int($bps_wr),
3941 iops_rd => int($iops_rd),
3942 iops_wr => int($iops_wr),
3943 bps_max => int($bps_max),
3944 bps_rd_max => int($bps_rd_max),
3945 bps_wr_max => int($bps_wr_max),
3946 iops_max => int($iops_max),
3947 iops_rd_max => int($iops_rd_max),
3948 iops_wr_max => int($iops_wr_max)
3953 # old code, only used to shutdown old VM after update
3955 my ($fh, $timeout) = @_;
3957 my $sel = new IO::Select;
3964 while (scalar (@ready = $sel->can_read($timeout))) {
3966 if ($count = $fh->sysread($buf, 8192)) {
3967 if ($buf =~ /^(.*)\(qemu\) $/s) {
3974 if (!defined($count)) {
3981 die "monitor
read timeout
\n" if !scalar(@ready);
3986 # old code, only used to shutdown old VM after update
3987 sub vm_monitor_command {
3988 my ($vmid, $cmdstr, $nocheck) = @_;
3993 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3995 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3997 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3998 die "unable to
connect to VM
$vmid socket - $!\n";
4002 # hack: migrate sometime blocks the monitor (when migrate_downtime
4004 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4005 $timeout = 60*60; # 1 hour
4009 my $data = __read_avail($sock, $timeout);
4011 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
4012 die "got unexpected qemu monitor banner
\n";
4015 my $sel = new IO::Select;
4018 if (!scalar(my @ready = $sel->can_write($timeout))) {
4019 die "monitor
write error
- timeout
";
4022 my $fullcmd = "$cmdstr\r";
4024 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
4027 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4028 die "monitor
write error
- $!";
4031 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
4035 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4036 $timeout = 60*60; # 1 hour
4037 } elsif ($cmdstr =~ m/^(eject|change)/) {
4038 $timeout = 60; # note: cdrom mount command is slow
4040 if ($res = __read_avail($sock, $timeout)) {
4042 my @lines = split("\r?
\n", $res);
4044 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4046 $res = join("\n", @lines);
4054 syslog("err
", "VM
$vmid monitor command failed
- $err");
4061 sub qemu_block_resize {
4062 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4064 my $running = check_running($vmid);
4066 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4068 return if !$running;
4070 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4074 sub qemu_volume_snapshot {
4075 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4077 my $running = check_running($vmid);
4079 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4080 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4082 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4086 sub qemu_volume_snapshot_delete {
4087 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4089 my $running = check_running($vmid);
4091 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4093 return if !$running;
4095 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4098 sub set_migration_caps {
4104 "auto-converge
" => 1,
4106 "x-rdma-pin-all
" => 0,
4111 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4113 for my $supported_capability (@$supported_capabilities) {
4115 capability => $supported_capability->{capability},
4116 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4120 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4123 my $fast_plug_option = {
4132 # hotplug changes in [PENDING]
4133 # $selection hash can be used to only apply specified options, for
4134 # example: { cores => 1 } (only apply changed 'cores')
4135 # $errors ref is used to return error messages
4136 sub vmconfig_hotplug_pending {
4137 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4139 my $defaults = load_defaults();
4141 # commit values which do not have any impact on running VM first
4142 # Note: those option cannot raise errors, we we do not care about
4143 # $selection and always apply them.
4145 my $add_error = sub {
4146 my ($opt, $msg) = @_;
4147 $errors->{$opt} = "hotplug problem
- $msg";
4151 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4152 if ($fast_plug_option->{$opt}) {
4153 $conf->{$opt} = $conf->{pending}->{$opt};
4154 delete $conf->{pending}->{$opt};
4160 write_config($vmid, $conf);
4161 $conf = load_config($vmid); # update/reload
4164 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4166 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4167 while (my ($opt, $force) = each %$pending_delete_hash) {
4168 next if $selection && !$selection->{$opt};
4170 if ($opt eq 'hotplug') {
4171 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4172 } elsif ($opt eq 'tablet') {
4173 die "skip
\n" if !$hotplug_features->{usb};
4174 if ($defaults->{tablet}) {
4175 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4177 vm_deviceunplug($vmid, $conf, $opt);
4179 } elsif ($opt eq 'vcpus') {
4180 die "skip
\n" if !$hotplug_features->{cpu};
4181 qemu_cpu_hotplug($vmid, $conf, undef);
4182 } elsif ($opt eq 'balloon') {
4183 # enable balloon device is not hotpluggable
4184 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4185 } elsif ($fast_plug_option->{$opt}) {
4187 } elsif ($opt =~ m/^net(\d+)$/) {
4188 die "skip
\n" if !$hotplug_features->{network};
4189 vm_deviceunplug($vmid, $conf, $opt);
4190 } elsif (valid_drivename($opt)) {
4191 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4192 vm_deviceunplug($vmid, $conf, $opt);
4193 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4194 } elsif ($opt =~ m/^memory$/) {
4195 die "skip
\n" if !$hotplug_features->{memory};
4196 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4197 } elsif ($opt eq 'cpuunits') {
4198 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4199 } elsif ($opt eq 'cpulimit') {
4200 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4206 &$add_error($opt, $err) if $err ne "skip
\n";
4208 # save new config if hotplug was successful
4209 delete $conf->{$opt};
4210 vmconfig_undelete_pending_option($conf, $opt);
4211 write_config($vmid, $conf);
4212 $conf = load_config($vmid); # update/reload
4216 foreach my $opt (keys %{$conf->{pending}}) {
4217 next if $selection && !$selection->{$opt};
4218 my $value = $conf->{pending}->{$opt};
4220 if ($opt eq 'hotplug') {
4221 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4222 } elsif ($opt eq 'tablet') {
4223 die "skip
\n" if !$hotplug_features->{usb};
4225 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4226 } elsif ($value == 0) {
4227 vm_deviceunplug($vmid, $conf, $opt);
4229 } elsif ($opt eq 'vcpus') {
4230 die "skip
\n" if !$hotplug_features->{cpu};
4231 qemu_cpu_hotplug($vmid, $conf, $value);
4232 } elsif ($opt eq 'balloon') {
4233 # enable/disable balloning device is not hotpluggable
4234 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4235 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4236 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4238 # allow manual ballooning if shares is set to zero
4239 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4240 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4241 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4243 } elsif ($opt =~ m/^net(\d+)$/) {
4244 # some changes can be done without hotplug
4245 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4246 $vmid, $opt, $value);
4247 } elsif (valid_drivename($opt)) {
4248 # some changes can be done without hotplug
4249 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4250 $vmid, $opt, $value, 1);
4251 } elsif ($opt =~ m/^memory$/) { #dimms
4252 die "skip
\n" if !$hotplug_features->{memory};
4253 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4254 } elsif ($opt eq 'cpuunits') {
4255 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4256 } elsif ($opt eq 'cpulimit') {
4257 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4258 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4260 die "skip
\n"; # skip non-hot-pluggable options
4264 &$add_error($opt, $err) if $err ne "skip
\n";
4266 # save new config if hotplug was successful
4267 $conf->{$opt} = $value;
4268 delete $conf->{pending}->{$opt};
4269 write_config($vmid, $conf);
4270 $conf = load_config($vmid); # update/reload
4275 sub try_deallocate_drive {
4276 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4278 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4279 my $volid = $drive->{file};
4280 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4281 my $sid = PVE::Storage::parse_volume_id($volid);
4282 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4284 # check if the disk is really unused
4285 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4286 if is_volume_in_use($storecfg, $conf, $key, $volid);
4287 PVE::Storage::vdisk_free($storecfg, $volid);
4290 # If vm is not owner of this disk remove from config
4298 sub vmconfig_delete_or_detach_drive {
4299 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4301 my $drive = parse_drive($opt, $conf->{$opt});
4303 my $rpcenv = PVE::RPCEnvironment::get();
4304 my $authuser = $rpcenv->get_user();
4307 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4308 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4310 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4314 sub vmconfig_apply_pending {
4315 my ($vmid, $conf, $storecfg) = @_;
4319 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4320 while (my ($opt, $force) = each %$pending_delete_hash) {
4321 die "internal error
" if $opt =~ m/^unused/;
4322 $conf = load_config($vmid); # update/reload
4323 if (!defined($conf->{$opt})) {
4324 vmconfig_undelete_pending_option($conf, $opt);
4325 write_config($vmid, $conf);
4326 } elsif (valid_drivename($opt)) {
4327 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4328 vmconfig_undelete_pending_option($conf, $opt);
4329 delete $conf->{$opt};
4330 write_config($vmid, $conf);
4332 vmconfig_undelete_pending_option($conf, $opt);
4333 delete $conf->{$opt};
4334 write_config($vmid, $conf);
4338 $conf = load_config($vmid); # update/reload
4340 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4341 $conf = load_config($vmid); # update/reload
4343 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4344 # skip if nothing changed
4345 } elsif (valid_drivename($opt)) {
4346 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4347 if defined($conf->{$opt});
4348 $conf->{$opt} = $conf->{pending}->{$opt};
4350 $conf->{$opt} = $conf->{pending}->{$opt};
4353 delete $conf->{pending}->{$opt};
4354 write_config($vmid, $conf);
4358 my $safe_num_ne = sub {
4361 return 0 if !defined($a) && !defined($b);
4362 return 1 if !defined($a);
4363 return 1 if !defined($b);
4368 my $safe_string_ne = sub {
4371 return 0 if !defined($a) && !defined($b);
4372 return 1 if !defined($a);
4373 return 1 if !defined($b);
4378 sub vmconfig_update_net {
4379 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4381 my $newnet = parse_net($value);
4383 if ($conf->{$opt}) {
4384 my $oldnet = parse_net($conf->{$opt});
4386 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4387 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4388 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4389 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4391 # for non online change, we try to hot-unplug
4392 die "skip
\n" if !$hotplug;
4393 vm_deviceunplug($vmid, $conf, $opt);
4396 die "internal error
" if $opt !~ m/net(\d+)/;
4397 my $iface = "tap
${vmid
}i
$1";
4399 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4400 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4403 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4404 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4405 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4406 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4407 PVE::Network::tap_unplug($iface);
4408 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks});
4411 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4412 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4420 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4426 sub vmconfig_update_disk {
4427 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4429 # fixme: do we need force?
4431 my $drive = parse_drive($opt, $value);
4433 if ($conf->{$opt}) {
4435 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4437 my $media = $drive->{media} || 'disk';
4438 my $oldmedia = $old_drive->{media} || 'disk';
4439 die "unable to change media type
\n" if $media ne $oldmedia;
4441 if (!drive_is_cdrom($old_drive)) {
4443 if ($drive->{file} ne $old_drive->{file}) {
4445 die "skip
\n" if !$hotplug;
4447 # unplug and register as unused
4448 vm_deviceunplug($vmid, $conf, $opt);
4449 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4452 # update existing disk
4454 # skip non hotpluggable value
4455 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4456 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4457 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4458 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4463 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4464 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4465 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4466 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4467 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4468 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4469 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4470 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4471 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4472 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4473 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4474 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4476 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4477 ($drive->{mbps} || 0)*1024*1024,
4478 ($drive->{mbps_rd} || 0)*1024*1024,
4479 ($drive->{mbps_wr} || 0)*1024*1024,
4480 $drive->{iops} || 0,
4481 $drive->{iops_rd} || 0,
4482 $drive->{iops_wr} || 0,
4483 ($drive->{mbps_max} || 0)*1024*1024,
4484 ($drive->{mbps_rd_max} || 0)*1024*1024,
4485 ($drive->{mbps_wr_max} || 0)*1024*1024,
4486 $drive->{iops_max} || 0,
4487 $drive->{iops_rd_max} || 0,
4488 $drive->{iops_wr_max} || 0);
4497 if ($drive->{file} eq 'none') {
4498 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4500 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4501 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4502 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4510 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4512 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4513 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4517 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4518 $forcemachine, $spice_ticket) = @_;
4520 lock_config($vmid, sub {
4521 my $conf = load_config($vmid, $migratedfrom);
4523 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4525 check_lock($conf) if !$skiplock;
4527 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4529 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4530 vmconfig_apply_pending($vmid, $conf, $storecfg);
4531 $conf = load_config($vmid); # update/reload
4534 my $defaults = load_defaults();
4536 # set environment variable useful inside network script
4537 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4539 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4541 my $migrate_port = 0;
4544 if ($statefile eq 'tcp') {
4545 my $localip = "localhost
";
4546 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4547 my $nodename = PVE::INotify::nodename();
4548 if ($datacenterconf->{migration_unsecure}) {
4549 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4550 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4552 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4553 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4554 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4555 push @$cmd, '-incoming', $migrate_uri;
4558 push @$cmd, '-loadstate', $statefile;
4565 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4566 my $d = parse_hostpci($conf->{"hostpci
$i"});
4568 my $pcidevices = $d->{pciid};
4569 foreach my $pcidevice (@$pcidevices) {
4570 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4572 my $info = pci_device_info("0000:$pciid");
4573 die "IOMMU
not present
\n" if !check_iommu_support();
4574 die "no pci device info
for device
'$pciid'\n" if !$info;
4575 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4576 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4580 PVE::Storage::activate_volumes($storecfg, $vollist);
4582 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4586 # deactivate volumes if start fails
4587 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4588 die "start failed
: $err";
4591 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4593 if ($statefile && $statefile ne 'tcp') {
4594 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4598 if ($migratedfrom) {
4601 set_migration_caps($vmid);
4606 print "spice listens on port
$spice_port\n";
4607 if ($spice_ticket) {
4608 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4609 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4615 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4616 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4617 if $conf->{balloon};
4620 foreach my $opt (keys %$conf) {
4621 next if $opt !~ m/^net\d+$/;
4622 my $nicconf = parse_net($conf->{$opt});
4623 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4627 vm_mon_cmd_nocheck($vmid, 'qom-set',
4628 path => "machine
/peripheral/balloon0
",
4629 property => "guest-stats-polling-interval
",
4630 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4636 my ($vmid, $execute, %params) = @_;
4638 my $cmd = { execute => $execute, arguments => \%params };
4639 vm_qmp_command($vmid, $cmd);
4642 sub vm_mon_cmd_nocheck {
4643 my ($vmid, $execute, %params) = @_;
4645 my $cmd = { execute => $execute, arguments => \%params };
4646 vm_qmp_command($vmid, $cmd, 1);
4649 sub vm_qmp_command {
4650 my ($vmid, $cmd, $nocheck) = @_;
4655 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4656 $timeout = $cmd->{arguments}->{timeout};
4657 delete $cmd->{arguments}->{timeout};
4661 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4662 my $sname = qmp_socket($vmid);
4663 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4664 my $qmpclient = PVE::QMPClient->new();
4666 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4667 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4668 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4669 if scalar(%{$cmd->{arguments}});
4670 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4672 die "unable to open monitor socket\n";
4676 syslog("err", "VM $vmid qmp command failed - $err");
4683 sub vm_human_monitor_command {
4684 my ($vmid, $cmdline) = @_;
4689 execute => 'human-monitor-command
',
4690 arguments => { 'command-line
' => $cmdline},
4693 return vm_qmp_command($vmid, $cmd);
4696 sub vm_commandline {
4697 my ($storecfg, $vmid) = @_;
4699 my $conf = load_config($vmid);
4701 my $defaults = load_defaults();
4703 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4705 return join(' ', @$cmd);
4709 my ($vmid, $skiplock) = @_;
4711 lock_config($vmid, sub {
4713 my $conf = load_config($vmid);
4715 check_lock($conf) if !$skiplock;
4717 vm_mon_cmd($vmid, "system_reset");
4721 sub get_vm_volumes {
4725 foreach_volid($conf, sub {
4726 my ($volid, $is_cdrom) = @_;
4728 return if $volid =~ m|^/|;
4730 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4733 push @$vollist, $volid;
4739 sub vm_stop_cleanup {
4740 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4745 my $vollist = get_vm_volumes($conf);
4746 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4749 foreach my $ext (qw(mon qmp pid vnc qga)) {
4750 unlink "/var/run/qemu-server/${vmid}.$ext";
4753 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4755 warn $@ if $@; # avoid errors - just warn
4758 # Note: use $nockeck to skip tests if VM configuration file exists.
4759 # We need that when migration VMs to other nodes (files already moved)
4760 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4762 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4764 $force = 1 if !defined($force) && !$shutdown;
4767 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4768 kill 15, $pid if $pid;
4769 my $conf = load_config
($vmid, $migratedfrom);
4770 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4774 lock_config
($vmid, sub {
4776 my $pid = check_running
($vmid, $nocheck);
4781 $conf = load_config
($vmid);
4782 check_lock
($conf) if !$skiplock;
4783 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4784 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4785 $timeout = $opts->{down
} if $opts->{down
};
4789 $timeout = 60 if !defined($timeout);
4793 if (defined($conf) && $conf->{agent
}) {
4794 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4796 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4799 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4806 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4811 if ($count >= $timeout) {
4813 warn "VM still running - terminating now with SIGTERM\n";
4816 die "VM quit/powerdown failed - got timeout\n";
4819 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4824 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4827 die "VM quit/powerdown failed\n";
4835 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4840 if ($count >= $timeout) {
4841 warn "VM still running - terminating now with SIGKILL\n";
4846 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4851 my ($vmid, $skiplock) = @_;
4853 lock_config
($vmid, sub {
4855 my $conf = load_config
($vmid);
4857 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4859 vm_mon_cmd
($vmid, "stop");
4864 my ($vmid, $skiplock, $nocheck) = @_;
4866 lock_config
($vmid, sub {
4870 my $conf = load_config
($vmid);
4872 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4874 vm_mon_cmd
($vmid, "cont");
4877 vm_mon_cmd_nocheck
($vmid, "cont");
4883 my ($vmid, $skiplock, $key) = @_;
4885 lock_config
($vmid, sub {
4887 my $conf = load_config
($vmid);
4889 # there is no qmp command, so we use the human monitor command
4890 vm_human_monitor_command
($vmid, "sendkey $key");
4895 my ($storecfg, $vmid, $skiplock) = @_;
4897 lock_config
($vmid, sub {
4899 my $conf = load_config
($vmid);
4901 if (!check_running
($vmid)) {
4902 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4904 die "VM $vmid is running - destroy failed\n";
4912 my ($filename, $buf) = @_;
4914 my $fh = IO
::File-
>new($filename, "w");
4915 return undef if !$fh;
4917 my $res = print $fh $buf;
4924 sub pci_device_info
{
4929 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4930 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4932 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4933 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4935 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4936 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4938 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4939 return undef if !defined($product) || $product !~ s/^0x//;
4944 product
=> $product,
4950 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4959 my $name = $dev->{name
};
4961 my $fn = "$pcisysfs/devices/$name/reset";
4963 return file_write
($fn, "1");
4966 sub pci_dev_bind_to_vfio
{
4969 my $name = $dev->{name
};
4971 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4973 if (!-d
$vfio_basedir) {
4974 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4976 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4978 my $testdir = "$vfio_basedir/$name";
4979 return 1 if -d
$testdir;
4981 my $data = "$dev->{vendor} $dev->{product}";
4982 return undef if !file_write
("$vfio_basedir/new_id", $data);
4984 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4985 if (!file_write
($fn, $name)) {
4986 return undef if -f
$fn;
4989 $fn = "$vfio_basedir/bind";
4990 if (! -d
$testdir) {
4991 return undef if !file_write
($fn, $name);
4997 sub pci_dev_group_bind_to_vfio
{
5000 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5002 if (!-d
$vfio_basedir) {
5003 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5005 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5007 # get IOMMU group devices
5008 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5009 my @devs = grep /^0000:/, readdir($D);
5012 foreach my $pciid (@devs) {
5013 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5015 # pci bridges, switches or root ports are not supported
5016 # they have a pci_bus subdirectory so skip them
5017 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5019 my $info = pci_device_info
($1);
5020 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5026 sub print_pci_addr
{
5027 my ($id, $bridges) = @_;
5031 piix3
=> { bus
=> 0, addr
=> 1 },
5032 #addr2 : first videocard
5033 balloon0
=> { bus
=> 0, addr
=> 3 },
5034 watchdog
=> { bus
=> 0, addr
=> 4 },
5035 scsihw0
=> { bus
=> 0, addr
=> 5 },
5036 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
5037 scsihw1
=> { bus
=> 0, addr
=> 6 },
5038 ahci0
=> { bus
=> 0, addr
=> 7 },
5039 qga0
=> { bus
=> 0, addr
=> 8 },
5040 spice
=> { bus
=> 0, addr
=> 9 },
5041 virtio0
=> { bus
=> 0, addr
=> 10 },
5042 virtio1
=> { bus
=> 0, addr
=> 11 },
5043 virtio2
=> { bus
=> 0, addr
=> 12 },
5044 virtio3
=> { bus
=> 0, addr
=> 13 },
5045 virtio4
=> { bus
=> 0, addr
=> 14 },
5046 virtio5
=> { bus
=> 0, addr
=> 15 },
5047 hostpci0
=> { bus
=> 0, addr
=> 16 },
5048 hostpci1
=> { bus
=> 0, addr
=> 17 },
5049 net0
=> { bus
=> 0, addr
=> 18 },
5050 net1
=> { bus
=> 0, addr
=> 19 },
5051 net2
=> { bus
=> 0, addr
=> 20 },
5052 net3
=> { bus
=> 0, addr
=> 21 },
5053 net4
=> { bus
=> 0, addr
=> 22 },
5054 net5
=> { bus
=> 0, addr
=> 23 },
5055 vga1
=> { bus
=> 0, addr
=> 24 },
5056 vga2
=> { bus
=> 0, addr
=> 25 },
5057 vga3
=> { bus
=> 0, addr
=> 26 },
5058 hostpci2
=> { bus
=> 0, addr
=> 27 },
5059 hostpci3
=> { bus
=> 0, addr
=> 28 },
5060 #addr29 : usb-host (pve-usb.cfg)
5061 'pci.1' => { bus
=> 0, addr
=> 30 },
5062 'pci.2' => { bus
=> 0, addr
=> 31 },
5063 'net6' => { bus
=> 1, addr
=> 1 },
5064 'net7' => { bus
=> 1, addr
=> 2 },
5065 'net8' => { bus
=> 1, addr
=> 3 },
5066 'net9' => { bus
=> 1, addr
=> 4 },
5067 'net10' => { bus
=> 1, addr
=> 5 },
5068 'net11' => { bus
=> 1, addr
=> 6 },
5069 'net12' => { bus
=> 1, addr
=> 7 },
5070 'net13' => { bus
=> 1, addr
=> 8 },
5071 'net14' => { bus
=> 1, addr
=> 9 },
5072 'net15' => { bus
=> 1, addr
=> 10 },
5073 'net16' => { bus
=> 1, addr
=> 11 },
5074 'net17' => { bus
=> 1, addr
=> 12 },
5075 'net18' => { bus
=> 1, addr
=> 13 },
5076 'net19' => { bus
=> 1, addr
=> 14 },
5077 'net20' => { bus
=> 1, addr
=> 15 },
5078 'net21' => { bus
=> 1, addr
=> 16 },
5079 'net22' => { bus
=> 1, addr
=> 17 },
5080 'net23' => { bus
=> 1, addr
=> 18 },
5081 'net24' => { bus
=> 1, addr
=> 19 },
5082 'net25' => { bus
=> 1, addr
=> 20 },
5083 'net26' => { bus
=> 1, addr
=> 21 },
5084 'net27' => { bus
=> 1, addr
=> 22 },
5085 'net28' => { bus
=> 1, addr
=> 23 },
5086 'net29' => { bus
=> 1, addr
=> 24 },
5087 'net30' => { bus
=> 1, addr
=> 25 },
5088 'net31' => { bus
=> 1, addr
=> 26 },
5089 'xhci' => { bus
=> 1, addr
=> 27 },
5090 'virtio6' => { bus
=> 2, addr
=> 1 },
5091 'virtio7' => { bus
=> 2, addr
=> 2 },
5092 'virtio8' => { bus
=> 2, addr
=> 3 },
5093 'virtio9' => { bus
=> 2, addr
=> 4 },
5094 'virtio10' => { bus
=> 2, addr
=> 5 },
5095 'virtio11' => { bus
=> 2, addr
=> 6 },
5096 'virtio12' => { bus
=> 2, addr
=> 7 },
5097 'virtio13' => { bus
=> 2, addr
=> 8 },
5098 'virtio14' => { bus
=> 2, addr
=> 9 },
5099 'virtio15' => { bus
=> 2, addr
=> 10 },
5100 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5101 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5102 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5103 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5104 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5105 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5106 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5107 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5108 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5109 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5110 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5111 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5112 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5113 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5114 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5115 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5116 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5117 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5118 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5119 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5120 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5121 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5122 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5123 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5124 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5125 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5126 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5127 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5128 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5129 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5130 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5134 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5135 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5136 my $bus = $devices->{$id}->{bus
};
5137 $res = ",bus=pci.$bus,addr=$addr";
5138 $bridges->{$bus} = 1 if $bridges;
5144 sub print_pcie_addr
{
5149 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5150 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5151 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5152 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5155 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5156 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5157 my $bus = $devices->{$id}->{bus
};
5158 $res = ",bus=$bus,addr=$addr";
5164 # vzdump restore implementaion
5166 sub tar_archive_read_firstfile
{
5167 my $archive = shift;
5169 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5171 # try to detect archive type first
5172 my $pid = open (TMP
, "tar tf '$archive'|") ||
5173 die "unable to open file '$archive'\n";
5174 my $firstfile = <TMP
>;
5178 die "ERROR: archive contaions no data\n" if !$firstfile;
5184 sub tar_restore_cleanup
{
5185 my ($storecfg, $statfile) = @_;
5187 print STDERR
"starting cleanup\n";
5189 if (my $fd = IO
::File-
>new($statfile, "r")) {
5190 while (defined(my $line = <$fd>)) {
5191 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5194 if ($volid =~ m
|^/|) {
5195 unlink $volid || die 'unlink failed\n';
5197 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5199 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5201 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5203 print STDERR
"unable to parse line in statfile - $line";
5210 sub restore_archive
{
5211 my ($archive, $vmid, $user, $opts) = @_;
5213 my $format = $opts->{format
};
5216 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5217 $format = 'tar' if !$format;
5219 } elsif ($archive =~ m/\.tar$/) {
5220 $format = 'tar' if !$format;
5221 } elsif ($archive =~ m/.tar.lzo$/) {
5222 $format = 'tar' if !$format;
5224 } elsif ($archive =~ m/\.vma$/) {
5225 $format = 'vma' if !$format;
5226 } elsif ($archive =~ m/\.vma\.gz$/) {
5227 $format = 'vma' if !$format;
5229 } elsif ($archive =~ m/\.vma\.lzo$/) {
5230 $format = 'vma' if !$format;
5233 $format = 'vma' if !$format; # default
5236 # try to detect archive format
5237 if ($format eq 'tar') {
5238 return restore_tar_archive
($archive, $vmid, $user, $opts);
5240 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5244 sub restore_update_config_line
{
5245 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5247 return if $line =~ m/^\#qmdump\#/;
5248 return if $line =~ m/^\#vzdump\#/;
5249 return if $line =~ m/^lock:/;
5250 return if $line =~ m/^unused\d+:/;
5251 return if $line =~ m/^parent:/;
5252 return if $line =~ m/^template:/; # restored VM is never a template
5254 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5255 # try to convert old 1.X settings
5256 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5257 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5258 my ($model, $macaddr) = split(/\=/, $devconfig);
5259 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5262 bridge
=> "vmbr$ind",
5263 macaddr
=> $macaddr,
5265 my $netstr = print_net
($net);
5267 print $outfd "net$cookie->{netcount}: $netstr\n";
5268 $cookie->{netcount
}++;
5270 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5271 my ($id, $netstr) = ($1, $2);
5272 my $net = parse_net
($netstr);
5273 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5274 $netstr = print_net
($net);
5275 print $outfd "$id: $netstr\n";
5276 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5279 my $di = parse_drive
($virtdev, $value);
5280 if (defined($di->{backup
}) && !$di->{backup
}) {
5281 print $outfd "#$line";
5282 } elsif ($map->{$virtdev}) {
5283 delete $di->{format
}; # format can change on restore
5284 $di->{file
} = $map->{$virtdev};
5285 $value = print_drive
($vmid, $di);
5286 print $outfd "$virtdev: $value\n";
5296 my ($cfg, $vmid) = @_;
5298 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5300 my $volid_hash = {};
5301 foreach my $storeid (keys %$info) {
5302 foreach my $item (@{$info->{$storeid}}) {
5303 next if !($item->{volid
} && $item->{size
});
5304 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5305 $volid_hash->{$item->{volid
}} = $item;
5312 sub is_volume_in_use
{
5313 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5315 my $path = PVE
::Storage
::path
($storecfg, $volid);
5317 my $scan_config = sub {
5318 my ($cref, $snapname) = @_;
5320 foreach my $key (keys %$cref) {
5321 my $value = $cref->{$key};
5322 if (valid_drivename
($key)) {
5323 next if $skip_drive && $key eq $skip_drive;
5324 my $drive = parse_drive
($key, $value);
5325 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5326 return 1 if $volid eq $drive->{file
};
5327 if ($drive->{file
} =~ m!^/!) {
5328 return 1 if $drive->{file
} eq $path;
5330 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5332 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5334 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5342 return 1 if &$scan_config($conf);
5346 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5347 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5353 sub update_disksize
{
5354 my ($vmid, $conf, $volid_hash) = @_;
5360 # Note: it is allowed to define multiple storages with same path (alias), so
5361 # we need to check both 'volid' and real 'path' (two different volid can point
5362 # to the same path).
5367 foreach my $opt (keys %$conf) {
5368 if (valid_drivename
($opt)) {
5369 my $drive = parse_drive
($opt, $conf->{$opt});
5370 my $volid = $drive->{file
};
5373 $used->{$volid} = 1;
5374 if ($volid_hash->{$volid} &&
5375 (my $path = $volid_hash->{$volid}->{path
})) {
5376 $usedpath->{$path} = 1;
5379 next if drive_is_cdrom
($drive);
5380 next if !$volid_hash->{$volid};
5382 $drive->{size
} = $volid_hash->{$volid}->{size
};
5383 my $new = print_drive
($vmid, $drive);
5384 if ($new ne $conf->{$opt}) {
5386 $conf->{$opt} = $new;
5391 # remove 'unusedX' entry if volume is used
5392 foreach my $opt (keys %$conf) {
5393 next if $opt !~ m/^unused\d+$/;
5394 my $volid = $conf->{$opt};
5395 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5396 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5398 delete $conf->{$opt};
5402 foreach my $volid (sort keys %$volid_hash) {
5403 next if $volid =~ m/vm-$vmid-state-/;
5404 next if $used->{$volid};
5405 my $path = $volid_hash->{$volid}->{path
};
5406 next if !$path; # just to be sure
5407 next if $usedpath->{$path};
5409 add_unused_volume
($conf, $volid);
5410 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5417 my ($vmid, $nolock) = @_;
5419 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5421 my $volid_hash = scan_volids
($cfg, $vmid);
5423 my $updatefn = sub {
5426 my $conf = load_config
($vmid);
5431 foreach my $volid (keys %$volid_hash) {
5432 my $info = $volid_hash->{$volid};
5433 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5436 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5438 write_config
($vmid, $conf) if $changes;
5441 if (defined($vmid)) {
5445 lock_config
($vmid, $updatefn, $vmid);
5448 my $vmlist = config_list
();
5449 foreach my $vmid (keys %$vmlist) {
5453 lock_config
($vmid, $updatefn, $vmid);
5459 sub restore_vma_archive
{
5460 my ($archive, $vmid, $user, $opts, $comp) = @_;
5462 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5463 my $readfrom = $archive;
5468 my $qarchive = PVE
::Tools
::shellquote
($archive);
5469 if ($comp eq 'gzip') {
5470 $uncomp = "zcat $qarchive|";
5471 } elsif ($comp eq 'lzop') {
5472 $uncomp = "lzop -d -c $qarchive|";
5474 die "unknown compression method '$comp'\n";
5479 my $tmpdir = "/var/tmp/vzdumptmp$$";
5482 # disable interrupts (always do cleanups)
5483 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5484 warn "got interrupt - ignored\n";
5487 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5488 POSIX
::mkfifo
($mapfifo, 0600);
5491 my $openfifo = sub {
5492 open($fifofh, '>', $mapfifo) || die $!;
5495 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5502 my $rpcenv = PVE
::RPCEnvironment
::get
();
5504 my $conffile = config_file
($vmid);
5505 my $tmpfn = "$conffile.$$.tmp";
5507 # Note: $oldconf is undef if VM does not exists
5508 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5510 my $print_devmap = sub {
5511 my $virtdev_hash = {};
5513 my $cfgfn = "$tmpdir/qemu-server.conf";
5515 # we can read the config - that is already extracted
5516 my $fh = IO
::File-
>new($cfgfn, "r") ||
5517 "unable to read qemu-server.conf - $!\n";
5519 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5521 my $pve_firewall_dir = '/etc/pve/firewall';
5522 mkdir $pve_firewall_dir; # make sure the dir exists
5523 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5526 while (defined(my $line = <$fh>)) {
5527 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5528 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5529 die "archive does not contain data for drive '$virtdev'\n"
5530 if !$devinfo->{$devname};
5531 if (defined($opts->{storage
})) {
5532 $storeid = $opts->{storage
} || 'local';
5533 } elsif (!$storeid) {
5536 $format = 'raw' if !$format;
5537 $devinfo->{$devname}->{devname
} = $devname;
5538 $devinfo->{$devname}->{virtdev
} = $virtdev;
5539 $devinfo->{$devname}->{format
} = $format;
5540 $devinfo->{$devname}->{storeid
} = $storeid;
5542 # check permission on storage
5543 my $pool = $opts->{pool
}; # todo: do we need that?
5544 if ($user ne 'root@pam') {
5545 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5548 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5552 foreach my $devname (keys %$devinfo) {
5553 die "found no device mapping information for device '$devname'\n"
5554 if !$devinfo->{$devname}->{virtdev
};
5557 my $cfg = cfs_read_file
('storage.cfg');
5559 # create empty/temp config
5561 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5562 foreach_drive
($oldconf, sub {
5563 my ($ds, $drive) = @_;
5565 return if drive_is_cdrom
($drive);
5567 my $volid = $drive->{file
};
5569 return if !$volid || $volid =~ m
|^/|;
5571 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5572 return if !$path || !$owner || ($owner != $vmid);
5574 # Note: only delete disk we want to restore
5575 # other volumes will become unused
5576 if ($virtdev_hash->{$ds}) {
5577 PVE
::Storage
::vdisk_free
($cfg, $volid);
5581 # delete vmstate files
5582 # since after the restore we have no snapshots anymore
5583 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5584 my $snap = $oldconf->{snapshots
}->{$snapname};
5585 if ($snap->{vmstate
}) {
5586 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5595 foreach my $virtdev (sort keys %$virtdev_hash) {
5596 my $d = $virtdev_hash->{$virtdev};
5597 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5598 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5600 # test if requested format is supported
5601 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5602 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5603 $d->{format
} = $defFormat if !$supported;
5605 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5606 $d->{format
}, undef, $alloc_size);
5607 print STDERR
"new volume ID is '$volid'\n";
5608 $d->{volid
} = $volid;
5609 my $path = PVE
::Storage
::path
($cfg, $volid);
5611 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5613 my $write_zeros = 1;
5614 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5618 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5620 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5621 $map->{$virtdev} = $volid;
5624 $fh->seek(0, 0) || die "seek failed - $!\n";
5626 my $outfd = new IO
::File
($tmpfn, "w") ||
5627 die "unable to write config for VM $vmid\n";
5629 my $cookie = { netcount
=> 0 };
5630 while (defined(my $line = <$fh>)) {
5631 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5640 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5641 die "interrupted by signal\n";
5643 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5645 $oldtimeout = alarm($timeout);
5652 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5653 my ($dev_id, $size, $devname) = ($1, $2, $3);
5654 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5655 } elsif ($line =~ m/^CTIME: /) {
5656 # we correctly received the vma config, so we can disable
5657 # the timeout now for disk allocation (set to 10 minutes, so
5658 # that we always timeout if something goes wrong)
5661 print $fifofh "done\n";
5662 my $tmp = $oldtimeout || 0;
5663 $oldtimeout = undef;
5669 print "restore vma archive: $cmd\n";
5670 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5674 alarm($oldtimeout) if $oldtimeout;
5677 foreach my $devname (keys %$devinfo) {
5678 my $volid = $devinfo->{$devname}->{volid
};
5679 push @$vollist, $volid if $volid;
5682 my $cfg = cfs_read_file
('storage.cfg');
5683 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5691 foreach my $devname (keys %$devinfo) {
5692 my $volid = $devinfo->{$devname}->{volid
};
5695 if ($volid =~ m
|^/|) {
5696 unlink $volid || die 'unlink failed\n';
5698 PVE
::Storage
::vdisk_free
($cfg, $volid);
5700 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5702 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5709 rename($tmpfn, $conffile) ||
5710 die "unable to commit configuration file '$conffile'\n";
5712 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5714 eval { rescan
($vmid, 1); };
5718 sub restore_tar_archive
{
5719 my ($archive, $vmid, $user, $opts) = @_;
5721 if ($archive ne '-') {
5722 my $firstfile = tar_archive_read_firstfile
($archive);
5723 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5724 if $firstfile ne 'qemu-server.conf';
5727 my $storecfg = cfs_read_file
('storage.cfg');
5729 # destroy existing data - keep empty config
5730 my $vmcfgfn = config_file
($vmid);
5731 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5733 my $tocmd = "/usr/lib/qemu-server/qmextract";
5735 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5736 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5737 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5738 $tocmd .= ' --info' if $opts->{info
};
5740 # tar option "xf" does not autodetect compression when read from STDIN,
5741 # so we pipe to zcat
5742 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5743 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5745 my $tmpdir = "/var/tmp/vzdumptmp$$";
5748 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5749 local $ENV{VZDUMP_VMID
} = $vmid;
5750 local $ENV{VZDUMP_USER
} = $user;
5752 my $conffile = config_file
($vmid);
5753 my $tmpfn = "$conffile.$$.tmp";
5755 # disable interrupts (always do cleanups)
5756 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5757 print STDERR
"got interrupt - ignored\n";
5762 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5763 die "interrupted by signal\n";
5766 if ($archive eq '-') {
5767 print "extracting archive from STDIN\n";
5768 run_command
($cmd, input
=> "<&STDIN");
5770 print "extracting archive '$archive'\n";
5774 return if $opts->{info
};
5778 my $statfile = "$tmpdir/qmrestore.stat";
5779 if (my $fd = IO
::File-
>new($statfile, "r")) {
5780 while (defined (my $line = <$fd>)) {
5781 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5782 $map->{$1} = $2 if $1;
5784 print STDERR
"unable to parse line in statfile - $line\n";
5790 my $confsrc = "$tmpdir/qemu-server.conf";
5792 my $srcfd = new IO
::File
($confsrc, "r") ||
5793 die "unable to open file '$confsrc'\n";
5795 my $outfd = new IO
::File
($tmpfn, "w") ||
5796 die "unable to write config for VM $vmid\n";
5798 my $cookie = { netcount
=> 0 };
5799 while (defined (my $line = <$srcfd>)) {
5800 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5812 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5819 rename $tmpfn, $conffile ||
5820 die "unable to commit configuration file '$conffile'\n";
5822 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5824 eval { rescan
($vmid, 1); };
5829 # Internal snapshots
5831 # NOTE: Snapshot create/delete involves several non-atomic
5832 # action, and can take a long time.
5833 # So we try to avoid locking the file and use 'lock' variable
5834 # inside the config file instead.
5836 my $snapshot_copy_config = sub {
5837 my ($source, $dest) = @_;
5839 foreach my $k (keys %$source) {
5840 next if $k eq 'snapshots';
5841 next if $k eq 'snapstate';
5842 next if $k eq 'snaptime';
5843 next if $k eq 'vmstate';
5844 next if $k eq 'lock';
5845 next if $k eq 'digest';
5846 next if $k eq 'description';
5847 next if $k =~ m/^unused\d+$/;
5849 $dest->{$k} = $source->{$k};
5853 my $snapshot_apply_config = sub {
5854 my ($conf, $snap) = @_;
5856 # copy snapshot list
5858 snapshots
=> $conf->{snapshots
},
5861 # keep description and list of unused disks
5862 foreach my $k (keys %$conf) {
5863 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5864 $newconf->{$k} = $conf->{$k};
5867 &$snapshot_copy_config($snap, $newconf);
5872 sub foreach_writable_storage
{
5873 my ($conf, $func) = @_;
5877 foreach my $ds (keys %$conf) {
5878 next if !valid_drivename
($ds);
5880 my $drive = parse_drive
($ds, $conf->{$ds});
5882 next if drive_is_cdrom
($drive);
5884 my $volid = $drive->{file
};
5886 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5887 $sidhash->{$sid} = $sid if $sid;
5890 foreach my $sid (sort keys %$sidhash) {
5895 my $alloc_vmstate_volid = sub {
5896 my ($storecfg, $vmid, $conf, $snapname) = @_;
5898 # Note: we try to be smart when selecting a $target storage
5902 # search shared storage first
5903 foreach_writable_storage
($conf, sub {
5905 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5906 return if !$scfg->{shared
};
5908 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5912 # now search local storage
5913 foreach_writable_storage
($conf, sub {
5915 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5916 return if $scfg->{shared
};
5918 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5922 $target = 'local' if !$target;
5924 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5925 # we abort live save after $conf->{memory}, so we need at max twice that space
5926 my $size = $conf->{memory
}*2 + $driver_state_size;
5928 my $name = "vm-$vmid-state-$snapname";
5929 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5930 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5931 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5936 sub snapshot_save_vmstate
{
5937 my ($vmid, $conf, $snapname, $storecfg) = @_;
5939 my $snap = $conf->{snapshots
}->{$snapname};
5941 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5942 # always overwrite machine if we save vmstate. This makes sure we
5943 # can restore it later using correct machine type
5944 $snap->{machine
} = get_current_qemu_machine
($vmid);
5947 sub snapshot_prepare
{
5948 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5952 my $updatefn = sub {
5954 my $conf = load_config
($vmid);
5956 die "you can't take a snapshot if it's a template\n"
5957 if is_template
($conf);
5961 $conf->{lock} = 'snapshot';
5963 die "snapshot name '$snapname' already used\n"
5964 if defined($conf->{snapshots
}->{$snapname});
5966 my $storecfg = PVE
::Storage
::config
();
5967 die "snapshot feature is not available\n" if !has_feature
('snapshot', $conf, $storecfg);
5969 $snap = $conf->{snapshots
}->{$snapname} = {};
5971 if ($save_vmstate && check_running
($vmid)) {
5972 snapshot_save_vmstate
($vmid, $conf, $snapname, $storecfg);
5975 &$snapshot_copy_config($conf, $snap);
5977 $snap->{snapstate
} = "prepare";
5978 $snap->{snaptime
} = time();
5979 $snap->{description
} = $comment if $comment;
5981 write_config
($vmid, $conf);
5984 lock_config
($vmid, $updatefn);
5989 sub snapshot_commit
{
5990 my ($vmid, $snapname) = @_;
5992 my $updatefn = sub {
5994 my $conf = load_config
($vmid);
5996 die "missing snapshot lock\n"
5997 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5999 my $has_machine_config = defined($conf->{machine
});
6001 my $snap = $conf->{snapshots
}->{$snapname};
6003 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6005 die "wrong snapshot state\n"
6006 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
6008 delete $snap->{snapstate
};
6009 delete $conf->{lock};
6011 my $newconf = &$snapshot_apply_config($conf, $snap);
6013 delete $newconf->{machine
} if !$has_machine_config;
6015 $newconf->{parent
} = $snapname;
6017 write_config
($vmid, $newconf);
6020 lock_config
($vmid, $updatefn);
6023 sub snapshot_rollback
{
6024 my ($vmid, $snapname) = @_;
6028 my $storecfg = PVE
::Storage
::config
();
6030 my $conf = load_config
($vmid);
6032 my $get_snapshot_config = sub {
6034 die "you can't rollback if vm is a template\n" if is_template
($conf);
6036 my $res = $conf->{snapshots
}->{$snapname};
6038 die "snapshot '$snapname' does not exist\n" if !defined($res);
6043 my $snap = &$get_snapshot_config();
6045 foreach_drive
($snap, sub {
6046 my ($ds, $drive) = @_;
6048 return if drive_is_cdrom
($drive);
6050 my $volid = $drive->{file
};
6052 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
6055 my $updatefn = sub {
6057 $conf = load_config
($vmid);
6059 $snap = &$get_snapshot_config();
6061 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
6062 if $snap->{snapstate
};
6066 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
6069 die "unable to rollback vm $vmid: vm is running\n"
6070 if check_running
($vmid);
6073 $conf->{lock} = 'rollback';
6075 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
6076 delete $conf->{lock};
6082 my $has_machine_config = defined($conf->{machine
});
6084 # copy snapshot config to current config
6085 $conf = &$snapshot_apply_config($conf, $snap);
6086 $conf->{parent
} = $snapname;
6088 # Note: old code did not store 'machine', so we try to be smart
6089 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
6090 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
6091 # we remove the 'machine' configuration if not explicitly specified
6092 # in the original config.
6093 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
6096 write_config
($vmid, $conf);
6098 if (!$prepare && $snap->{vmstate
}) {
6099 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6100 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
6104 lock_config
($vmid, $updatefn);
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 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
6118 lock_config
($vmid, $updatefn);
6121 my $savevm_wait = sub {
6125 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6126 if (!$stat->{status
}) {
6127 die "savevm not active\n";
6128 } elsif ($stat->{status
} eq 'active') {
6131 } elsif ($stat->{status
} eq 'completed') {
6134 die "query-savevm returned status '$stat->{status}'\n";
6139 sub do_snapshots_with_qemu
{
6140 my ($storecfg, $volid) = @_;
6142 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
6144 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
6145 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
6149 if ($volid =~ m/\.(qcow2|qed)$/){
6156 sub qga_check_running
{
6159 eval { vm_mon_cmd
($vmid, "guest-ping", timeout
=> 3); };
6161 warn "Qemu Guest Agent are not running - $@";
6167 sub check_freeze_needed
{
6168 my ($vmid, $config, $save_vmstate) = @_;
6170 my $running = check_running
($vmid);
6171 if ($save_vmstate) {
6172 return ($running, $running && $config->{agent
} && qga_check_running
($vmid));
6174 return ($running, 0);
6178 sub snapshot_create
{
6179 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
6181 my $snap = snapshot_prepare
($vmid, $snapname, $save_vmstate, $comment);
6183 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
6185 my $config = load_config
($vmid);
6187 my ($running, $freezefs) = check_freeze_needed
($vmid, $config, $snap->{vmstate
});
6193 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6194 warn "guest-fsfreeze-freeze problems - $@" if $@;
6197 # create internal snapshots of all drives
6199 my $storecfg = PVE
::Storage
::config
();
6202 if ($snap->{vmstate
}) {
6203 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6204 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
6205 &$savevm_wait($vmid);
6207 vm_mon_cmd
($vmid, "savevm-start");
6211 foreach_drive
($snap, sub {
6212 my ($ds, $drive) = @_;
6214 return if drive_is_cdrom
($drive);
6216 my $volid = $drive->{file
};
6217 my $device = "drive-$ds";
6219 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
6220 $drivehash->{$ds} = 1;
6226 eval { vm_mon_cmd
($vmid, "savevm-end") };
6230 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6231 warn "guest-fsfreeze-thaw problems - $@" if $@;
6234 # savevm-end is async, we need to wait
6236 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6237 if (!$stat->{bytes
}) {
6240 print "savevm not yet finished\n";
6248 warn "snapshot create failed: starting cleanup\n";
6249 eval { snapshot_delete
($vmid, $snapname, 1, $drivehash); };
6254 snapshot_commit
($vmid, $snapname);
6257 # Note: $drivehash is only set when called from snapshot_create.
6258 sub snapshot_delete
{
6259 my ($vmid, $snapname, $force, $drivehash) = @_;
6266 my $unlink_parent = sub {
6267 my ($confref, $new_parent) = @_;
6269 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6271 $confref->{parent
} = $new_parent;
6273 delete $confref->{parent
};
6278 my $updatefn = sub {
6279 my ($remove_drive) = @_;
6281 my $conf = load_config
($vmid);
6285 die "you can't delete a snapshot if vm is a template\n"
6286 if is_template
($conf);
6289 $snap = $conf->{snapshots
}->{$snapname};
6291 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6293 # remove parent refs
6295 &$unlink_parent($conf, $snap->{parent
});
6296 foreach my $sn (keys %{$conf->{snapshots
}}) {
6297 next if $sn eq $snapname;
6298 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6302 if ($remove_drive) {
6303 if ($remove_drive eq 'vmstate') {
6304 delete $snap->{$remove_drive};
6306 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6307 my $volid = $drive->{file
};
6308 delete $snap->{$remove_drive};
6309 add_unused_volume
($conf, $volid);
6314 $snap->{snapstate
} = 'delete';
6316 delete $conf->{snapshots
}->{$snapname};
6317 delete $conf->{lock} if $drivehash;
6318 foreach my $volid (@$unused) {
6319 add_unused_volume
($conf, $volid);
6323 write_config
($vmid, $conf);
6326 lock_config
($vmid, $updatefn);
6328 # now remove vmstate file
6330 my $storecfg = PVE
::Storage
::config
();
6332 if ($snap->{vmstate
}) {
6333 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6335 die $err if !$force;
6338 # save changes (remove vmstate from snapshot)
6339 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6342 # now remove all internal snapshots
6343 foreach_drive
($snap, sub {
6344 my ($ds, $drive) = @_;
6346 return if drive_is_cdrom
($drive);
6348 my $volid = $drive->{file
};
6349 my $device = "drive-$ds";
6351 if (!$drivehash || $drivehash->{$ds}) {
6352 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6354 die $err if !$force;
6359 # save changes (remove drive fron snapshot)
6360 lock_config
($vmid, $updatefn, $ds) if !$force;
6361 push @$unused, $volid;
6364 # now cleanup config
6366 lock_config
($vmid, $updatefn);
6370 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6373 foreach_drive
($conf, sub {
6374 my ($ds, $drive) = @_;
6376 return if drive_is_cdrom
($drive);
6377 my $volid = $drive->{file
};
6378 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6381 return $err ?
0 : 1;
6384 sub template_create
{
6385 my ($vmid, $conf, $disk) = @_;
6387 my $storecfg = PVE
::Storage
::config
();
6389 foreach_drive
($conf, sub {
6390 my ($ds, $drive) = @_;
6392 return if drive_is_cdrom
($drive);
6393 return if $disk && $ds ne $disk;
6395 my $volid = $drive->{file
};
6396 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6398 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6399 $drive->{file
} = $voliddst;
6400 $conf->{$ds} = print_drive
($vmid, $drive);
6401 write_config
($vmid, $conf);
6408 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6411 sub qemu_img_convert
{
6412 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6414 my $storecfg = PVE
::Storage
::config
();
6415 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6416 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6418 if ($src_storeid && $dst_storeid) {
6420 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6422 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6423 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6425 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6426 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6428 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6429 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6432 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6433 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6434 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6438 if($line =~ m/\((\S+)\/100\
%\)/){
6440 my $transferred = int($size * $percent / 100);
6441 my $remaining = $size - $transferred;
6443 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6448 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6450 die "copy failed: $err" if $err;
6454 sub qemu_img_format
{
6455 my ($scfg, $volname) = @_;
6457 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6464 sub qemu_drive_mirror
{
6465 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6467 my $storecfg = PVE
::Storage
::config
();
6468 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6470 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6472 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6474 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6476 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6477 $opts->{format
} = $format if $format;
6479 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6482 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6484 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6485 my $stat = @$stats[0];
6486 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6487 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6489 my $busy = $stat->{busy
};
6490 my $ready = $stat->{ready
};
6492 if (my $total = $stat->{len
}) {
6493 my $transferred = $stat->{offset
} || 0;
6494 my $remaining = $total - $transferred;
6495 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6497 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6501 if ($stat->{ready
} eq 'true') {
6503 last if $vmiddst != $vmid;
6505 # try to switch the disk if source and destination are on the same guest
6506 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6508 die $@ if $@ !~ m/cannot be completed/;
6517 my $cancel_job = sub {
6518 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6520 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6521 my $stat = @$stats[0];
6528 eval { &$cancel_job(); };
6529 die "mirroring error: $err";
6532 if ($vmiddst != $vmid) {
6533 # if we clone a disk for a new target vm, we don't switch the disk
6534 &$cancel_job(); # so we call block-job-cancel
6539 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6540 $newvmid, $storage, $format, $full, $newvollist) = @_;
6545 print "create linked clone of drive $drivename ($drive->{file})\n";
6546 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6547 push @$newvollist, $newvolid;
6549 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6550 $storeid = $storage if $storage;
6552 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6554 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6555 $format = qemu_img_format
($scfg, $volname);
6558 # test if requested format is supported - else use default
6559 my $supported = grep { $_ eq $format } @$validFormats;
6560 $format = $defFormat if !$supported;
6562 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6564 print "create full clone of drive $drivename ($drive->{file})\n";
6565 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6566 push @$newvollist, $newvolid;
6568 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6570 if (!$running || $snapname) {
6571 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6573 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6577 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6580 $disk->{format
} = undef;
6581 $disk->{file
} = $newvolid;
6582 $disk->{size
} = $size;
6587 # this only works if VM is running
6588 sub get_current_qemu_machine
{
6591 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6592 my $res = vm_qmp_command
($vmid, $cmd);
6594 my ($current, $default);
6595 foreach my $e (@$res) {
6596 $default = $e->{name
} if $e->{'is-default'};
6597 $current = $e->{name
} if $e->{'is-current'};
6600 # fallback to the default machine if current is not supported by qemu
6601 return $current || $default || 'pc';
6604 sub qemu_machine_feature_enabled
{
6605 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6610 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6612 $current_major = $3;
6613 $current_minor = $4;
6615 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6617 $current_major = $1;
6618 $current_minor = $2;
6621 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6626 sub qemu_machine_pxe
{
6627 my ($vmid, $conf, $machine) = @_;
6629 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6631 foreach my $opt (keys %$conf) {
6632 next if $opt !~ m/^net(\d+)$/;
6633 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6635 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6636 return $machine.".pxe" if $romfile =~ m/pxe/;
6643 sub qemu_use_old_bios_files
{
6644 my ($machine_type) = @_;
6646 return if !$machine_type;
6648 my $use_old_bios_files = undef;
6650 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6652 $use_old_bios_files = 1;
6654 my $kvmver = kvm_user_version
();
6655 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6656 # load new efi bios files on migration. So this hack is required to allow
6657 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6658 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6659 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6662 return ($use_old_bios_files, $machine_type);
6669 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6670 my (undef, $id, $function) = @_;
6671 my $res = { id
=> $id, function
=> $function};
6672 push @{$devices->{$id}}, $res;
6678 sub vm_iothreads_list
{
6681 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6684 foreach my $iothread (@$res) {
6685 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6692 my ($conf, $drive) = @_;
6696 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6698 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6704 my $controller = int($drive->{index} / $maxdev);
6705 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6707 return ($maxdev, $controller, $controller_prefix);
6710 # bash completion helper
6712 sub complete_backup_archives
{
6713 my ($cmdname, $pname, $cvalue) = @_;
6715 my $cfg = PVE
::Storage
::config
();
6719 if ($cvalue =~ m/^([^:]+):/) {
6723 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6726 foreach my $id (keys %$data) {
6727 foreach my $item (@{$data->{$id}}) {
6728 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6729 push @$res, $item->{volid
} if defined($item->{volid
});
6736 my $complete_vmid_full = sub {
6739 my $idlist = vmstatus
();
6743 foreach my $id (keys %$idlist) {
6744 my $d = $idlist->{$id};
6745 if (defined($running)) {
6746 next if $d->{template
};
6747 next if $running && $d->{status
} ne 'running';
6748 next if !$running && $d->{status
} eq 'running';
6757 return &$complete_vmid_full();
6760 sub complete_vmid_stopped
{
6761 return &$complete_vmid_full(0);
6764 sub complete_vmid_running
{
6765 return &$complete_vmid_full(1);
6768 sub complete_storage
{
6770 my $cfg = PVE
::Storage
::config
();
6771 my $ids = $cfg->{ids
};
6774 foreach my $sid (keys %$ids) {
6775 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6776 next if !$ids->{$sid}->{content
}->{images
};