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';
886 my $tmp = `kvm -help 2>/dev/null`;
888 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
889 $kvm_user_version = $2;
892 return $kvm_user_version;
896 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
899 # order is important - used to autoselect boot disk
900 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
901 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
902 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
903 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
906 sub valid_drivename
{
909 return defined($drivename_hash->{$dev});
914 return defined($confdesc->{$key});
918 return $nic_model_list;
921 sub os_list_description
{
926 w2k
=> 'Windows 2000',
927 w2k3
=>, 'Windows 2003',
928 w2k8
=> 'Windows 2008',
929 wvista
=> 'Windows Vista',
931 win8
=> 'Windows 8/2012',
941 return $cdrom_path if $cdrom_path;
943 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
944 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
945 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
949 my ($storecfg, $vmid, $cdrom) = @_;
951 if ($cdrom eq 'cdrom') {
952 return get_cdrom_path
();
953 } elsif ($cdrom eq 'none') {
955 } elsif ($cdrom =~ m
|^/|) {
958 return PVE
::Storage
::path
($storecfg, $cdrom);
962 # try to convert old style file names to volume IDs
963 sub filename_to_volume_id
{
964 my ($vmid, $file, $media) = @_;
966 if (!($file eq 'none' || $file eq 'cdrom' ||
967 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
969 return undef if $file =~ m
|/|;
971 if ($media && $media eq 'cdrom') {
972 $file = "local:iso/$file";
974 $file = "local:$vmid/$file";
981 sub verify_media_type
{
982 my ($opt, $vtype, $media) = @_;
987 if ($media eq 'disk') {
989 } elsif ($media eq 'cdrom') {
992 die "internal error";
995 return if ($vtype eq $etype);
997 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
1000 sub cleanup_drive_path
{
1001 my ($opt, $storecfg, $drive) = @_;
1003 # try to convert filesystem paths to volume IDs
1005 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
1006 ($drive->{file
} !~ m
|^/dev/.+|) &&
1007 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
1008 ($drive->{file
} !~ m/^\d+$/)) {
1009 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
1010 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
1011 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
1012 verify_media_type
($opt, $vtype, $drive->{media
});
1013 $drive->{file
} = $volid;
1016 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
1019 sub create_conf_nolock
{
1020 my ($vmid, $settings) = @_;
1022 my $filename = config_file
($vmid);
1024 die "configuration file '$filename' already exists\n" if -f
$filename;
1026 my $defaults = load_defaults
();
1028 $settings->{name
} = "vm$vmid" if !$settings->{name
};
1029 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
1032 foreach my $opt (keys %$settings) {
1033 next if !$confdesc->{$opt};
1035 my $value = $settings->{$opt};
1038 $data .= "$opt: $value\n";
1041 PVE
::Tools
::file_set_contents
($filename, $data);
1044 sub parse_hotplug_features
{
1049 return $res if $data eq '0';
1051 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1053 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1054 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1057 warn "ignoring unknown hotplug feature '$feature'\n";
1063 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1064 sub pve_verify_hotplug_features
{
1065 my ($value, $noerr) = @_;
1067 return $value if parse_hotplug_features
($value);
1069 return undef if $noerr;
1071 die "unable to parse hotplug option\n";
1074 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1075 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1076 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1077 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1078 # [,iothread=on][,serial=serial][,model=model]
1081 my ($key, $data) = @_;
1083 my ($interface, $index);
1085 if ($key =~ m/^([^\d]+)(\d+)$/) {
1092 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1093 : $confdesc->{$key}->{format
};
1095 warn "invalid drive key: $key\n";
1098 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1099 return undef if !$res;
1100 $res->{interface
} = $interface;
1101 $res->{index} = $index;
1104 foreach my $opt (qw(bps bps_rd bps_wr)) {
1105 if (my $bps = defined(delete $res->{$opt})) {
1106 if (defined($res->{"m$opt"})) {
1107 warn "both $opt and m$opt specified\n";
1111 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1114 return undef if $error;
1116 return undef if $res->{mbps_rd
} && $res->{mbps
};
1117 return undef if $res->{mbps_wr
} && $res->{mbps
};
1118 return undef if $res->{iops_rd
} && $res->{iops
};
1119 return undef if $res->{iops_wr
} && $res->{iops
};
1121 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1122 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1123 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1124 return undef if $res->{interface
} eq 'virtio';
1127 if (my $size = $res->{size
}) {
1128 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1135 my ($vmid, $drive) = @_;
1136 my $data = { %$drive };
1137 delete $data->{$_} for qw(index interface);
1138 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1142 my($fh, $noerr) = @_;
1145 my $SG_GET_VERSION_NUM = 0x2282;
1147 my $versionbuf = "\x00" x
8;
1148 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1150 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1153 my $version = unpack("I", $versionbuf);
1154 if ($version < 30000) {
1155 die "scsi generic interface too old\n" if !$noerr;
1159 my $buf = "\x00" x
36;
1160 my $sensebuf = "\x00" x
8;
1161 my $cmd = pack("C x3 C x1", 0x12, 36);
1163 # see /usr/include/scsi/sg.h
1164 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";
1166 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1167 length($sensebuf), 0, length($buf), $buf,
1168 $cmd, $sensebuf, 6000);
1170 $ret = ioctl($fh, $SG_IO, $packet);
1172 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1176 my @res = unpack($sg_io_hdr_t, $packet);
1177 if ($res[17] || $res[18]) {
1178 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1183 (my $byte0, my $byte1, $res->{vendor
},
1184 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1186 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1187 $res->{type
} = $byte0 & 31;
1195 my $fh = IO
::File-
>new("+<$path") || return undef;
1196 my $res = scsi_inquiry
($fh, 1);
1202 sub machine_type_is_q35
{
1205 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1208 sub print_tabletdevice_full
{
1211 my $q35 = machine_type_is_q35
($conf);
1213 # we use uhci for old VMs because tablet driver was buggy in older qemu
1214 my $usbbus = $q35 ?
"ehci" : "uhci";
1216 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1219 sub print_drivedevice_full
{
1220 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1225 if ($drive->{interface
} eq 'virtio') {
1226 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1227 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1228 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1229 } elsif ($drive->{interface
} eq 'scsi') {
1231 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1232 my $unit = $drive->{index} % $maxdev;
1233 my $devicetype = 'hd';
1235 if (drive_is_cdrom
($drive)) {
1238 if ($drive->{file
} =~ m
|^/|) {
1239 $path = $drive->{file
};
1241 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1244 if($path =~ m/^iscsi\:\/\
//){
1245 $devicetype = 'generic';
1247 if (my $info = path_is_scsi
($path)) {
1248 if ($info->{type
} == 0) {
1249 $devicetype = 'block';
1250 } elsif ($info->{type
} == 1) { # tape
1251 $devicetype = 'generic';
1257 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1258 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1260 $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}";
1263 } elsif ($drive->{interface
} eq 'ide'){
1265 my $controller = int($drive->{index} / $maxdev);
1266 my $unit = $drive->{index} % $maxdev;
1267 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1269 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1270 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1271 $device .= ",model=$model";
1273 } elsif ($drive->{interface
} eq 'sata'){
1274 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1275 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1276 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1277 } elsif ($drive->{interface
} eq 'usb') {
1279 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1281 die "unsupported interface type";
1284 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1289 sub get_initiator_name
{
1292 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1293 while (defined(my $line = <$fh>)) {
1294 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1303 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);
1304 sub print_drive_full
{
1305 my ($storecfg, $vmid, $drive) = @_;
1308 my $volid = $drive->{file
};
1311 if (drive_is_cdrom
($drive)) {
1312 $path = get_iso_path
($storecfg, $vmid, $volid);
1314 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1316 $path = PVE
::Storage
::path
($storecfg, $volid);
1317 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1318 $format = qemu_img_format
($scfg, $volname);
1326 foreach my $o (@qemu_drive_options) {
1327 next if $o eq 'bootindex';
1328 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1331 $opts .= ",format=$format" if $format && !$drive->{format
};
1333 foreach my $o (qw(bps bps_rd bps_wr)) {
1334 my $v = $drive->{"m$o"};
1335 $opts .= ",$o=" . int($v*1024*1024) if $v;
1338 my $cache_direct = 0;
1340 if (my $cache = $drive->{cache
}) {
1341 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1342 } elsif (!drive_is_cdrom
($drive)) {
1343 $opts .= ",cache=none";
1347 # aio native works only with O_DIRECT
1348 if (!$drive->{aio
}) {
1350 $opts .= ",aio=native";
1352 $opts .= ",aio=threads";
1356 if (!drive_is_cdrom
($drive)) {
1358 if (defined($drive->{detect_zeroes
}) && !$drive->{detect_zeroes
}) {
1359 $detectzeroes = 'off';
1360 } elsif ($drive->{discard
}) {
1361 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1363 # This used to be our default with discard not being specified:
1364 $detectzeroes = 'on';
1366 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1369 my $pathinfo = $path ?
"file=$path," : '';
1371 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1374 sub print_netdevice_full
{
1375 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1377 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1379 my $device = $net->{model
};
1380 if ($net->{model
} eq 'virtio') {
1381 $device = 'virtio-net-pci';
1384 my $pciaddr = print_pci_addr
("$netid", $bridges);
1385 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1386 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1387 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1388 my $vectors = $net->{queues
} * 2 + 2;
1389 $tmpstr .= ",vectors=$vectors,mq=on";
1391 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1393 if ($use_old_bios_files) {
1395 if ($device eq 'virtio-net-pci') {
1396 $romfile = 'pxe-virtio.rom';
1397 } elsif ($device eq 'e1000') {
1398 $romfile = 'pxe-e1000.rom';
1399 } elsif ($device eq 'ne2k') {
1400 $romfile = 'pxe-ne2k_pci.rom';
1401 } elsif ($device eq 'pcnet') {
1402 $romfile = 'pxe-pcnet.rom';
1403 } elsif ($device eq 'rtl8139') {
1404 $romfile = 'pxe-rtl8139.rom';
1406 $tmpstr .= ",romfile=$romfile" if $romfile;
1412 sub print_netdev_full
{
1413 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1416 if ($netid =~ m/^net(\d+)$/) {
1420 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1422 my $ifname = "tap${vmid}i$i";
1424 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1425 die "interface name '$ifname' is too long (max 15 character)\n"
1426 if length($ifname) >= 16;
1428 my $vhostparam = '';
1429 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1431 my $vmname = $conf->{name
} || "vm$vmid";
1434 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1436 if ($net->{bridge
}) {
1437 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1439 $netdev = "type=user,id=$netid,hostname=$vmname";
1442 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1447 sub drive_is_cdrom
{
1450 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1459 foreach my $kvp (split(/,/, $data)) {
1461 if ($kvp =~ m/^memory=(\S+)$/) {
1462 $res->{memory
} = $1;
1463 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1464 $res->{policy
} = $1;
1465 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1466 $res->{cpus
}->{start
} = $1;
1467 $res->{cpus
}->{end
} = $3;
1468 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1469 $res->{hostnodes
}->{start
} = $1;
1470 $res->{hostnodes
}->{end
} = $3;
1482 return undef if !$value;
1485 my @list = split(/,/, $value);
1489 foreach my $kv (@list) {
1491 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1494 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1497 my $pcidevices = lspci
($2);
1498 $res->{pciid
} = $pcidevices->{$2};
1500 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1501 $res->{rombar
} = $1;
1502 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1503 $res->{'x-vga'} = $1;
1504 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1505 $res->{pcie
} = 1 if $1 == 1;
1507 warn "unknown hostpci setting '$kv'\n";
1511 return undef if !$found;
1516 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1522 foreach my $kvp (split(/,/, $data)) {
1524 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) {
1526 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1527 $res->{model
} = $model;
1528 $res->{macaddr
} = $mac;
1529 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1530 $res->{bridge
} = $1;
1531 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1532 $res->{queues
} = $1;
1533 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1535 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1537 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1538 $res->{trunks
} = $1;
1539 } elsif ($kvp =~ m/^firewall=([01])$/) {
1540 $res->{firewall
} = $1;
1541 } elsif ($kvp =~ m/^link_down=([01])$/) {
1542 $res->{link_down
} = $1;
1549 return undef if !$res->{model
};
1557 my $res = "$net->{model}";
1558 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1559 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1560 $res .= ",rate=$net->{rate}" if $net->{rate
};
1561 $res .= ",tag=$net->{tag}" if $net->{tag
};
1562 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1563 $res .= ",firewall=1" if $net->{firewall
};
1564 $res .= ",link_down=1" if $net->{link_down
};
1565 $res .= ",queues=$net->{queues}" if $net->{queues
};
1570 sub add_random_macs
{
1571 my ($settings) = @_;
1573 foreach my $opt (keys %$settings) {
1574 next if $opt !~ m/^net(\d+)$/;
1575 my $net = parse_net
($settings->{$opt});
1577 $settings->{$opt} = print_net
($net);
1581 sub add_unused_volume
{
1582 my ($config, $volid) = @_;
1585 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1586 my $test = "unused$ind";
1587 if (my $vid = $config->{$test}) {
1588 return if $vid eq $volid; # do not add duplicates
1594 die "To many unused volume - please delete them first.\n" if !$key;
1596 $config->{$key} = $volid;
1601 sub vm_is_volid_owner
{
1602 my ($storecfg, $vmid, $volid) = @_;
1604 if ($volid !~ m
|^/|) {
1606 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1607 if ($owner && ($owner == $vmid)) {
1615 sub split_flagged_list
{
1616 my $text = shift || '';
1617 $text =~ s/[,;]/ /g;
1619 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1622 sub join_flagged_list
{
1623 my ($how, $lst) = @_;
1624 join $how, map { $lst->{$_} . $_ } keys %$lst;
1627 sub vmconfig_delete_pending_option
{
1628 my ($conf, $key, $force) = @_;
1630 delete $conf->{pending
}->{$key};
1631 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1632 $pending_delete_hash->{$key} = $force ?
'!' : '';
1633 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1636 sub vmconfig_undelete_pending_option
{
1637 my ($conf, $key) = @_;
1639 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1640 delete $pending_delete_hash->{$key};
1642 if (%$pending_delete_hash) {
1643 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1645 delete $conf->{pending
}->{delete};
1649 sub vmconfig_register_unused_drive
{
1650 my ($storecfg, $vmid, $conf, $drive) = @_;
1652 if (!drive_is_cdrom
($drive)) {
1653 my $volid = $drive->{file
};
1654 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1655 add_unused_volume
($conf, $volid, $vmid);
1660 sub vmconfig_cleanup_pending
{
1663 # remove pending changes when nothing changed
1665 foreach my $opt (keys %{$conf->{pending
}}) {
1666 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1668 delete $conf->{pending
}->{$opt};
1672 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1673 my $pending_delete_hash = {};
1674 while (my ($opt, $force) = each %$current_delete_hash) {
1675 if (defined($conf->{$opt})) {
1676 $pending_delete_hash->{$opt} = $force;
1682 if (%$pending_delete_hash) {
1683 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1685 delete $conf->{pending
}->{delete};
1691 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1692 my $smbios1_desc = {
1695 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1696 format_description
=> 'UUID',
1702 format_description
=> 'str',
1708 format_description
=> 'str',
1714 format_description
=> 'name',
1720 format_description
=> 'name',
1726 format_description
=> 'str',
1732 format_description
=> 'str',
1740 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_desc, $data) };
1747 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_desc);
1750 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_desc);
1752 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1753 sub verify_bootdisk
{
1754 my ($value, $noerr) = @_;
1756 return $value if valid_drivename
($value);
1758 return undef if $noerr;
1760 die "invalid boot disk '$value'\n";
1763 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1765 my ($value, $noerr) = @_;
1767 return $value if parse_numa
($value);
1769 return undef if $noerr;
1771 die "unable to parse numa options\n";
1774 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1776 my ($value, $noerr) = @_;
1778 return $value if parse_net
($value);
1780 return undef if $noerr;
1782 die "unable to parse network options\n";
1785 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1786 sub verify_hostpci
{
1787 my ($value, $noerr) = @_;
1789 return $value if parse_hostpci
($value);
1791 return undef if $noerr;
1793 die "unable to parse pci id\n";
1796 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1797 sub verify_watchdog
{
1798 my ($value, $noerr) = @_;
1800 return $value if parse_watchdog
($value);
1802 return undef if $noerr;
1804 die "unable to parse watchdog options\n";
1807 sub parse_watchdog
{
1810 return undef if !$value;
1814 foreach my $p (split(/,/, $value)) {
1815 next if $p =~ m/^\s*$/;
1817 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1819 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1820 $res->{action
} = $2;
1829 sub parse_usb_device
{
1832 return undef if !$value;
1835 if ($value =~ m/^(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1836 $res->{vendorid
} = $2;
1837 $res->{productid
} = $4;
1838 } elsif ($value =~ m/^(\d+)\-(\d+(\.\d+)*)$/) {
1839 $res->{hostbus
} = $1;
1840 $res->{hostport
} = $2;
1841 } elsif ($value =~ m/^spice$/i) {
1850 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1851 sub verify_usb_device
{
1852 my ($value, $noerr) = @_;
1854 return $value if parse_usb_device
($value);
1856 return undef if $noerr;
1858 die "unable to parse usb device\n";
1861 # add JSON properties for create and set function
1862 sub json_config_properties
{
1865 foreach my $opt (keys %$confdesc) {
1866 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1867 $prop->{$opt} = $confdesc->{$opt};
1874 my ($key, $value) = @_;
1876 die "unknown setting '$key'\n" if !$confdesc->{$key};
1878 my $type = $confdesc->{$key}->{type
};
1880 if (!defined($value)) {
1881 die "got undefined value\n";
1884 if ($value =~ m/[\n\r]/) {
1885 die "property contains a line feed\n";
1888 if ($type eq 'boolean') {
1889 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1890 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1891 die "type check ('boolean') failed - got '$value'\n";
1892 } elsif ($type eq 'integer') {
1893 return int($1) if $value =~ m/^(\d+)$/;
1894 die "type check ('integer') failed - got '$value'\n";
1895 } elsif ($type eq 'number') {
1896 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1897 die "type check ('number') failed - got '$value'\n";
1898 } elsif ($type eq 'string') {
1899 if (my $fmt = $confdesc->{$key}->{format
}) {
1900 if ($fmt eq 'pve-qm-drive') {
1901 # special case - we need to pass $key to parse_drive()
1902 my $drive = parse_drive
($key, $value);
1903 return $value if $drive;
1904 die "unable to parse drive options\n";
1906 PVE
::JSONSchema
::check_format
($fmt, $value);
1909 $value =~ s/^\"(.*)\"$/$1/;
1912 die "internal error"
1916 sub lock_config_full
{
1917 my ($vmid, $timeout, $code, @param) = @_;
1919 my $filename = config_file_lock
($vmid);
1921 my $res = lock_file
($filename, $timeout, $code, @param);
1928 sub lock_config_mode
{
1929 my ($vmid, $timeout, $shared, $code, @param) = @_;
1931 my $filename = config_file_lock
($vmid);
1933 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1941 my ($vmid, $code, @param) = @_;
1943 return lock_config_full
($vmid, 10, $code, @param);
1946 sub cfs_config_path
{
1947 my ($vmid, $node) = @_;
1949 $node = $nodename if !$node;
1950 return "nodes/$node/qemu-server/$vmid.conf";
1953 sub check_iommu_support
{
1954 #fixme : need to check IOMMU support
1955 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1963 my ($vmid, $node) = @_;
1965 my $cfspath = cfs_config_path
($vmid, $node);
1966 return "/etc/pve/$cfspath";
1969 sub config_file_lock
{
1972 return "$lock_dir/lock-$vmid.conf";
1978 my $conf = config_file
($vmid);
1979 utime undef, undef, $conf;
1983 my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
1985 my $conffile = config_file
($vmid);
1987 my $conf = load_config
($vmid);
1989 check_lock
($conf) if !$skiplock;
1991 # only remove disks owned by this VM
1992 foreach_drive
($conf, sub {
1993 my ($ds, $drive) = @_;
1995 return if drive_is_cdrom
($drive);
1997 my $volid = $drive->{file
};
1999 return if !$volid || $volid =~ m
|^/|;
2001 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
2002 return if !$path || !$owner || ($owner != $vmid);
2004 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2007 if ($keep_empty_config) {
2008 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
2013 # also remove unused disk
2015 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
2018 PVE
::Storage
::foreach_volid
($dl, sub {
2019 my ($volid, $sid, $volname, $d) = @_;
2020 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2030 my ($vmid, $node) = @_;
2032 my $cfspath = cfs_config_path
($vmid, $node);
2034 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
2036 die "no such VM ('$vmid')\n" if !defined($conf);
2041 sub parse_vm_config
{
2042 my ($filename, $raw) = @_;
2044 return undef if !defined($raw);
2047 digest
=> Digest
::SHA
::sha1_hex
($raw),
2052 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2053 || die "got strange filename '$filename'";
2061 my @lines = split(/\n/, $raw);
2062 foreach my $line (@lines) {
2063 next if $line =~ m/^\s*$/;
2065 if ($line =~ m/^\[PENDING\]\s*$/i) {
2066 $section = 'pending';
2067 if (defined($descr)) {
2069 $conf->{description
} = $descr;
2072 $conf = $res->{$section} = {};
2075 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2077 if (defined($descr)) {
2079 $conf->{description
} = $descr;
2082 $conf = $res->{snapshots
}->{$section} = {};
2086 if ($line =~ m/^\#(.*)\s*$/) {
2087 $descr = '' if !defined($descr);
2088 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2092 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2093 $descr = '' if !defined($descr);
2094 $descr .= PVE
::Tools
::decode_text
($2);
2095 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2096 $conf->{snapstate
} = $1;
2097 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2100 $conf->{$key} = $value;
2101 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2103 if ($section eq 'pending') {
2104 $conf->{delete} = $value; # we parse this later
2106 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2108 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2111 eval { $value = check_type
($key, $value); };
2113 warn "vm $vmid - unable to parse value of '$key' - $@";
2115 my $fmt = $confdesc->{$key}->{format
};
2116 if ($fmt && $fmt eq 'pve-qm-drive') {
2117 my $v = parse_drive
($key, $value);
2118 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2119 $v->{file
} = $volid;
2120 $value = print_drive
($vmid, $v);
2122 warn "vm $vmid - unable to parse value of '$key'\n";
2127 if ($key eq 'cdrom') {
2128 $conf->{ide2
} = $value;
2130 $conf->{$key} = $value;
2136 if (defined($descr)) {
2138 $conf->{description
} = $descr;
2140 delete $res->{snapstate
}; # just to be sure
2145 sub write_vm_config
{
2146 my ($filename, $conf) = @_;
2148 delete $conf->{snapstate
}; # just to be sure
2150 if ($conf->{cdrom
}) {
2151 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2152 $conf->{ide2
} = $conf->{cdrom
};
2153 delete $conf->{cdrom
};
2156 # we do not use 'smp' any longer
2157 if ($conf->{sockets
}) {
2158 delete $conf->{smp
};
2159 } elsif ($conf->{smp
}) {
2160 $conf->{sockets
} = $conf->{smp
};
2161 delete $conf->{cores
};
2162 delete $conf->{smp
};
2165 my $used_volids = {};
2167 my $cleanup_config = sub {
2168 my ($cref, $pending, $snapname) = @_;
2170 foreach my $key (keys %$cref) {
2171 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2172 $key eq 'snapstate' || $key eq 'pending';
2173 my $value = $cref->{$key};
2174 if ($key eq 'delete') {
2175 die "propertry 'delete' is only allowed in [PENDING]\n"
2177 # fixme: check syntax?
2180 eval { $value = check_type
($key, $value); };
2181 die "unable to parse value of '$key' - $@" if $@;
2183 $cref->{$key} = $value;
2185 if (!$snapname && valid_drivename
($key)) {
2186 my $drive = parse_drive
($key, $value);
2187 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2192 &$cleanup_config($conf);
2194 &$cleanup_config($conf->{pending
}, 1);
2196 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2197 die "internal error" if $snapname eq 'pending';
2198 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2201 # remove 'unusedX' settings if we re-add a volume
2202 foreach my $key (keys %$conf) {
2203 my $value = $conf->{$key};
2204 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2205 delete $conf->{$key};
2209 my $generate_raw_config = sub {
2210 my ($conf, $pending) = @_;
2214 # add description as comment to top of file
2215 if (defined(my $descr = $conf->{description
})) {
2217 foreach my $cl (split(/\n/, $descr)) {
2218 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2221 $raw .= "#\n" if $pending;
2225 foreach my $key (sort keys %$conf) {
2226 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2227 $raw .= "$key: $conf->{$key}\n";
2232 my $raw = &$generate_raw_config($conf);
2234 if (scalar(keys %{$conf->{pending
}})){
2235 $raw .= "\n[PENDING]\n";
2236 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2239 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2240 $raw .= "\n[$snapname]\n";
2241 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2247 sub update_config_nolock
{
2248 my ($vmid, $conf, $skiplock) = @_;
2250 check_lock
($conf) if !$skiplock;
2252 my $cfspath = cfs_config_path
($vmid);
2254 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2258 my ($vmid, $conf, $skiplock) = @_;
2260 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2267 # we use static defaults from our JSON schema configuration
2268 foreach my $key (keys %$confdesc) {
2269 if (defined(my $default = $confdesc->{$key}->{default})) {
2270 $res->{$key} = $default;
2274 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2275 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2281 my $vmlist = PVE
::Cluster
::get_vmlist
();
2283 return $res if !$vmlist || !$vmlist->{ids
};
2284 my $ids = $vmlist->{ids
};
2286 foreach my $vmid (keys %$ids) {
2287 my $d = $ids->{$vmid};
2288 next if !$d->{node
} || $d->{node
} ne $nodename;
2289 next if !$d->{type
} || $d->{type
} ne 'qemu';
2290 $res->{$vmid}->{exists} = 1;
2295 # test if VM uses local resources (to prevent migration)
2296 sub check_local_resources
{
2297 my ($conf, $noerr) = @_;
2301 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2302 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2304 foreach my $k (keys %$conf) {
2305 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2306 # sockets are safe: they will recreated be on the target side post-migrate
2307 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2308 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2311 die "VM uses local resources\n" if $loc_res && !$noerr;
2316 # check if used storages are available on all nodes (use by migrate)
2317 sub check_storage_availability
{
2318 my ($storecfg, $conf, $node) = @_;
2320 foreach_drive
($conf, sub {
2321 my ($ds, $drive) = @_;
2323 my $volid = $drive->{file
};
2326 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2329 # check if storage is available on both nodes
2330 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2331 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2335 # list nodes where all VM images are available (used by has_feature API)
2337 my ($conf, $storecfg) = @_;
2339 my $nodelist = PVE
::Cluster
::get_nodelist
();
2340 my $nodehash = { map { $_ => 1 } @$nodelist };
2341 my $nodename = PVE
::INotify
::nodename
();
2343 foreach_drive
($conf, sub {
2344 my ($ds, $drive) = @_;
2346 my $volid = $drive->{file
};
2349 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2351 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2352 if ($scfg->{disable
}) {
2354 } elsif (my $avail = $scfg->{nodes
}) {
2355 foreach my $node (keys %$nodehash) {
2356 delete $nodehash->{$node} if !$avail->{$node};
2358 } elsif (!$scfg->{shared
}) {
2359 foreach my $node (keys %$nodehash) {
2360 delete $nodehash->{$node} if $node ne $nodename
2372 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2376 my ($pidfile, $pid) = @_;
2378 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2382 return undef if !$line;
2383 my @param = split(/\0/, $line);
2385 my $cmd = $param[0];
2386 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2388 for (my $i = 0; $i < scalar (@param); $i++) {
2391 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2392 my $p = $param[$i+1];
2393 return 1 if $p && ($p eq $pidfile);
2402 my ($vmid, $nocheck, $node) = @_;
2404 my $filename = config_file
($vmid, $node);
2406 die "unable to find configuration file for VM $vmid - no such machine\n"
2407 if !$nocheck && ! -f
$filename;
2409 my $pidfile = pidfile_name
($vmid);
2411 if (my $fd = IO
::File-
>new("<$pidfile")) {
2416 my $mtime = $st->mtime;
2417 if ($mtime > time()) {
2418 warn "file '$filename' modified in future\n";
2421 if ($line =~ m/^(\d+)$/) {
2423 if (check_cmdline
($pidfile, $pid)) {
2424 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2436 my $vzlist = config_list
();
2438 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2440 while (defined(my $de = $fd->read)) {
2441 next if $de !~ m/^(\d+)\.pid$/;
2443 next if !defined($vzlist->{$vmid});
2444 if (my $pid = check_running
($vmid)) {
2445 $vzlist->{$vmid}->{pid
} = $pid;
2453 my ($storecfg, $conf) = @_;
2455 my $bootdisk = $conf->{bootdisk
};
2456 return undef if !$bootdisk;
2457 return undef if !valid_drivename
($bootdisk);
2459 return undef if !$conf->{$bootdisk};
2461 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2462 return undef if !defined($drive);
2464 return undef if drive_is_cdrom
($drive);
2466 my $volid = $drive->{file
};
2467 return undef if !$volid;
2469 return $drive->{size
};
2472 my $last_proc_pid_stat;
2474 # get VM status information
2475 # This must be fast and should not block ($full == false)
2476 # We only query KVM using QMP if $full == true (this can be slow)
2478 my ($opt_vmid, $full) = @_;
2482 my $storecfg = PVE
::Storage
::config
();
2484 my $list = vzlist
();
2485 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2487 my $cpucount = $cpuinfo->{cpus
} || 1;
2489 foreach my $vmid (keys %$list) {
2490 next if $opt_vmid && ($vmid ne $opt_vmid);
2492 my $cfspath = cfs_config_path
($vmid);
2493 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2496 $d->{pid
} = $list->{$vmid}->{pid
};
2498 # fixme: better status?
2499 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2501 my $size = disksize
($storecfg, $conf);
2502 if (defined($size)) {
2503 $d->{disk
} = 0; # no info available
2504 $d->{maxdisk
} = $size;
2510 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2511 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2512 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2514 $d->{name
} = $conf->{name
} || "VM $vmid";
2515 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2517 if ($conf->{balloon
}) {
2518 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2519 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2530 $d->{diskwrite
} = 0;
2532 $d->{template
} = is_template
($conf);
2537 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2538 foreach my $dev (keys %$netdev) {
2539 next if $dev !~ m/^tap([1-9]\d*)i/;
2541 my $d = $res->{$vmid};
2544 $d->{netout
} += $netdev->{$dev}->{receive
};
2545 $d->{netin
} += $netdev->{$dev}->{transmit
};
2548 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2549 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2554 my $ctime = gettimeofday
;
2556 foreach my $vmid (keys %$list) {
2558 my $d = $res->{$vmid};
2559 my $pid = $d->{pid
};
2562 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2563 next if !$pstat; # not running
2565 my $used = $pstat->{utime} + $pstat->{stime
};
2567 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2569 if ($pstat->{vsize
}) {
2570 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2573 my $old = $last_proc_pid_stat->{$pid};
2575 $last_proc_pid_stat->{$pid} = {
2583 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2585 if ($dtime > 1000) {
2586 my $dutime = $used - $old->{used
};
2588 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2589 $last_proc_pid_stat->{$pid} = {
2595 $d->{cpu
} = $old->{cpu
};
2599 return $res if !$full;
2601 my $qmpclient = PVE
::QMPClient-
>new();
2603 my $ballooncb = sub {
2604 my ($vmid, $resp) = @_;
2606 my $info = $resp->{'return'};
2607 return if !$info->{max_mem
};
2609 my $d = $res->{$vmid};
2611 # use memory assigned to VM
2612 $d->{maxmem
} = $info->{max_mem
};
2613 $d->{balloon
} = $info->{actual
};
2615 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2616 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2617 $d->{freemem
} = $info->{free_mem
};
2620 $d->{ballooninfo
} = $info;
2623 my $blockstatscb = sub {
2624 my ($vmid, $resp) = @_;
2625 my $data = $resp->{'return'} || [];
2626 my $totalrdbytes = 0;
2627 my $totalwrbytes = 0;
2629 for my $blockstat (@$data) {
2630 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2631 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2633 $blockstat->{device
} =~ s/drive-//;
2634 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2636 $res->{$vmid}->{diskread
} = $totalrdbytes;
2637 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2640 my $statuscb = sub {
2641 my ($vmid, $resp) = @_;
2643 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2644 # this fails if ballon driver is not loaded, so this must be
2645 # the last commnand (following command are aborted if this fails).
2646 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2648 my $status = 'unknown';
2649 if (!defined($status = $resp->{'return'}->{status
})) {
2650 warn "unable to get VM status\n";
2654 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2657 foreach my $vmid (keys %$list) {
2658 next if $opt_vmid && ($vmid ne $opt_vmid);
2659 next if !$res->{$vmid}->{pid
}; # not running
2660 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2663 $qmpclient->queue_execute(undef, 1);
2665 foreach my $vmid (keys %$list) {
2666 next if $opt_vmid && ($vmid ne $opt_vmid);
2667 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2674 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2677 my $current_size = 1024;
2678 my $dimm_size = 512;
2679 return if $current_size == $memory;
2681 for (my $j = 0; $j < 8; $j++) {
2682 for (my $i = 0; $i < 32; $i++) {
2683 my $name = "dimm${dimm_id}";
2685 my $numanode = $i % $sockets;
2686 $current_size += $dimm_size;
2687 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2688 return $current_size if $current_size >= $memory;
2694 sub foreach_reverse_dimm
{
2695 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2698 my $current_size = 4177920;
2699 my $dimm_size = 65536;
2700 return if $current_size == $memory;
2702 for (my $j = 0; $j < 8; $j++) {
2703 for (my $i = 0; $i < 32; $i++) {
2704 my $name = "dimm${dimm_id}";
2706 my $numanode = $i % $sockets;
2707 $current_size -= $dimm_size;
2708 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2709 return $current_size if $current_size <= $memory;
2716 my ($conf, $func) = @_;
2718 foreach my $ds (keys %$conf) {
2719 next if !valid_drivename
($ds);
2721 my $drive = parse_drive
($ds, $conf->{$ds});
2724 &$func($ds, $drive);
2729 my ($conf, $func) = @_;
2733 my $test_volid = sub {
2734 my ($volid, $is_cdrom) = @_;
2738 $volhash->{$volid} = $is_cdrom || 0;
2741 foreach_drive
($conf, sub {
2742 my ($ds, $drive) = @_;
2743 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2746 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2747 my $snap = $conf->{snapshots
}->{$snapname};
2748 &$test_volid($snap->{vmstate
}, 0);
2749 foreach_drive
($snap, sub {
2750 my ($ds, $drive) = @_;
2751 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2755 foreach my $volid (keys %$volhash) {
2756 &$func($volid, $volhash->{$volid});
2760 sub vga_conf_has_spice
{
2763 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2768 sub config_to_command
{
2769 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2772 my $globalFlags = [];
2773 my $machineFlags = [];
2779 my $kvmver = kvm_user_version
();
2780 my $vernum = 0; # unknown
2781 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2782 $vernum = $1*1000000+$2*1000;
2783 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2784 $vernum = $1*1000000+$2*1000+$3;
2787 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2789 my $have_ovz = -f
'/proc/vz/vestat';
2791 my $q35 = machine_type_is_q35
($conf);
2792 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2793 my $machine_type = $forcemachine || $conf->{machine
};
2794 my $use_old_bios_files = undef;
2795 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2797 my $cpuunits = defined($conf->{cpuunits
}) ?
2798 $conf->{cpuunits
} : $defaults->{cpuunits
};
2800 push @$cmd, '/usr/bin/systemd-run';
2801 push @$cmd, '--scope';
2802 push @$cmd, '--slice', "qemu";
2803 push @$cmd, '--unit', $vmid;
2804 # set KillMode=none, so that systemd don't kill those scopes
2805 # at shutdown (pve-manager service should stop the VMs instead)
2806 push @$cmd, '-p', "KillMode=none";
2807 push @$cmd, '-p', "CPUShares=$cpuunits";
2808 if ($conf->{cpulimit
}) {
2809 my $cpulimit = int($conf->{cpulimit
} * 100);
2810 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2813 push @$cmd, '/usr/bin/kvm';
2815 push @$cmd, '-id', $vmid;
2819 my $qmpsocket = qmp_socket
($vmid);
2820 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2821 push @$cmd, '-mon', "chardev=qmp,mode=control";
2823 my $socket = vnc_socket
($vmid);
2824 push @$cmd, '-vnc', "unix:$socket,x509,password";
2826 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2828 push @$cmd, '-daemonize';
2830 if ($conf->{smbios1
}) {
2831 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2834 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2835 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2836 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2837 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2838 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2839 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2840 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2844 # the q35 chipset support native usb2, so we enable usb controller
2845 # by default for this machine type
2846 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2848 $pciaddr = print_pci_addr
("piix3", $bridges);
2849 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2852 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2853 next if !$conf->{"usb$i"};
2854 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2855 next if !$d || $d->{usb3
}; # do not add usb2 controller if we have only usb3 devices
2858 # include usb device config
2859 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2862 # add usb3 controller if needed
2865 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2866 next if !$conf->{"usb$i"};
2867 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2868 next if !$d || !$d->{usb3
};
2872 $pciaddr = print_pci_addr
("xhci", $bridges);
2873 push @$devices, '-device', "nec-usb-xhci,id=xhci$pciaddr" if $use_usb3;
2875 my $vga = $conf->{vga
};
2877 my $qxlnum = vga_conf_has_spice
($vga);
2878 $vga = 'qxl' if $qxlnum;
2881 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2882 $conf->{ostype
} eq 'win7' ||
2883 $conf->{ostype
} eq 'w2k8')) {
2890 # enable absolute mouse coordinates (needed by vnc)
2892 if (defined($conf->{tablet
})) {
2893 $tablet = $conf->{tablet
};
2895 $tablet = $defaults->{tablet
};
2896 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2897 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2900 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2905 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2906 my $d = parse_hostpci
($conf->{"hostpci$i"});
2909 my $pcie = $d->{pcie
};
2911 die "q35 machine model is not enabled" if !$q35;
2912 $pciaddr = print_pcie_addr
("hostpci$i");
2914 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2917 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2918 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2919 if ($xvga && $xvga ne '') {
2923 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2927 my $pcidevices = $d->{pciid
};
2928 my $multifunction = 1 if @$pcidevices > 1;
2931 foreach my $pcidevice (@$pcidevices) {
2933 my $id = "hostpci$i";
2934 $id .= ".$j" if $multifunction;
2935 my $addr = $pciaddr;
2936 $addr .= ".$j" if $multifunction;
2937 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2940 $devicestr .= "$rombar$xvga";
2941 $devicestr .= ",multifunction=on" if $multifunction;
2944 push @$devices, '-device', $devicestr;
2950 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2951 next if !$conf->{"usb$i"};
2952 my $d = eval { PVE
::JSONSchema
::parse_property_string
($usbdesc->{format
},$conf->{"usb$i"}) };
2955 # if it is a usb3 device, attach it to the xhci controller, else omit the bus option
2957 if (defined($d->{usb3
}) && $d->{usb3
}) {
2958 $usbbus = ',bus=xhci.0';
2961 if (defined($d->{host
})) {
2962 $d = parse_usb_device
($d->{host
});
2963 if (defined($d->{vendorid
}) && defined($d->{productid
})) {
2964 push @$devices, '-device', "usb-host$usbbus,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2965 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2966 push @$devices, '-device', "usb-host$usbbus,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2967 } elsif (defined($d->{spice
}) && $d->{spice
}) {
2968 # usb redir support for spice, currently no usb3
2969 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2970 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2976 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2977 if (my $path = $conf->{"serial$i"}) {
2978 if ($path eq 'socket') {
2979 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2980 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2981 push @$devices, '-device', "isa-serial,chardev=serial$i";
2983 die "no such serial device\n" if ! -c
$path;
2984 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2985 push @$devices, '-device', "isa-serial,chardev=serial$i";
2991 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2992 if (my $path = $conf->{"parallel$i"}) {
2993 die "no such parallel device\n" if ! -c
$path;
2994 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2995 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2996 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
3000 my $vmname = $conf->{name
} || "vm$vmid";
3002 push @$cmd, '-name', $vmname;
3005 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
3006 $sockets = $conf->{sockets
} if $conf->{sockets
};
3008 my $cores = $conf->{cores
} || 1;
3010 my $maxcpus = $sockets * $cores;
3012 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
3014 my $allowed_vcpus = $cpuinfo->{cpus
};
3016 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
3017 if ($allowed_vcpus < $maxcpus);
3019 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
3021 push @$cmd, '-nodefaults';
3023 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
3025 my $bootindex_hash = {};
3027 foreach my $o (split(//, $bootorder)) {
3028 $bootindex_hash->{$o} = $i*100;
3032 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
3034 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
3036 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
3038 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
3041 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
3043 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
3044 my $useLocaltime = $conf->{localtime};
3046 if (my $ost = $conf->{ostype
}) {
3047 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
3049 if ($ost =~ m/^w/) { # windows
3050 $useLocaltime = 1 if !defined($conf->{localtime});
3052 # use time drift fix when acpi is enabled
3053 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3054 $tdf = 1 if !defined($conf->{tdf
});
3058 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
3060 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3061 push @$cmd, '-no-hpet';
3062 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3063 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm && !$nohyperv;
3064 push @$cpuFlags , 'hv_vapic' if !$nokvm && !$nohyperv;
3065 push @$cpuFlags , 'hv_time' if !$nokvm && !$nohyperv;
3068 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm && !$nohyperv;
3072 if ($ost eq 'win7' || $ost eq 'win8') {
3073 push @$cpuFlags , 'hv_relaxed' if !$nokvm && !$nohyperv;
3077 push @$rtcFlags, 'driftfix=slew' if $tdf;
3080 push @$machineFlags, 'accel=tcg';
3082 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3085 if ($machine_type) {
3086 push @$machineFlags, "type=${machine_type}";
3089 if ($conf->{startdate
}) {
3090 push @$rtcFlags, "base=$conf->{startdate}";
3091 } elsif ($useLocaltime) {
3092 push @$rtcFlags, 'base=localtime';
3095 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3096 if (my $cputype = $conf->{cpu
}) {
3097 my $cpuconf = PVE
::JSONSchema
::parse_property_string
($cpudesc, $cputype)
3098 or die "Cannot parse cpu description: $cputype\n";
3099 $cpu = $cpuconf->{cputype
};
3100 $kvm_off = 1 if $cpuconf->{hidden
};
3103 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3105 push @$cpuFlags , '-x2apic'
3106 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3108 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3110 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3112 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3114 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3115 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3118 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3120 push @$cpuFlags, 'kvm=off' if $kvm_off;
3122 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3124 push @$cmd, '-cpu', $cpu;
3126 my $memory = $conf->{memory
} || $defaults->{memory
};
3127 my $static_memory = 0;
3128 my $dimm_memory = 0;
3130 if ($hotplug_features->{memory
}) {
3131 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3132 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3133 $static_memory = $STATICMEM;
3134 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3135 $dimm_memory = $memory - $static_memory;
3136 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3140 $static_memory = $memory;
3141 push @$cmd, '-m', $static_memory;
3144 if ($conf->{numa
}) {
3146 my $numa_totalmemory = undef;
3147 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3148 next if !$conf->{"numa$i"};
3149 my $numa = parse_numa
($conf->{"numa$i"});
3152 die "missing numa node$i memory value\n" if !$numa->{memory
};
3153 my $numa_memory = $numa->{memory
};
3154 $numa_totalmemory += $numa_memory;
3155 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3158 my $cpus_start = $numa->{cpus
}->{start
};
3159 die "missing numa node$i cpus\n" if !defined($cpus_start);
3160 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3161 my $cpus = $cpus_start;
3162 if (defined($cpus_end)) {
3163 $cpus .= "-$cpus_end";
3164 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3168 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3169 if (defined($hostnodes_start)) {
3170 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3171 my $hostnodes = $hostnodes_start;
3172 if (defined($hostnodes_end)) {
3173 $hostnodes .= "-$hostnodes_end";
3174 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3177 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3178 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3179 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3183 my $policy = $numa->{policy
};
3184 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3185 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3188 push @$cmd, '-object', $numa_object;
3189 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3192 die "total memory for NUMA nodes must be equal to vm static memory\n"
3193 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3195 #if no custom tology, we split memory and cores across numa nodes
3196 if(!$numa_totalmemory) {
3198 my $numa_memory = ($static_memory / $sockets) . "M";
3200 for (my $i = 0; $i < $sockets; $i++) {
3202 my $cpustart = ($cores * $i);
3203 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3204 my $cpus = $cpustart;
3205 $cpus .= "-$cpuend" if $cpuend;
3207 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3208 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3213 if ($hotplug_features->{memory
}) {
3214 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3215 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3216 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3217 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3219 #if dimm_memory is not aligned to dimm map
3220 if($current_size > $memory) {
3221 $conf->{memory
} = $current_size;
3222 update_config_nolock
($vmid, $conf, 1);
3227 push @$cmd, '-S' if $conf->{freeze
};
3229 # set keyboard layout
3230 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3231 push @$cmd, '-k', $kb if $kb;
3234 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3235 #push @$cmd, '-soundhw', 'es1370';
3236 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3238 if($conf->{agent
}) {
3239 my $qgasocket = qmp_socket
($vmid, 1);
3240 my $pciaddr = print_pci_addr
("qga0", $bridges);
3241 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3242 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3243 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3250 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3251 for(my $i = 1; $i < $qxlnum; $i++){
3252 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3253 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3256 # assume other OS works like Linux
3257 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3258 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3262 my $pciaddr = print_pci_addr
("spice", $bridges);
3264 my $nodename = PVE
::INotify
::nodename
();
3265 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3266 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3268 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3270 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3271 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3272 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3275 # enable balloon by default, unless explicitly disabled
3276 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3277 $pciaddr = print_pci_addr
("balloon0", $bridges);
3278 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3281 if ($conf->{watchdog
}) {
3282 my $wdopts = parse_watchdog
($conf->{watchdog
});
3283 $pciaddr = print_pci_addr
("watchdog", $bridges);
3284 my $watchdog = $wdopts->{model
} || 'i6300esb';
3285 push @$devices, '-device', "$watchdog$pciaddr";
3286 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3290 my $scsicontroller = {};
3291 my $ahcicontroller = {};
3292 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3294 # Add iscsi initiator name if available
3295 if (my $initiator = get_initiator_name
()) {
3296 push @$devices, '-iscsi', "initiator-name=$initiator";
3299 foreach_drive
($conf, sub {
3300 my ($ds, $drive) = @_;
3302 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3303 push @$vollist, $drive->{file
};
3306 $use_virtio = 1 if $ds =~ m/^virtio/;
3308 if (drive_is_cdrom
($drive)) {
3309 if ($bootindex_hash->{d
}) {
3310 $drive->{bootindex
} = $bootindex_hash->{d
};
3311 $bootindex_hash->{d
} += 1;
3314 if ($bootindex_hash->{c
}) {
3315 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3316 $bootindex_hash->{c
} += 1;
3320 if($drive->{interface
} eq 'virtio'){
3321 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3324 if ($drive->{interface
} eq 'scsi') {
3326 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3328 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3329 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3332 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3333 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3334 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3338 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3339 $queues = ",num_queues=$drive->{queues}";
3342 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3343 $scsicontroller->{$controller}=1;
3346 if ($drive->{interface
} eq 'sata') {
3347 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3348 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3349 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3350 $ahcicontroller->{$controller}=1;
3353 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3354 push @$devices, '-drive',$drive_cmd;
3355 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3358 for (my $i = 0; $i < $MAX_NETS; $i++) {
3359 next if !$conf->{"net$i"};
3360 my $d = parse_net
($conf->{"net$i"});
3363 $use_virtio = 1 if $d->{model
} eq 'virtio';
3365 if ($bootindex_hash->{n
}) {
3366 $d->{bootindex
} = $bootindex_hash->{n
};
3367 $bootindex_hash->{n
} += 1;
3370 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3371 push @$devices, '-netdev', $netdevfull;
3373 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3374 push @$devices, '-device', $netdevicefull;
3379 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3384 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3386 while (my ($k, $v) = each %$bridges) {
3387 $pciaddr = print_pci_addr
("pci.$k");
3388 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3393 if ($conf->{args
}) {
3394 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3398 push @$cmd, @$devices;
3399 push @$cmd, '-rtc', join(',', @$rtcFlags)
3400 if scalar(@$rtcFlags);
3401 push @$cmd, '-machine', join(',', @$machineFlags)
3402 if scalar(@$machineFlags);
3403 push @$cmd, '-global', join(',', @$globalFlags)
3404 if scalar(@$globalFlags);
3406 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3411 return "${var_run_tmpdir}/$vmid.vnc";
3417 my $res = vm_mon_cmd
($vmid, 'query-spice');
3419 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3423 my ($vmid, $qga) = @_;
3424 my $sockettype = $qga ?
'qga' : 'qmp';
3425 return "${var_run_tmpdir}/$vmid.$sockettype";
3430 return "${var_run_tmpdir}/$vmid.pid";
3433 sub vm_devices_list
{
3436 my $res = vm_mon_cmd
($vmid, 'query-pci');
3438 foreach my $pcibus (@$res) {
3439 foreach my $device (@{$pcibus->{devices
}}) {
3440 next if !$device->{'qdev_id'};
3441 if ($device->{'pci_bridge'}) {
3442 $devices->{$device->{'qdev_id'}} = 1;
3443 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3444 next if !$bridge_device->{'qdev_id'};
3445 $devices->{$bridge_device->{'qdev_id'}} = 1;
3446 $devices->{$device->{'qdev_id'}}++;
3449 $devices->{$device->{'qdev_id'}} = 1;
3454 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3455 foreach my $block (@$resblock) {
3456 if($block->{device
} =~ m/^drive-(\S+)/){
3461 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3462 foreach my $mice (@$resmice) {
3463 if ($mice->{name
} eq 'QEMU HID Tablet') {
3464 $devices->{tablet
} = 1;
3473 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3475 my $q35 = machine_type_is_q35
($conf);
3477 my $devices_list = vm_devices_list
($vmid);
3478 return 1 if defined($devices_list->{$deviceid});
3480 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3482 if ($deviceid eq 'tablet') {
3484 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3486 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3488 qemu_iothread_add
($vmid, $deviceid, $device);
3490 qemu_driveadd
($storecfg, $vmid, $device);
3491 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3493 qemu_deviceadd
($vmid, $devicefull);
3494 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3496 eval { qemu_drivedel
($vmid, $deviceid); };
3501 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3504 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3505 my $pciaddr = print_pci_addr
($deviceid);
3506 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3508 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3510 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3511 qemu_iothread_add
($vmid, $deviceid, $device);
3512 $devicefull .= ",iothread=iothread-$deviceid";
3515 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3516 $devicefull .= ",num_queues=$device->{queues}";
3519 qemu_deviceadd
($vmid, $devicefull);
3520 qemu_deviceaddverify
($vmid, $deviceid);
3522 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3524 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3525 qemu_driveadd
($storecfg, $vmid, $device);
3527 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3528 eval { qemu_deviceadd
($vmid, $devicefull); };
3530 eval { qemu_drivedel
($vmid, $deviceid); };
3535 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3537 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3539 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3540 my $use_old_bios_files = undef;
3541 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3543 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3544 qemu_deviceadd
($vmid, $netdevicefull);
3545 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3547 eval { qemu_netdevdel
($vmid, $deviceid); };
3552 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3555 my $pciaddr = print_pci_addr
($deviceid);
3556 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3558 qemu_deviceadd
($vmid, $devicefull);
3559 qemu_deviceaddverify
($vmid, $deviceid);
3562 die "can't hotplug device '$deviceid'\n";
3568 # fixme: this should raise exceptions on error!
3569 sub vm_deviceunplug
{
3570 my ($vmid, $conf, $deviceid) = @_;
3572 my $devices_list = vm_devices_list
($vmid);
3573 return 1 if !defined($devices_list->{$deviceid});
3575 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3577 if ($deviceid eq 'tablet') {
3579 qemu_devicedel
($vmid, $deviceid);
3581 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3583 qemu_devicedel
($vmid, $deviceid);
3584 qemu_devicedelverify
($vmid, $deviceid);
3585 qemu_drivedel
($vmid, $deviceid);
3586 qemu_iothread_del
($conf, $vmid, $deviceid);
3588 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3590 qemu_devicedel
($vmid, $deviceid);
3591 qemu_devicedelverify
($vmid, $deviceid);
3592 qemu_iothread_del
($conf, $vmid, $deviceid);
3594 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3596 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3597 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3598 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3600 qemu_devicedel
($vmid, $deviceid);
3601 qemu_drivedel
($vmid, $deviceid);
3602 qemu_deletescsihw
($conf, $vmid, $deviceid);
3604 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3606 qemu_devicedel
($vmid, $deviceid);
3607 qemu_devicedelverify
($vmid, $deviceid);
3608 qemu_netdevdel
($vmid, $deviceid);
3611 die "can't unplug device '$deviceid'\n";
3617 sub qemu_deviceadd
{
3618 my ($vmid, $devicefull) = @_;
3620 $devicefull = "driver=".$devicefull;
3621 my %options = split(/[=,]/, $devicefull);
3623 vm_mon_cmd
($vmid, "device_add" , %options);
3626 sub qemu_devicedel
{
3627 my ($vmid, $deviceid) = @_;
3629 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3632 sub qemu_iothread_add
{
3633 my($vmid, $deviceid, $device) = @_;
3635 if ($device->{iothread
}) {
3636 my $iothreads = vm_iothreads_list
($vmid);
3637 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3641 sub qemu_iothread_del
{
3642 my($conf, $vmid, $deviceid) = @_;
3644 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3645 if ($device->{iothread
}) {
3646 my $iothreads = vm_iothreads_list
($vmid);
3647 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3651 sub qemu_objectadd
{
3652 my($vmid, $objectid, $qomtype) = @_;
3654 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3659 sub qemu_objectdel
{
3660 my($vmid, $objectid) = @_;
3662 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3668 my ($storecfg, $vmid, $device) = @_;
3670 my $drive = print_drive_full
($storecfg, $vmid, $device);
3671 $drive =~ s/\\/\\\\/g;
3672 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3674 # If the command succeeds qemu prints: "OK
"
3675 return 1 if $ret =~ m/OK/s;
3677 die "adding drive failed
: $ret\n";
3681 my($vmid, $deviceid) = @_;
3683 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3686 return 1 if $ret eq "";
3688 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3689 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3691 die "deleting drive
$deviceid failed
: $ret\n";
3694 sub qemu_deviceaddverify {
3695 my ($vmid, $deviceid) = @_;
3697 for (my $i = 0; $i <= 5; $i++) {
3698 my $devices_list = vm_devices_list($vmid);
3699 return 1 if defined($devices_list->{$deviceid});
3703 die "error on hotplug device
'$deviceid'\n";
3707 sub qemu_devicedelverify {
3708 my ($vmid, $deviceid) = @_;
3710 # need to verify that the device is correctly removed as device_del
3711 # is async and empty return is not reliable
3713 for (my $i = 0; $i <= 5; $i++) {
3714 my $devices_list = vm_devices_list($vmid);
3715 return 1 if !defined($devices_list->{$deviceid});
3719 die "error on hot-unplugging device
'$deviceid'\n";
3722 sub qemu_findorcreatescsihw {
3723 my ($storecfg, $conf, $vmid, $device) = @_;
3725 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3727 my $scsihwid="$controller_prefix$controller";
3728 my $devices_list = vm_devices_list($vmid);
3730 if(!defined($devices_list->{$scsihwid})) {
3731 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3737 sub qemu_deletescsihw {
3738 my ($conf, $vmid, $opt) = @_;
3740 my $device = parse_drive($opt, $conf->{$opt});
3742 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3743 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3747 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3749 my $devices_list = vm_devices_list($vmid);
3750 foreach my $opt (keys %{$devices_list}) {
3751 if (PVE::QemuServer::valid_drivename($opt)) {
3752 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3753 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3759 my $scsihwid="scsihw
$controller";
3761 vm_deviceunplug($vmid, $conf, $scsihwid);
3766 sub qemu_add_pci_bridge {
3767 my ($storecfg, $conf, $vmid, $device) = @_;
3773 print_pci_addr($device, $bridges);
3775 while (my ($k, $v) = each %$bridges) {
3778 return 1 if !defined($bridgeid) || $bridgeid < 1;
3780 my $bridge = "pci
.$bridgeid";
3781 my $devices_list = vm_devices_list($vmid);
3783 if (!defined($devices_list->{$bridge})) {
3784 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3790 sub qemu_set_link_status {
3791 my ($vmid, $device, $up) = @_;
3793 vm_mon_cmd($vmid, "set_link
", name => $device,
3794 up => $up ? JSON::true : JSON::false);
3797 sub qemu_netdevadd {
3798 my ($vmid, $conf, $device, $deviceid) = @_;
3800 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3801 my %options = split(/[=,]/, $netdev);
3803 vm_mon_cmd($vmid, "netdev_add
", %options);
3807 sub qemu_netdevdel {
3808 my ($vmid, $deviceid) = @_;
3810 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3813 sub qemu_cpu_hotplug {
3814 my ($vmid, $conf, $vcpus) = @_;
3817 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3818 $sockets = $conf->{sockets} if $conf->{sockets};
3819 my $cores = $conf->{cores} || 1;
3820 my $maxcpus = $sockets * $cores;
3822 $vcpus = $maxcpus if !$vcpus;
3824 die "you can
't add more vcpus than maxcpus\n"
3825 if $vcpus > $maxcpus;
3827 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3828 die "online cpu unplug is not yet possible\n"
3829 if $vcpus < $currentvcpus;
3831 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3832 die "vcpus in running vm is different than configuration\n"
3833 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3835 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3836 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3840 sub qemu_memory_hotplug {
3841 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3843 return $value if !check_running($vmid);
3845 my $memory = $conf->{memory} || $defaults->{memory};
3846 $value = $defaults->{memory} if !$value;
3847 return $value if $value == $memory;
3849 my $static_memory = $STATICMEM;
3850 my $dimm_memory = $memory - $static_memory;
3852 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3853 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3857 $sockets = $conf->{sockets} if $conf->{sockets};
3859 if($value > $memory) {
3861 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3862 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3864 return if $current_size <= $conf->{memory};
3866 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3868 eval { qemu_objectdel($vmid, "mem-
$name"); };
3872 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3874 eval { qemu_objectdel($vmid, "mem-
$name"); };
3877 #update conf after each succesful module hotplug
3878 $conf->{memory} = $current_size;
3879 update_config_nolock($vmid, $conf, 1);
3884 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3885 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3887 return if $current_size >= $conf->{memory};
3888 print "try to unplug memory dimm
$name\n";
3892 eval { qemu_devicedel($vmid, $name) };
3894 my $dimm_list = qemu_dimm_list($vmid);
3895 last if !$dimm_list->{$name};
3896 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3900 #update conf after each succesful module unplug
3901 $conf->{memory} = $current_size;
3903 eval { qemu_objectdel($vmid, "mem-
$name"); };
3904 update_config_nolock($vmid, $conf, 1);
3909 sub qemu_dimm_list {
3912 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3915 foreach my $dimm (@$dimmarray) {
3917 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3918 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3919 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3920 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3921 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3926 sub qemu_block_set_io_throttle {
3927 my ($vmid, $deviceid,
3928 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3929 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3931 return if !check_running($vmid) ;
3933 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3935 bps_rd => int($bps_rd),
3936 bps_wr => int($bps_wr),
3938 iops_rd => int($iops_rd),
3939 iops_wr => int($iops_wr),
3940 bps_max => int($bps_max),
3941 bps_rd_max => int($bps_rd_max),
3942 bps_wr_max => int($bps_wr_max),
3943 iops_max => int($iops_max),
3944 iops_rd_max => int($iops_rd_max),
3945 iops_wr_max => int($iops_wr_max)
3950 # old code, only used to shutdown old VM after update
3952 my ($fh, $timeout) = @_;
3954 my $sel = new IO::Select;
3961 while (scalar (@ready = $sel->can_read($timeout))) {
3963 if ($count = $fh->sysread($buf, 8192)) {
3964 if ($buf =~ /^(.*)\(qemu\) $/s) {
3971 if (!defined($count)) {
3978 die "monitor
read timeout
\n" if !scalar(@ready);
3983 # old code, only used to shutdown old VM after update
3984 sub vm_monitor_command {
3985 my ($vmid, $cmdstr, $nocheck) = @_;
3990 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3992 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3994 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3995 die "unable to
connect to VM
$vmid socket - $!\n";
3999 # hack: migrate sometime blocks the monitor (when migrate_downtime
4001 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4002 $timeout = 60*60; # 1 hour
4006 my $data = __read_avail($sock, $timeout);
4008 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
4009 die "got unexpected qemu monitor banner
\n";
4012 my $sel = new IO::Select;
4015 if (!scalar(my @ready = $sel->can_write($timeout))) {
4016 die "monitor
write error
- timeout
";
4019 my $fullcmd = "$cmdstr\r";
4021 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
4024 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
4025 die "monitor
write error
- $!";
4028 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
4032 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
4033 $timeout = 60*60; # 1 hour
4034 } elsif ($cmdstr =~ m/^(eject|change)/) {
4035 $timeout = 60; # note: cdrom mount command is slow
4037 if ($res = __read_avail($sock, $timeout)) {
4039 my @lines = split("\r?
\n", $res);
4041 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
4043 $res = join("\n", @lines);
4051 syslog("err
", "VM
$vmid monitor command failed
- $err");
4058 sub qemu_block_resize {
4059 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4061 my $running = check_running($vmid);
4063 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4065 return if !$running;
4067 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4071 sub qemu_volume_snapshot {
4072 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4074 my $running = check_running($vmid);
4076 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4077 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4079 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4083 sub qemu_volume_snapshot_delete {
4084 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4086 my $running = check_running($vmid);
4088 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4090 return if !$running;
4092 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4095 sub set_migration_caps {
4101 "auto-converge
" => 1,
4103 "x-rdma-pin-all
" => 0,
4108 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4110 for my $supported_capability (@$supported_capabilities) {
4112 capability => $supported_capability->{capability},
4113 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4117 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4120 my $fast_plug_option = {
4129 # hotplug changes in [PENDING]
4130 # $selection hash can be used to only apply specified options, for
4131 # example: { cores => 1 } (only apply changed 'cores')
4132 # $errors ref is used to return error messages
4133 sub vmconfig_hotplug_pending {
4134 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4136 my $defaults = load_defaults();
4138 # commit values which do not have any impact on running VM first
4139 # Note: those option cannot raise errors, we we do not care about
4140 # $selection and always apply them.
4142 my $add_error = sub {
4143 my ($opt, $msg) = @_;
4144 $errors->{$opt} = "hotplug problem
- $msg";
4148 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4149 if ($fast_plug_option->{$opt}) {
4150 $conf->{$opt} = $conf->{pending}->{$opt};
4151 delete $conf->{pending}->{$opt};
4157 update_config_nolock($vmid, $conf, 1);
4158 $conf = load_config($vmid); # update/reload
4161 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4163 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4164 while (my ($opt, $force) = each %$pending_delete_hash) {
4165 next if $selection && !$selection->{$opt};
4167 if ($opt eq 'hotplug') {
4168 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4169 } elsif ($opt eq 'tablet') {
4170 die "skip
\n" if !$hotplug_features->{usb};
4171 if ($defaults->{tablet}) {
4172 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4174 vm_deviceunplug($vmid, $conf, $opt);
4176 } elsif ($opt eq 'vcpus') {
4177 die "skip
\n" if !$hotplug_features->{cpu};
4178 qemu_cpu_hotplug($vmid, $conf, undef);
4179 } elsif ($opt eq 'balloon') {
4180 # enable balloon device is not hotpluggable
4181 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4182 } elsif ($fast_plug_option->{$opt}) {
4184 } elsif ($opt =~ m/^net(\d+)$/) {
4185 die "skip
\n" if !$hotplug_features->{network};
4186 vm_deviceunplug($vmid, $conf, $opt);
4187 } elsif (valid_drivename($opt)) {
4188 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4189 vm_deviceunplug($vmid, $conf, $opt);
4190 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4191 } elsif ($opt =~ m/^memory$/) {
4192 die "skip
\n" if !$hotplug_features->{memory};
4193 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4194 } elsif ($opt eq 'cpuunits') {
4195 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4196 } elsif ($opt eq 'cpulimit') {
4197 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4203 &$add_error($opt, $err) if $err ne "skip
\n";
4205 # save new config if hotplug was successful
4206 delete $conf->{$opt};
4207 vmconfig_undelete_pending_option($conf, $opt);
4208 update_config_nolock($vmid, $conf, 1);
4209 $conf = load_config($vmid); # update/reload
4213 foreach my $opt (keys %{$conf->{pending}}) {
4214 next if $selection && !$selection->{$opt};
4215 my $value = $conf->{pending}->{$opt};
4217 if ($opt eq 'hotplug') {
4218 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4219 } elsif ($opt eq 'tablet') {
4220 die "skip
\n" if !$hotplug_features->{usb};
4222 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4223 } elsif ($value == 0) {
4224 vm_deviceunplug($vmid, $conf, $opt);
4226 } elsif ($opt eq 'vcpus') {
4227 die "skip
\n" if !$hotplug_features->{cpu};
4228 qemu_cpu_hotplug($vmid, $conf, $value);
4229 } elsif ($opt eq 'balloon') {
4230 # enable/disable balloning device is not hotpluggable
4231 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4232 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4233 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4235 # allow manual ballooning if shares is set to zero
4236 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4237 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4238 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4240 } elsif ($opt =~ m/^net(\d+)$/) {
4241 # some changes can be done without hotplug
4242 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4243 $vmid, $opt, $value);
4244 } elsif (valid_drivename($opt)) {
4245 # some changes can be done without hotplug
4246 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4247 $vmid, $opt, $value, 1);
4248 } elsif ($opt =~ m/^memory$/) { #dimms
4249 die "skip
\n" if !$hotplug_features->{memory};
4250 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4251 } elsif ($opt eq 'cpuunits') {
4252 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4253 } elsif ($opt eq 'cpulimit') {
4254 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4255 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4257 die "skip
\n"; # skip non-hot-pluggable options
4261 &$add_error($opt, $err) if $err ne "skip
\n";
4263 # save new config if hotplug was successful
4264 $conf->{$opt} = $value;
4265 delete $conf->{pending}->{$opt};
4266 update_config_nolock($vmid, $conf, 1);
4267 $conf = load_config($vmid); # update/reload
4272 sub try_deallocate_drive {
4273 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4275 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4276 my $volid = $drive->{file};
4277 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4278 my $sid = PVE::Storage::parse_volume_id($volid);
4279 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4281 # check if the disk is really unused
4282 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4283 if is_volume_in_use($storecfg, $conf, $key, $volid);
4284 PVE::Storage::vdisk_free($storecfg, $volid);
4287 # If vm is not owner of this disk remove from config
4295 sub vmconfig_delete_or_detach_drive {
4296 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4298 my $drive = parse_drive($opt, $conf->{$opt});
4300 my $rpcenv = PVE::RPCEnvironment::get();
4301 my $authuser = $rpcenv->get_user();
4304 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4305 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4307 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4311 sub vmconfig_apply_pending {
4312 my ($vmid, $conf, $storecfg) = @_;
4316 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4317 while (my ($opt, $force) = each %$pending_delete_hash) {
4318 die "internal error
" if $opt =~ m/^unused/;
4319 $conf = load_config($vmid); # update/reload
4320 if (!defined($conf->{$opt})) {
4321 vmconfig_undelete_pending_option($conf, $opt);
4322 update_config_nolock($vmid, $conf, 1);
4323 } elsif (valid_drivename($opt)) {
4324 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4325 vmconfig_undelete_pending_option($conf, $opt);
4326 delete $conf->{$opt};
4327 update_config_nolock($vmid, $conf, 1);
4329 vmconfig_undelete_pending_option($conf, $opt);
4330 delete $conf->{$opt};
4331 update_config_nolock($vmid, $conf, 1);
4335 $conf = load_config($vmid); # update/reload
4337 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4338 $conf = load_config($vmid); # update/reload
4340 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4341 # skip if nothing changed
4342 } elsif (valid_drivename($opt)) {
4343 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4344 if defined($conf->{$opt});
4345 $conf->{$opt} = $conf->{pending}->{$opt};
4347 $conf->{$opt} = $conf->{pending}->{$opt};
4350 delete $conf->{pending}->{$opt};
4351 update_config_nolock($vmid, $conf, 1);
4355 my $safe_num_ne = sub {
4358 return 0 if !defined($a) && !defined($b);
4359 return 1 if !defined($a);
4360 return 1 if !defined($b);
4365 my $safe_string_ne = sub {
4368 return 0 if !defined($a) && !defined($b);
4369 return 1 if !defined($a);
4370 return 1 if !defined($b);
4375 sub vmconfig_update_net {
4376 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4378 my $newnet = parse_net($value);
4380 if ($conf->{$opt}) {
4381 my $oldnet = parse_net($conf->{$opt});
4383 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4384 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4385 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4386 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4388 # for non online change, we try to hot-unplug
4389 die "skip
\n" if !$hotplug;
4390 vm_deviceunplug($vmid, $conf, $opt);
4393 die "internal error
" if $opt !~ m/net(\d+)/;
4394 my $iface = "tap
${vmid
}i
$1";
4396 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4397 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4400 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4401 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4402 &$safe_string_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4403 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4404 PVE::Network::tap_unplug($iface);
4405 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks});
4408 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4409 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4417 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4423 sub vmconfig_update_disk {
4424 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4426 # fixme: do we need force?
4428 my $drive = parse_drive($opt, $value);
4430 if ($conf->{$opt}) {
4432 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4434 my $media = $drive->{media} || 'disk';
4435 my $oldmedia = $old_drive->{media} || 'disk';
4436 die "unable to change media type
\n" if $media ne $oldmedia;
4438 if (!drive_is_cdrom($old_drive)) {
4440 if ($drive->{file} ne $old_drive->{file}) {
4442 die "skip
\n" if !$hotplug;
4444 # unplug and register as unused
4445 vm_deviceunplug($vmid, $conf, $opt);
4446 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4449 # update existing disk
4451 # skip non hotpluggable value
4452 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4453 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4454 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4455 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4460 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4461 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4462 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4463 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4464 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4465 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4466 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4467 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4468 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4469 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4470 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4471 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4473 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4474 ($drive->{mbps} || 0)*1024*1024,
4475 ($drive->{mbps_rd} || 0)*1024*1024,
4476 ($drive->{mbps_wr} || 0)*1024*1024,
4477 $drive->{iops} || 0,
4478 $drive->{iops_rd} || 0,
4479 $drive->{iops_wr} || 0,
4480 ($drive->{mbps_max} || 0)*1024*1024,
4481 ($drive->{mbps_rd_max} || 0)*1024*1024,
4482 ($drive->{mbps_wr_max} || 0)*1024*1024,
4483 $drive->{iops_max} || 0,
4484 $drive->{iops_rd_max} || 0,
4485 $drive->{iops_wr_max} || 0);
4494 if ($drive->{file} eq 'none') {
4495 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4497 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4498 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4499 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4507 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4509 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]) if $drive->{file} !~ m|^/dev/.+|;
4510 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4514 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4515 $forcemachine, $spice_ticket) = @_;
4517 lock_config($vmid, sub {
4518 my $conf = load_config($vmid, $migratedfrom);
4520 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4522 check_lock($conf) if !$skiplock;
4524 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4526 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4527 vmconfig_apply_pending($vmid, $conf, $storecfg);
4528 $conf = load_config($vmid); # update/reload
4531 my $defaults = load_defaults();
4533 # set environment variable useful inside network script
4534 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4536 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4538 my $migrate_port = 0;
4541 if ($statefile eq 'tcp') {
4542 my $localip = "localhost
";
4543 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4544 my $nodename = PVE::INotify::nodename();
4545 if ($datacenterconf->{migration_unsecure}) {
4546 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4547 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4549 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4550 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4551 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4552 push @$cmd, '-incoming', $migrate_uri;
4555 push @$cmd, '-loadstate', $statefile;
4562 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4563 my $d = parse_hostpci($conf->{"hostpci
$i"});
4565 my $pcidevices = $d->{pciid};
4566 foreach my $pcidevice (@$pcidevices) {
4567 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4569 my $info = pci_device_info("0000:$pciid");
4570 die "IOMMU
not present
\n" if !check_iommu_support();
4571 die "no pci device info
for device
'$pciid'\n" if !$info;
4572 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4573 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4577 PVE::Storage::activate_volumes($storecfg, $vollist);
4579 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4582 die "start failed
: $err" if $err;
4584 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4586 if ($statefile && $statefile ne 'tcp') {
4587 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4591 if ($migratedfrom) {
4594 set_migration_caps($vmid);
4599 print "spice listens on port
$spice_port\n";
4600 if ($spice_ticket) {
4601 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4602 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4608 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4609 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4610 if $conf->{balloon};
4613 foreach my $opt (keys %$conf) {
4614 next if $opt !~ m/^net\d+$/;
4615 my $nicconf = parse_net($conf->{$opt});
4616 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4620 vm_mon_cmd_nocheck($vmid, 'qom-set',
4621 path => "machine
/peripheral/balloon0
",
4622 property => "guest-stats-polling-interval
",
4623 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4629 my ($vmid, $execute, %params) = @_;
4631 my $cmd = { execute => $execute, arguments => \%params };
4632 vm_qmp_command($vmid, $cmd);
4635 sub vm_mon_cmd_nocheck {
4636 my ($vmid, $execute, %params) = @_;
4638 my $cmd = { execute => $execute, arguments => \%params };
4639 vm_qmp_command($vmid, $cmd, 1);
4642 sub vm_qmp_command {
4643 my ($vmid, $cmd, $nocheck) = @_;
4648 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4649 $timeout = $cmd->{arguments}->{timeout};
4650 delete $cmd->{arguments}->{timeout};
4654 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4655 my $sname = qmp_socket($vmid);
4656 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4657 my $qmpclient = PVE::QMPClient->new();
4659 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4660 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4661 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4662 if scalar(%{$cmd->{arguments}});
4663 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4665 die "unable to open monitor socket\n";
4669 syslog("err", "VM $vmid qmp command failed - $err");
4676 sub vm_human_monitor_command {
4677 my ($vmid, $cmdline) = @_;
4682 execute => 'human-monitor-command
',
4683 arguments => { 'command-line
' => $cmdline},
4686 return vm_qmp_command($vmid, $cmd);
4689 sub vm_commandline {
4690 my ($storecfg, $vmid) = @_;
4692 my $conf = load_config($vmid);
4694 my $defaults = load_defaults();
4696 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4698 return join(' ', @$cmd);
4702 my ($vmid, $skiplock) = @_;
4704 lock_config($vmid, sub {
4706 my $conf = load_config($vmid);
4708 check_lock($conf) if !$skiplock;
4710 vm_mon_cmd($vmid, "system_reset");
4714 sub get_vm_volumes {
4718 foreach_volid($conf, sub {
4719 my ($volid, $is_cdrom) = @_;
4721 return if $volid =~ m|^/|;
4723 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4726 push @$vollist, $volid;
4732 sub vm_stop_cleanup {
4733 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4738 my $vollist = get_vm_volumes($conf);
4739 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4742 foreach my $ext (qw(mon qmp pid vnc qga)) {
4743 unlink "/var/run/qemu-server/${vmid}.$ext";
4746 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4748 warn $@ if $@; # avoid errors - just warn
4751 # Note: use $nockeck to skip tests if VM configuration file exists.
4752 # We need that when migration VMs to other nodes (files already moved)
4753 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4755 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4757 $force = 1 if !defined($force) && !$shutdown;
4760 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4761 kill 15, $pid if $pid;
4762 my $conf = load_config
($vmid, $migratedfrom);
4763 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4767 lock_config
($vmid, sub {
4769 my $pid = check_running
($vmid, $nocheck);
4774 $conf = load_config
($vmid);
4775 check_lock
($conf) if !$skiplock;
4776 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4777 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4778 $timeout = $opts->{down
} if $opts->{down
};
4782 $timeout = 60 if !defined($timeout);
4786 if (defined($conf) && $conf->{agent
}) {
4787 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4789 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4792 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4799 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4804 if ($count >= $timeout) {
4806 warn "VM still running - terminating now with SIGTERM\n";
4809 die "VM quit/powerdown failed - got timeout\n";
4812 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4817 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4820 die "VM quit/powerdown failed\n";
4828 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4833 if ($count >= $timeout) {
4834 warn "VM still running - terminating now with SIGKILL\n";
4839 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4844 my ($vmid, $skiplock) = @_;
4846 lock_config
($vmid, sub {
4848 my $conf = load_config
($vmid);
4850 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4852 vm_mon_cmd
($vmid, "stop");
4857 my ($vmid, $skiplock, $nocheck) = @_;
4859 lock_config
($vmid, sub {
4863 my $conf = load_config
($vmid);
4865 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4867 vm_mon_cmd
($vmid, "cont");
4870 vm_mon_cmd_nocheck
($vmid, "cont");
4876 my ($vmid, $skiplock, $key) = @_;
4878 lock_config
($vmid, sub {
4880 my $conf = load_config
($vmid);
4882 # there is no qmp command, so we use the human monitor command
4883 vm_human_monitor_command
($vmid, "sendkey $key");
4888 my ($storecfg, $vmid, $skiplock) = @_;
4890 lock_config
($vmid, sub {
4892 my $conf = load_config
($vmid);
4894 if (!check_running
($vmid)) {
4895 destroy_vm
($storecfg, $vmid, undef, $skiplock);
4897 die "VM $vmid is running - destroy failed\n";
4905 my ($filename, $buf) = @_;
4907 my $fh = IO
::File-
>new($filename, "w");
4908 return undef if !$fh;
4910 my $res = print $fh $buf;
4917 sub pci_device_info
{
4922 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4923 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4925 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4926 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4928 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4929 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4931 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4932 return undef if !defined($product) || $product !~ s/^0x//;
4937 product
=> $product,
4943 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4952 my $name = $dev->{name
};
4954 my $fn = "$pcisysfs/devices/$name/reset";
4956 return file_write
($fn, "1");
4959 sub pci_dev_bind_to_vfio
{
4962 my $name = $dev->{name
};
4964 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4966 if (!-d
$vfio_basedir) {
4967 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4969 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4971 my $testdir = "$vfio_basedir/$name";
4972 return 1 if -d
$testdir;
4974 my $data = "$dev->{vendor} $dev->{product}";
4975 return undef if !file_write
("$vfio_basedir/new_id", $data);
4977 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4978 if (!file_write
($fn, $name)) {
4979 return undef if -f
$fn;
4982 $fn = "$vfio_basedir/bind";
4983 if (! -d
$testdir) {
4984 return undef if !file_write
($fn, $name);
4990 sub pci_dev_group_bind_to_vfio
{
4993 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4995 if (!-d
$vfio_basedir) {
4996 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4998 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
5000 # get IOMMU group devices
5001 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
5002 my @devs = grep /^0000:/, readdir($D);
5005 foreach my $pciid (@devs) {
5006 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
5008 # pci bridges, switches or root ports are not supported
5009 # they have a pci_bus subdirectory so skip them
5010 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
5012 my $info = pci_device_info
($1);
5013 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
5019 sub print_pci_addr
{
5020 my ($id, $bridges) = @_;
5024 piix3
=> { bus
=> 0, addr
=> 1 },
5025 #addr2 : first videocard
5026 balloon0
=> { bus
=> 0, addr
=> 3 },
5027 watchdog
=> { bus
=> 0, addr
=> 4 },
5028 scsihw0
=> { bus
=> 0, addr
=> 5 },
5029 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
5030 scsihw1
=> { bus
=> 0, addr
=> 6 },
5031 ahci0
=> { bus
=> 0, addr
=> 7 },
5032 qga0
=> { bus
=> 0, addr
=> 8 },
5033 spice
=> { bus
=> 0, addr
=> 9 },
5034 virtio0
=> { bus
=> 0, addr
=> 10 },
5035 virtio1
=> { bus
=> 0, addr
=> 11 },
5036 virtio2
=> { bus
=> 0, addr
=> 12 },
5037 virtio3
=> { bus
=> 0, addr
=> 13 },
5038 virtio4
=> { bus
=> 0, addr
=> 14 },
5039 virtio5
=> { bus
=> 0, addr
=> 15 },
5040 hostpci0
=> { bus
=> 0, addr
=> 16 },
5041 hostpci1
=> { bus
=> 0, addr
=> 17 },
5042 net0
=> { bus
=> 0, addr
=> 18 },
5043 net1
=> { bus
=> 0, addr
=> 19 },
5044 net2
=> { bus
=> 0, addr
=> 20 },
5045 net3
=> { bus
=> 0, addr
=> 21 },
5046 net4
=> { bus
=> 0, addr
=> 22 },
5047 net5
=> { bus
=> 0, addr
=> 23 },
5048 vga1
=> { bus
=> 0, addr
=> 24 },
5049 vga2
=> { bus
=> 0, addr
=> 25 },
5050 vga3
=> { bus
=> 0, addr
=> 26 },
5051 hostpci2
=> { bus
=> 0, addr
=> 27 },
5052 hostpci3
=> { bus
=> 0, addr
=> 28 },
5053 #addr29 : usb-host (pve-usb.cfg)
5054 'pci.1' => { bus
=> 0, addr
=> 30 },
5055 'pci.2' => { bus
=> 0, addr
=> 31 },
5056 'net6' => { bus
=> 1, addr
=> 1 },
5057 'net7' => { bus
=> 1, addr
=> 2 },
5058 'net8' => { bus
=> 1, addr
=> 3 },
5059 'net9' => { bus
=> 1, addr
=> 4 },
5060 'net10' => { bus
=> 1, addr
=> 5 },
5061 'net11' => { bus
=> 1, addr
=> 6 },
5062 'net12' => { bus
=> 1, addr
=> 7 },
5063 'net13' => { bus
=> 1, addr
=> 8 },
5064 'net14' => { bus
=> 1, addr
=> 9 },
5065 'net15' => { bus
=> 1, addr
=> 10 },
5066 'net16' => { bus
=> 1, addr
=> 11 },
5067 'net17' => { bus
=> 1, addr
=> 12 },
5068 'net18' => { bus
=> 1, addr
=> 13 },
5069 'net19' => { bus
=> 1, addr
=> 14 },
5070 'net20' => { bus
=> 1, addr
=> 15 },
5071 'net21' => { bus
=> 1, addr
=> 16 },
5072 'net22' => { bus
=> 1, addr
=> 17 },
5073 'net23' => { bus
=> 1, addr
=> 18 },
5074 'net24' => { bus
=> 1, addr
=> 19 },
5075 'net25' => { bus
=> 1, addr
=> 20 },
5076 'net26' => { bus
=> 1, addr
=> 21 },
5077 'net27' => { bus
=> 1, addr
=> 22 },
5078 'net28' => { bus
=> 1, addr
=> 23 },
5079 'net29' => { bus
=> 1, addr
=> 24 },
5080 'net30' => { bus
=> 1, addr
=> 25 },
5081 'net31' => { bus
=> 1, addr
=> 26 },
5082 'xhci' => { bus
=> 1, addr
=> 27 },
5083 'virtio6' => { bus
=> 2, addr
=> 1 },
5084 'virtio7' => { bus
=> 2, addr
=> 2 },
5085 'virtio8' => { bus
=> 2, addr
=> 3 },
5086 'virtio9' => { bus
=> 2, addr
=> 4 },
5087 'virtio10' => { bus
=> 2, addr
=> 5 },
5088 'virtio11' => { bus
=> 2, addr
=> 6 },
5089 'virtio12' => { bus
=> 2, addr
=> 7 },
5090 'virtio13' => { bus
=> 2, addr
=> 8 },
5091 'virtio14' => { bus
=> 2, addr
=> 9 },
5092 'virtio15' => { bus
=> 2, addr
=> 10 },
5093 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5094 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5095 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5096 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5097 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5098 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5099 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5100 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5101 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5102 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5103 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5104 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5105 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5106 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5107 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5108 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5109 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5110 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5111 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5112 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5113 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5114 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5115 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5116 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5117 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5118 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5119 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5120 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5121 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5122 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5123 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5127 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5128 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5129 my $bus = $devices->{$id}->{bus
};
5130 $res = ",bus=pci.$bus,addr=$addr";
5131 $bridges->{$bus} = 1 if $bridges;
5137 sub print_pcie_addr
{
5142 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5143 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5144 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5145 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5148 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5149 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5150 my $bus = $devices->{$id}->{bus
};
5151 $res = ",bus=$bus,addr=$addr";
5157 # vzdump restore implementaion
5159 sub tar_archive_read_firstfile
{
5160 my $archive = shift;
5162 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5164 # try to detect archive type first
5165 my $pid = open (TMP
, "tar tf '$archive'|") ||
5166 die "unable to open file '$archive'\n";
5167 my $firstfile = <TMP
>;
5171 die "ERROR: archive contaions no data\n" if !$firstfile;
5177 sub tar_restore_cleanup
{
5178 my ($storecfg, $statfile) = @_;
5180 print STDERR
"starting cleanup\n";
5182 if (my $fd = IO
::File-
>new($statfile, "r")) {
5183 while (defined(my $line = <$fd>)) {
5184 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5187 if ($volid =~ m
|^/|) {
5188 unlink $volid || die 'unlink failed\n';
5190 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5192 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5194 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5196 print STDERR
"unable to parse line in statfile - $line";
5203 sub restore_archive
{
5204 my ($archive, $vmid, $user, $opts) = @_;
5206 my $format = $opts->{format
};
5209 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5210 $format = 'tar' if !$format;
5212 } elsif ($archive =~ m/\.tar$/) {
5213 $format = 'tar' if !$format;
5214 } elsif ($archive =~ m/.tar.lzo$/) {
5215 $format = 'tar' if !$format;
5217 } elsif ($archive =~ m/\.vma$/) {
5218 $format = 'vma' if !$format;
5219 } elsif ($archive =~ m/\.vma\.gz$/) {
5220 $format = 'vma' if !$format;
5222 } elsif ($archive =~ m/\.vma\.lzo$/) {
5223 $format = 'vma' if !$format;
5226 $format = 'vma' if !$format; # default
5229 # try to detect archive format
5230 if ($format eq 'tar') {
5231 return restore_tar_archive
($archive, $vmid, $user, $opts);
5233 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5237 sub restore_update_config_line
{
5238 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5240 return if $line =~ m/^\#qmdump\#/;
5241 return if $line =~ m/^\#vzdump\#/;
5242 return if $line =~ m/^lock:/;
5243 return if $line =~ m/^unused\d+:/;
5244 return if $line =~ m/^parent:/;
5245 return if $line =~ m/^template:/; # restored VM is never a template
5247 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5248 # try to convert old 1.X settings
5249 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5250 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5251 my ($model, $macaddr) = split(/\=/, $devconfig);
5252 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5255 bridge
=> "vmbr$ind",
5256 macaddr
=> $macaddr,
5258 my $netstr = print_net
($net);
5260 print $outfd "net$cookie->{netcount}: $netstr\n";
5261 $cookie->{netcount
}++;
5263 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5264 my ($id, $netstr) = ($1, $2);
5265 my $net = parse_net
($netstr);
5266 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5267 $netstr = print_net
($net);
5268 print $outfd "$id: $netstr\n";
5269 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5272 my $di = parse_drive
($virtdev, $value);
5273 if (defined($di->{backup
}) && !$di->{backup
}) {
5274 print $outfd "#$line";
5275 } elsif ($map->{$virtdev}) {
5276 delete $di->{format
}; # format can change on restore
5277 $di->{file
} = $map->{$virtdev};
5278 $value = print_drive
($vmid, $di);
5279 print $outfd "$virtdev: $value\n";
5289 my ($cfg, $vmid) = @_;
5291 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5293 my $volid_hash = {};
5294 foreach my $storeid (keys %$info) {
5295 foreach my $item (@{$info->{$storeid}}) {
5296 next if !($item->{volid
} && $item->{size
});
5297 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5298 $volid_hash->{$item->{volid
}} = $item;
5305 sub is_volume_in_use
{
5306 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5308 my $path = PVE
::Storage
::path
($storecfg, $volid);
5310 my $scan_config = sub {
5311 my ($cref, $snapname) = @_;
5313 foreach my $key (keys %$cref) {
5314 my $value = $cref->{$key};
5315 if (valid_drivename
($key)) {
5316 next if $skip_drive && $key eq $skip_drive;
5317 my $drive = parse_drive
($key, $value);
5318 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5319 return 1 if $volid eq $drive->{file
};
5320 if ($drive->{file
} =~ m!^/!) {
5321 return 1 if $drive->{file
} eq $path;
5323 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5325 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5327 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5335 return 1 if &$scan_config($conf);
5339 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5340 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5346 sub update_disksize
{
5347 my ($vmid, $conf, $volid_hash) = @_;
5353 # Note: it is allowed to define multiple storages with same path (alias), so
5354 # we need to check both 'volid' and real 'path' (two different volid can point
5355 # to the same path).
5360 foreach my $opt (keys %$conf) {
5361 if (valid_drivename
($opt)) {
5362 my $drive = parse_drive
($opt, $conf->{$opt});
5363 my $volid = $drive->{file
};
5366 $used->{$volid} = 1;
5367 if ($volid_hash->{$volid} &&
5368 (my $path = $volid_hash->{$volid}->{path
})) {
5369 $usedpath->{$path} = 1;
5372 next if drive_is_cdrom
($drive);
5373 next if !$volid_hash->{$volid};
5375 $drive->{size
} = $volid_hash->{$volid}->{size
};
5376 my $new = print_drive
($vmid, $drive);
5377 if ($new ne $conf->{$opt}) {
5379 $conf->{$opt} = $new;
5384 # remove 'unusedX' entry if volume is used
5385 foreach my $opt (keys %$conf) {
5386 next if $opt !~ m/^unused\d+$/;
5387 my $volid = $conf->{$opt};
5388 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5389 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5391 delete $conf->{$opt};
5395 foreach my $volid (sort keys %$volid_hash) {
5396 next if $volid =~ m/vm-$vmid-state-/;
5397 next if $used->{$volid};
5398 my $path = $volid_hash->{$volid}->{path
};
5399 next if !$path; # just to be sure
5400 next if $usedpath->{$path};
5402 add_unused_volume
($conf, $volid);
5403 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5410 my ($vmid, $nolock) = @_;
5412 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5414 my $volid_hash = scan_volids
($cfg, $vmid);
5416 my $updatefn = sub {
5419 my $conf = load_config
($vmid);
5424 foreach my $volid (keys %$volid_hash) {
5425 my $info = $volid_hash->{$volid};
5426 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5429 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5431 update_config_nolock
($vmid, $conf, 1) if $changes;
5434 if (defined($vmid)) {
5438 lock_config
($vmid, $updatefn, $vmid);
5441 my $vmlist = config_list
();
5442 foreach my $vmid (keys %$vmlist) {
5446 lock_config
($vmid, $updatefn, $vmid);
5452 sub restore_vma_archive
{
5453 my ($archive, $vmid, $user, $opts, $comp) = @_;
5455 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5456 my $readfrom = $archive;
5461 my $qarchive = PVE
::Tools
::shellquote
($archive);
5462 if ($comp eq 'gzip') {
5463 $uncomp = "zcat $qarchive|";
5464 } elsif ($comp eq 'lzop') {
5465 $uncomp = "lzop -d -c $qarchive|";
5467 die "unknown compression method '$comp'\n";
5472 my $tmpdir = "/var/tmp/vzdumptmp$$";
5475 # disable interrupts (always do cleanups)
5476 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5477 warn "got interrupt - ignored\n";
5480 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5481 POSIX
::mkfifo
($mapfifo, 0600);
5484 my $openfifo = sub {
5485 open($fifofh, '>', $mapfifo) || die $!;
5488 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5495 my $rpcenv = PVE
::RPCEnvironment
::get
();
5497 my $conffile = config_file
($vmid);
5498 my $tmpfn = "$conffile.$$.tmp";
5500 # Note: $oldconf is undef if VM does not exists
5501 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5503 my $print_devmap = sub {
5504 my $virtdev_hash = {};
5506 my $cfgfn = "$tmpdir/qemu-server.conf";
5508 # we can read the config - that is already extracted
5509 my $fh = IO
::File-
>new($cfgfn, "r") ||
5510 "unable to read qemu-server.conf - $!\n";
5512 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5514 my $pve_firewall_dir = '/etc/pve/firewall';
5515 mkdir $pve_firewall_dir; # make sure the dir exists
5516 PVE
::Tools
::file_copy
($fwcfgfn, "${pve_firewall_dir}/$vmid.fw");
5519 while (defined(my $line = <$fh>)) {
5520 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5521 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5522 die "archive does not contain data for drive '$virtdev'\n"
5523 if !$devinfo->{$devname};
5524 if (defined($opts->{storage
})) {
5525 $storeid = $opts->{storage
} || 'local';
5526 } elsif (!$storeid) {
5529 $format = 'raw' if !$format;
5530 $devinfo->{$devname}->{devname
} = $devname;
5531 $devinfo->{$devname}->{virtdev
} = $virtdev;
5532 $devinfo->{$devname}->{format
} = $format;
5533 $devinfo->{$devname}->{storeid
} = $storeid;
5535 # check permission on storage
5536 my $pool = $opts->{pool
}; # todo: do we need that?
5537 if ($user ne 'root@pam') {
5538 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5541 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5545 foreach my $devname (keys %$devinfo) {
5546 die "found no device mapping information for device '$devname'\n"
5547 if !$devinfo->{$devname}->{virtdev
};
5550 my $cfg = cfs_read_file
('storage.cfg');
5552 # create empty/temp config
5554 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5555 foreach_drive
($oldconf, sub {
5556 my ($ds, $drive) = @_;
5558 return if drive_is_cdrom
($drive);
5560 my $volid = $drive->{file
};
5562 return if !$volid || $volid =~ m
|^/|;
5564 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5565 return if !$path || !$owner || ($owner != $vmid);
5567 # Note: only delete disk we want to restore
5568 # other volumes will become unused
5569 if ($virtdev_hash->{$ds}) {
5570 PVE
::Storage
::vdisk_free
($cfg, $volid);
5576 foreach my $virtdev (sort keys %$virtdev_hash) {
5577 my $d = $virtdev_hash->{$virtdev};
5578 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5579 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5581 # test if requested format is supported
5582 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5583 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5584 $d->{format
} = $defFormat if !$supported;
5586 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5587 $d->{format
}, undef, $alloc_size);
5588 print STDERR
"new volume ID is '$volid'\n";
5589 $d->{volid
} = $volid;
5590 my $path = PVE
::Storage
::path
($cfg, $volid);
5592 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5594 my $write_zeros = 1;
5595 # fixme: what other storages types initialize volumes with zero?
5596 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5597 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5601 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5603 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5604 $map->{$virtdev} = $volid;
5607 $fh->seek(0, 0) || die "seek failed - $!\n";
5609 my $outfd = new IO
::File
($tmpfn, "w") ||
5610 die "unable to write config for VM $vmid\n";
5612 my $cookie = { netcount
=> 0 };
5613 while (defined(my $line = <$fh>)) {
5614 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5623 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5624 die "interrupted by signal\n";
5626 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5628 $oldtimeout = alarm($timeout);
5635 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5636 my ($dev_id, $size, $devname) = ($1, $2, $3);
5637 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5638 } elsif ($line =~ m/^CTIME: /) {
5639 # we correctly received the vma config, so we can disable
5640 # the timeout now for disk allocation (set to 10 minutes, so
5641 # that we always timeout if something goes wrong)
5644 print $fifofh "done\n";
5645 my $tmp = $oldtimeout || 0;
5646 $oldtimeout = undef;
5652 print "restore vma archive: $cmd\n";
5653 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5657 alarm($oldtimeout) if $oldtimeout;
5660 foreach my $devname (keys %$devinfo) {
5661 my $volid = $devinfo->{$devname}->{volid
};
5662 push @$vollist, $volid if $volid;
5665 my $cfg = cfs_read_file
('storage.cfg');
5666 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5674 foreach my $devname (keys %$devinfo) {
5675 my $volid = $devinfo->{$devname}->{volid
};
5678 if ($volid =~ m
|^/|) {
5679 unlink $volid || die 'unlink failed\n';
5681 PVE
::Storage
::vdisk_free
($cfg, $volid);
5683 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5685 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5692 rename($tmpfn, $conffile) ||
5693 die "unable to commit configuration file '$conffile'\n";
5695 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5697 eval { rescan
($vmid, 1); };
5701 sub restore_tar_archive
{
5702 my ($archive, $vmid, $user, $opts) = @_;
5704 if ($archive ne '-') {
5705 my $firstfile = tar_archive_read_firstfile
($archive);
5706 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5707 if $firstfile ne 'qemu-server.conf';
5710 my $storecfg = cfs_read_file
('storage.cfg');
5712 # destroy existing data - keep empty config
5713 my $vmcfgfn = config_file
($vmid);
5714 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5716 my $tocmd = "/usr/lib/qemu-server/qmextract";
5718 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5719 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5720 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5721 $tocmd .= ' --info' if $opts->{info
};
5723 # tar option "xf" does not autodetect compression when read from STDIN,
5724 # so we pipe to zcat
5725 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5726 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5728 my $tmpdir = "/var/tmp/vzdumptmp$$";
5731 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5732 local $ENV{VZDUMP_VMID
} = $vmid;
5733 local $ENV{VZDUMP_USER
} = $user;
5735 my $conffile = config_file
($vmid);
5736 my $tmpfn = "$conffile.$$.tmp";
5738 # disable interrupts (always do cleanups)
5739 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5740 print STDERR
"got interrupt - ignored\n";
5745 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5746 die "interrupted by signal\n";
5749 if ($archive eq '-') {
5750 print "extracting archive from STDIN\n";
5751 run_command
($cmd, input
=> "<&STDIN");
5753 print "extracting archive '$archive'\n";
5757 return if $opts->{info
};
5761 my $statfile = "$tmpdir/qmrestore.stat";
5762 if (my $fd = IO
::File-
>new($statfile, "r")) {
5763 while (defined (my $line = <$fd>)) {
5764 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5765 $map->{$1} = $2 if $1;
5767 print STDERR
"unable to parse line in statfile - $line\n";
5773 my $confsrc = "$tmpdir/qemu-server.conf";
5775 my $srcfd = new IO
::File
($confsrc, "r") ||
5776 die "unable to open file '$confsrc'\n";
5778 my $outfd = new IO
::File
($tmpfn, "w") ||
5779 die "unable to write config for VM $vmid\n";
5781 my $cookie = { netcount
=> 0 };
5782 while (defined (my $line = <$srcfd>)) {
5783 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5795 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5802 rename $tmpfn, $conffile ||
5803 die "unable to commit configuration file '$conffile'\n";
5805 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5807 eval { rescan
($vmid, 1); };
5812 # Internal snapshots
5814 # NOTE: Snapshot create/delete involves several non-atomic
5815 # action, and can take a long time.
5816 # So we try to avoid locking the file and use 'lock' variable
5817 # inside the config file instead.
5819 my $snapshot_copy_config = sub {
5820 my ($source, $dest) = @_;
5822 foreach my $k (keys %$source) {
5823 next if $k eq 'snapshots';
5824 next if $k eq 'snapstate';
5825 next if $k eq 'snaptime';
5826 next if $k eq 'vmstate';
5827 next if $k eq 'lock';
5828 next if $k eq 'digest';
5829 next if $k eq 'description';
5830 next if $k =~ m/^unused\d+$/;
5832 $dest->{$k} = $source->{$k};
5836 my $snapshot_apply_config = sub {
5837 my ($conf, $snap) = @_;
5839 # copy snapshot list
5841 snapshots
=> $conf->{snapshots
},
5844 # keep description and list of unused disks
5845 foreach my $k (keys %$conf) {
5846 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5847 $newconf->{$k} = $conf->{$k};
5850 &$snapshot_copy_config($snap, $newconf);
5855 sub foreach_writable_storage
{
5856 my ($conf, $func) = @_;
5860 foreach my $ds (keys %$conf) {
5861 next if !valid_drivename
($ds);
5863 my $drive = parse_drive
($ds, $conf->{$ds});
5865 next if drive_is_cdrom
($drive);
5867 my $volid = $drive->{file
};
5869 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5870 $sidhash->{$sid} = $sid if $sid;
5873 foreach my $sid (sort keys %$sidhash) {
5878 my $alloc_vmstate_volid = sub {
5879 my ($storecfg, $vmid, $conf, $snapname) = @_;
5881 # Note: we try to be smart when selecting a $target storage
5885 # search shared storage first
5886 foreach_writable_storage
($conf, sub {
5888 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5889 return if !$scfg->{shared
};
5891 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5895 # now search local storage
5896 foreach_writable_storage
($conf, sub {
5898 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5899 return if $scfg->{shared
};
5901 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5905 $target = 'local' if !$target;
5907 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5908 # we abort live save after $conf->{memory}, so we need at max twice that space
5909 my $size = $conf->{memory
}*2 + $driver_state_size;
5911 my $name = "vm-$vmid-state-$snapname";
5912 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5913 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5914 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5919 my $snapshot_prepare = sub {
5920 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5924 my $updatefn = sub {
5926 my $conf = load_config
($vmid);
5928 die "you can't take a snapshot if it's a template\n"
5929 if is_template
($conf);
5933 $conf->{lock} = 'snapshot';
5935 die "snapshot name '$snapname' already used\n"
5936 if defined($conf->{snapshots
}->{$snapname});
5938 my $storecfg = PVE
::Storage
::config
();
5939 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5941 $snap = $conf->{snapshots
}->{$snapname} = {};
5943 if ($save_vmstate && check_running
($vmid)) {
5944 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5947 &$snapshot_copy_config($conf, $snap);
5949 $snap->{snapstate
} = "prepare";
5950 $snap->{snaptime
} = time();
5951 $snap->{description
} = $comment if $comment;
5953 # always overwrite machine if we save vmstate. This makes sure we
5954 # can restore it later using correct machine type
5955 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5957 update_config_nolock
($vmid, $conf, 1);
5960 lock_config
($vmid, $updatefn);
5965 my $snapshot_commit = sub {
5966 my ($vmid, $snapname) = @_;
5968 my $updatefn = sub {
5970 my $conf = load_config
($vmid);
5972 die "missing snapshot lock\n"
5973 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5975 my $has_machine_config = defined($conf->{machine
});
5977 my $snap = $conf->{snapshots
}->{$snapname};
5979 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5981 die "wrong snapshot state\n"
5982 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5984 delete $snap->{snapstate
};
5985 delete $conf->{lock};
5987 my $newconf = &$snapshot_apply_config($conf, $snap);
5989 delete $newconf->{machine
} if !$has_machine_config;
5991 $newconf->{parent
} = $snapname;
5993 update_config_nolock
($vmid, $newconf, 1);
5996 lock_config
($vmid, $updatefn);
5999 sub snapshot_rollback
{
6000 my ($vmid, $snapname) = @_;
6004 my $storecfg = PVE
::Storage
::config
();
6006 my $conf = load_config
($vmid);
6008 my $get_snapshot_config = sub {
6010 die "you can't rollback if vm is a template\n" if is_template
($conf);
6012 my $res = $conf->{snapshots
}->{$snapname};
6014 die "snapshot '$snapname' does not exist\n" if !defined($res);
6019 my $snap = &$get_snapshot_config();
6021 foreach_drive
($snap, sub {
6022 my ($ds, $drive) = @_;
6024 return if drive_is_cdrom
($drive);
6026 my $volid = $drive->{file
};
6028 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
6031 my $updatefn = sub {
6033 $conf = load_config
($vmid);
6035 $snap = &$get_snapshot_config();
6037 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
6038 if $snap->{snapstate
};
6042 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
6045 die "unable to rollback vm $vmid: vm is running\n"
6046 if check_running
($vmid);
6049 $conf->{lock} = 'rollback';
6051 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
6052 delete $conf->{lock};
6058 my $has_machine_config = defined($conf->{machine
});
6060 # copy snapshot config to current config
6061 $conf = &$snapshot_apply_config($conf, $snap);
6062 $conf->{parent
} = $snapname;
6064 # Note: old code did not store 'machine', so we try to be smart
6065 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
6066 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
6067 # we remove the 'machine' configuration if not explicitly specified
6068 # in the original config.
6069 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
6072 update_config_nolock
($vmid, $conf, 1);
6074 if (!$prepare && $snap->{vmstate
}) {
6075 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6076 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
6080 lock_config
($vmid, $updatefn);
6082 foreach_drive
($snap, sub {
6083 my ($ds, $drive) = @_;
6085 return if drive_is_cdrom
($drive);
6087 my $volid = $drive->{file
};
6088 my $device = "drive-$ds";
6090 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
6094 lock_config
($vmid, $updatefn);
6097 my $savevm_wait = sub {
6101 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6102 if (!$stat->{status
}) {
6103 die "savevm not active\n";
6104 } elsif ($stat->{status
} eq 'active') {
6107 } elsif ($stat->{status
} eq 'completed') {
6110 die "query-savevm returned status '$stat->{status}'\n";
6115 sub do_snapshots_with_qemu
{
6116 my ($storecfg, $volid) = @_;
6118 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
6120 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
6121 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
6125 if ($volid =~ m/\.(qcow2|qed)$/){
6132 sub snapshot_create
{
6133 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
6135 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
6137 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
6139 my $config = load_config
($vmid);
6141 my $running = check_running
($vmid);
6143 my $freezefs = $running && $config->{agent
};
6144 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
6149 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6150 warn "guest-fsfreeze-freeze problems - $@" if $@;
6154 # create internal snapshots of all drives
6156 my $storecfg = PVE
::Storage
::config
();
6159 if ($snap->{vmstate
}) {
6160 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6161 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
6162 &$savevm_wait($vmid);
6164 vm_mon_cmd
($vmid, "savevm-start");
6168 foreach_drive
($snap, sub {
6169 my ($ds, $drive) = @_;
6171 return if drive_is_cdrom
($drive);
6173 my $volid = $drive->{file
};
6174 my $device = "drive-$ds";
6176 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
6177 $drivehash->{$ds} = 1;
6183 eval { vm_mon_cmd
($vmid, "savevm-end") };
6187 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6188 warn "guest-fsfreeze-thaw problems - $@" if $@;
6191 # savevm-end is async, we need to wait
6193 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6194 if (!$stat->{bytes
}) {
6197 print "savevm not yet finished\n";
6205 warn "snapshot create failed: starting cleanup\n";
6206 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
6211 &$snapshot_commit($vmid, $snapname);
6214 # Note: $drivehash is only set when called from snapshot_create.
6215 sub snapshot_delete
{
6216 my ($vmid, $snapname, $force, $drivehash) = @_;
6223 my $unlink_parent = sub {
6224 my ($confref, $new_parent) = @_;
6226 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6228 $confref->{parent
} = $new_parent;
6230 delete $confref->{parent
};
6235 my $updatefn = sub {
6236 my ($remove_drive) = @_;
6238 my $conf = load_config
($vmid);
6242 die "you can't delete a snapshot if vm is a template\n"
6243 if is_template
($conf);
6246 $snap = $conf->{snapshots
}->{$snapname};
6248 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6250 # remove parent refs
6252 &$unlink_parent($conf, $snap->{parent
});
6253 foreach my $sn (keys %{$conf->{snapshots
}}) {
6254 next if $sn eq $snapname;
6255 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6259 if ($remove_drive) {
6260 if ($remove_drive eq 'vmstate') {
6261 delete $snap->{$remove_drive};
6263 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6264 my $volid = $drive->{file
};
6265 delete $snap->{$remove_drive};
6266 add_unused_volume
($conf, $volid);
6271 $snap->{snapstate
} = 'delete';
6273 delete $conf->{snapshots
}->{$snapname};
6274 delete $conf->{lock} if $drivehash;
6275 foreach my $volid (@$unused) {
6276 add_unused_volume
($conf, $volid);
6280 update_config_nolock
($vmid, $conf, 1);
6283 lock_config
($vmid, $updatefn);
6285 # now remove vmstate file
6287 my $storecfg = PVE
::Storage
::config
();
6289 if ($snap->{vmstate
}) {
6290 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6292 die $err if !$force;
6295 # save changes (remove vmstate from snapshot)
6296 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6299 # now remove all internal snapshots
6300 foreach_drive
($snap, sub {
6301 my ($ds, $drive) = @_;
6303 return if drive_is_cdrom
($drive);
6305 my $volid = $drive->{file
};
6306 my $device = "drive-$ds";
6308 if (!$drivehash || $drivehash->{$ds}) {
6309 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6311 die $err if !$force;
6316 # save changes (remove drive fron snapshot)
6317 lock_config
($vmid, $updatefn, $ds) if !$force;
6318 push @$unused, $volid;
6321 # now cleanup config
6323 lock_config
($vmid, $updatefn);
6327 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6330 foreach_drive
($conf, sub {
6331 my ($ds, $drive) = @_;
6333 return if drive_is_cdrom
($drive);
6334 my $volid = $drive->{file
};
6335 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6338 return $err ?
0 : 1;
6341 sub template_create
{
6342 my ($vmid, $conf, $disk) = @_;
6344 my $storecfg = PVE
::Storage
::config
();
6346 foreach_drive
($conf, sub {
6347 my ($ds, $drive) = @_;
6349 return if drive_is_cdrom
($drive);
6350 return if $disk && $ds ne $disk;
6352 my $volid = $drive->{file
};
6353 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6355 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6356 $drive->{file
} = $voliddst;
6357 $conf->{$ds} = print_drive
($vmid, $drive);
6358 update_config_nolock
($vmid, $conf, 1);
6365 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6368 sub qemu_img_convert
{
6369 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6371 my $storecfg = PVE
::Storage
::config
();
6372 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6373 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6375 if ($src_storeid && $dst_storeid) {
6377 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6379 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6380 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6382 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6383 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6385 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6386 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6389 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6390 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6391 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6395 if($line =~ m/\((\S+)\/100\
%\)/){
6397 my $transferred = int($size * $percent / 100);
6398 my $remaining = $size - $transferred;
6400 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6405 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6407 die "copy failed: $err" if $err;
6411 sub qemu_img_format
{
6412 my ($scfg, $volname) = @_;
6414 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6421 sub qemu_drive_mirror
{
6422 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6424 my $storecfg = PVE
::Storage
::config
();
6425 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6427 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6429 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6431 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6433 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6434 $opts->{format
} = $format if $format;
6436 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6439 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6441 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6442 my $stat = @$stats[0];
6443 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6444 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6446 my $busy = $stat->{busy
};
6447 my $ready = $stat->{ready
};
6449 if (my $total = $stat->{len
}) {
6450 my $transferred = $stat->{offset
} || 0;
6451 my $remaining = $total - $transferred;
6452 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6454 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6458 if ($stat->{ready
} eq 'true') {
6460 last if $vmiddst != $vmid;
6462 # try to switch the disk if source and destination are on the same guest
6463 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6465 die $@ if $@ !~ m/cannot be completed/;
6474 my $cancel_job = sub {
6475 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6477 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6478 my $stat = @$stats[0];
6485 eval { &$cancel_job(); };
6486 die "mirroring error: $err";
6489 if ($vmiddst != $vmid) {
6490 # if we clone a disk for a new target vm, we don't switch the disk
6491 &$cancel_job(); # so we call block-job-cancel
6496 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6497 $newvmid, $storage, $format, $full, $newvollist) = @_;
6502 print "create linked clone of drive $drivename ($drive->{file})\n";
6503 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6504 push @$newvollist, $newvolid;
6506 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6507 $storeid = $storage if $storage;
6509 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6511 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6512 $format = qemu_img_format
($scfg, $volname);
6515 # test if requested format is supported - else use default
6516 my $supported = grep { $_ eq $format } @$validFormats;
6517 $format = $defFormat if !$supported;
6519 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6521 print "create full clone of drive $drivename ($drive->{file})\n";
6522 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6523 push @$newvollist, $newvolid;
6525 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6527 if (!$running || $snapname) {
6528 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6530 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6534 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6537 $disk->{format
} = undef;
6538 $disk->{file
} = $newvolid;
6539 $disk->{size
} = $size;
6544 # this only works if VM is running
6545 sub get_current_qemu_machine
{
6548 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6549 my $res = vm_qmp_command
($vmid, $cmd);
6551 my ($current, $default);
6552 foreach my $e (@$res) {
6553 $default = $e->{name
} if $e->{'is-default'};
6554 $current = $e->{name
} if $e->{'is-current'};
6557 # fallback to the default machine if current is not supported by qemu
6558 return $current || $default || 'pc';
6561 sub qemu_machine_feature_enabled
{
6562 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6567 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6569 $current_major = $3;
6570 $current_minor = $4;
6572 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6574 $current_major = $1;
6575 $current_minor = $2;
6578 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6583 sub qemu_machine_pxe
{
6584 my ($vmid, $conf, $machine) = @_;
6586 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6588 foreach my $opt (keys %$conf) {
6589 next if $opt !~ m/^net(\d+)$/;
6590 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6592 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6593 return $machine.".pxe" if $romfile =~ m/pxe/;
6599 sub qemu_use_old_bios_files
{
6600 my ($machine_type) = @_;
6602 return if !$machine_type;
6604 my $use_old_bios_files = undef;
6606 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6608 $use_old_bios_files = 1;
6610 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6611 # load new efi bios files on migration. So this hack is required to allow
6612 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6613 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6614 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6617 return ($use_old_bios_files, $machine_type);
6624 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6625 my (undef, $id, $function) = @_;
6626 my $res = { id
=> $id, function
=> $function};
6627 push @{$devices->{$id}}, $res;
6633 sub vm_iothreads_list
{
6636 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6639 foreach my $iothread (@$res) {
6640 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6647 my ($conf, $drive) = @_;
6651 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6653 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6659 my $controller = int($drive->{index} / $maxdev);
6660 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6662 return ($maxdev, $controller, $controller_prefix);
6665 # bash completion helper
6667 sub complete_backup_archives
{
6668 my ($cmdname, $pname, $cvalue) = @_;
6670 my $cfg = PVE
::Storage
::config
();
6674 if ($cvalue =~ m/^([^:]+):/) {
6678 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6681 foreach my $id (keys %$data) {
6682 foreach my $item (@{$data->{$id}}) {
6683 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6684 push @$res, $item->{volid
} if defined($item->{volid
});
6691 my $complete_vmid_full = sub {
6694 my $idlist = vmstatus
();
6698 foreach my $id (keys %$idlist) {
6699 my $d = $idlist->{$id};
6700 if (defined($running)) {
6701 next if $d->{template
};
6702 next if $running && $d->{status
} ne 'running';
6703 next if !$running && $d->{status
} eq 'running';
6712 return &$complete_vmid_full();
6715 sub complete_vmid_stopped
{
6716 return &$complete_vmid_full(0);
6719 sub complete_vmid_running
{
6720 return &$complete_vmid_full(1);
6723 sub complete_storage
{
6725 my $cfg = PVE
::Storage
::config
();
6726 my $ids = $cfg->{ids
};
6729 foreach my $sid (keys %$ids) {
6730 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6731 next if !$ids->{$sid}->{content
}->{images
};