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
};
1244 if (my $info = path_is_scsi
($path)) {
1245 if ($info->{type
} == 0) {
1246 $devicetype = 'block';
1247 } elsif ($info->{type
} == 1) { # tape
1248 $devicetype = 'generic';
1252 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1255 if($path =~ m/^iscsi\:\/\
//){
1256 $devicetype = 'generic';
1260 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1261 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1263 $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}";
1266 } elsif ($drive->{interface
} eq 'ide'){
1268 my $controller = int($drive->{index} / $maxdev);
1269 my $unit = $drive->{index} % $maxdev;
1270 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1272 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1273 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1274 $device .= ",model=$model";
1276 } elsif ($drive->{interface
} eq 'sata'){
1277 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1278 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1279 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1280 } elsif ($drive->{interface
} eq 'usb') {
1282 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1284 die "unsupported interface type";
1287 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1292 sub get_initiator_name
{
1295 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1296 while (defined(my $line = <$fh>)) {
1297 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1306 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);
1307 sub print_drive_full
{
1308 my ($storecfg, $vmid, $drive) = @_;
1311 my $volid = $drive->{file
};
1314 if (drive_is_cdrom
($drive)) {
1315 $path = get_iso_path
($storecfg, $vmid, $volid);
1317 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1319 $path = PVE
::Storage
::path
($storecfg, $volid);
1320 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1321 $format = qemu_img_format
($scfg, $volname);
1329 foreach my $o (@qemu_drive_options) {
1330 next if $o eq 'bootindex';
1331 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1334 $opts .= ",format=$format" if $format && !$drive->{format
};
1336 foreach my $o (qw(bps bps_rd bps_wr)) {
1337 my $v = $drive->{"m$o"};
1338 $opts .= ",$o=" . int($v*1024*1024) if $v;
1341 my $cache_direct = 0;
1343 if (my $cache = $drive->{cache
}) {
1344 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1345 } elsif (!drive_is_cdrom
($drive)) {
1346 $opts .= ",cache=none";
1350 # aio native works only with O_DIRECT
1351 if (!$drive->{aio
}) {
1353 $opts .= ",aio=native";
1355 $opts .= ",aio=threads";
1359 if (!drive_is_cdrom
($drive)) {
1361 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1362 $detectzeroes = 'off';
1363 } elsif ($drive->{discard
}) {
1364 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1366 # This used to be our default with discard not being specified:
1367 $detectzeroes = 'on';
1369 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1372 my $pathinfo = $path ?
"file=$path," : '';
1374 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1377 sub print_netdevice_full
{
1378 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1380 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1382 my $device = $net->{model
};
1383 if ($net->{model
} eq 'virtio') {
1384 $device = 'virtio-net-pci';
1387 my $pciaddr = print_pci_addr
("$netid", $bridges);
1388 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1389 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1390 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1391 my $vectors = $net->{queues
} * 2 + 2;
1392 $tmpstr .= ",vectors=$vectors,mq=on";
1394 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1396 if ($use_old_bios_files) {
1398 if ($device eq 'virtio-net-pci') {
1399 $romfile = 'pxe-virtio.rom';
1400 } elsif ($device eq 'e1000') {
1401 $romfile = 'pxe-e1000.rom';
1402 } elsif ($device eq 'ne2k') {
1403 $romfile = 'pxe-ne2k_pci.rom';
1404 } elsif ($device eq 'pcnet') {
1405 $romfile = 'pxe-pcnet.rom';
1406 } elsif ($device eq 'rtl8139') {
1407 $romfile = 'pxe-rtl8139.rom';
1409 $tmpstr .= ",romfile=$romfile" if $romfile;
1415 sub print_netdev_full
{
1416 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1419 if ($netid =~ m/^net(\d+)$/) {
1423 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1425 my $ifname = "tap${vmid}i$i";
1427 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1428 die "interface name '$ifname' is too long (max 15 character)\n"
1429 if length($ifname) >= 16;
1431 my $vhostparam = '';
1432 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1434 my $vmname = $conf->{name
} || "vm$vmid";
1437 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1439 if ($net->{bridge
}) {
1440 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1442 $netdev = "type=user,id=$netid,hostname=$vmname";
1445 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1450 sub drive_is_cdrom
{
1453 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1462 foreach my $kvp (split(/,/, $data)) {
1464 if ($kvp =~ m/^memory=(\S+)$/) {
1465 $res->{memory
} = $1;
1466 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1467 $res->{policy
} = $1;
1468 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1469 $res->{cpus
}->{start
} = $1;
1470 $res->{cpus
}->{end
} = $3;
1471 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1472 $res->{hostnodes
}->{start
} = $1;
1473 $res->{hostnodes
}->{end
} = $3;
1485 return undef if !$value;
1488 my @list = split(/,/, $value);
1492 foreach my $kv (@list) {
1494 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1497 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1500 my $pcidevices = lspci
($2);
1501 $res->{pciid
} = $pcidevices->{$2};
1503 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1504 $res->{rombar
} = $1;
1505 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1506 $res->{'x-vga'} = $1;
1507 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1508 $res->{pcie
} = 1 if $1 == 1;
1510 warn "unknown hostpci setting '$kv'\n";
1514 return undef if !$found;
1519 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1525 foreach my $kvp (split(/,/, $data)) {
1527 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) {
1529 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1530 $res->{model
} = $model;
1531 $res->{macaddr
} = $mac;
1532 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1533 $res->{bridge
} = $1;
1534 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1535 $res->{queues
} = $1;
1536 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1538 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1540 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1541 $res->{trunks
} = $1;
1542 } elsif ($kvp =~ m/^firewall=([01])$/) {
1543 $res->{firewall
} = $1;
1544 } elsif ($kvp =~ m/^link_down=([01])$/) {
1545 $res->{link_down
} = $1;
1552 return undef if !$res->{model
};
1560 my $res = "$net->{model}";
1561 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1562 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1563 $res .= ",rate=$net->{rate}" if $net->{rate
};
1564 $res .= ",tag=$net->{tag}" if $net->{tag
};
1565 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1566 $res .= ",firewall=1" if $net->{firewall
};
1567 $res .= ",link_down=1" if $net->{link_down
};
1568 $res .= ",queues=$net->{queues}" if $net->{queues
};
1573 sub add_random_macs
{
1574 my ($settings) = @_;
1576 foreach my $opt (keys %$settings) {
1577 next if $opt !~ m/^net(\d+)$/;
1578 my $net = parse_net
($settings->{$opt});
1580 $settings->{$opt} = print_net
($net);
1584 sub add_unused_volume
{
1585 my ($config, $volid) = @_;
1588 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1589 my $test = "unused$ind";
1590 if (my $vid = $config->{$test}) {
1591 return if $vid eq $volid; # do not add duplicates
1597 die "To many unused volume - please delete them first.\n" if !$key;
1599 $config->{$key} = $volid;
1604 sub vm_is_volid_owner
{
1605 my ($storecfg, $vmid, $volid) = @_;
1607 if ($volid !~ m
|^/|) {
1609 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1610 if ($owner && ($owner == $vmid)) {
1618 sub split_flagged_list
{
1619 my $text = shift || '';
1620 $text =~ s/[,;]/ /g;
1622 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1625 sub join_flagged_list
{
1626 my ($how, $lst) = @_;
1627 join $how, map { $lst->{$_} . $_ } keys %$lst;
1630 sub vmconfig_delete_pending_option
{
1631 my ($conf, $key, $force) = @_;
1633 delete $conf->{pending
}->{$key};
1634 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1635 $pending_delete_hash->{$key} = $force ?
'!' : '';
1636 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1639 sub vmconfig_undelete_pending_option
{
1640 my ($conf, $key) = @_;
1642 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1643 delete $pending_delete_hash->{$key};
1645 if (%$pending_delete_hash) {
1646 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1648 delete $conf->{pending
}->{delete};
1652 sub vmconfig_register_unused_drive
{
1653 my ($storecfg, $vmid, $conf, $drive) = @_;
1655 if (!drive_is_cdrom
($drive)) {
1656 my $volid = $drive->{file
};
1657 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1658 add_unused_volume
($conf, $volid, $vmid);
1663 sub vmconfig_cleanup_pending
{
1666 # remove pending changes when nothing changed
1668 foreach my $opt (keys %{$conf->{pending
}}) {
1669 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1671 delete $conf->{pending
}->{$opt};
1675 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1676 my $pending_delete_hash = {};
1677 while (my ($opt, $force) = each %$current_delete_hash) {
1678 if (defined($conf->{$opt})) {
1679 $pending_delete_hash->{$opt} = $force;
1685 if (%$pending_delete_hash) {
1686 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1688 delete $conf->{pending
}->{delete};
1694 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1695 my $smbios1_desc = {
1698 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1699 format_description
=> 'UUID',
1705 format_description
=> 'str',
1711 format_description
=> 'str',
1717 format_description
=> 'name',
1723 format_description
=> 'name',
1729 format_description
=> 'str',
1735 format_description
=> 'str',
1743 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_desc, $data) };
1750 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_desc);
1753 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_desc);
1755 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1756 sub verify_bootdisk
{
1757 my ($value, $noerr) = @_;
1759 return $value if valid_drivename
($value);
1761 return undef if $noerr;
1763 die "invalid boot disk '$value'\n";
1766 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1768 my ($value, $noerr) = @_;
1770 return $value if parse_numa
($value);
1772 return undef if $noerr;
1774 die "unable to parse numa options\n";
1777 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1779 my ($value, $noerr) = @_;
1781 return $value if parse_net
($value);
1783 return undef if $noerr;
1785 die "unable to parse network options\n";
1788 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1789 sub verify_hostpci
{
1790 my ($value, $noerr) = @_;
1792 return $value if parse_hostpci
($value);
1794 return undef if $noerr;
1796 die "unable to parse pci id\n";
1799 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1800 sub verify_watchdog
{
1801 my ($value, $noerr) = @_;
1803 return $value if parse_watchdog
($value);
1805 return undef if $noerr;
1807 die "unable to parse watchdog options\n";
1810 sub parse_watchdog
{
1813 return undef if !$value;
1817 foreach my $p (split(/,/, $value)) {
1818 next if $p =~ m/^\s*$/;
1820 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1822 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1823 $res->{action
} = $2;
1832 sub parse_usb_device
{
1835 return undef if !$value;
1838 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1839 $res->{vendorid
} = $2;
1840 $res->{productid
} = $4;
1841 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1842 $res->{hostbus
} = $1;
1843 $res->{hostport
} = $2;
1844 } elsif ($value =~ m/^spice$/i) {
1853 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1854 sub verify_usb_device
{
1855 my ($value, $noerr) = @_;
1857 return $value if parse_usb_device
($value);
1859 return undef if $noerr;
1861 die "unable to parse usb device\n";
1864 # add JSON properties for create and set function
1865 sub json_config_properties
{
1868 foreach my $opt (keys %$confdesc) {
1869 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1870 $prop->{$opt} = $confdesc->{$opt};
1877 my ($key, $value) = @_;
1879 die "unknown setting '$key'\n" if !$confdesc->{$key};
1881 my $type = $confdesc->{$key}->{type
};
1883 if (!defined($value)) {
1884 die "got undefined value\n";
1887 if ($value =~ m/[\n\r]/) {
1888 die "property contains a line feed\n";
1891 if ($type eq 'boolean') {
1892 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1893 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1894 die "type check ('boolean') failed - got '$value'\n";
1895 } elsif ($type eq 'integer') {
1896 return int($1) if $value =~ m/^(\d+)$/;
1897 die "type check ('integer') failed - got '$value'\n";
1898 } elsif ($type eq 'number') {
1899 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1900 die "type check ('number') failed - got '$value'\n";
1901 } elsif ($type eq 'string') {
1902 if (my $fmt = $confdesc->{$key}->{format
}) {
1903 if ($fmt eq 'pve-qm-drive') {
1904 # special case - we need to pass $key to parse_drive()
1905 my $drive = parse_drive
($key, $value);
1906 return $value if $drive;
1907 die "unable to parse drive options\n";
1909 PVE
::JSONSchema
::check_format
($fmt, $value);
1912 $value =~ s/^\"(.*)\"$/$1/;
1915 die "internal error"
1919 sub lock_config_full
{
1920 my ($vmid, $timeout, $code, @param) = @_;
1922 my $filename = config_file_lock
($vmid);
1924 my $res = lock_file
($filename, $timeout, $code, @param);
1931 sub lock_config_mode
{
1932 my ($vmid, $timeout, $shared, $code, @param) = @_;
1934 my $filename = config_file_lock
($vmid);
1936 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1944 my ($vmid, $code, @param) = @_;
1946 return lock_config_full
($vmid, 10, $code, @param);
1949 sub cfs_config_path
{
1950 my ($vmid, $node) = @_;
1952 $node = $nodename if !$node;
1953 return "nodes/$node/qemu-server/$vmid.conf";
1956 sub check_iommu_support
{
1957 #fixme : need to check IOMMU support
1958 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1966 my ($vmid, $node) = @_;
1968 my $cfspath = cfs_config_path
($vmid, $node);
1969 return "/etc/pve/$cfspath";
1972 sub config_file_lock
{
1975 return "$lock_dir/lock-$vmid.conf";
1981 my $conf = config_file
($vmid);
1982 utime undef, undef, $conf;
1986 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1988 my $conffile = config_file
($vmid);
1990 my $conf = load_config
($vmid);
1992 check_lock
($conf) if !$skiplock;
1994 # only remove disks owned by this VM
1995 foreach_drive
($conf, sub {
1996 my ($ds, $drive) = @_;
1998 return if drive_is_cdrom
($drive);
2000 my $volid = $drive->{file
};
2002 return if !$volid || $volid =~ m
|^/|;
2004 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2005 return if !$path || !$owner || ($owner != $vmid);
2007 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2010 if ($keep_empty_config) {
2011 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2016 # also remove unused disk
2018 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2021 PVE
::Storage
::foreach_volid
($dl, sub {
2022 my ($volid, $sid, $volname, $d) = @_;
2023 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2033 my ($vmid, $node) = @_;
2035 my $cfspath = cfs_config_path
($vmid, $node);
2037 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
2039 die "no such VM ('$vmid')\n" if !defined($conf);
2044 sub parse_vm_config
{
2045 my ($filename, $raw) = @_;
2047 return undef if !defined($raw);
2050 digest
=> Digest
::SHA
::sha1_hex
($raw),
2055 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2056 || die "got strange filename '$filename'";
2064 my @lines = split(/\n/, $raw);
2065 foreach my $line (@lines) {
2066 next if $line =~ m/^\s*$/;
2068 if ($line =~ m/^\[PENDING\]\s*$/i) {
2069 $section = 'pending';
2070 if (defined($descr)) {
2072 $conf->{description
} = $descr;
2075 $conf = $res->{$section} = {};
2078 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2080 if (defined($descr)) {
2082 $conf->{description
} = $descr;
2085 $conf = $res->{snapshots
}->{$section} = {};
2089 if ($line =~ m/^\#(.*)\s*$/) {
2090 $descr = '' if !defined($descr);
2091 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2095 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2096 $descr = '' if !defined($descr);
2097 $descr .= PVE
::Tools
::decode_text
($2);
2098 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2099 $conf->{snapstate
} = $1;
2100 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2103 $conf->{$key} = $value;
2104 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2106 if ($section eq 'pending') {
2107 $conf->{delete} = $value; # we parse this later
2109 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2111 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2114 eval { $value = check_type
($key, $value); };
2116 warn "vm $vmid - unable to parse value of '$key' - $@";
2118 my $fmt = $confdesc->{$key}->{format
};
2119 if ($fmt && $fmt eq 'pve-qm-drive') {
2120 my $v = parse_drive
($key, $value);
2121 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2122 $v->{file
} = $volid;
2123 $value = print_drive
($vmid, $v);
2125 warn "vm $vmid - unable to parse value of '$key'\n";
2130 if ($key eq 'cdrom') {
2131 $conf->{ide2
} = $value;
2133 $conf->{$key} = $value;
2139 if (defined($descr)) {
2141 $conf->{description
} = $descr;
2143 delete $res->{snapstate
}; # just to be sure
2148 sub write_vm_config
{
2149 my ($filename, $conf) = @_;
2151 delete $conf->{snapstate
}; # just to be sure
2153 if ($conf->{cdrom
}) {
2154 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2155 $conf->{ide2
} = $conf->{cdrom
};
2156 delete $conf->{cdrom
};
2159 # we do not use 'smp' any longer
2160 if ($conf->{sockets
}) {
2161 delete $conf->{smp
};
2162 } elsif ($conf->{smp
}) {
2163 $conf->{sockets
} = $conf->{smp
};
2164 delete $conf->{cores
};
2165 delete $conf->{smp
};
2168 my $used_volids = {};
2170 my $cleanup_config = sub {
2171 my ($cref, $pending, $snapname) = @_;
2173 foreach my $key (keys %$cref) {
2174 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2175 $key eq 'snapstate' || $key eq 'pending';
2176 my $value = $cref->{$key};
2177 if ($key eq 'delete') {
2178 die "propertry 'delete' is only allowed in [PENDING]\n"
2180 # fixme: check syntax?
2183 eval { $value = check_type
($key, $value); };
2184 die "unable to parse value of '$key' - $@" if $@;
2186 $cref->{$key} = $value;
2188 if (!$snapname && valid_drivename
($key)) {
2189 my $drive = parse_drive
($key, $value);
2190 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2195 &$cleanup_config($conf);
2197 &$cleanup_config($conf->{pending
}, 1);
2199 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2200 die "internal error" if $snapname eq 'pending';
2201 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2204 # remove 'unusedX' settings if we re-add a volume
2205 foreach my $key (keys %$conf) {
2206 my $value = $conf->{$key};
2207 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2208 delete $conf->{$key};
2212 my $generate_raw_config = sub {
2213 my ($conf, $pending) = @_;
2217 # add description as comment to top of file
2218 if (defined(my $descr = $conf->{description
})) {
2220 foreach my $cl (split(/\n/, $descr)) {
2221 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2224 $raw .= "#\n" if $pending;
2228 foreach my $key (sort keys %$conf) {
2229 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2230 $raw .= "$key: $conf->{$key}\n";
2235 my $raw = &$generate_raw_config($conf);
2237 if (scalar(keys %{$conf->{pending
}})){
2238 $raw .= "\n[PENDING]\n";
2239 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2242 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2243 $raw .= "\n[$snapname]\n";
2244 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2251 my ($vmid, $conf) = @_;
2253 my $cfspath = cfs_config_path
($vmid);
2255 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2262 # we use static defaults from our JSON schema configuration
2263 foreach my $key (keys %$confdesc) {
2264 if (defined(my $default = $confdesc->{$key}->{default})) {
2265 $res->{$key} = $default;
2269 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2270 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2276 my $vmlist = PVE
::Cluster
::get_vmlist
();
2278 return $res if !$vmlist || !$vmlist->{ids
};
2279 my $ids = $vmlist->{ids
};
2281 foreach my $vmid (keys %$ids) {
2282 my $d = $ids->{$vmid};
2283 next if !$d->{node
} || $d->{node
} ne $nodename;
2284 next if !$d->{type
} || $d->{type
} ne 'qemu';
2285 $res->{$vmid}->{exists} = 1;
2290 # test if VM uses local resources (to prevent migration)
2291 sub check_local_resources
{
2292 my ($conf, $noerr) = @_;
2296 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2297 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2299 foreach my $k (keys %$conf) {
2300 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2301 # sockets are safe: they will recreated be on the target side post-migrate
2302 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2303 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2306 die "VM uses local resources\n" if $loc_res && !$noerr;
2311 # check if used storages are available on all nodes (use by migrate)
2312 sub check_storage_availability
{
2313 my ($storecfg, $conf, $node) = @_;
2315 foreach_drive
($conf, sub {
2316 my ($ds, $drive) = @_;
2318 my $volid = $drive->{file
};
2321 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2324 # check if storage is available on both nodes
2325 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2326 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2330 # list nodes where all VM images are available (used by has_feature API)
2332 my ($conf, $storecfg) = @_;
2334 my $nodelist = PVE
::Cluster
::get_nodelist
();
2335 my $nodehash = { map { $_ => 1 } @$nodelist };
2336 my $nodename = PVE
::INotify
::nodename
();
2338 foreach_drive
($conf, sub {
2339 my ($ds, $drive) = @_;
2341 my $volid = $drive->{file
};
2344 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2346 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2347 if ($scfg->{disable
}) {
2349 } elsif (my $avail = $scfg->{nodes
}) {
2350 foreach my $node (keys %$nodehash) {
2351 delete $nodehash->{$node} if !$avail->{$node};
2353 } elsif (!$scfg->{shared
}) {
2354 foreach my $node (keys %$nodehash) {
2355 delete $nodehash->{$node} if $node ne $nodename
2367 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2371 my ($pidfile, $pid) = @_;
2373 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2377 return undef if !$line;
2378 my @param = split(/\0/, $line);
2380 my $cmd = $param[0];
2381 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2383 for (my $i = 0; $i < scalar (@param); $i++) {
2386 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2387 my $p = $param[$i+1];
2388 return 1 if $p && ($p eq $pidfile);
2397 my ($vmid, $nocheck, $node) = @_;
2399 my $filename = config_file
($vmid, $node);
2401 die "unable to find configuration file for VM $vmid - no such machine\n"
2402 if !$nocheck && ! -f
$filename;
2404 my $pidfile = pidfile_name
($vmid);
2406 if (my $fd = IO
::File-
>new("<$pidfile")) {
2411 my $mtime = $st->mtime;
2412 if ($mtime > time()) {
2413 warn "file '$filename' modified in future\n";
2416 if ($line =~ m/^(\d+)$/) {
2418 if (check_cmdline
($pidfile, $pid)) {
2419 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2431 my $vzlist = config_list
();
2433 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2435 while (defined(my $de = $fd->read)) {
2436 next if $de !~ m/^(\d+)\.pid$/;
2438 next if !defined($vzlist->{$vmid});
2439 if (my $pid = check_running
($vmid)) {
2440 $vzlist->{$vmid}->{pid
} = $pid;
2448 my ($storecfg, $conf) = @_;
2450 my $bootdisk = $conf->{bootdisk
};
2451 return undef if !$bootdisk;
2452 return undef if !valid_drivename
($bootdisk);
2454 return undef if !$conf->{$bootdisk};
2456 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2457 return undef if !defined($drive);
2459 return undef if drive_is_cdrom
($drive);
2461 my $volid = $drive->{file
};
2462 return undef if !$volid;
2464 return $drive->{size
};
2467 my $last_proc_pid_stat;
2469 # get VM status information
2470 # This must be fast and should not block ($full == false)
2471 # We only query KVM using QMP if $full == true (this can be slow)
2473 my ($opt_vmid, $full) = @_;
2477 my $storecfg = PVE
::Storage
::config
();
2479 my $list = vzlist
();
2480 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2482 my $cpucount = $cpuinfo->{cpus
} || 1;
2484 foreach my $vmid (keys %$list) {
2485 next if $opt_vmid && ($vmid ne $opt_vmid);
2487 my $cfspath = cfs_config_path
($vmid);
2488 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2491 $d->{pid
} = $list->{$vmid}->{pid
};
2493 # fixme: better status?
2494 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2496 my $size = disksize
($storecfg, $conf);
2497 if (defined($size)) {
2498 $d->{disk
} = 0; # no info available
2499 $d->{maxdisk
} = $size;
2505 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2506 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2507 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2509 $d->{name
} = $conf->{name
} || "VM $vmid";
2510 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2512 if ($conf->{balloon
}) {
2513 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2514 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2525 $d->{diskwrite
} = 0;
2527 $d->{template
} = is_template
($conf);
2532 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2533 foreach my $dev (keys %$netdev) {
2534 next if $dev !~ m/^tap([1-9]\d*)i/;
2536 my $d = $res->{$vmid};
2539 $d->{netout
} += $netdev->{$dev}->{receive
};
2540 $d->{netin
} += $netdev->{$dev}->{transmit
};
2543 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2544 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2549 my $ctime = gettimeofday
;
2551 foreach my $vmid (keys %$list) {
2553 my $d = $res->{$vmid};
2554 my $pid = $d->{pid
};
2557 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2558 next if !$pstat; # not running
2560 my $used = $pstat->{utime} + $pstat->{stime
};
2562 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2564 if ($pstat->{vsize
}) {
2565 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2568 my $old = $last_proc_pid_stat->{$pid};
2570 $last_proc_pid_stat->{$pid} = {
2578 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2580 if ($dtime > 1000) {
2581 my $dutime = $used - $old->{used
};
2583 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2584 $last_proc_pid_stat->{$pid} = {
2590 $d->{cpu
} = $old->{cpu
};
2594 return $res if !$full;
2596 my $qmpclient = PVE
::QMPClient-
>new();
2598 my $ballooncb = sub {
2599 my ($vmid, $resp) = @_;
2601 my $info = $resp->{'return'};
2602 return if !$info->{max_mem
};
2604 my $d = $res->{$vmid};
2606 # use memory assigned to VM
2607 $d->{maxmem
} = $info->{max_mem
};
2608 $d->{balloon
} = $info->{actual
};
2610 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2611 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2612 $d->{freemem
} = $info->{free_mem
};
2615 $d->{ballooninfo
} = $info;
2618 my $blockstatscb = sub {
2619 my ($vmid, $resp) = @_;
2620 my $data = $resp->{'return'} || [];
2621 my $totalrdbytes = 0;
2622 my $totalwrbytes = 0;
2624 for my $blockstat (@$data) {
2625 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2626 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2628 $blockstat->{device
} =~ s/drive-//;
2629 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2631 $res->{$vmid}->{diskread
} = $totalrdbytes;
2632 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2635 my $statuscb = sub {
2636 my ($vmid, $resp) = @_;
2638 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2639 # this fails if ballon driver is not loaded, so this must be
2640 # the last commnand (following command are aborted if this fails).
2641 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2643 my $status = 'unknown';
2644 if (!defined($status = $resp->{'return'}->{status
})) {
2645 warn "unable to get VM status\n";
2649 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2652 foreach my $vmid (keys %$list) {
2653 next if $opt_vmid && ($vmid ne $opt_vmid);
2654 next if !$res->{$vmid}->{pid
}; # not running
2655 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2658 $qmpclient->queue_execute(undef, 1);
2660 foreach my $vmid (keys %$list) {
2661 next if $opt_vmid && ($vmid ne $opt_vmid);
2662 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2669 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2672 my $current_size = 1024;
2673 my $dimm_size = 512;
2674 return if $current_size == $memory;
2676 for (my $j = 0; $j < 8; $j++) {
2677 for (my $i = 0; $i < 32; $i++) {
2678 my $name = "dimm${dimm_id}";
2680 my $numanode = $i % $sockets;
2681 $current_size += $dimm_size;
2682 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2683 return $current_size if $current_size >= $memory;
2689 sub foreach_reverse_dimm
{
2690 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2693 my $current_size = 4177920;
2694 my $dimm_size = 65536;
2695 return if $current_size == $memory;
2697 for (my $j = 0; $j < 8; $j++) {
2698 for (my $i = 0; $i < 32; $i++) {
2699 my $name = "dimm${dimm_id}";
2701 my $numanode = $i % $sockets;
2702 $current_size -= $dimm_size;
2703 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2704 return $current_size if $current_size <= $memory;
2711 my ($conf, $func) = @_;
2713 foreach my $ds (keys %$conf) {
2714 next if !valid_drivename
($ds);
2716 my $drive = parse_drive
($ds, $conf->{$ds});
2719 &$func($ds, $drive);
2724 my ($conf, $func) = @_;
2728 my $test_volid = sub {
2729 my ($volid, $is_cdrom) = @_;
2733 $volhash->{$volid} = $is_cdrom || 0;
2736 foreach_drive
($conf, sub {
2737 my ($ds, $drive) = @_;
2738 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2741 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2742 my $snap = $conf->{snapshots
}->{$snapname};
2743 &$test_volid($snap->{vmstate
}, 0);
2744 foreach_drive
($snap, sub {
2745 my ($ds, $drive) = @_;
2746 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2750 foreach my $volid (keys %$volhash) {
2751 &$func($volid, $volhash->{$volid});
2755 sub vga_conf_has_spice
{
2758 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2763 sub config_to_command
{
2764 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2767 my $globalFlags = [];
2768 my $machineFlags = [];
2774 my $kvmver = kvm_user_version
();
2775 my $vernum = 0; # unknown
2776 my $ostype = $conf->{ostype
};
2777 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2778 $vernum = $1*1000000+$2*1000;
2779 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2780 $vernum = $1*1000000+$2*1000+$3;
2783 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2785 my $have_ovz = -f
'/proc/vz/vestat';
2787 my $q35 = machine_type_is_q35
($conf);
2788 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2789 my $machine_type = $forcemachine || $conf->{machine
};
2790 my $use_old_bios_files = undef;
2791 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2793 my $cpuunits = defined($conf->{cpuunits
}) ?
2794 $conf->{cpuunits
} : $defaults->{cpuunits
};
2796 push @$cmd, '/usr/bin/systemd-run';
2797 push @$cmd, '--scope';
2798 push @$cmd, '--slice', "qemu";
2799 push @$cmd, '--unit', $vmid;
2800 # set KillMode=none, so that systemd don't kill those scopes
2801 # at shutdown (pve-manager service should stop the VMs instead)
2802 push @$cmd, '-p', "KillMode=none";
2803 push @$cmd, '-p', "CPUShares=$cpuunits";
2804 if ($conf->{cpulimit
}) {
2805 my $cpulimit = int($conf->{cpulimit
} * 100);
2806 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2809 push @$cmd, '/usr/bin/kvm';
2811 push @$cmd, '-id', $vmid;
2815 my $qmpsocket = qmp_socket
($vmid);
2816 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2817 push @$cmd, '-mon', "chardev=qmp,mode=control";
2820 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2822 push @$cmd, '-daemonize';
2824 if ($conf->{smbios1
}) {
2825 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2828 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2829 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2830 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2831 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2832 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2833 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2834 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2838 # the q35 chipset support native usb2, so we enable usb controller
2839 # by default for this machine type
2840 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2842 $pciaddr = print_pci_addr
("piix3", $bridges);
2843 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2846 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2847 next if !$conf->{"usb$i"};
2848 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2849 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2852 # include usb device config
2853 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2856 # add usb3 controller if needed
2859 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2860 next if !$conf->{"usb$i"};
2861 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2862 next if !$d || !$d->{usb3
};
2866 $pciaddr = print_pci_addr
("xhci", $bridges);
2867 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2869 my $vga = $conf->{vga
};
2871 my $qxlnum = vga_conf_has_spice
($vga);
2872 $vga = 'qxl' if $qxlnum;
2875 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2876 $conf->{ostype
} eq 'win7' ||
2877 $conf->{ostype
} eq 'w2k8')) {
2884 # enable absolute mouse coordinates (needed by vnc)
2886 if (defined($conf->{tablet
})) {
2887 $tablet = $conf->{tablet
};
2889 $tablet = $defaults->{tablet
};
2890 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2891 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2894 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2898 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2899 my $d = parse_hostpci
($conf->{"hostpci$i"});
2902 my $pcie = $d->{pcie
};
2904 die "q35 machine model is not enabled" if !$q35;
2905 $pciaddr = print_pcie_addr
("hostpci$i");
2907 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2910 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2911 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2912 if ($xvga && $xvga ne '') {
2915 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8') {
2916 push @$cpuFlags , 'hv_vendor_id=proxmox';
2918 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2922 my $pcidevices = $d->{pciid
};
2923 my $multifunction = 1 if @$pcidevices > 1;
2926 foreach my $pcidevice (@$pcidevices) {
2928 my $id = "hostpci$i";
2929 $id .= ".$j" if $multifunction;
2930 my $addr = $pciaddr;
2931 $addr .= ".$j" if $multifunction;
2932 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2935 $devicestr .= "$rombar$xvga";
2936 $devicestr .= ",multifunction=on" if $multifunction;
2939 push @$devices, '-device', $devicestr;
2945 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2946 next if !$conf->{"usb$i"};
2947 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2950 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2952 if (defined($d->{usb3
}) && $d->{usb3
}) {
2953 $usbbus = ',bus=xhci.0';
2956 if (defined($d->{host
})) {
2957 $d = parse_usb_device
($d->{host
});
2958 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2959 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2960 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2961 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2962 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2963 # usb redir support for spice, currently no usb3
2964 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2965 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2971 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2972 if (my $path = $conf->{"serial$i"}) {
2973 if ($path eq 'socket') {
2974 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2975 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2976 push @$devices, '-device', "isa-serial,chardev=serial$i";
2978 die "no such serial device\n" if ! -c
$path;
2979 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2980 push @$devices, '-device', "isa-serial,chardev=serial$i";
2986 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2987 if (my $path = $conf->{"parallel$i"}) {
2988 die "no such parallel device\n" if ! -c
$path;
2989 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2990 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2991 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2995 my $vmname = $conf->{name
} || "vm$vmid";
2997 push @$cmd, '-name', $vmname;
3000 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
3001 $sockets = $conf->{sockets
} if $conf->{sockets
};
3003 my $cores = $conf->{cores
} || 1;
3005 my $maxcpus = $sockets * $cores;
3007 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3009 my $allowed_vcpus = $cpuinfo->{cpus
};
3011 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3012 if ($allowed_vcpus < $maxcpus);
3014 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3016 push @$cmd, '-nodefaults';
3018 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3020 my $bootindex_hash = {};
3022 foreach my $o (split(//, $bootorder)) {
3023 $bootindex_hash->{$o} = $i*100;
3027 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
3029 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3031 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3033 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3035 if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
3036 my $socket = vnc_socket
($vmid);
3037 push @$cmd, '-vnc', "unix:$socket,x509,password";
3039 push @$cmd, '-nographic';
3043 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3045 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3046 my $useLocaltime = $conf->{localtime};
3049 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3051 if ($ostype =~ m/^w/) { # windows
3052 $useLocaltime = 1 if !defined($conf->{localtime});
3054 # use time drift fix when acpi is enabled
3055 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3056 $tdf = 1 if !defined($conf->{tdf
});
3060 if ($ostype eq 'win7' || $ostype eq 'win8' || $ostype eq 'w2k8' ||
3061 $ostype eq 'wvista') {
3062 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3063 push @$cmd, '-no-hpet';
3064 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3065 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
3066 push @$cpuFlags , 'hv_vapic' if !$nokvm;
3067 push @$cpuFlags , 'hv_time' if !$nokvm;
3070 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
3074 if ($ostype eq 'win7' || $ostype eq 'win8') {
3075 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
3079 push @$rtcFlags, 'driftfix=slew' if $tdf;
3082 push @$machineFlags, 'accel=tcg';
3084 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3087 if ($machine_type) {
3088 push @$machineFlags, "type=${machine_type}";
3091 if ($conf->{startdate
}) {
3092 push @$rtcFlags, "base=$conf->{startdate}";
3093 } elsif ($useLocaltime) {
3094 push @$rtcFlags, 'base=localtime';
3097 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3098 if (my $cputype = $conf->{cpu
}) {
3099 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpudesc, $cputype)
3100 or die "Cannot parse cpu description: $cputype\n";
3101 $cpu = $cpuconf->{cputype
};
3102 $kvm_off = 1 if $cpuconf->{hidden
};
3105 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3107 push @$cpuFlags , '-x2apic'
3108 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3110 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3112 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3114 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3116 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3117 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3120 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3122 push @$cpuFlags, 'kvm=off' if $kvm_off;
3124 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3126 push @$cmd, '-cpu', $cpu;
3128 my $memory = $conf->{memory
} || $defaults->{memory
};
3129 my $static_memory = 0;
3130 my $dimm_memory = 0;
3132 if ($hotplug_features->{memory
}) {
3133 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3134 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3135 $static_memory = $STATICMEM;
3136 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3137 $dimm_memory = $memory - $static_memory;
3138 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3142 $static_memory = $memory;
3143 push @$cmd, '-m', $static_memory;
3146 if ($conf->{numa
}) {
3148 my $numa_totalmemory = undef;
3149 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3150 next if !$conf->{"numa$i"};
3151 my $numa = parse_numa
($conf->{"numa$i"});
3154 die "missing numa node$i memory value\n" if !$numa->{memory
};
3155 my $numa_memory = $numa->{memory
};
3156 $numa_totalmemory += $numa_memory;
3157 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3160 my $cpus_start = $numa->{cpus
}->{start
};
3161 die "missing numa node$i cpus\n" if !defined($cpus_start);
3162 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3163 my $cpus = $cpus_start;
3164 if (defined($cpus_end)) {
3165 $cpus .= "-$cpus_end";
3166 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3170 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3171 if (defined($hostnodes_start)) {
3172 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3173 my $hostnodes = $hostnodes_start;
3174 if (defined($hostnodes_end)) {
3175 $hostnodes .= "-$hostnodes_end";
3176 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3179 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3180 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3181 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3185 my $policy = $numa->{policy
};
3186 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3187 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3190 push @$cmd, '-object', $numa_object;
3191 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3194 die "total memory for NUMA nodes must be equal to vm static memory\n"
3195 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3197 #if no custom tology, we split memory and cores across numa nodes
3198 if(!$numa_totalmemory) {
3200 my $numa_memory = ($static_memory / $sockets) . "M";
3202 for (my $i = 0; $i < $sockets; $i++) {
3204 my $cpustart = ($cores * $i);
3205 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3206 my $cpus = $cpustart;
3207 $cpus .= "-$cpuend" if $cpuend;
3209 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3210 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3215 if ($hotplug_features->{memory
}) {
3216 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3217 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3218 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3219 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3221 #if dimm_memory is not aligned to dimm map
3222 if($current_size > $memory) {
3223 $conf->{memory
} = $current_size;
3224 write_config
($vmid, $conf);
3229 push @$cmd, '-S' if $conf->{freeze
};
3231 # set keyboard layout
3232 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3233 push @$cmd, '-k', $kb if $kb;
3236 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3237 #push @$cmd, '-soundhw', 'es1370';
3238 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3240 if($conf->{agent
}) {
3241 my $qgasocket = qmp_socket
($vmid, 1);
3242 my $pciaddr = print_pci_addr
("qga0", $bridges);
3243 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3244 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3245 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3252 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3253 for(my $i = 1; $i < $qxlnum; $i++){
3254 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3255 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3258 # assume other OS works like Linux
3259 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3260 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3264 my $pciaddr = print_pci_addr
("spice", $bridges);
3266 my $nodename = PVE
::INotify
::nodename
();
3267 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3268 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3270 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3272 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3273 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3274 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3277 # enable balloon by default, unless explicitly disabled
3278 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3279 $pciaddr = print_pci_addr
("balloon0", $bridges);
3280 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3283 if ($conf->{watchdog
}) {
3284 my $wdopts = parse_watchdog
($conf->{watchdog
});
3285 $pciaddr = print_pci_addr
("watchdog", $bridges);
3286 my $watchdog = $wdopts->{model
} || 'i6300esb';
3287 push @$devices, '-device', "$watchdog$pciaddr";
3288 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3292 my $scsicontroller = {};
3293 my $ahcicontroller = {};
3294 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3296 # Add iscsi initiator name if available
3297 if (my $initiator = get_initiator_name
()) {
3298 push @$devices, '-iscsi', "initiator-name=$initiator";
3301 foreach_drive
($conf, sub {
3302 my ($ds, $drive) = @_;
3304 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3305 push @$vollist, $drive->{file
};
3308 $use_virtio = 1 if $ds =~ m/^virtio/;
3310 if (drive_is_cdrom
($drive)) {
3311 if ($bootindex_hash->{d
}) {
3312 $drive->{bootindex
} = $bootindex_hash->{d
};
3313 $bootindex_hash->{d
} += 1;
3316 if ($bootindex_hash->{c
}) {
3317 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3318 $bootindex_hash->{c
} += 1;
3322 if($drive->{interface
} eq 'virtio'){
3323 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3326 if ($drive->{interface
} eq 'scsi') {
3328 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3330 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3331 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3334 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3335 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3336 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3340 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3341 $queues = ",num_queues=$drive->{queues}";
3344 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3345 $scsicontroller->{$controller}=1;
3348 if ($drive->{interface
} eq 'sata') {
3349 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3350 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3351 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3352 $ahcicontroller->{$controller}=1;
3355 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3356 push @$devices, '-drive',$drive_cmd;
3357 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3360 for (my $i = 0; $i < $MAX_NETS; $i++) {
3361 next if !$conf->{"net$i"};
3362 my $d = parse_net
($conf->{"net$i"});
3365 $use_virtio = 1 if $d->{model
} eq 'virtio';
3367 if ($bootindex_hash->{n
}) {
3368 $d->{bootindex
} = $bootindex_hash->{n
};
3369 $bootindex_hash->{n
} += 1;
3372 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3373 push @$devices, '-netdev', $netdevfull;
3375 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3376 push @$devices, '-device', $netdevicefull;
3381 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3386 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3388 while (my ($k, $v) = each %$bridges) {
3389 $pciaddr = print_pci_addr
("pci.$k");
3390 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3395 if ($conf->{args
}) {
3396 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3400 push @$cmd, @$devices;
3401 push @$cmd, '-rtc', join(',', @$rtcFlags)
3402 if scalar(@$rtcFlags);
3403 push @$cmd, '-machine', join(',', @$machineFlags)
3404 if scalar(@$machineFlags);
3405 push @$cmd, '-global', join(',', @$globalFlags)
3406 if scalar(@$globalFlags);
3408 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3413 return "${var_run_tmpdir}/$vmid.vnc";
3419 my $res = vm_mon_cmd
($vmid, 'query-spice');
3421 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3425 my ($vmid, $qga) = @_;
3426 my $sockettype = $qga ?
'qga' : 'qmp';
3427 return "${var_run_tmpdir}/$vmid.$sockettype";
3432 return "${var_run_tmpdir}/$vmid.pid";
3435 sub vm_devices_list
{
3438 my $res = vm_mon_cmd
($vmid, 'query-pci');
3440 foreach my $pcibus (@$res) {
3441 foreach my $device (@{$pcibus->{devices
}}) {
3442 next if !$device->{'qdev_id'};
3443 if ($device->{'pci_bridge'}) {
3444 $devices->{$device->{'qdev_id'}} = 1;
3445 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3446 next if !$bridge_device->{'qdev_id'};
3447 $devices->{$bridge_device->{'qdev_id'}} = 1;
3448 $devices->{$device->{'qdev_id'}}++;
3451 $devices->{$device->{'qdev_id'}} = 1;
3456 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3457 foreach my $block (@$resblock) {
3458 if($block->{device
} =~ m/^drive-(\S+)/){
3463 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3464 foreach my $mice (@$resmice) {
3465 if ($mice->{name
} eq 'QEMU HID Tablet') {
3466 $devices->{tablet
} = 1;
3475 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3477 my $q35 = machine_type_is_q35
($conf);
3479 my $devices_list = vm_devices_list
($vmid);
3480 return 1 if defined($devices_list->{$deviceid});
3482 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3484 if ($deviceid eq 'tablet') {
3486 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3488 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3490 qemu_iothread_add
($vmid, $deviceid, $device);
3492 qemu_driveadd
($storecfg, $vmid, $device);
3493 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3495 qemu_deviceadd
($vmid, $devicefull);
3496 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3498 eval { qemu_drivedel
($vmid, $deviceid); };
3503 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3506 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3507 my $pciaddr = print_pci_addr
($deviceid);
3508 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3510 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3512 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3513 qemu_iothread_add
($vmid, $deviceid, $device);
3514 $devicefull .= ",iothread=iothread-$deviceid";
3517 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3518 $devicefull .= ",num_queues=$device->{queues}";
3521 qemu_deviceadd
($vmid, $devicefull);
3522 qemu_deviceaddverify
($vmid, $deviceid);
3524 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3526 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3527 qemu_driveadd
($storecfg, $vmid, $device);
3529 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3530 eval { qemu_deviceadd
($vmid, $devicefull); };
3532 eval { qemu_drivedel
($vmid, $deviceid); };
3537 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3539 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3541 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3542 my $use_old_bios_files = undef;
3543 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3545 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3546 qemu_deviceadd
($vmid, $netdevicefull);
3547 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3549 eval { qemu_netdevdel
($vmid, $deviceid); };
3554 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3557 my $pciaddr = print_pci_addr
($deviceid);
3558 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3560 qemu_deviceadd
($vmid, $devicefull);
3561 qemu_deviceaddverify
($vmid, $deviceid);
3564 die "can't hotplug device '$deviceid'\n";
3570 # fixme: this should raise exceptions on error!
3571 sub vm_deviceunplug
{
3572 my ($vmid, $conf, $deviceid) = @_;
3574 my $devices_list = vm_devices_list
($vmid);
3575 return 1 if !defined($devices_list->{$deviceid});
3577 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3579 if ($deviceid eq 'tablet') {
3581 qemu_devicedel
($vmid, $deviceid);
3583 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3585 qemu_devicedel
($vmid, $deviceid);
3586 qemu_devicedelverify
($vmid, $deviceid);
3587 qemu_drivedel
($vmid, $deviceid);
3588 qemu_iothread_del
($conf, $vmid, $deviceid);
3590 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3592 qemu_devicedel
($vmid, $deviceid);
3593 qemu_devicedelverify
($vmid, $deviceid);
3594 qemu_iothread_del
($conf, $vmid, $deviceid);
3596 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3598 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3599 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3600 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3602 qemu_devicedel
($vmid, $deviceid);
3603 qemu_drivedel
($vmid, $deviceid);
3604 qemu_deletescsihw
($conf, $vmid, $deviceid);
3606 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3608 qemu_devicedel
($vmid, $deviceid);
3609 qemu_devicedelverify
($vmid, $deviceid);
3610 qemu_netdevdel
($vmid, $deviceid);
3613 die "can't unplug device '$deviceid'\n";
3619 sub qemu_deviceadd
{
3620 my ($vmid, $devicefull) = @_;
3622 $devicefull = "driver=".$devicefull;
3623 my %options = split(/[=,]/, $devicefull);
3625 vm_mon_cmd
($vmid, "device_add" , %options);
3628 sub qemu_devicedel
{
3629 my ($vmid, $deviceid) = @_;
3631 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3634 sub qemu_iothread_add
{
3635 my($vmid, $deviceid, $device) = @_;
3637 if ($device->{iothread
}) {
3638 my $iothreads = vm_iothreads_list
($vmid);
3639 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3643 sub qemu_iothread_del
{
3644 my($conf, $vmid, $deviceid) = @_;
3646 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3647 if ($device->{iothread
}) {
3648 my $iothreads = vm_iothreads_list
($vmid);
3649 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3653 sub qemu_objectadd
{
3654 my($vmid, $objectid, $qomtype) = @_;
3656 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3661 sub qemu_objectdel
{
3662 my($vmid, $objectid) = @_;
3664 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3670 my ($storecfg, $vmid, $device) = @_;
3672 my $drive = print_drive_full
($storecfg, $vmid, $device);
3673 $drive =~ s/\\/\\\\/g;
3674 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3676 # If the command succeeds qemu prints: "OK
"
3677 return 1 if $ret =~ m/OK/s;
3679 die "adding drive failed
: $ret\n";
3683 my($vmid, $deviceid) = @_;
3685 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3688 return 1 if $ret eq "";
3690 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3691 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3693 die "deleting drive
$deviceid failed
: $ret\n";
3696 sub qemu_deviceaddverify {
3697 my ($vmid, $deviceid) = @_;
3699 for (my $i = 0; $i <= 5; $i++) {
3700 my $devices_list = vm_devices_list($vmid);
3701 return 1 if defined($devices_list->{$deviceid});
3705 die "error on hotplug device
'$deviceid'\n";
3709 sub qemu_devicedelverify {
3710 my ($vmid, $deviceid) = @_;
3712 # need to verify that the device is correctly removed as device_del
3713 # is async and empty return is not reliable
3715 for (my $i = 0; $i <= 5; $i++) {
3716 my $devices_list = vm_devices_list($vmid);
3717 return 1 if !defined($devices_list->{$deviceid});
3721 die "error on hot-unplugging device
'$deviceid'\n";
3724 sub qemu_findorcreatescsihw {
3725 my ($storecfg, $conf, $vmid, $device) = @_;
3727 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3729 my $scsihwid="$controller_prefix$controller";
3730 my $devices_list = vm_devices_list($vmid);
3732 if(!defined($devices_list->{$scsihwid})) {
3733 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3739 sub qemu_deletescsihw {
3740 my ($conf, $vmid, $opt) = @_;
3742 my $device = parse_drive($opt, $conf->{$opt});
3744 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3745 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3749 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3751 my $devices_list = vm_devices_list($vmid);
3752 foreach my $opt (keys %{$devices_list}) {
3753 if (PVE::QemuServer::valid_drivename($opt)) {
3754 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3755 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3761 my $scsihwid="scsihw
$controller";
3763 vm_deviceunplug($vmid, $conf, $scsihwid);
3768 sub qemu_add_pci_bridge {
3769 my ($storecfg, $conf, $vmid, $device) = @_;
3775 print_pci_addr($device, $bridges);
3777 while (my ($k, $v) = each %$bridges) {
3780 return 1 if !defined($bridgeid) || $bridgeid < 1;
3782 my $bridge = "pci
.$bridgeid";
3783 my $devices_list = vm_devices_list($vmid);
3785 if (!defined($devices_list->{$bridge})) {
3786 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3792 sub qemu_set_link_status {
3793 my ($vmid, $device, $up) = @_;
3795 vm_mon_cmd($vmid, "set_link
", name => $device,
3796 up => $up ? JSON::true : JSON::false);
3799 sub qemu_netdevadd {
3800 my ($vmid, $conf, $device, $deviceid) = @_;
3802 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3803 my %options = split(/[=,]/, $netdev);
3805 vm_mon_cmd($vmid, "netdev_add
", %options);
3809 sub qemu_netdevdel {
3810 my ($vmid, $deviceid) = @_;
3812 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3815 sub qemu_cpu_hotplug {
3816 my ($vmid, $conf, $vcpus) = @_;
3819 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3820 $sockets = $conf->{sockets} if $conf->{sockets};
3821 my $cores = $conf->{cores} || 1;
3822 my $maxcpus = $sockets * $cores;
3824 $vcpus = $maxcpus if !$vcpus;
3826 die "you can
't add more vcpus than maxcpus\n"
3827 if $vcpus > $maxcpus;
3829 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3830 die "online cpu unplug is not yet possible\n"
3831 if $vcpus < $currentvcpus;
3833 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3834 die "vcpus in running vm is different than configuration\n"
3835 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3837 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3838 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3842 sub qemu_memory_hotplug {
3843 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3845 return $value if !check_running($vmid);
3847 my $memory = $conf->{memory} || $defaults->{memory};
3848 $value = $defaults->{memory} if !$value;
3849 return $value if $value == $memory;
3851 my $static_memory = $STATICMEM;
3852 my $dimm_memory = $memory - $static_memory;
3854 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3855 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3859 $sockets = $conf->{sockets} if $conf->{sockets};
3861 if($value > $memory) {
3863 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3864 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3866 return if $current_size <= $conf->{memory};
3868 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3870 eval { qemu_objectdel($vmid, "mem-
$name"); };
3874 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3876 eval { qemu_objectdel($vmid, "mem-
$name"); };
3879 #update conf after each succesful module hotplug
3880 $conf->{memory} = $current_size;
3881 write_config($vmid, $conf);
3886 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3887 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3889 return if $current_size >= $conf->{memory};
3890 print "try to unplug memory dimm
$name\n";
3894 eval { qemu_devicedel($vmid, $name) };
3896 my $dimm_list = qemu_dimm_list($vmid);
3897 last if !$dimm_list->{$name};
3898 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3902 #update conf after each succesful module unplug
3903 $conf->{memory} = $current_size;
3905 eval { qemu_objectdel($vmid, "mem-
$name"); };
3906 write_config($vmid, $conf);
3911 sub qemu_dimm_list {
3914 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3917 foreach my $dimm (@$dimmarray) {
3919 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3920 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3921 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3922 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3923 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3928 sub qemu_block_set_io_throttle {
3929 my ($vmid, $deviceid,
3930 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3931 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3933 return if !check_running($vmid) ;
3935 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3937 bps_rd => int($bps_rd),
3938 bps_wr => int($bps_wr),
3940 iops_rd => int($iops_rd),
3941 iops_wr => int($iops_wr),
3942 bps_max => int($bps_max),
3943 bps_rd_max => int($bps_rd_max),
3944 bps_wr_max => int($bps_wr_max),
3945 iops_max => int($iops_max),
3946 iops_rd_max => int($iops_rd_max),
3947 iops_wr_max => int($iops_wr_max)
3952 # old code, only used to shutdown old VM after update
3954 my ($fh, $timeout) = @_;
3956 my $sel = new IO::Select;
3963 while (scalar (@ready = $sel->can_read($timeout))) {
3965 if ($count = $fh->sysread($buf, 8192)) {
3966 if ($buf =~ /^(.*)\(qemu\) $/s) {
3973 if (!defined($count)) {
3980 die "monitor
read timeout
\n" if !scalar(@ready);
3985 # old code, only used to shutdown old VM after update
3986 sub vm_monitor_command {
3987 my ($vmid, $cmdstr, $nocheck) = @_;
3992 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3994 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3996 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3997 die "unable to
connect to VM
$vmid socket - $!\n";
4001 # hack: migrate sometime blocks the monitor (when migrate_downtime
4003 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4004 $timeout = 60*60; # 1 hour
4008 my $data = __read_avail($sock, $timeout);
4010 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
4011 die "got unexpected qemu monitor banner
\n";
4014 my $sel = new IO::Select;
4017 if (!scalar(my @ready = $sel->can_write($timeout))) {
4018 die "monitor
write error
- timeout
";
4021 my $fullcmd = "$cmdstr\r";
4023 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
4026 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4027 die "monitor
write error
- $!";
4030 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
4034 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4035 $timeout = 60*60; # 1 hour
4036 } elsif ($cmdstr =~ m/^(eject|change)/) {
4037 $timeout = 60; # note: cdrom mount command is slow
4039 if ($res = __read_avail($sock, $timeout)) {
4041 my @lines = split("\r?
\n", $res);
4043 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4045 $res = join("\n", @lines);
4053 syslog("err
", "VM
$vmid monitor command failed
- $err");
4060 sub qemu_block_resize {
4061 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4063 my $running = check_running($vmid);
4065 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4067 return if !$running;
4069 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4073 sub qemu_volume_snapshot {
4074 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4076 my $running = check_running($vmid);
4078 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4079 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4081 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4085 sub qemu_volume_snapshot_delete {
4086 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4088 my $running = check_running($vmid);
4090 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4092 return if !$running;
4094 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4097 sub set_migration_caps {
4103 "auto-converge
" => 1,
4105 "x-rdma-pin-all
" => 0,
4110 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4112 for my $supported_capability (@$supported_capabilities) {
4114 capability => $supported_capability->{capability},
4115 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4119 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4122 my $fast_plug_option = {
4131 # hotplug changes in [PENDING]
4132 # $selection hash can be used to only apply specified options, for
4133 # example: { cores => 1 } (only apply changed 'cores')
4134 # $errors ref is used to return error messages
4135 sub vmconfig_hotplug_pending {
4136 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4138 my $defaults = load_defaults();
4140 # commit values which do not have any impact on running VM first
4141 # Note: those option cannot raise errors, we we do not care about
4142 # $selection and always apply them.
4144 my $add_error = sub {
4145 my ($opt, $msg) = @_;
4146 $errors->{$opt} = "hotplug problem
- $msg";
4150 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4151 if ($fast_plug_option->{$opt}) {
4152 $conf->{$opt} = $conf->{pending}->{$opt};
4153 delete $conf->{pending}->{$opt};
4159 write_config($vmid, $conf);
4160 $conf = load_config($vmid); # update/reload
4163 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4165 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4166 while (my ($opt, $force) = each %$pending_delete_hash) {
4167 next if $selection && !$selection->{$opt};
4169 if ($opt eq 'hotplug') {
4170 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4171 } elsif ($opt eq 'tablet') {
4172 die "skip
\n" if !$hotplug_features->{usb};
4173 if ($defaults->{tablet}) {
4174 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4176 vm_deviceunplug($vmid, $conf, $opt);
4178 } elsif ($opt eq 'vcpus') {
4179 die "skip
\n" if !$hotplug_features->{cpu};
4180 qemu_cpu_hotplug($vmid, $conf, undef);
4181 } elsif ($opt eq 'balloon') {
4182 # enable balloon device is not hotpluggable
4183 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4184 } elsif ($fast_plug_option->{$opt}) {
4186 } elsif ($opt =~ m/^net(\d+)$/) {
4187 die "skip
\n" if !$hotplug_features->{network};
4188 vm_deviceunplug($vmid, $conf, $opt);
4189 } elsif (valid_drivename($opt)) {
4190 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4191 vm_deviceunplug($vmid, $conf, $opt);
4192 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4193 } elsif ($opt =~ m/^memory$/) {
4194 die "skip
\n" if !$hotplug_features->{memory};
4195 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4196 } elsif ($opt eq 'cpuunits') {
4197 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4198 } elsif ($opt eq 'cpulimit') {
4199 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4205 &$add_error($opt, $err) if $err ne "skip
\n";
4207 # save new config if hotplug was successful
4208 delete $conf->{$opt};
4209 vmconfig_undelete_pending_option($conf, $opt);
4210 write_config($vmid, $conf);
4211 $conf = load_config($vmid); # update/reload
4215 foreach my $opt (keys %{$conf->{pending}}) {
4216 next if $selection && !$selection->{$opt};
4217 my $value = $conf->{pending}->{$opt};
4219 if ($opt eq 'hotplug') {
4220 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4221 } elsif ($opt eq 'tablet') {
4222 die "skip
\n" if !$hotplug_features->{usb};
4224 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4225 } elsif ($value == 0) {
4226 vm_deviceunplug($vmid, $conf, $opt);
4228 } elsif ($opt eq 'vcpus') {
4229 die "skip
\n" if !$hotplug_features->{cpu};
4230 qemu_cpu_hotplug($vmid, $conf, $value);
4231 } elsif ($opt eq 'balloon') {
4232 # enable/disable balloning device is not hotpluggable
4233 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4234 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4235 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4237 # allow manual ballooning if shares is set to zero
4238 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4239 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4240 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4242 } elsif ($opt =~ m/^net(\d+)$/) {
4243 # some changes can be done without hotplug
4244 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4245 $vmid, $opt, $value);
4246 } elsif (valid_drivename($opt)) {
4247 # some changes can be done without hotplug
4248 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4249 $vmid, $opt, $value, 1);
4250 } elsif ($opt =~ m/^memory$/) { #dimms
4251 die "skip
\n" if !$hotplug_features->{memory};
4252 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4253 } elsif ($opt eq 'cpuunits') {
4254 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4255 } elsif ($opt eq 'cpulimit') {
4256 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4257 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4259 die "skip
\n"; # skip non-hot-pluggable options
4263 &$add_error($opt, $err) if $err ne "skip
\n";
4265 # save new config if hotplug was successful
4266 $conf->{$opt} = $value;
4267 delete $conf->{pending}->{$opt};
4268 write_config($vmid, $conf);
4269 $conf = load_config($vmid); # update/reload
4274 sub try_deallocate_drive {
4275 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4277 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4278 my $volid = $drive->{file};
4279 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4280 my $sid = PVE::Storage::parse_volume_id($volid);
4281 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4283 # check if the disk is really unused
4284 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4285 if is_volume_in_use($storecfg, $conf, $key, $volid);
4286 PVE::Storage::vdisk_free($storecfg, $volid);
4289 # If vm is not owner of this disk remove from config
4297 sub vmconfig_delete_or_detach_drive {
4298 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4300 my $drive = parse_drive($opt, $conf->{$opt});
4302 my $rpcenv = PVE::RPCEnvironment::get();
4303 my $authuser = $rpcenv->get_user();
4306 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4307 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4309 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4313 sub vmconfig_apply_pending {
4314 my ($vmid, $conf, $storecfg) = @_;
4318 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4319 while (my ($opt, $force) = each %$pending_delete_hash) {
4320 die "internal error
" if $opt =~ m/^unused/;
4321 $conf = load_config($vmid); # update/reload
4322 if (!defined($conf->{$opt})) {
4323 vmconfig_undelete_pending_option($conf, $opt);
4324 write_config($vmid, $conf);
4325 } elsif (valid_drivename($opt)) {
4326 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4327 vmconfig_undelete_pending_option($conf, $opt);
4328 delete $conf->{$opt};
4329 write_config($vmid, $conf);
4331 vmconfig_undelete_pending_option($conf, $opt);
4332 delete $conf->{$opt};
4333 write_config($vmid, $conf);
4337 $conf = load_config($vmid); # update/reload
4339 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4340 $conf = load_config($vmid); # update/reload
4342 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4343 # skip if nothing changed
4344 } elsif (valid_drivename($opt)) {
4345 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4346 if defined($conf->{$opt});
4347 $conf->{$opt} = $conf->{pending}->{$opt};
4349 $conf->{$opt} = $conf->{pending}->{$opt};
4352 delete $conf->{pending}->{$opt};
4353 write_config($vmid, $conf);
4357 my $safe_num_ne = sub {
4360 return 0 if !defined($a) && !defined($b);
4361 return 1 if !defined($a);
4362 return 1 if !defined($b);
4367 my $safe_string_ne = sub {
4370 return 0 if !defined($a) && !defined($b);
4371 return 1 if !defined($a);
4372 return 1 if !defined($b);
4377 sub vmconfig_update_net {
4378 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4380 my $newnet = parse_net($value);
4382 if ($conf->{$opt}) {
4383 my $oldnet = parse_net($conf->{$opt});
4385 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4386 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4387 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4388 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4390 # for non online change, we try to hot-unplug
4391 die "skip
\n" if !$hotplug;
4392 vm_deviceunplug($vmid, $conf, $opt);
4395 die "internal error
" if $opt !~ m/net(\d+)/;
4396 my $iface = "tap
${vmid
}i
$1";
4398 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4399 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4402 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4403 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4404 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4405 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4406 PVE::Network::tap_unplug($iface);
4407 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks});
4410 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4411 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4419 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4425 sub vmconfig_update_disk {
4426 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4428 # fixme: do we need force?
4430 my $drive = parse_drive($opt, $value);
4432 if ($conf->{$opt}) {
4434 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4436 my $media = $drive->{media} || 'disk';
4437 my $oldmedia = $old_drive->{media} || 'disk';
4438 die "unable to change media type
\n" if $media ne $oldmedia;
4440 if (!drive_is_cdrom($old_drive)) {
4442 if ($drive->{file} ne $old_drive->{file}) {
4444 die "skip
\n" if !$hotplug;
4446 # unplug and register as unused
4447 vm_deviceunplug($vmid, $conf, $opt);
4448 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4451 # update existing disk
4453 # skip non hotpluggable value
4454 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4455 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4456 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4457 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4462 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4463 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4464 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4465 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4466 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4467 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4468 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4469 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4470 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4471 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4472 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4473 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4475 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4476 ($drive->{mbps} || 0)*1024*1024,
4477 ($drive->{mbps_rd} || 0)*1024*1024,
4478 ($drive->{mbps_wr} || 0)*1024*1024,
4479 $drive->{iops} || 0,
4480 $drive->{iops_rd} || 0,
4481 $drive->{iops_wr} || 0,
4482 ($drive->{mbps_max} || 0)*1024*1024,
4483 ($drive->{mbps_rd_max} || 0)*1024*1024,
4484 ($drive->{mbps_wr_max} || 0)*1024*1024,
4485 $drive->{iops_max} || 0,
4486 $drive->{iops_rd_max} || 0,
4487 $drive->{iops_wr_max} || 0);
4496 if ($drive->{file} eq 'none') {
4497 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4499 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4500 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4501 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4509 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4511 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4512 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4516 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4517 $forcemachine, $spice_ticket) = @_;
4519 lock_config($vmid, sub {
4520 my $conf = load_config($vmid, $migratedfrom);
4522 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4524 check_lock($conf) if !$skiplock;
4526 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4528 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4529 vmconfig_apply_pending($vmid, $conf, $storecfg);
4530 $conf = load_config($vmid); # update/reload
4533 my $defaults = load_defaults();
4535 # set environment variable useful inside network script
4536 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4538 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4540 my $migrate_port = 0;
4543 if ($statefile eq 'tcp') {
4544 my $localip = "localhost
";
4545 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4546 my $nodename = PVE::INotify::nodename();
4547 if ($datacenterconf->{migration_unsecure}) {
4548 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4549 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4551 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4552 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4553 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4554 push @$cmd, '-incoming', $migrate_uri;
4557 push @$cmd, '-loadstate', $statefile;
4564 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4565 my $d = parse_hostpci($conf->{"hostpci
$i"});
4567 my $pcidevices = $d->{pciid};
4568 foreach my $pcidevice (@$pcidevices) {
4569 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4571 my $info = pci_device_info("0000:$pciid");
4572 die "IOMMU
not present
\n" if !check_iommu_support();
4573 die "no pci device info
for device
'$pciid'\n" if !$info;
4574 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4575 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4579 PVE::Storage::activate_volumes($storecfg, $vollist);
4581 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4585 # deactivate volumes if start fails
4586 eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
4587 die "start failed
: $err";
4590 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4592 if ($statefile && $statefile ne 'tcp') {
4593 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4597 if ($migratedfrom) {
4600 set_migration_caps($vmid);
4605 print "spice listens on port
$spice_port\n";
4606 if ($spice_ticket) {
4607 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4608 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4614 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4615 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4616 if $conf->{balloon};
4619 foreach my $opt (keys %$conf) {
4620 next if $opt !~ m/^net\d+$/;
4621 my $nicconf = parse_net($conf->{$opt});
4622 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4626 vm_mon_cmd_nocheck($vmid, 'qom-set',
4627 path => "machine
/peripheral/balloon0
",
4628 property => "guest-stats-polling-interval
",
4629 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4635 my ($vmid, $execute, %params) = @_;
4637 my $cmd = { execute => $execute, arguments => \%params };
4638 vm_qmp_command($vmid, $cmd);
4641 sub vm_mon_cmd_nocheck {
4642 my ($vmid, $execute, %params) = @_;
4644 my $cmd = { execute => $execute, arguments => \%params };
4645 vm_qmp_command($vmid, $cmd, 1);
4648 sub vm_qmp_command {
4649 my ($vmid, $cmd, $nocheck) = @_;
4654 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4655 $timeout = $cmd->{arguments}->{timeout};
4656 delete $cmd->{arguments}->{timeout};
4660 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4661 my $sname = qmp_socket($vmid);
4662 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4663 my $qmpclient = PVE::QMPClient->new();
4665 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4666 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4667 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4668 if scalar(%{$cmd->{arguments}});
4669 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4671 die "unable to open monitor socket\n";
4675 syslog("err", "VM $vmid qmp command failed - $err");
4682 sub vm_human_monitor_command {
4683 my ($vmid, $cmdline) = @_;
4688 execute => 'human-monitor-command
',
4689 arguments => { 'command-line
' => $cmdline},
4692 return vm_qmp_command($vmid, $cmd);
4695 sub vm_commandline {
4696 my ($storecfg, $vmid) = @_;
4698 my $conf = load_config($vmid);
4700 my $defaults = load_defaults();
4702 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4704 return join(' ', @$cmd);
4708 my ($vmid, $skiplock) = @_;
4710 lock_config($vmid, sub {
4712 my $conf = load_config($vmid);
4714 check_lock($conf) if !$skiplock;
4716 vm_mon_cmd($vmid, "system_reset");
4720 sub get_vm_volumes {
4724 foreach_volid($conf, sub {
4725 my ($volid, $is_cdrom) = @_;
4727 return if $volid =~ m|^/|;
4729 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4732 push @$vollist, $volid;
4738 sub vm_stop_cleanup {
4739 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4744 my $vollist = get_vm_volumes($conf);
4745 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4748 foreach my $ext (qw(mon qmp pid vnc qga)) {
4749 unlink "/var/run/qemu-server/${vmid}.$ext";
4752 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4754 warn $@ if $@; # avoid errors - just warn
4757 # Note: use $nockeck to skip tests if VM configuration file exists.
4758 # We need that when migration VMs to other nodes (files already moved)
4759 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4761 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4763 $force = 1 if !defined($force) && !$shutdown;
4766 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4767 kill 15, $pid if $pid;
4768 my $conf = load_config
($vmid, $migratedfrom);
4769 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4773 lock_config
($vmid, sub {
4775 my $pid = check_running
($vmid, $nocheck);
4780 $conf = load_config
($vmid);
4781 check_lock
($conf) if !$skiplock;
4782 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4783 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4784 $timeout = $opts->{down
} if $opts->{down
};
4788 $timeout = 60 if !defined($timeout);
4792 if (defined($conf) && $conf->{agent
}) {
4793 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4795 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4798 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4805 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4810 if ($count >= $timeout) {
4812 warn "VM still running - terminating now with SIGTERM\n";
4815 die "VM quit/powerdown failed - got timeout\n";
4818 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4823 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4826 die "VM quit/powerdown failed\n";
4834 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4839 if ($count >= $timeout) {
4840 warn "VM still running - terminating now with SIGKILL\n";
4845 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4850 my ($vmid, $skiplock) = @_;
4852 lock_config
($vmid, sub {
4854 my $conf = load_config
($vmid);
4856 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4858 vm_mon_cmd
($vmid, "stop");
4863 my ($vmid, $skiplock, $nocheck) = @_;
4865 lock_config
($vmid, sub {
4869 my $conf = load_config
($vmid);
4871 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4873 vm_mon_cmd
($vmid, "cont");
4876 vm_mon_cmd_nocheck
($vmid, "cont");
4882 my ($vmid, $skiplock, $key) = @_;
4884 lock_config
($vmid, sub {
4886 my $conf = load_config
($vmid);
4888 # there is no qmp command, so we use the human monitor command
4889 vm_human_monitor_command
($vmid, "sendkey $key");
4894 my ($storecfg, $vmid, $skiplock) = @_;
4896 lock_config
($vmid, sub {
4898 my $conf = load_config
($vmid);
4900 if (!check_running
($vmid)) {
4901 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4903 die "VM $vmid is running - destroy failed\n";
4911 my ($filename, $buf) = @_;
4913 my $fh = IO
::File-
>new($filename, "w");
4914 return undef if !$fh;
4916 my $res = print $fh $buf;
4923 sub pci_device_info
{
4928 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4929 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4931 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4932 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4934 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4935 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4937 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4938 return undef if !defined($product) || $product !~ s/^0x//;
4943 product
=> $product,
4949 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4958 my $name = $dev->{name
};
4960 my $fn = "$pcisysfs/devices/$name/reset";
4962 return file_write
($fn, "1");
4965 sub pci_dev_bind_to_vfio
{
4968 my $name = $dev->{name
};
4970 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4972 if (!-d
$vfio_basedir) {
4973 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4975 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4977 my $testdir = "$vfio_basedir/$name";
4978 return 1 if -d
$testdir;
4980 my $data = "$dev->{vendor} $dev->{product}";
4981 return undef if !file_write
("$vfio_basedir/new_id", $data);
4983 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4984 if (!file_write
($fn, $name)) {
4985 return undef if -f
$fn;
4988 $fn = "$vfio_basedir/bind";
4989 if (! -d
$testdir) {
4990 return undef if !file_write
($fn, $name);
4996 sub pci_dev_group_bind_to_vfio
{
4999 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
5001 if (!-d
$vfio_basedir) {
5002 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
5004 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5006 # get IOMMU group devices
5007 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5008 my @devs = grep /^0000:/, readdir($D);
5011 foreach my $pciid (@devs) {
5012 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5014 # pci bridges, switches or root ports are not supported
5015 # they have a pci_bus subdirectory so skip them
5016 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5018 my $info = pci_device_info
($1);
5019 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5025 sub print_pci_addr
{
5026 my ($id, $bridges) = @_;
5030 piix3
=> { bus
=> 0, addr
=> 1 },
5031 #addr2 : first videocard
5032 balloon0
=> { bus
=> 0, addr
=> 3 },
5033 watchdog
=> { bus
=> 0, addr
=> 4 },
5034 scsihw0
=> { bus
=> 0, addr
=> 5 },
5035 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
5036 scsihw1
=> { bus
=> 0, addr
=> 6 },
5037 ahci0
=> { bus
=> 0, addr
=> 7 },
5038 qga0
=> { bus
=> 0, addr
=> 8 },
5039 spice
=> { bus
=> 0, addr
=> 9 },
5040 virtio0
=> { bus
=> 0, addr
=> 10 },
5041 virtio1
=> { bus
=> 0, addr
=> 11 },
5042 virtio2
=> { bus
=> 0, addr
=> 12 },
5043 virtio3
=> { bus
=> 0, addr
=> 13 },
5044 virtio4
=> { bus
=> 0, addr
=> 14 },
5045 virtio5
=> { bus
=> 0, addr
=> 15 },
5046 hostpci0
=> { bus
=> 0, addr
=> 16 },
5047 hostpci1
=> { bus
=> 0, addr
=> 17 },
5048 net0
=> { bus
=> 0, addr
=> 18 },
5049 net1
=> { bus
=> 0, addr
=> 19 },
5050 net2
=> { bus
=> 0, addr
=> 20 },
5051 net3
=> { bus
=> 0, addr
=> 21 },
5052 net4
=> { bus
=> 0, addr
=> 22 },
5053 net5
=> { bus
=> 0, addr
=> 23 },
5054 vga1
=> { bus
=> 0, addr
=> 24 },
5055 vga2
=> { bus
=> 0, addr
=> 25 },
5056 vga3
=> { bus
=> 0, addr
=> 26 },
5057 hostpci2
=> { bus
=> 0, addr
=> 27 },
5058 hostpci3
=> { bus
=> 0, addr
=> 28 },
5059 #addr29 : usb-host (pve-usb.cfg)
5060 'pci.1' => { bus
=> 0, addr
=> 30 },
5061 'pci.2' => { bus
=> 0, addr
=> 31 },
5062 'net6' => { bus
=> 1, addr
=> 1 },
5063 'net7' => { bus
=> 1, addr
=> 2 },
5064 'net8' => { bus
=> 1, addr
=> 3 },
5065 'net9' => { bus
=> 1, addr
=> 4 },
5066 'net10' => { bus
=> 1, addr
=> 5 },
5067 'net11' => { bus
=> 1, addr
=> 6 },
5068 'net12' => { bus
=> 1, addr
=> 7 },
5069 'net13' => { bus
=> 1, addr
=> 8 },
5070 'net14' => { bus
=> 1, addr
=> 9 },
5071 'net15' => { bus
=> 1, addr
=> 10 },
5072 'net16' => { bus
=> 1, addr
=> 11 },
5073 'net17' => { bus
=> 1, addr
=> 12 },
5074 'net18' => { bus
=> 1, addr
=> 13 },
5075 'net19' => { bus
=> 1, addr
=> 14 },
5076 'net20' => { bus
=> 1, addr
=> 15 },
5077 'net21' => { bus
=> 1, addr
=> 16 },
5078 'net22' => { bus
=> 1, addr
=> 17 },
5079 'net23' => { bus
=> 1, addr
=> 18 },
5080 'net24' => { bus
=> 1, addr
=> 19 },
5081 'net25' => { bus
=> 1, addr
=> 20 },
5082 'net26' => { bus
=> 1, addr
=> 21 },
5083 'net27' => { bus
=> 1, addr
=> 22 },
5084 'net28' => { bus
=> 1, addr
=> 23 },
5085 'net29' => { bus
=> 1, addr
=> 24 },
5086 'net30' => { bus
=> 1, addr
=> 25 },
5087 'net31' => { bus
=> 1, addr
=> 26 },
5088 'xhci' => { bus
=> 1, addr
=> 27 },
5089 'virtio6' => { bus
=> 2, addr
=> 1 },
5090 'virtio7' => { bus
=> 2, addr
=> 2 },
5091 'virtio8' => { bus
=> 2, addr
=> 3 },
5092 'virtio9' => { bus
=> 2, addr
=> 4 },
5093 'virtio10' => { bus
=> 2, addr
=> 5 },
5094 'virtio11' => { bus
=> 2, addr
=> 6 },
5095 'virtio12' => { bus
=> 2, addr
=> 7 },
5096 'virtio13' => { bus
=> 2, addr
=> 8 },
5097 'virtio14' => { bus
=> 2, addr
=> 9 },
5098 'virtio15' => { bus
=> 2, addr
=> 10 },
5099 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5100 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5101 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5102 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5103 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5104 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5105 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5106 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5107 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5108 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5109 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5110 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5111 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5112 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5113 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5114 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5115 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5116 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5117 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5118 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5119 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5120 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5121 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5122 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5123 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5124 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5125 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5126 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5127 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5128 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5129 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5133 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5134 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5135 my $bus = $devices->{$id}->{bus
};
5136 $res = ",bus=pci.$bus,addr=$addr";
5137 $bridges->{$bus} = 1 if $bridges;
5143 sub print_pcie_addr
{
5148 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5149 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5150 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5151 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5154 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5155 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5156 my $bus = $devices->{$id}->{bus
};
5157 $res = ",bus=$bus,addr=$addr";
5163 # vzdump restore implementaion
5165 sub tar_archive_read_firstfile
{
5166 my $archive = shift;
5168 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5170 # try to detect archive type first
5171 my $pid = open (TMP
, "tar tf '$archive'|") ||
5172 die "unable to open file '$archive'\n";
5173 my $firstfile = <TMP
>;
5177 die "ERROR: archive contaions no data\n" if !$firstfile;
5183 sub tar_restore_cleanup
{
5184 my ($storecfg, $statfile) = @_;
5186 print STDERR
"starting cleanup\n";
5188 if (my $fd = IO
::File-
>new($statfile, "r")) {
5189 while (defined(my $line = <$fd>)) {
5190 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5193 if ($volid =~ m
|^/|) {
5194 unlink $volid || die 'unlink failed\n';
5196 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5198 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5200 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5202 print STDERR
"unable to parse line in statfile - $line";
5209 sub restore_archive
{
5210 my ($archive, $vmid, $user, $opts) = @_;
5212 my $format = $opts->{format
};
5215 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5216 $format = 'tar' if !$format;
5218 } elsif ($archive =~ m/\.tar$/) {
5219 $format = 'tar' if !$format;
5220 } elsif ($archive =~ m/.tar.lzo$/) {
5221 $format = 'tar' if !$format;
5223 } elsif ($archive =~ m/\.vma$/) {
5224 $format = 'vma' if !$format;
5225 } elsif ($archive =~ m/\.vma\.gz$/) {
5226 $format = 'vma' if !$format;
5228 } elsif ($archive =~ m/\.vma\.lzo$/) {
5229 $format = 'vma' if !$format;
5232 $format = 'vma' if !$format; # default
5235 # try to detect archive format
5236 if ($format eq 'tar') {
5237 return restore_tar_archive
($archive, $vmid, $user, $opts);
5239 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5243 sub restore_update_config_line
{
5244 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5246 return if $line =~ m/^\#qmdump\#/;
5247 return if $line =~ m/^\#vzdump\#/;
5248 return if $line =~ m/^lock:/;
5249 return if $line =~ m/^unused\d+:/;
5250 return if $line =~ m/^parent:/;
5251 return if $line =~ m/^template:/; # restored VM is never a template
5253 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5254 # try to convert old 1.X settings
5255 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5256 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5257 my ($model, $macaddr) = split(/\=/, $devconfig);
5258 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5261 bridge
=> "vmbr$ind",
5262 macaddr
=> $macaddr,
5264 my $netstr = print_net
($net);
5266 print $outfd "net$cookie->{netcount}: $netstr\n";
5267 $cookie->{netcount
}++;
5269 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5270 my ($id, $netstr) = ($1, $2);
5271 my $net = parse_net
($netstr);
5272 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5273 $netstr = print_net
($net);
5274 print $outfd "$id: $netstr\n";
5275 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5278 my $di = parse_drive
($virtdev, $value);
5279 if (defined($di->{backup
}) && !$di->{backup
}) {
5280 print $outfd "#$line";
5281 } elsif ($map->{$virtdev}) {
5282 delete $di->{format
}; # format can change on restore
5283 $di->{file
} = $map->{$virtdev};
5284 $value = print_drive
($vmid, $di);
5285 print $outfd "$virtdev: $value\n";
5295 my ($cfg, $vmid) = @_;
5297 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5299 my $volid_hash = {};
5300 foreach my $storeid (keys %$info) {
5301 foreach my $item (@{$info->{$storeid}}) {
5302 next if !($item->{volid
} && $item->{size
});
5303 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5304 $volid_hash->{$item->{volid
}} = $item;
5311 sub is_volume_in_use
{
5312 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5314 my $path = PVE
::Storage
::path
($storecfg, $volid);
5316 my $scan_config = sub {
5317 my ($cref, $snapname) = @_;
5319 foreach my $key (keys %$cref) {
5320 my $value = $cref->{$key};
5321 if (valid_drivename
($key)) {
5322 next if $skip_drive && $key eq $skip_drive;
5323 my $drive = parse_drive
($key, $value);
5324 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5325 return 1 if $volid eq $drive->{file
};
5326 if ($drive->{file
} =~ m!^/!) {
5327 return 1 if $drive->{file
} eq $path;
5329 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5331 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5333 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5341 return 1 if &$scan_config($conf);
5345 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5346 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5352 sub update_disksize
{
5353 my ($vmid, $conf, $volid_hash) = @_;
5359 # Note: it is allowed to define multiple storages with same path (alias), so
5360 # we need to check both 'volid' and real 'path' (two different volid can point
5361 # to the same path).
5366 foreach my $opt (keys %$conf) {
5367 if (valid_drivename
($opt)) {
5368 my $drive = parse_drive
($opt, $conf->{$opt});
5369 my $volid = $drive->{file
};
5372 $used->{$volid} = 1;
5373 if ($volid_hash->{$volid} &&
5374 (my $path = $volid_hash->{$volid}->{path
})) {
5375 $usedpath->{$path} = 1;
5378 next if drive_is_cdrom
($drive);
5379 next if !$volid_hash->{$volid};
5381 $drive->{size
} = $volid_hash->{$volid}->{size
};
5382 my $new = print_drive
($vmid, $drive);
5383 if ($new ne $conf->{$opt}) {
5385 $conf->{$opt} = $new;
5390 # remove 'unusedX' entry if volume is used
5391 foreach my $opt (keys %$conf) {
5392 next if $opt !~ m/^unused\d+$/;
5393 my $volid = $conf->{$opt};
5394 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5395 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5397 delete $conf->{$opt};
5401 foreach my $volid (sort keys %$volid_hash) {
5402 next if $volid =~ m/vm-$vmid-state-/;
5403 next if $used->{$volid};
5404 my $path = $volid_hash->{$volid}->{path
};
5405 next if !$path; # just to be sure
5406 next if $usedpath->{$path};
5408 add_unused_volume
($conf, $volid);
5409 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5416 my ($vmid, $nolock) = @_;
5418 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5420 my $volid_hash = scan_volids
($cfg, $vmid);
5422 my $updatefn = sub {
5425 my $conf = load_config
($vmid);
5430 foreach my $volid (keys %$volid_hash) {
5431 my $info = $volid_hash->{$volid};
5432 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5435 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5437 write_config
($vmid, $conf) if $changes;
5440 if (defined($vmid)) {
5444 lock_config
($vmid, $updatefn, $vmid);
5447 my $vmlist = config_list
();
5448 foreach my $vmid (keys %$vmlist) {
5452 lock_config
($vmid, $updatefn, $vmid);
5458 sub restore_vma_archive
{
5459 my ($archive, $vmid, $user, $opts, $comp) = @_;
5461 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5462 my $readfrom = $archive;
5467 my $qarchive = PVE
::Tools
::shellquote
($archive);
5468 if ($comp eq 'gzip') {
5469 $uncomp = "zcat $qarchive|";
5470 } elsif ($comp eq 'lzop') {
5471 $uncomp = "lzop -d -c $qarchive|";
5473 die "unknown compression method '$comp'\n";
5478 my $tmpdir = "/var/tmp/vzdumptmp$$";
5481 # disable interrupts (always do cleanups)
5482 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5483 warn "got interrupt - ignored\n";
5486 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5487 POSIX
::mkfifo
($mapfifo, 0600);
5490 my $openfifo = sub {
5491 open($fifofh, '>', $mapfifo) || die $!;
5494 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5501 my $rpcenv = PVE
::RPCEnvironment
::get
();
5503 my $conffile = config_file
($vmid);
5504 my $tmpfn = "$conffile.$$.tmp";
5506 # Note: $oldconf is undef if VM does not exists
5507 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5509 my $print_devmap = sub {
5510 my $virtdev_hash = {};
5512 my $cfgfn = "$tmpdir/qemu-server.conf";
5514 # we can read the config - that is already extracted
5515 my $fh = IO
::File-
>new($cfgfn, "r") ||
5516 "unable to read qemu-server.conf - $!\n";
5518 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5520 my $pve_firewall_dir = '/etc/pve/firewall';
5521 mkdir $pve_firewall_dir; # make sure the dir exists
5522 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5525 while (defined(my $line = <$fh>)) {
5526 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5527 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5528 die "archive does not contain data for drive '$virtdev'\n"
5529 if !$devinfo->{$devname};
5530 if (defined($opts->{storage
})) {
5531 $storeid = $opts->{storage
} || 'local';
5532 } elsif (!$storeid) {
5535 $format = 'raw' if !$format;
5536 $devinfo->{$devname}->{devname
} = $devname;
5537 $devinfo->{$devname}->{virtdev
} = $virtdev;
5538 $devinfo->{$devname}->{format
} = $format;
5539 $devinfo->{$devname}->{storeid
} = $storeid;
5541 # check permission on storage
5542 my $pool = $opts->{pool
}; # todo: do we need that?
5543 if ($user ne 'root@pam') {
5544 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5547 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5551 foreach my $devname (keys %$devinfo) {
5552 die "found no device mapping information for device '$devname'\n"
5553 if !$devinfo->{$devname}->{virtdev
};
5556 my $cfg = cfs_read_file
('storage.cfg');
5558 # create empty/temp config
5560 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5561 foreach_drive
($oldconf, sub {
5562 my ($ds, $drive) = @_;
5564 return if drive_is_cdrom
($drive);
5566 my $volid = $drive->{file
};
5568 return if !$volid || $volid =~ m
|^/|;
5570 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5571 return if !$path || !$owner || ($owner != $vmid);
5573 # Note: only delete disk we want to restore
5574 # other volumes will become unused
5575 if ($virtdev_hash->{$ds}) {
5576 PVE
::Storage
::vdisk_free
($cfg, $volid);
5580 # delete vmstate files
5581 # since after the restore we have no snapshots anymore
5582 foreach my $snapname (keys %{$oldconf->{snapshots
}}) {
5583 my $snap = $oldconf->{snapshots
}->{$snapname};
5584 if ($snap->{vmstate
}) {
5585 eval { PVE
::Storage
::vdisk_free
($cfg, $snap->{vmstate
}); };
5594 foreach my $virtdev (sort keys %$virtdev_hash) {
5595 my $d = $virtdev_hash->{$virtdev};
5596 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5597 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5599 # test if requested format is supported
5600 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5601 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5602 $d->{format
} = $defFormat if !$supported;
5604 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5605 $d->{format
}, undef, $alloc_size);
5606 print STDERR
"new volume ID is '$volid'\n";
5607 $d->{volid
} = $volid;
5608 my $path = PVE
::Storage
::path
($cfg, $volid);
5610 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5612 my $write_zeros = 1;
5613 if (PVE
::Storage
::volume_has_feature
($cfg, 'sparseinit', $volid)) {
5617 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5619 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5620 $map->{$virtdev} = $volid;
5623 $fh->seek(0, 0) || die "seek failed - $!\n";
5625 my $outfd = new IO
::File
($tmpfn, "w") ||
5626 die "unable to write config for VM $vmid\n";
5628 my $cookie = { netcount
=> 0 };
5629 while (defined(my $line = <$fh>)) {
5630 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5639 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5640 die "interrupted by signal\n";
5642 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5644 $oldtimeout = alarm($timeout);
5651 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5652 my ($dev_id, $size, $devname) = ($1, $2, $3);
5653 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5654 } elsif ($line =~ m/^CTIME: /) {
5655 # we correctly received the vma config, so we can disable
5656 # the timeout now for disk allocation (set to 10 minutes, so
5657 # that we always timeout if something goes wrong)
5660 print $fifofh "done\n";
5661 my $tmp = $oldtimeout || 0;
5662 $oldtimeout = undef;
5668 print "restore vma archive: $cmd\n";
5669 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5673 alarm($oldtimeout) if $oldtimeout;
5676 foreach my $devname (keys %$devinfo) {
5677 my $volid = $devinfo->{$devname}->{volid
};
5678 push @$vollist, $volid if $volid;
5681 my $cfg = cfs_read_file
('storage.cfg');
5682 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5690 foreach my $devname (keys %$devinfo) {
5691 my $volid = $devinfo->{$devname}->{volid
};
5694 if ($volid =~ m
|^/|) {
5695 unlink $volid || die 'unlink failed\n';
5697 PVE
::Storage
::vdisk_free
($cfg, $volid);
5699 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5701 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5708 rename($tmpfn, $conffile) ||
5709 die "unable to commit configuration file '$conffile'\n";
5711 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5713 eval { rescan
($vmid, 1); };
5717 sub restore_tar_archive
{
5718 my ($archive, $vmid, $user, $opts) = @_;
5720 if ($archive ne '-') {
5721 my $firstfile = tar_archive_read_firstfile
($archive);
5722 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5723 if $firstfile ne 'qemu-server.conf';
5726 my $storecfg = cfs_read_file
('storage.cfg');
5728 # destroy existing data - keep empty config
5729 my $vmcfgfn = config_file
($vmid);
5730 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5732 my $tocmd = "/usr/lib/qemu-server/qmextract";
5734 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5735 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5736 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5737 $tocmd .= ' --info' if $opts->{info
};
5739 # tar option "xf" does not autodetect compression when read from STDIN,
5740 # so we pipe to zcat
5741 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5742 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5744 my $tmpdir = "/var/tmp/vzdumptmp$$";
5747 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5748 local $ENV{VZDUMP_VMID
} = $vmid;
5749 local $ENV{VZDUMP_USER
} = $user;
5751 my $conffile = config_file
($vmid);
5752 my $tmpfn = "$conffile.$$.tmp";
5754 # disable interrupts (always do cleanups)
5755 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5756 print STDERR
"got interrupt - ignored\n";
5761 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5762 die "interrupted by signal\n";
5765 if ($archive eq '-') {
5766 print "extracting archive from STDIN\n";
5767 run_command
($cmd, input
=> "<&STDIN");
5769 print "extracting archive '$archive'\n";
5773 return if $opts->{info
};
5777 my $statfile = "$tmpdir/qmrestore.stat";
5778 if (my $fd = IO
::File-
>new($statfile, "r")) {
5779 while (defined (my $line = <$fd>)) {
5780 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5781 $map->{$1} = $2 if $1;
5783 print STDERR
"unable to parse line in statfile - $line\n";
5789 my $confsrc = "$tmpdir/qemu-server.conf";
5791 my $srcfd = new IO
::File
($confsrc, "r") ||
5792 die "unable to open file '$confsrc'\n";
5794 my $outfd = new IO
::File
($tmpfn, "w") ||
5795 die "unable to write config for VM $vmid\n";
5797 my $cookie = { netcount
=> 0 };
5798 while (defined (my $line = <$srcfd>)) {
5799 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5811 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5818 rename $tmpfn, $conffile ||
5819 die "unable to commit configuration file '$conffile'\n";
5821 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5823 eval { rescan
($vmid, 1); };
5828 # Internal snapshots
5830 # NOTE: Snapshot create/delete involves several non-atomic
5831 # action, and can take a long time.
5832 # So we try to avoid locking the file and use 'lock' variable
5833 # inside the config file instead.
5835 my $snapshot_copy_config = sub {
5836 my ($source, $dest) = @_;
5838 foreach my $k (keys %$source) {
5839 next if $k eq 'snapshots';
5840 next if $k eq 'snapstate';
5841 next if $k eq 'snaptime';
5842 next if $k eq 'vmstate';
5843 next if $k eq 'lock';
5844 next if $k eq 'digest';
5845 next if $k eq 'description';
5846 next if $k =~ m/^unused\d+$/;
5848 $dest->{$k} = $source->{$k};
5852 my $snapshot_apply_config = sub {
5853 my ($conf, $snap) = @_;
5855 # copy snapshot list
5857 snapshots
=> $conf->{snapshots
},
5860 # keep description and list of unused disks
5861 foreach my $k (keys %$conf) {
5862 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5863 $newconf->{$k} = $conf->{$k};
5866 &$snapshot_copy_config($snap, $newconf);
5871 sub foreach_writable_storage
{
5872 my ($conf, $func) = @_;
5876 foreach my $ds (keys %$conf) {
5877 next if !valid_drivename
($ds);
5879 my $drive = parse_drive
($ds, $conf->{$ds});
5881 next if drive_is_cdrom
($drive);
5883 my $volid = $drive->{file
};
5885 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5886 $sidhash->{$sid} = $sid if $sid;
5889 foreach my $sid (sort keys %$sidhash) {
5894 my $alloc_vmstate_volid = sub {
5895 my ($storecfg, $vmid, $conf, $snapname) = @_;
5897 # Note: we try to be smart when selecting a $target storage
5901 # search shared storage first
5902 foreach_writable_storage
($conf, sub {
5904 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5905 return if !$scfg->{shared
};
5907 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5911 # now search local storage
5912 foreach_writable_storage
($conf, sub {
5914 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5915 return if $scfg->{shared
};
5917 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5921 $target = 'local' if !$target;
5923 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5924 # we abort live save after $conf->{memory}, so we need at max twice that space
5925 my $size = $conf->{memory
}*2 + $driver_state_size;
5927 my $name = "vm-$vmid-state-$snapname";
5928 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5929 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5930 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5935 sub snapshot_save_vmstate
{
5936 my ($vmid, $conf, $snapname, $storecfg) = @_;
5938 my $snap = $conf->{snapshots
}->{$snapname};
5940 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5941 # always overwrite machine if we save vmstate. This makes sure we
5942 # can restore it later using correct machine type
5943 $snap->{machine
} = get_current_qemu_machine
($vmid);
5946 sub snapshot_prepare
{
5947 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5951 my $updatefn = sub {
5953 my $conf = load_config
($vmid);
5955 die "you can't take a snapshot if it's a template\n"
5956 if is_template
($conf);
5960 $conf->{lock} = 'snapshot';
5962 die "snapshot name '$snapname' already used\n"
5963 if defined($conf->{snapshots
}->{$snapname});
5965 my $storecfg = PVE
::Storage
::config
();
5966 die "snapshot feature is not available\n"
5967 if !has_feature
('snapshot', $conf, $storecfg, undef, undef, $snapname eq 'vzdump');
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, $backup_only) = @_;
6373 foreach_drive
($conf, sub {
6374 my ($ds, $drive) = @_;
6376 return if drive_is_cdrom
($drive);
6377 return if $backup_only && !$drive->{backup
};
6378 my $volid = $drive->{file
};
6379 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6382 return $err ?
0 : 1;
6385 sub template_create
{
6386 my ($vmid, $conf, $disk) = @_;
6388 my $storecfg = PVE
::Storage
::config
();
6390 foreach_drive
($conf, sub {
6391 my ($ds, $drive) = @_;
6393 return if drive_is_cdrom
($drive);
6394 return if $disk && $ds ne $disk;
6396 my $volid = $drive->{file
};
6397 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6399 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6400 $drive->{file
} = $voliddst;
6401 $conf->{$ds} = print_drive
($vmid, $drive);
6402 write_config
($vmid, $conf);
6409 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6412 sub qemu_img_convert
{
6413 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6415 my $storecfg = PVE
::Storage
::config
();
6416 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6417 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6419 if ($src_storeid && $dst_storeid) {
6421 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6423 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6424 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6426 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6427 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6429 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6430 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6433 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6434 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6435 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6439 if($line =~ m/\((\S+)\/100\
%\)/){
6441 my $transferred = int($size * $percent / 100);
6442 my $remaining = $size - $transferred;
6444 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6449 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6451 die "copy failed: $err" if $err;
6455 sub qemu_img_format
{
6456 my ($scfg, $volname) = @_;
6458 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6465 sub qemu_drive_mirror
{
6466 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6468 my $storecfg = PVE
::Storage
::config
();
6469 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6471 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6473 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6475 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6477 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6478 $opts->{format
} = $format if $format;
6480 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6483 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6485 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6486 my $stat = @$stats[0];
6487 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6488 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6490 my $busy = $stat->{busy
};
6491 my $ready = $stat->{ready
};
6493 if (my $total = $stat->{len
}) {
6494 my $transferred = $stat->{offset
} || 0;
6495 my $remaining = $total - $transferred;
6496 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6498 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6502 if ($stat->{ready
} eq 'true') {
6504 last if $vmiddst != $vmid;
6506 # try to switch the disk if source and destination are on the same guest
6507 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6509 die $@ if $@ !~ m/cannot be completed/;
6518 my $cancel_job = sub {
6519 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6521 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6522 my $stat = @$stats[0];
6529 eval { &$cancel_job(); };
6530 die "mirroring error: $err";
6533 if ($vmiddst != $vmid) {
6534 # if we clone a disk for a new target vm, we don't switch the disk
6535 &$cancel_job(); # so we call block-job-cancel
6540 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6541 $newvmid, $storage, $format, $full, $newvollist) = @_;
6546 print "create linked clone of drive $drivename ($drive->{file})\n";
6547 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6548 push @$newvollist, $newvolid;
6550 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6551 $storeid = $storage if $storage;
6553 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6555 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6556 $format = qemu_img_format
($scfg, $volname);
6559 # test if requested format is supported - else use default
6560 my $supported = grep { $_ eq $format } @$validFormats;
6561 $format = $defFormat if !$supported;
6563 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6565 print "create full clone of drive $drivename ($drive->{file})\n";
6566 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6567 push @$newvollist, $newvolid;
6569 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6571 if (!$running || $snapname) {
6572 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6574 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6578 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6581 $disk->{format
} = undef;
6582 $disk->{file
} = $newvolid;
6583 $disk->{size
} = $size;
6588 # this only works if VM is running
6589 sub get_current_qemu_machine
{
6592 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6593 my $res = vm_qmp_command
($vmid, $cmd);
6595 my ($current, $default);
6596 foreach my $e (@$res) {
6597 $default = $e->{name
} if $e->{'is-default'};
6598 $current = $e->{name
} if $e->{'is-current'};
6601 # fallback to the default machine if current is not supported by qemu
6602 return $current || $default || 'pc';
6605 sub qemu_machine_feature_enabled
{
6606 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6611 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6613 $current_major = $3;
6614 $current_minor = $4;
6616 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6618 $current_major = $1;
6619 $current_minor = $2;
6622 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6627 sub qemu_machine_pxe
{
6628 my ($vmid, $conf, $machine) = @_;
6630 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6632 foreach my $opt (keys %$conf) {
6633 next if $opt !~ m/^net(\d+)$/;
6634 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6636 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6637 return $machine.".pxe" if $romfile =~ m/pxe/;
6644 sub qemu_use_old_bios_files
{
6645 my ($machine_type) = @_;
6647 return if !$machine_type;
6649 my $use_old_bios_files = undef;
6651 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6653 $use_old_bios_files = 1;
6655 my $kvmver = kvm_user_version
();
6656 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6657 # load new efi bios files on migration. So this hack is required to allow
6658 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6659 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6660 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 4);
6663 return ($use_old_bios_files, $machine_type);
6670 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6671 my (undef, $id, $function) = @_;
6672 my $res = { id
=> $id, function
=> $function};
6673 push @{$devices->{$id}}, $res;
6679 sub vm_iothreads_list
{
6682 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6685 foreach my $iothread (@$res) {
6686 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6693 my ($conf, $drive) = @_;
6697 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6699 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6705 my $controller = int($drive->{index} / $maxdev);
6706 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6708 return ($maxdev, $controller, $controller_prefix);
6711 # bash completion helper
6713 sub complete_backup_archives
{
6714 my ($cmdname, $pname, $cvalue) = @_;
6716 my $cfg = PVE
::Storage
::config
();
6720 if ($cvalue =~ m/^([^:]+):/) {
6724 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6727 foreach my $id (keys %$data) {
6728 foreach my $item (@{$data->{$id}}) {
6729 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6730 push @$res, $item->{volid
} if defined($item->{volid
});
6737 my $complete_vmid_full = sub {
6740 my $idlist = vmstatus
();
6744 foreach my $id (keys %$idlist) {
6745 my $d = $idlist->{$id};
6746 if (defined($running)) {
6747 next if $d->{template
};
6748 next if $running && $d->{status
} ne 'running';
6749 next if !$running && $d->{status
} eq 'running';
6758 return &$complete_vmid_full();
6761 sub complete_vmid_stopped
{
6762 return &$complete_vmid_full(0);
6765 sub complete_vmid_running
{
6766 return &$complete_vmid_full(1);
6769 sub complete_storage
{
6771 my $cfg = PVE
::Storage
::config
();
6772 my $ids = $cfg->{ids
};
6775 foreach my $sid (keys %$ids) {
6776 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6777 next if !$ids->{$sid}->{content
}->{images
};