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";
97 description
=> "Specifies whether a VM will be started during system bootup.",
103 description
=> "Automatic restart after crash (currently ignored).",
108 type
=> 'string', format
=> 'pve-hotplug-features',
109 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'.",
110 default => 'network,disk,usb',
115 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
121 description
=> "Lock/unlock the VM.",
122 enum
=> [qw(migrate backup snapshot rollback)],
127 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.",
135 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.",
143 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
150 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
156 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",
164 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
165 enum
=> PVE
::Tools
::kvmkeymaplist
(),
170 type
=> 'string', format
=> 'dns-name',
171 description
=> "Set a name for the VM. Only used on the configuration web interface.",
176 description
=> "scsi controller model",
177 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
183 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
188 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
189 description
=> <<EODESC,
190 Used to enable special optimization/features for specific
193 other => unspecified OS
194 wxp => Microsoft Windows XP
195 w2k => Microsoft Windows 2000
196 w2k3 => Microsoft Windows 2003
197 w2k8 => Microsoft Windows 2008
198 wvista => Microsoft Windows Vista
199 win7 => Microsoft Windows 7
200 win8 => Microsoft Windows 8/2012
201 l24 => Linux 2.4 Kernel
202 l26 => Linux 2.6/3.X Kernel
203 solaris => solaris/opensolaris/openindiania kernel
205 other|l24|l26|solaris ... no special behaviour
206 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
212 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
213 pattern
=> '[acdn]{1,4}',
218 type
=> 'string', format
=> 'pve-qm-bootdisk',
219 description
=> "Enable booting from specified disk.",
220 pattern
=> '(ide|sata|scsi|virtio)\d+',
225 description
=> "The number of CPUs. Please use option -sockets instead.",
232 description
=> "The number of CPU sockets.",
239 description
=> "The number of cores per socket.",
246 description
=> "Enable/disable Numa.",
252 description
=> "Number of hotplugged vcpus.",
259 description
=> "Enable/disable ACPI.",
265 description
=> "Enable/disable Qemu GuestAgent.",
271 description
=> "Enable/disable KVM hardware virtualization.",
277 description
=> "Enable/disable time drift fix.",
283 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
288 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
293 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.",
294 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
298 type
=> 'string', format
=> 'pve-qm-watchdog',
299 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
300 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)",
305 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
306 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'.",
307 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
310 startup
=> get_standard_option
('pve-startup-order'),
314 description
=> "Enable/disable Template.",
320 description
=> <<EODESCR,
321 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
323 args: -no-reboot -no-hpet
330 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).",
335 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
339 migrate_downtime
=> {
342 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
348 type
=> 'string', format
=> 'pve-qm-drive',
349 typetext
=> 'volume',
350 description
=> "This is an alias for option -ide2",
354 description
=> "Emulated CPU type.",
356 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) ],
359 parent
=> get_standard_option
('pve-snapshot-name', {
361 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
365 description
=> "Timestamp for snapshots.",
371 type
=> 'string', format
=> 'pve-volume-id',
372 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
375 description
=> "Specific the Qemu machine type.",
377 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?)',
382 description
=> "Specify SMBIOS type 1 fields.",
383 type
=> 'string', format
=> 'pve-qm-smbios1',
390 description
=> "Sets the protection flag of the VM. This will prevent the remove operation.",
396 enum
=> [ qw(seabios ovmf) ],
397 description
=> "Select BIOS implementation.",
398 default => 'seabios',
402 # what about other qemu settings ?
404 #machine => 'string',
417 ##soundhw => 'string',
419 while (my ($k, $v) = each %$confdesc) {
420 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
423 my $MAX_IDE_DISKS = 4;
424 my $MAX_SCSI_DISKS = 14;
425 my $MAX_VIRTIO_DISKS = 16;
426 my $MAX_SATA_DISKS = 6;
427 my $MAX_USB_DEVICES = 5;
429 my $MAX_UNUSED_DISKS = 8;
430 my $MAX_HOSTPCI_DEVICES = 4;
431 my $MAX_SERIAL_PORTS = 4;
432 my $MAX_PARALLEL_PORTS = 3;
434 my $MAX_MEM = 4194304;
435 my $STATICMEM = 1024;
439 type
=> 'string', format
=> 'pve-qm-numanode',
440 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
441 description
=> "numa topology",
443 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
445 for (my $i = 0; $i < $MAX_NUMA; $i++) {
446 $confdesc->{"numa$i"} = $numadesc;
449 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
450 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
451 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
452 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
456 type
=> 'string', format
=> 'pve-qm-net',
457 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]",
458 description
=> <<EODESCR,
459 Specify network devices.
461 MODEL is one of: $nic_model_list_txt
463 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
464 automatically generated if not specified.
466 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
468 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'.
470 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
476 The DHCP server assign addresses to the guest starting from 10.0.2.15.
480 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
482 for (my $i = 0; $i < $MAX_NETS; $i++) {
483 $confdesc->{"net$i"} = $netdesc;
488 my %drivedesc_base = (
489 volume
=> { alias
=> 'file' },
491 type
=> 'pve-volume-id',
493 format_description
=> 'volume',
494 description
=> "The drive's backing volume.",
498 format_description
=> 'cdrom|disk',
499 enum
=> [qw(cdrom disk)],
500 description
=> "The drive's media type.",
506 format_description
=> 'count',
507 description
=> "Force the drive's physical geometry to have a specific cylinder count.",
512 format_description
=> 'count',
513 description
=> "Force the drive's physical geometry to have a specific head count.",
518 format_description
=> 'count',
519 description
=> "Force the drive's physical geometry to have a specific sector count.",
524 format_description
=> 'none|lba|auto',
525 enum
=> [qw(none lba auto)],
526 description
=> "Force disk geometry bios translation mode.",
531 format_description
=> 'on|off',
532 description
=> "Whether the drive should be included when making snapshots.",
537 format_description
=> 'none|writethrough|writeback|unsafe|directsync',
538 enum
=> [qw(none writethrough writeback unsafe directsync)],
539 description
=> "The drive's cache mode",
544 format_description
=> 'drive format',
545 enum
=> [qw(raw cow qcow qed qcow2 vmdk cloop)],
546 description
=> "The drive's backing file's data format.",
551 description
=> "Disk size. This is purely informational and has no effect.",
556 format_description
=> 'on|off',
557 description
=> "Whether the drive should be included when making backups.",
562 format_description
=> 'enospc|ignore|report|stop',
563 enum
=> [qw(enospc ignore report stop)],
564 description
=> 'Write error action.',
569 format_description
=> 'native|threads',
570 enum
=> [qw(native threads)],
571 description
=> 'AIO type to use.',
576 format_description
=> 'ignore|on',
577 enum
=> [qw(ignore on)],
578 description
=> 'Controls whether to pass discard/trim requests to the underlying storage.',
583 description
=> 'Controls whether to detect and try to optimize writes of zeroes.',
588 format_description
=> 'serial',
589 description
=> "The drive's reported serial number.",
597 format_description
=> 'ignore|report|stop',
598 enum
=> [qw(ignore report stop)],
599 description
=> 'Read error action.',
604 my %iothread_fmt = ( iothread
=> {
606 format_description
=> 'off|on',
607 description
=> "Whether to use iothreads for this drive",
614 format_description
=> 'model',
615 description
=> "The drive's reported model name.",
623 format_description
=> 'nbqueues',
624 description
=> "Number of queues.",
630 my $add_throttle_desc = sub {
631 my ($key, $type, $what, $size, $longsize) = @_;
632 $drivedesc_base{$key} = {
634 format_description
=> $size,
635 description
=> "Maximum $what speed in $longsize per second.",
639 # throughput: (leaky bucket)
640 $add_throttle_desc->('bps', 'integer', 'r/w speed', 'bps', 'bytes');
641 $add_throttle_desc->('bps_rd', 'integer', 'read speed', 'bps', 'bytes');
642 $add_throttle_desc->('bps_wr', 'integer', 'write speed', 'bps', 'bytes');
643 $add_throttle_desc->('mbps', 'float', 'r/w speed', 'mbps', 'megabytes');
644 $add_throttle_desc->('mbps_rd', 'float', 'read speed', 'mbps', 'megabytes');
645 $add_throttle_desc->('mbps_wr', 'float', 'write speed', 'mbps', 'megabytes');
646 $add_throttle_desc->('iops', 'integer', 'r/w I/O', 'iops', 'operations');
647 $add_throttle_desc->('iops_rd', 'integer', 'read I/O', 'iops', 'operations');
648 $add_throttle_desc->('iops_wr', 'integer', 'write I/O', 'iops', 'operations');
650 # pools: (pool of IO before throttling starts taking effect)
651 $add_throttle_desc->('mbps_max', 'float', 'unthrottled r/w pool', 'mbps', 'megabytes');
652 $add_throttle_desc->('mbps_rd_max', 'float', 'unthrottled read pool', 'mbps', 'megabytes');
653 $add_throttle_desc->('mbps_wr_max', 'float', 'unthrottled write pool', 'mbps', 'megabytes');
654 $add_throttle_desc->('iops_max', 'integer', 'unthrottled r/w I/O pool', 'iops', 'operations');
655 $add_throttle_desc->('iops_rd_max', 'integer', 'unthrottled read I/O pool', 'iops', 'operations');
656 $add_throttle_desc->('iops_wr_max', 'integer', 'unthrottled write I/O pool', 'iops', 'operations');
666 type
=> 'string', format
=> $ide_fmt,
667 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
669 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
678 type
=> 'string', format
=> $scsi_fmt,
679 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
681 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
689 type
=> 'string', format
=> $sata_fmt,
690 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
692 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
701 type
=> 'string', format
=> $virtio_fmt,
702 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
704 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
716 type
=> 'string', format
=> 'pve-qm-usb-device',
717 typetext
=> 'host=HOSTUSBDEVICE|spice',
718 description
=> <<EODESCR,
719 Configure an USB device (n is 0 to 4). This can be used to
720 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
722 'bus-port(.port)*' (decimal numbers) or
723 'vendor_id:product_id' (hexadeciaml numbers)
725 You can use the 'lsusb -t' command to list existing usb devices.
727 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
729 The value 'spice' can be used to add a usb redirection devices for spice.
733 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
737 type
=> 'string', format
=> 'pve-qm-hostpci',
738 typetext
=> "[host=]HOSTPCIDEVICE [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
739 description
=> <<EODESCR,
740 Map host pci devices. HOSTPCIDEVICE syntax is:
742 'bus:dev.func' (hexadecimal numbers)
744 You can us the 'lspci' command to list existing pci devices.
746 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
748 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
750 Experimental: user reported problems with this option.
753 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
758 pattern
=> '(/dev/.+|socket)',
759 description
=> <<EODESCR,
760 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).
762 Note: If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
764 Experimental: user reported problems with this option.
771 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
772 description
=> <<EODESCR,
773 Map host parallel devices (n is 0 to 2).
775 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
777 Experimental: user reported problems with this option.
781 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
782 $confdesc->{"parallel$i"} = $paralleldesc;
785 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
786 $confdesc->{"serial$i"} = $serialdesc;
789 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
790 $confdesc->{"hostpci$i"} = $hostpcidesc;
793 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
794 $drivename_hash->{"ide$i"} = 1;
795 $confdesc->{"ide$i"} = $idedesc;
798 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
799 $drivename_hash->{"sata$i"} = 1;
800 $confdesc->{"sata$i"} = $satadesc;
803 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
804 $drivename_hash->{"scsi$i"} = 1;
805 $confdesc->{"scsi$i"} = $scsidesc ;
808 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
809 $drivename_hash->{"virtio$i"} = 1;
810 $confdesc->{"virtio$i"} = $virtiodesc;
813 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
814 $confdesc->{"usb$i"} = $usbdesc;
819 type
=> 'string', format
=> 'pve-volume-id',
820 description
=> "Reference to unused volumes.",
823 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
824 $confdesc->{"unused$i"} = $unuseddesc;
827 my $kvm_api_version = 0;
831 return $kvm_api_version if $kvm_api_version;
833 my $fh = IO
::File-
>new("</dev/kvm") ||
836 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
837 $kvm_api_version = $v;
842 return $kvm_api_version;
845 my $kvm_user_version;
847 sub kvm_user_version
{
849 return $kvm_user_version if $kvm_user_version;
851 $kvm_user_version = 'unknown';
853 my $tmp = `kvm -help 2>/dev/null`;
855 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)(\.\d+)?[,\s]/) {
856 $kvm_user_version = $2;
859 return $kvm_user_version;
863 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
866 # order is important - used to autoselect boot disk
867 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
868 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
869 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
870 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
873 sub valid_drivename
{
876 return defined($drivename_hash->{$dev});
881 return defined($confdesc->{$key});
885 return $nic_model_list;
888 sub os_list_description
{
893 w2k
=> 'Windows 2000',
894 w2k3
=>, 'Windows 2003',
895 w2k8
=> 'Windows 2008',
896 wvista
=> 'Windows Vista',
898 win8
=> 'Windows 8/2012',
908 return $cdrom_path if $cdrom_path;
910 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
911 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
912 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
916 my ($storecfg, $vmid, $cdrom) = @_;
918 if ($cdrom eq 'cdrom') {
919 return get_cdrom_path
();
920 } elsif ($cdrom eq 'none') {
922 } elsif ($cdrom =~ m
|^/|) {
925 return PVE
::Storage
::path
($storecfg, $cdrom);
929 # try to convert old style file names to volume IDs
930 sub filename_to_volume_id
{
931 my ($vmid, $file, $media) = @_;
933 if (!($file eq 'none' || $file eq 'cdrom' ||
934 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
936 return undef if $file =~ m
|/|;
938 if ($media && $media eq 'cdrom') {
939 $file = "local:iso/$file";
941 $file = "local:$vmid/$file";
948 sub verify_media_type
{
949 my ($opt, $vtype, $media) = @_;
954 if ($media eq 'disk') {
956 } elsif ($media eq 'cdrom') {
959 die "internal error";
962 return if ($vtype eq $etype);
964 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
967 sub cleanup_drive_path
{
968 my ($opt, $storecfg, $drive) = @_;
970 # try to convert filesystem paths to volume IDs
972 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
973 ($drive->{file
} !~ m
|^/dev/.+|) &&
974 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
975 ($drive->{file
} !~ m/^\d+$/)) {
976 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
977 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
978 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
979 verify_media_type
($opt, $vtype, $drive->{media
});
980 $drive->{file
} = $volid;
983 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
986 sub create_conf_nolock
{
987 my ($vmid, $settings) = @_;
989 my $filename = config_file
($vmid);
991 die "configuration file '$filename' already exists\n" if -f
$filename;
993 my $defaults = load_defaults
();
995 $settings->{name
} = "vm$vmid" if !$settings->{name
};
996 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
999 foreach my $opt (keys %$settings) {
1000 next if !$confdesc->{$opt};
1002 my $value = $settings->{$opt};
1005 $data .= "$opt: $value\n";
1008 PVE
::Tools
::file_set_contents
($filename, $data);
1011 sub parse_hotplug_features
{
1016 return $res if $data eq '0';
1018 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
1020 foreach my $feature (PVE
::Tools
::split_list
($data)) {
1021 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
1024 warn "ignoring unknown hotplug feature '$feature'\n";
1030 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
1031 sub pve_verify_hotplug_features
{
1032 my ($value, $noerr) = @_;
1034 return $value if parse_hotplug_features
($value);
1036 return undef if $noerr;
1038 die "unable to parse hotplug option\n";
1041 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
1042 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
1043 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
1044 # [,aio=native|threads][,discard=ignore|on][,detect_zeroes=on|off]
1045 # [,iothread=on][,serial=serial][,model=model]
1048 my ($key, $data) = @_;
1050 my ($interface, $index);
1052 if ($key =~ m/^([^\d]+)(\d+)$/) {
1059 my $desc = $key =~ /^unused\d+$/ ?
$alldrive_fmt
1060 : $confdesc->{$key}->{format
};
1062 warn "invalid drive key: $key\n";
1065 my $res = eval { PVE
::JSONSchema
::parse_property_string
($desc, $data) };
1066 return undef if !$res;
1067 $res->{interface
} = $interface;
1068 $res->{index} = $index;
1071 foreach my $opt (qw(bps bps_rd bps_wr)) {
1072 if (my $bps = defined(delete $res->{$opt})) {
1073 if (defined($res->{"m$opt"})) {
1074 warn "both $opt and m$opt specified\n";
1078 $res->{"m$opt"} = sprintf("%.3f", $bps / (1024*1024.0));
1081 return undef if $error;
1083 return undef if $res->{mbps_rd
} && $res->{mbps
};
1084 return undef if $res->{mbps_wr
} && $res->{mbps
};
1085 return undef if $res->{iops_rd
} && $res->{iops
};
1086 return undef if $res->{iops_wr
} && $res->{iops
};
1088 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
1089 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
1090 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
1091 return undef if $res->{interface
} eq 'virtio';
1094 if (my $size = $res->{size
}) {
1095 return undef if !defined($res->{size
} = PVE
::JSONSchema
::parse_size
($size));
1102 my ($vmid, $drive) = @_;
1103 my $data = { %$drive };
1104 delete $data->{$_} for qw(index interface);
1105 return PVE
::JSONSchema
::print_property_string
($data, $alldrive_fmt);
1109 my($fh, $noerr) = @_;
1112 my $SG_GET_VERSION_NUM = 0x2282;
1114 my $versionbuf = "\x00" x
8;
1115 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
1117 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1120 my $version = unpack("I", $versionbuf);
1121 if ($version < 30000) {
1122 die "scsi generic interface too old\n" if !$noerr;
1126 my $buf = "\x00" x
36;
1127 my $sensebuf = "\x00" x
8;
1128 my $cmd = pack("C x3 C x1", 0x12, 36);
1130 # see /usr/include/scsi/sg.h
1131 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";
1133 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1134 length($sensebuf), 0, length($buf), $buf,
1135 $cmd, $sensebuf, 6000);
1137 $ret = ioctl($fh, $SG_IO, $packet);
1139 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1143 my @res = unpack($sg_io_hdr_t, $packet);
1144 if ($res[17] || $res[18]) {
1145 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1150 (my $byte0, my $byte1, $res->{vendor
},
1151 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1153 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1154 $res->{type
} = $byte0 & 31;
1162 my $fh = IO
::File-
>new("+<$path") || return undef;
1163 my $res = scsi_inquiry
($fh, 1);
1169 sub machine_type_is_q35
{
1172 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1175 sub print_tabletdevice_full
{
1178 my $q35 = machine_type_is_q35
($conf);
1180 # we use uhci for old VMs because tablet driver was buggy in older qemu
1181 my $usbbus = $q35 ?
"ehci" : "uhci";
1183 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1186 sub print_drivedevice_full
{
1187 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1192 if ($drive->{interface
} eq 'virtio') {
1193 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1194 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1195 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1196 } elsif ($drive->{interface
} eq 'scsi') {
1198 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1199 my $unit = $drive->{index} % $maxdev;
1200 my $devicetype = 'hd';
1202 if (drive_is_cdrom
($drive)) {
1205 if ($drive->{file
} =~ m
|^/|) {
1206 $path = $drive->{file
};
1208 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1211 if($path =~ m/^iscsi\:\/\
//){
1212 $devicetype = 'generic';
1214 if (my $info = path_is_scsi
($path)) {
1215 if ($info->{type
} == 0) {
1216 $devicetype = 'block';
1217 } elsif ($info->{type
} == 1) { # tape
1218 $devicetype = 'generic';
1224 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1225 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1227 $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}";
1230 } elsif ($drive->{interface
} eq 'ide'){
1232 my $controller = int($drive->{index} / $maxdev);
1233 my $unit = $drive->{index} % $maxdev;
1234 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1236 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1237 if ($devicetype eq 'hd' && (my $model = $drive->{model
})) {
1238 $device .= ",model=$model";
1240 } elsif ($drive->{interface
} eq 'sata'){
1241 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1242 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1243 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1244 } elsif ($drive->{interface
} eq 'usb') {
1246 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1248 die "unsupported interface type";
1251 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1256 sub get_initiator_name
{
1259 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1260 while (defined(my $line = <$fh>)) {
1261 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1270 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);
1271 sub print_drive_full
{
1272 my ($storecfg, $vmid, $drive) = @_;
1275 my $volid = $drive->{file
};
1278 if (drive_is_cdrom
($drive)) {
1279 $path = get_iso_path
($storecfg, $vmid, $volid);
1281 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1283 $path = PVE
::Storage
::path
($storecfg, $volid);
1284 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1285 $format = qemu_img_format
($scfg, $volname);
1292 foreach my $o (@qemu_drive_options) {
1293 next if $o eq 'bootindex';
1294 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1297 $opts .= ",format=$format" if $format && !$drive->{format
};
1299 foreach my $o (qw(bps bps_rd bps_wr)) {
1300 my $v = $drive->{"m$o"};
1301 $opts .= ",$o=" . int($v*1024*1024) if $v;
1304 my $cache_direct = 0;
1306 if (my $cache = $drive->{cache
}) {
1307 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1308 } elsif (!drive_is_cdrom
($drive)) {
1309 $opts .= ",cache=none";
1313 # aio native works only with O_DIRECT
1314 if (!$drive->{aio
}) {
1316 $opts .= ",aio=native";
1318 $opts .= ",aio=threads";
1322 if (!drive_is_cdrom
($drive)) {
1324 if ($drive->{detect_zeroes
} && $drive->{detect_zeroes
} eq 'off') {
1325 $detectzeroes = 'off';
1326 } elsif ($drive->{discard
}) {
1327 $detectzeroes = $drive->{discard
} eq 'on' ?
'unmap' : 'on';
1329 # This used to be our default with discard not being specified:
1330 $detectzeroes = 'on';
1332 $opts .= ",detect-zeroes=$detectzeroes" if $detectzeroes;
1335 my $pathinfo = $path ?
"file=$path," : '';
1337 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1340 sub print_netdevice_full
{
1341 my ($vmid, $conf, $net, $netid, $bridges, $use_old_bios_files) = @_;
1343 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1345 my $device = $net->{model
};
1346 if ($net->{model
} eq 'virtio') {
1347 $device = 'virtio-net-pci';
1350 my $pciaddr = print_pci_addr
("$netid", $bridges);
1351 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1352 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1353 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1354 my $vectors = $net->{queues
} * 2 + 2;
1355 $tmpstr .= ",vectors=$vectors,mq=on";
1357 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1359 if ($use_old_bios_files) {
1361 if ($device eq 'virtio-net-pci') {
1362 $romfile = 'pxe-virtio.rom';
1363 } elsif ($device eq 'e1000') {
1364 $romfile = 'pxe-e1000.rom';
1365 } elsif ($device eq 'ne2k') {
1366 $romfile = 'pxe-ne2k_pci.rom';
1367 } elsif ($device eq 'pcnet') {
1368 $romfile = 'pxe-pcnet.rom';
1369 } elsif ($device eq 'rtl8139') {
1370 $romfile = 'pxe-rtl8139.rom';
1372 $tmpstr .= ",romfile=$romfile" if $romfile;
1378 sub print_netdev_full
{
1379 my ($vmid, $conf, $net, $netid, $hotplug) = @_;
1382 if ($netid =~ m/^net(\d+)$/) {
1386 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1388 my $ifname = "tap${vmid}i$i";
1390 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1391 die "interface name '$ifname' is too long (max 15 character)\n"
1392 if length($ifname) >= 16;
1394 my $vhostparam = '';
1395 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1397 my $vmname = $conf->{name
} || "vm$vmid";
1400 my $script = $hotplug ?
"pve-bridge-hotplug" : "pve-bridge";
1402 if ($net->{bridge
}) {
1403 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/$script,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1405 $netdev = "type=user,id=$netid,hostname=$vmname";
1408 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1413 sub drive_is_cdrom
{
1416 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1425 foreach my $kvp (split(/,/, $data)) {
1427 if ($kvp =~ m/^memory=(\S+)$/) {
1428 $res->{memory
} = $1;
1429 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1430 $res->{policy
} = $1;
1431 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1432 $res->{cpus
}->{start
} = $1;
1433 $res->{cpus
}->{end
} = $3;
1434 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1435 $res->{hostnodes
}->{start
} = $1;
1436 $res->{hostnodes
}->{end
} = $3;
1448 return undef if !$value;
1451 my @list = split(/,/, $value);
1455 foreach my $kv (@list) {
1457 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1460 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1463 my $pcidevices = lspci
($2);
1464 $res->{pciid
} = $pcidevices->{$2};
1466 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1467 $res->{rombar
} = $1;
1468 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1469 $res->{'x-vga'} = $1;
1470 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1471 $res->{pcie
} = 1 if $1 == 1;
1473 warn "unknown hostpci setting '$kv'\n";
1477 return undef if !$found;
1482 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1488 foreach my $kvp (split(/,/, $data)) {
1490 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) {
1492 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1493 $res->{model
} = $model;
1494 $res->{macaddr
} = $mac;
1495 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1496 $res->{bridge
} = $1;
1497 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1498 $res->{queues
} = $1;
1499 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1501 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1503 } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {
1504 $res->{trunks
} = $1;
1505 } elsif ($kvp =~ m/^firewall=([01])$/) {
1506 $res->{firewall
} = $1;
1507 } elsif ($kvp =~ m/^link_down=([01])$/) {
1508 $res->{link_down
} = $1;
1515 return undef if !$res->{model
};
1523 my $res = "$net->{model}";
1524 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1525 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1526 $res .= ",rate=$net->{rate}" if $net->{rate
};
1527 $res .= ",tag=$net->{tag}" if $net->{tag
};
1528 $res .= ",trunks=$net->{trunks}" if $net->{trunks
};
1529 $res .= ",firewall=1" if $net->{firewall
};
1530 $res .= ",link_down=1" if $net->{link_down
};
1531 $res .= ",queues=$net->{queues}" if $net->{queues
};
1536 sub add_random_macs
{
1537 my ($settings) = @_;
1539 foreach my $opt (keys %$settings) {
1540 next if $opt !~ m/^net(\d+)$/;
1541 my $net = parse_net
($settings->{$opt});
1543 $settings->{$opt} = print_net
($net);
1547 sub add_unused_volume
{
1548 my ($config, $volid) = @_;
1551 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1552 my $test = "unused$ind";
1553 if (my $vid = $config->{$test}) {
1554 return if $vid eq $volid; # do not add duplicates
1560 die "To many unused volume - please delete them first.\n" if !$key;
1562 $config->{$key} = $volid;
1567 sub vm_is_volid_owner
{
1568 my ($storecfg, $vmid, $volid) = @_;
1570 if ($volid !~ m
|^/|) {
1572 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1573 if ($owner && ($owner == $vmid)) {
1581 sub split_flagged_list
{
1582 my $text = shift || '';
1583 $text =~ s/[,;]/ /g;
1585 return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
1588 sub join_flagged_list
{
1589 my ($how, $lst) = @_;
1590 join $how, map { $lst->{$_} . $_ } keys %$lst;
1593 sub vmconfig_delete_pending_option
{
1594 my ($conf, $key, $force) = @_;
1596 delete $conf->{pending
}->{$key};
1597 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1598 $pending_delete_hash->{$key} = $force ?
'!' : '';
1599 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1602 sub vmconfig_undelete_pending_option
{
1603 my ($conf, $key) = @_;
1605 my $pending_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1606 delete $pending_delete_hash->{$key};
1608 if (%$pending_delete_hash) {
1609 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1611 delete $conf->{pending
}->{delete};
1615 sub vmconfig_register_unused_drive
{
1616 my ($storecfg, $vmid, $conf, $drive) = @_;
1618 if (!drive_is_cdrom
($drive)) {
1619 my $volid = $drive->{file
};
1620 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1621 add_unused_volume
($conf, $volid, $vmid);
1626 sub vmconfig_cleanup_pending
{
1629 # remove pending changes when nothing changed
1631 foreach my $opt (keys %{$conf->{pending
}}) {
1632 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1634 delete $conf->{pending
}->{$opt};
1638 my $current_delete_hash = split_flagged_list
($conf->{pending
}->{delete});
1639 my $pending_delete_hash = {};
1640 while (my ($opt, $force) = each %$current_delete_hash) {
1641 if (defined($conf->{$opt})) {
1642 $pending_delete_hash->{$opt} = $force;
1648 if (%$pending_delete_hash) {
1649 $conf->{pending
}->{delete} = join_flagged_list
(',', $pending_delete_hash);
1651 delete $conf->{pending
}->{delete};
1657 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1658 my $smbios1_desc = {
1661 pattern
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1662 format_description
=> 'UUID',
1668 format_description
=> 'str',
1674 format_description
=> 'str',
1680 format_description
=> 'name',
1686 format_description
=> 'name',
1692 format_description
=> 'str',
1698 format_description
=> 'str',
1706 my $res = eval { PVE
::JSONSchema
::parse_property_string
($smbios1_desc, $data) };
1713 return PVE
::JSONSchema
::print_property_string
($smbios1, $smbios1_desc);
1716 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', $smbios1_desc);
1718 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1719 sub verify_bootdisk
{
1720 my ($value, $noerr) = @_;
1722 return $value if valid_drivename
($value);
1724 return undef if $noerr;
1726 die "invalid boot disk '$value'\n";
1729 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1731 my ($value, $noerr) = @_;
1733 return $value if parse_numa
($value);
1735 return undef if $noerr;
1737 die "unable to parse numa options\n";
1740 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1742 my ($value, $noerr) = @_;
1744 return $value if parse_net
($value);
1746 return undef if $noerr;
1748 die "unable to parse network options\n";
1751 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1752 sub verify_hostpci
{
1753 my ($value, $noerr) = @_;
1755 return $value if parse_hostpci
($value);
1757 return undef if $noerr;
1759 die "unable to parse pci id\n";
1762 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1763 sub verify_watchdog
{
1764 my ($value, $noerr) = @_;
1766 return $value if parse_watchdog
($value);
1768 return undef if $noerr;
1770 die "unable to parse watchdog options\n";
1773 sub parse_watchdog
{
1776 return undef if !$value;
1780 foreach my $p (split(/,/, $value)) {
1781 next if $p =~ m/^\s*$/;
1783 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1785 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1786 $res->{action
} = $2;
1795 sub parse_usb_device
{
1798 return undef if !$value;
1800 my @dl = split(/,/, $value);
1804 foreach my $v (@dl) {
1805 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1807 $res->{vendorid
} = $2;
1808 $res->{productid
} = $4;
1809 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1811 $res->{hostbus
} = $1;
1812 $res->{hostport
} = $2;
1813 } elsif ($v =~ m/^spice$/) {
1820 return undef if !$found;
1825 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1826 sub verify_usb_device
{
1827 my ($value, $noerr) = @_;
1829 return $value if parse_usb_device
($value);
1831 return undef if $noerr;
1833 die "unable to parse usb device\n";
1836 # add JSON properties for create and set function
1837 sub json_config_properties
{
1840 foreach my $opt (keys %$confdesc) {
1841 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1842 $prop->{$opt} = $confdesc->{$opt};
1849 my ($key, $value) = @_;
1851 die "unknown setting '$key'\n" if !$confdesc->{$key};
1853 my $type = $confdesc->{$key}->{type
};
1855 if (!defined($value)) {
1856 die "got undefined value\n";
1859 if ($value =~ m/[\n\r]/) {
1860 die "property contains a line feed\n";
1863 if ($type eq 'boolean') {
1864 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1865 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1866 die "type check ('boolean') failed - got '$value'\n";
1867 } elsif ($type eq 'integer') {
1868 return int($1) if $value =~ m/^(\d+)$/;
1869 die "type check ('integer') failed - got '$value'\n";
1870 } elsif ($type eq 'number') {
1871 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1872 die "type check ('number') failed - got '$value'\n";
1873 } elsif ($type eq 'string') {
1874 if (my $fmt = $confdesc->{$key}->{format
}) {
1875 if ($fmt eq 'pve-qm-drive') {
1876 # special case - we need to pass $key to parse_drive()
1877 my $drive = parse_drive
($key, $value);
1878 return $value if $drive;
1879 die "unable to parse drive options\n";
1881 PVE
::JSONSchema
::check_format
($fmt, $value);
1884 $value =~ s/^\"(.*)\"$/$1/;
1887 die "internal error"
1891 sub lock_config_full
{
1892 my ($vmid, $timeout, $code, @param) = @_;
1894 my $filename = config_file_lock
($vmid);
1896 my $res = lock_file
($filename, $timeout, $code, @param);
1903 sub lock_config_mode
{
1904 my ($vmid, $timeout, $shared, $code, @param) = @_;
1906 my $filename = config_file_lock
($vmid);
1908 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1916 my ($vmid, $code, @param) = @_;
1918 return lock_config_full
($vmid, 10, $code, @param);
1921 sub cfs_config_path
{
1922 my ($vmid, $node) = @_;
1924 $node = $nodename if !$node;
1925 return "nodes/$node/qemu-server/$vmid.conf";
1928 sub check_iommu_support
{
1929 #fixme : need to check IOMMU support
1930 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1938 my ($vmid, $node) = @_;
1940 my $cfspath = cfs_config_path
($vmid, $node);
1941 return "/etc/pve/$cfspath";
1944 sub config_file_lock
{
1947 return "$lock_dir/lock-$vmid.conf";
1953 my $conf = config_file
($vmid);
1954 utime undef, undef, $conf;
1958 my ($storecfg, $vmid, $keep_empty_config) = @_;
1960 my $conffile = config_file
($vmid);
1962 my $conf = load_config
($vmid);
1966 # only remove disks owned by this VM
1967 foreach_drive
($conf, sub {
1968 my ($ds, $drive) = @_;
1970 return if drive_is_cdrom
($drive);
1972 my $volid = $drive->{file
};
1974 return if !$volid || $volid =~ m
|^/|;
1976 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1977 return if !$path || !$owner || ($owner != $vmid);
1979 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1982 if ($keep_empty_config) {
1983 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1988 # also remove unused disk
1990 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1993 PVE
::Storage
::foreach_volid
($dl, sub {
1994 my ($volid, $sid, $volname, $d) = @_;
1995 PVE
::Storage
::vdisk_free
($storecfg, $volid);
2005 my ($vmid, $node) = @_;
2007 my $cfspath = cfs_config_path
($vmid, $node);
2009 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
2011 die "no such VM ('$vmid')\n" if !defined($conf);
2016 sub parse_vm_config
{
2017 my ($filename, $raw) = @_;
2019 return undef if !defined($raw);
2022 digest
=> Digest
::SHA
::sha1_hex
($raw),
2027 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
2028 || die "got strange filename '$filename'";
2036 my @lines = split(/\n/, $raw);
2037 foreach my $line (@lines) {
2038 next if $line =~ m/^\s*$/;
2040 if ($line =~ m/^\[PENDING\]\s*$/i) {
2041 $section = 'pending';
2042 if (defined($descr)) {
2044 $conf->{description
} = $descr;
2047 $conf = $res->{$section} = {};
2050 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
2052 if (defined($descr)) {
2054 $conf->{description
} = $descr;
2057 $conf = $res->{snapshots
}->{$section} = {};
2061 if ($line =~ m/^\#(.*)\s*$/) {
2062 $descr = '' if !defined($descr);
2063 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
2067 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
2068 $descr = '' if !defined($descr);
2069 $descr .= PVE
::Tools
::decode_text
($2);
2070 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
2071 $conf->{snapstate
} = $1;
2072 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
2075 $conf->{$key} = $value;
2076 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
2078 if ($section eq 'pending') {
2079 $conf->{delete} = $value; # we parse this later
2081 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
2083 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
2086 eval { $value = check_type
($key, $value); };
2088 warn "vm $vmid - unable to parse value of '$key' - $@";
2090 my $fmt = $confdesc->{$key}->{format
};
2091 if ($fmt && $fmt eq 'pve-qm-drive') {
2092 my $v = parse_drive
($key, $value);
2093 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
2094 $v->{file
} = $volid;
2095 $value = print_drive
($vmid, $v);
2097 warn "vm $vmid - unable to parse value of '$key'\n";
2102 if ($key eq 'cdrom') {
2103 $conf->{ide2
} = $value;
2105 $conf->{$key} = $value;
2111 if (defined($descr)) {
2113 $conf->{description
} = $descr;
2115 delete $res->{snapstate
}; # just to be sure
2120 sub write_vm_config
{
2121 my ($filename, $conf) = @_;
2123 delete $conf->{snapstate
}; # just to be sure
2125 if ($conf->{cdrom
}) {
2126 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
2127 $conf->{ide2
} = $conf->{cdrom
};
2128 delete $conf->{cdrom
};
2131 # we do not use 'smp' any longer
2132 if ($conf->{sockets
}) {
2133 delete $conf->{smp
};
2134 } elsif ($conf->{smp
}) {
2135 $conf->{sockets
} = $conf->{smp
};
2136 delete $conf->{cores
};
2137 delete $conf->{smp
};
2140 my $used_volids = {};
2142 my $cleanup_config = sub {
2143 my ($cref, $pending, $snapname) = @_;
2145 foreach my $key (keys %$cref) {
2146 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
2147 $key eq 'snapstate' || $key eq 'pending';
2148 my $value = $cref->{$key};
2149 if ($key eq 'delete') {
2150 die "propertry 'delete' is only allowed in [PENDING]\n"
2152 # fixme: check syntax?
2155 eval { $value = check_type
($key, $value); };
2156 die "unable to parse value of '$key' - $@" if $@;
2158 $cref->{$key} = $value;
2160 if (!$snapname && valid_drivename
($key)) {
2161 my $drive = parse_drive
($key, $value);
2162 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2167 &$cleanup_config($conf);
2169 &$cleanup_config($conf->{pending
}, 1);
2171 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2172 die "internal error" if $snapname eq 'pending';
2173 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2176 # remove 'unusedX' settings if we re-add a volume
2177 foreach my $key (keys %$conf) {
2178 my $value = $conf->{$key};
2179 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2180 delete $conf->{$key};
2184 my $generate_raw_config = sub {
2185 my ($conf, $pending) = @_;
2189 # add description as comment to top of file
2190 if (defined(my $descr = $conf->{description
})) {
2192 foreach my $cl (split(/\n/, $descr)) {
2193 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2196 $raw .= "#\n" if $pending;
2200 foreach my $key (sort keys %$conf) {
2201 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2202 $raw .= "$key: $conf->{$key}\n";
2207 my $raw = &$generate_raw_config($conf);
2209 if (scalar(keys %{$conf->{pending
}})){
2210 $raw .= "\n[PENDING]\n";
2211 $raw .= &$generate_raw_config($conf->{pending
}, 1);
2214 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2215 $raw .= "\n[$snapname]\n";
2216 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2222 sub update_config_nolock
{
2223 my ($vmid, $conf, $skiplock) = @_;
2225 check_lock
($conf) if !$skiplock;
2227 my $cfspath = cfs_config_path
($vmid);
2229 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2233 my ($vmid, $conf, $skiplock) = @_;
2235 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2242 # we use static defaults from our JSON schema configuration
2243 foreach my $key (keys %$confdesc) {
2244 if (defined(my $default = $confdesc->{$key}->{default})) {
2245 $res->{$key} = $default;
2249 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2250 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2256 my $vmlist = PVE
::Cluster
::get_vmlist
();
2258 return $res if !$vmlist || !$vmlist->{ids
};
2259 my $ids = $vmlist->{ids
};
2261 foreach my $vmid (keys %$ids) {
2262 my $d = $ids->{$vmid};
2263 next if !$d->{node
} || $d->{node
} ne $nodename;
2264 next if !$d->{type
} || $d->{type
} ne 'qemu';
2265 $res->{$vmid}->{exists} = 1;
2270 # test if VM uses local resources (to prevent migration)
2271 sub check_local_resources
{
2272 my ($conf, $noerr) = @_;
2276 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2277 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2279 foreach my $k (keys %$conf) {
2280 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2281 # sockets are safe: they will recreated be on the target side post-migrate
2282 next if $k =~ m/^serial/ && ($conf->{$k} eq 'socket');
2283 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2286 die "VM uses local resources\n" if $loc_res && !$noerr;
2291 # check if used storages are available on all nodes (use by migrate)
2292 sub check_storage_availability
{
2293 my ($storecfg, $conf, $node) = @_;
2295 foreach_drive
($conf, sub {
2296 my ($ds, $drive) = @_;
2298 my $volid = $drive->{file
};
2301 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2304 # check if storage is available on both nodes
2305 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2306 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2310 # list nodes where all VM images are available (used by has_feature API)
2312 my ($conf, $storecfg) = @_;
2314 my $nodelist = PVE
::Cluster
::get_nodelist
();
2315 my $nodehash = { map { $_ => 1 } @$nodelist };
2316 my $nodename = PVE
::INotify
::nodename
();
2318 foreach_drive
($conf, sub {
2319 my ($ds, $drive) = @_;
2321 my $volid = $drive->{file
};
2324 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2326 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2327 if ($scfg->{disable
}) {
2329 } elsif (my $avail = $scfg->{nodes
}) {
2330 foreach my $node (keys %$nodehash) {
2331 delete $nodehash->{$node} if !$avail->{$node};
2333 } elsif (!$scfg->{shared
}) {
2334 foreach my $node (keys %$nodehash) {
2335 delete $nodehash->{$node} if $node ne $nodename
2347 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2351 my ($pidfile, $pid) = @_;
2353 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2357 return undef if !$line;
2358 my @param = split(/\0/, $line);
2360 my $cmd = $param[0];
2361 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2363 for (my $i = 0; $i < scalar (@param); $i++) {
2366 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2367 my $p = $param[$i+1];
2368 return 1 if $p && ($p eq $pidfile);
2377 my ($vmid, $nocheck, $node) = @_;
2379 my $filename = config_file
($vmid, $node);
2381 die "unable to find configuration file for VM $vmid - no such machine\n"
2382 if !$nocheck && ! -f
$filename;
2384 my $pidfile = pidfile_name
($vmid);
2386 if (my $fd = IO
::File-
>new("<$pidfile")) {
2391 my $mtime = $st->mtime;
2392 if ($mtime > time()) {
2393 warn "file '$filename' modified in future\n";
2396 if ($line =~ m/^(\d+)$/) {
2398 if (check_cmdline
($pidfile, $pid)) {
2399 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2411 my $vzlist = config_list
();
2413 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2415 while (defined(my $de = $fd->read)) {
2416 next if $de !~ m/^(\d+)\.pid$/;
2418 next if !defined($vzlist->{$vmid});
2419 if (my $pid = check_running
($vmid)) {
2420 $vzlist->{$vmid}->{pid
} = $pid;
2428 my ($storecfg, $conf) = @_;
2430 my $bootdisk = $conf->{bootdisk
};
2431 return undef if !$bootdisk;
2432 return undef if !valid_drivename
($bootdisk);
2434 return undef if !$conf->{$bootdisk};
2436 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2437 return undef if !defined($drive);
2439 return undef if drive_is_cdrom
($drive);
2441 my $volid = $drive->{file
};
2442 return undef if !$volid;
2444 return $drive->{size
};
2447 my $last_proc_pid_stat;
2449 # get VM status information
2450 # This must be fast and should not block ($full == false)
2451 # We only query KVM using QMP if $full == true (this can be slow)
2453 my ($opt_vmid, $full) = @_;
2457 my $storecfg = PVE
::Storage
::config
();
2459 my $list = vzlist
();
2460 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2462 my $cpucount = $cpuinfo->{cpus
} || 1;
2464 foreach my $vmid (keys %$list) {
2465 next if $opt_vmid && ($vmid ne $opt_vmid);
2467 my $cfspath = cfs_config_path
($vmid);
2468 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2471 $d->{pid
} = $list->{$vmid}->{pid
};
2473 # fixme: better status?
2474 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2476 my $size = disksize
($storecfg, $conf);
2477 if (defined($size)) {
2478 $d->{disk
} = 0; # no info available
2479 $d->{maxdisk
} = $size;
2485 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2486 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2487 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2489 $d->{name
} = $conf->{name
} || "VM $vmid";
2490 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2492 if ($conf->{balloon
}) {
2493 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2494 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2505 $d->{diskwrite
} = 0;
2507 $d->{template
} = is_template
($conf);
2512 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2513 foreach my $dev (keys %$netdev) {
2514 next if $dev !~ m/^tap([1-9]\d*)i/;
2516 my $d = $res->{$vmid};
2519 $d->{netout
} += $netdev->{$dev}->{receive
};
2520 $d->{netin
} += $netdev->{$dev}->{transmit
};
2523 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2524 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2529 my $ctime = gettimeofday
;
2531 foreach my $vmid (keys %$list) {
2533 my $d = $res->{$vmid};
2534 my $pid = $d->{pid
};
2537 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2538 next if !$pstat; # not running
2540 my $used = $pstat->{utime} + $pstat->{stime
};
2542 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2544 if ($pstat->{vsize
}) {
2545 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2548 my $old = $last_proc_pid_stat->{$pid};
2550 $last_proc_pid_stat->{$pid} = {
2558 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2560 if ($dtime > 1000) {
2561 my $dutime = $used - $old->{used
};
2563 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2564 $last_proc_pid_stat->{$pid} = {
2570 $d->{cpu
} = $old->{cpu
};
2574 return $res if !$full;
2576 my $qmpclient = PVE
::QMPClient-
>new();
2578 my $ballooncb = sub {
2579 my ($vmid, $resp) = @_;
2581 my $info = $resp->{'return'};
2582 return if !$info->{max_mem
};
2584 my $d = $res->{$vmid};
2586 # use memory assigned to VM
2587 $d->{maxmem
} = $info->{max_mem
};
2588 $d->{balloon
} = $info->{actual
};
2590 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2591 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2592 $d->{freemem
} = $info->{free_mem
};
2595 $d->{ballooninfo
} = $info;
2598 my $blockstatscb = sub {
2599 my ($vmid, $resp) = @_;
2600 my $data = $resp->{'return'} || [];
2601 my $totalrdbytes = 0;
2602 my $totalwrbytes = 0;
2604 for my $blockstat (@$data) {
2605 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2606 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2608 $blockstat->{device
} =~ s/drive-//;
2609 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2611 $res->{$vmid}->{diskread
} = $totalrdbytes;
2612 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2615 my $statuscb = sub {
2616 my ($vmid, $resp) = @_;
2618 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2619 # this fails if ballon driver is not loaded, so this must be
2620 # the last commnand (following command are aborted if this fails).
2621 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2623 my $status = 'unknown';
2624 if (!defined($status = $resp->{'return'}->{status
})) {
2625 warn "unable to get VM status\n";
2629 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2632 foreach my $vmid (keys %$list) {
2633 next if $opt_vmid && ($vmid ne $opt_vmid);
2634 next if !$res->{$vmid}->{pid
}; # not running
2635 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2638 $qmpclient->queue_execute(undef, 1);
2640 foreach my $vmid (keys %$list) {
2641 next if $opt_vmid && ($vmid ne $opt_vmid);
2642 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2649 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2652 my $current_size = 1024;
2653 my $dimm_size = 512;
2654 return if $current_size == $memory;
2656 for (my $j = 0; $j < 8; $j++) {
2657 for (my $i = 0; $i < 32; $i++) {
2658 my $name = "dimm${dimm_id}";
2660 my $numanode = $i % $sockets;
2661 $current_size += $dimm_size;
2662 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2663 return $current_size if $current_size >= $memory;
2669 sub foreach_reverse_dimm
{
2670 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2673 my $current_size = 4177920;
2674 my $dimm_size = 65536;
2675 return if $current_size == $memory;
2677 for (my $j = 0; $j < 8; $j++) {
2678 for (my $i = 0; $i < 32; $i++) {
2679 my $name = "dimm${dimm_id}";
2681 my $numanode = $i % $sockets;
2682 $current_size -= $dimm_size;
2683 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2684 return $current_size if $current_size <= $memory;
2691 my ($conf, $func) = @_;
2693 foreach my $ds (keys %$conf) {
2694 next if !valid_drivename
($ds);
2696 my $drive = parse_drive
($ds, $conf->{$ds});
2699 &$func($ds, $drive);
2704 my ($conf, $func) = @_;
2708 my $test_volid = sub {
2709 my ($volid, $is_cdrom) = @_;
2713 $volhash->{$volid} = $is_cdrom || 0;
2716 foreach_drive
($conf, sub {
2717 my ($ds, $drive) = @_;
2718 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2721 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2722 my $snap = $conf->{snapshots
}->{$snapname};
2723 &$test_volid($snap->{vmstate
}, 0);
2724 foreach_drive
($snap, sub {
2725 my ($ds, $drive) = @_;
2726 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2730 foreach my $volid (keys %$volhash) {
2731 &$func($volid, $volhash->{$volid});
2735 sub vga_conf_has_spice
{
2738 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2743 sub config_to_command
{
2744 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2747 my $globalFlags = [];
2748 my $machineFlags = [];
2754 my $kvmver = kvm_user_version
();
2755 my $vernum = 0; # unknown
2756 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2757 $vernum = $1*1000000+$2*1000;
2758 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2759 $vernum = $1*1000000+$2*1000+$3;
2762 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2764 my $have_ovz = -f
'/proc/vz/vestat';
2766 my $q35 = machine_type_is_q35
($conf);
2767 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2768 my $machine_type = $forcemachine || $conf->{machine
};
2769 my $use_old_bios_files = undef;
2770 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
2772 my $cpuunits = defined($conf->{cpuunits
}) ?
2773 $conf->{cpuunits
} : $defaults->{cpuunits
};
2775 push @$cmd, '/usr/bin/systemd-run';
2776 push @$cmd, '--scope';
2777 push @$cmd, '--slice', "qemu";
2778 push @$cmd, '--unit', $vmid;
2779 # set KillMode=none, so that systemd don't kill those scopes
2780 # at shutdown (pve-manager service should stop the VMs instead)
2781 push @$cmd, '-p', "KillMode=none";
2782 push @$cmd, '-p', "CPUShares=$cpuunits";
2783 if ($conf->{cpulimit
}) {
2784 my $cpulimit = int($conf->{cpulimit
} * 100);
2785 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2788 push @$cmd, '/usr/bin/kvm';
2790 push @$cmd, '-id', $vmid;
2794 my $qmpsocket = qmp_socket
($vmid);
2795 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2796 push @$cmd, '-mon', "chardev=qmp,mode=control";
2798 my $socket = vnc_socket
($vmid);
2799 push @$cmd, '-vnc', "unix:$socket,x509,password";
2801 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2803 push @$cmd, '-daemonize';
2805 if ($conf->{smbios1
}) {
2806 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2809 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2810 my $ovmfvar = "OVMF_VARS-pure-efi.fd";
2811 my $ovmfvar_src = "/usr/share/kvm/$ovmfvar";
2812 my $ovmfvar_dst = "/tmp/$vmid-$ovmfvar";
2813 PVE
::Tools
::file_copy
($ovmfvar_src, $ovmfvar_dst, 256*1024);
2814 push @$cmd, '-drive', "if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd";
2815 push @$cmd, '-drive', "if=pflash,format=raw,file=$ovmfvar_dst";
2819 # the q35 chipset support native usb2, so we enable usb controller
2820 # by default for this machine type
2821 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2823 $pciaddr = print_pci_addr
("piix3", $bridges);
2824 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2827 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2828 next if !$conf->{"usb$i"};
2831 # include usb device config
2832 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2835 my $vga = $conf->{vga
};
2837 my $qxlnum = vga_conf_has_spice
($vga);
2838 $vga = 'qxl' if $qxlnum;
2841 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2842 $conf->{ostype
} eq 'win7' ||
2843 $conf->{ostype
} eq 'w2k8')) {
2850 # enable absolute mouse coordinates (needed by vnc)
2852 if (defined($conf->{tablet
})) {
2853 $tablet = $conf->{tablet
};
2855 $tablet = $defaults->{tablet
};
2856 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2857 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2860 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2864 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2865 my $d = parse_hostpci
($conf->{"hostpci$i"});
2868 my $pcie = $d->{pcie
};
2870 die "q35 machine model is not enabled" if !$q35;
2871 $pciaddr = print_pcie_addr
("hostpci$i");
2873 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2876 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2877 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2878 if ($xvga && $xvga ne '') {
2879 push @$cpuFlags, 'kvm=off';
2882 if ($conf->{bios
} && $conf->{bios
} eq 'ovmf') {
2886 my $pcidevices = $d->{pciid
};
2887 my $multifunction = 1 if @$pcidevices > 1;
2890 foreach my $pcidevice (@$pcidevices) {
2892 my $id = "hostpci$i";
2893 $id .= ".$j" if $multifunction;
2894 my $addr = $pciaddr;
2895 $addr .= ".$j" if $multifunction;
2896 my $devicestr = "vfio-pci,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2899 $devicestr .= "$rombar$xvga";
2900 $devicestr .= ",multifunction=on" if $multifunction;
2903 push @$devices, '-device', $devicestr;
2909 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2910 my $d = parse_usb_device
($conf->{"usb$i"});
2912 if ($d->{vendorid
} && $d->{productid
}) {
2913 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2914 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2915 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2916 } elsif ($d->{spice
}) {
2917 # usb redir support for spice
2918 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2919 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2924 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2925 if (my $path = $conf->{"serial$i"}) {
2926 if ($path eq 'socket') {
2927 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2928 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2929 push @$devices, '-device', "isa-serial,chardev=serial$i";
2931 die "no such serial device\n" if ! -c
$path;
2932 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2933 push @$devices, '-device', "isa-serial,chardev=serial$i";
2939 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2940 if (my $path = $conf->{"parallel$i"}) {
2941 die "no such parallel device\n" if ! -c
$path;
2942 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2943 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2944 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2948 my $vmname = $conf->{name
} || "vm$vmid";
2950 push @$cmd, '-name', $vmname;
2953 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2954 $sockets = $conf->{sockets
} if $conf->{sockets
};
2956 my $cores = $conf->{cores
} || 1;
2958 my $maxcpus = $sockets * $cores;
2960 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2962 my $allowed_vcpus = $cpuinfo->{cpus
};
2964 die "MAX $allowed_vcpus vcpus allowed per VM on this node\n"
2965 if ($allowed_vcpus < $maxcpus);
2967 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2969 push @$cmd, '-nodefaults';
2971 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2973 my $bootindex_hash = {};
2975 foreach my $o (split(//, $bootorder)) {
2976 $bootindex_hash->{$o} = $i*100;
2980 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2982 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2984 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2986 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2989 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2991 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2992 my $useLocaltime = $conf->{localtime};
2994 if (my $ost = $conf->{ostype
}) {
2995 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2997 if ($ost =~ m/^w/) { # windows
2998 $useLocaltime = 1 if !defined($conf->{localtime});
3000 # use time drift fix when acpi is enabled
3001 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
3002 $tdf = 1 if !defined($conf->{tdf
});
3006 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
3008 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
3009 push @$cmd, '-no-hpet';
3010 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3011 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm && !$nohyperv;
3012 push @$cpuFlags , 'hv_vapic' if !$nokvm && !$nohyperv;
3013 push @$cpuFlags , 'hv_time' if !$nokvm && !$nohyperv;
3016 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm && !$nohyperv;
3020 if ($ost eq 'win7' || $ost eq 'win8') {
3021 push @$cpuFlags , 'hv_relaxed' if !$nokvm && !$nohyperv;
3025 push @$rtcFlags, 'driftfix=slew' if $tdf;
3028 push @$machineFlags, 'accel=tcg';
3030 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
3033 if ($machine_type) {
3034 push @$machineFlags, "type=${machine_type}";
3037 if ($conf->{startdate
}) {
3038 push @$rtcFlags, "base=$conf->{startdate}";
3039 } elsif ($useLocaltime) {
3040 push @$rtcFlags, 'base=localtime';
3043 my $cpu = $nokvm ?
"qemu64" : "kvm64";
3044 $cpu = $conf->{cpu
} if $conf->{cpu
};
3046 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
3048 push @$cpuFlags , '-x2apic'
3049 if $conf->{ostype
} && $conf->{ostype
} eq 'solaris';
3051 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
3053 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
3055 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3057 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
3058 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
3061 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
3063 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
3065 push @$cmd, '-cpu', $cpu;
3067 my $memory = $conf->{memory
} || $defaults->{memory
};
3068 my $static_memory = 0;
3069 my $dimm_memory = 0;
3071 if ($hotplug_features->{memory
}) {
3072 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
3073 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
3074 $static_memory = $STATICMEM;
3075 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
3076 $dimm_memory = $memory - $static_memory;
3077 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
3081 $static_memory = $memory;
3082 push @$cmd, '-m', $static_memory;
3085 if ($conf->{numa
}) {
3087 my $numa_totalmemory = undef;
3088 for (my $i = 0; $i < $MAX_NUMA; $i++) {
3089 next if !$conf->{"numa$i"};
3090 my $numa = parse_numa
($conf->{"numa$i"});
3093 die "missing numa node$i memory value\n" if !$numa->{memory
};
3094 my $numa_memory = $numa->{memory
};
3095 $numa_totalmemory += $numa_memory;
3096 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
3099 my $cpus_start = $numa->{cpus
}->{start
};
3100 die "missing numa node$i cpus\n" if !defined($cpus_start);
3101 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
3102 my $cpus = $cpus_start;
3103 if (defined($cpus_end)) {
3104 $cpus .= "-$cpus_end";
3105 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
3109 my $hostnodes_start = $numa->{hostnodes
}->{start
};
3110 if (defined($hostnodes_start)) {
3111 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
3112 my $hostnodes = $hostnodes_start;
3113 if (defined($hostnodes_end)) {
3114 $hostnodes .= "-$hostnodes_end";
3115 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
3118 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
3119 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
3120 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
3124 my $policy = $numa->{policy
};
3125 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
3126 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
3129 push @$cmd, '-object', $numa_object;
3130 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3133 die "total memory for NUMA nodes must be equal to vm static memory\n"
3134 if $numa_totalmemory && $numa_totalmemory != $static_memory;
3136 #if no custom tology, we split memory and cores across numa nodes
3137 if(!$numa_totalmemory) {
3139 my $numa_memory = ($static_memory / $sockets) . "M";
3141 for (my $i = 0; $i < $sockets; $i++) {
3143 my $cpustart = ($cores * $i);
3144 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
3145 my $cpus = $cpustart;
3146 $cpus .= "-$cpuend" if $cpuend;
3148 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
3149 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
3154 if ($hotplug_features->{memory
}) {
3155 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
3156 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3157 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
3158 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
3160 #if dimm_memory is not aligned to dimm map
3161 if($current_size > $memory) {
3162 $conf->{memory
} = $current_size;
3163 update_config_nolock
($vmid, $conf, 1);
3168 push @$cmd, '-S' if $conf->{freeze
};
3170 # set keyboard layout
3171 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
3172 push @$cmd, '-k', $kb if $kb;
3175 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
3176 #push @$cmd, '-soundhw', 'es1370';
3177 #push @$cmd, '-soundhw', $soundhw if $soundhw;
3179 if($conf->{agent
}) {
3180 my $qgasocket = qmp_socket
($vmid, 1);
3181 my $pciaddr = print_pci_addr
("qga0", $bridges);
3182 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
3183 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
3184 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3191 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3192 for(my $i = 1; $i < $qxlnum; $i++){
3193 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3194 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3197 # assume other OS works like Linux
3198 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3199 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3203 my $pciaddr = print_pci_addr
("spice", $bridges);
3205 my $nodename = PVE
::INotify
::nodename
();
3206 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3207 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3209 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3211 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3212 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3213 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3216 # enable balloon by default, unless explicitly disabled
3217 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3218 $pciaddr = print_pci_addr
("balloon0", $bridges);
3219 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3222 if ($conf->{watchdog
}) {
3223 my $wdopts = parse_watchdog
($conf->{watchdog
});
3224 $pciaddr = print_pci_addr
("watchdog", $bridges);
3225 my $watchdog = $wdopts->{model
} || 'i6300esb';
3226 push @$devices, '-device', "$watchdog$pciaddr";
3227 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3231 my $scsicontroller = {};
3232 my $ahcicontroller = {};
3233 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3235 # Add iscsi initiator name if available
3236 if (my $initiator = get_initiator_name
()) {
3237 push @$devices, '-iscsi', "initiator-name=$initiator";
3240 foreach_drive
($conf, sub {
3241 my ($ds, $drive) = @_;
3243 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3244 push @$vollist, $drive->{file
};
3247 $use_virtio = 1 if $ds =~ m/^virtio/;
3249 if (drive_is_cdrom
($drive)) {
3250 if ($bootindex_hash->{d
}) {
3251 $drive->{bootindex
} = $bootindex_hash->{d
};
3252 $bootindex_hash->{d
} += 1;
3255 if ($bootindex_hash->{c
}) {
3256 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3257 $bootindex_hash->{c
} += 1;
3261 if($drive->{interface
} eq 'virtio'){
3262 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3265 if ($drive->{interface
} eq 'scsi') {
3267 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3269 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3270 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3273 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3274 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3275 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3279 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3280 $queues = ",num_queues=$drive->{queues}";
3283 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3284 $scsicontroller->{$controller}=1;
3287 if ($drive->{interface
} eq 'sata') {
3288 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3289 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3290 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3291 $ahcicontroller->{$controller}=1;
3294 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3295 push @$devices, '-drive',$drive_cmd;
3296 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3299 for (my $i = 0; $i < $MAX_NETS; $i++) {
3300 next if !$conf->{"net$i"};
3301 my $d = parse_net
($conf->{"net$i"});
3304 $use_virtio = 1 if $d->{model
} eq 'virtio';
3306 if ($bootindex_hash->{n
}) {
3307 $d->{bootindex
} = $bootindex_hash->{n
};
3308 $bootindex_hash->{n
} += 1;
3311 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3312 push @$devices, '-netdev', $netdevfull;
3314 my $netdevicefull = print_netdevice_full
($vmid, $conf, $d, "net$i", $bridges, $use_old_bios_files);
3315 push @$devices, '-device', $netdevicefull;
3320 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3325 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3327 while (my ($k, $v) = each %$bridges) {
3328 $pciaddr = print_pci_addr
("pci.$k");
3329 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3334 if ($conf->{args
}) {
3335 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3339 push @$cmd, @$devices;
3340 push @$cmd, '-rtc', join(',', @$rtcFlags)
3341 if scalar(@$rtcFlags);
3342 push @$cmd, '-machine', join(',', @$machineFlags)
3343 if scalar(@$machineFlags);
3344 push @$cmd, '-global', join(',', @$globalFlags)
3345 if scalar(@$globalFlags);
3347 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3352 return "${var_run_tmpdir}/$vmid.vnc";
3358 my $res = vm_mon_cmd
($vmid, 'query-spice');
3360 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3364 my ($vmid, $qga) = @_;
3365 my $sockettype = $qga ?
'qga' : 'qmp';
3366 return "${var_run_tmpdir}/$vmid.$sockettype";
3371 return "${var_run_tmpdir}/$vmid.pid";
3374 sub vm_devices_list
{
3377 my $res = vm_mon_cmd
($vmid, 'query-pci');
3379 foreach my $pcibus (@$res) {
3380 foreach my $device (@{$pcibus->{devices
}}) {
3381 next if !$device->{'qdev_id'};
3382 if ($device->{'pci_bridge'}) {
3383 $devices->{$device->{'qdev_id'}} = 1;
3384 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3385 next if !$bridge_device->{'qdev_id'};
3386 $devices->{$bridge_device->{'qdev_id'}} = 1;
3387 $devices->{$device->{'qdev_id'}}++;
3390 $devices->{$device->{'qdev_id'}} = 1;
3395 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3396 foreach my $block (@$resblock) {
3397 if($block->{device
} =~ m/^drive-(\S+)/){
3402 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3403 foreach my $mice (@$resmice) {
3404 if ($mice->{name
} eq 'QEMU HID Tablet') {
3405 $devices->{tablet
} = 1;
3414 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3416 my $q35 = machine_type_is_q35
($conf);
3418 my $devices_list = vm_devices_list
($vmid);
3419 return 1 if defined($devices_list->{$deviceid});
3421 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3423 if ($deviceid eq 'tablet') {
3425 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3427 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3429 qemu_iothread_add
($vmid, $deviceid, $device);
3431 qemu_driveadd
($storecfg, $vmid, $device);
3432 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3434 qemu_deviceadd
($vmid, $devicefull);
3435 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3437 eval { qemu_drivedel
($vmid, $deviceid); };
3442 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3445 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3446 my $pciaddr = print_pci_addr
($deviceid);
3447 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3449 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3451 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3452 qemu_iothread_add
($vmid, $deviceid, $device);
3453 $devicefull .= ",iothread=iothread-$deviceid";
3456 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3457 $devicefull .= ",num_queues=$device->{queues}";
3460 qemu_deviceadd
($vmid, $devicefull);
3461 qemu_deviceaddverify
($vmid, $deviceid);
3463 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3465 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3466 qemu_driveadd
($storecfg, $vmid, $device);
3468 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3469 eval { qemu_deviceadd
($vmid, $devicefull); };
3471 eval { qemu_drivedel
($vmid, $deviceid); };
3476 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3478 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3480 my $machine_type = PVE
::QemuServer
::qemu_machine_pxe
($vmid, $conf);
3481 my $use_old_bios_files = undef;
3482 ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files
($machine_type);
3484 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid, undef, $use_old_bios_files);
3485 qemu_deviceadd
($vmid, $netdevicefull);
3486 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3488 eval { qemu_netdevdel
($vmid, $deviceid); };
3493 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3496 my $pciaddr = print_pci_addr
($deviceid);
3497 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3499 qemu_deviceadd
($vmid, $devicefull);
3500 qemu_deviceaddverify
($vmid, $deviceid);
3503 die "can't hotplug device '$deviceid'\n";
3509 # fixme: this should raise exceptions on error!
3510 sub vm_deviceunplug
{
3511 my ($vmid, $conf, $deviceid) = @_;
3513 my $devices_list = vm_devices_list
($vmid);
3514 return 1 if !defined($devices_list->{$deviceid});
3516 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3518 if ($deviceid eq 'tablet') {
3520 qemu_devicedel
($vmid, $deviceid);
3522 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3524 qemu_devicedel
($vmid, $deviceid);
3525 qemu_devicedelverify
($vmid, $deviceid);
3526 qemu_drivedel
($vmid, $deviceid);
3527 qemu_iothread_del
($conf, $vmid, $deviceid);
3529 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3531 qemu_devicedel
($vmid, $deviceid);
3532 qemu_devicedelverify
($vmid, $deviceid);
3533 qemu_iothread_del
($conf, $vmid, $deviceid);
3535 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3537 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3538 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3539 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3541 qemu_devicedel
($vmid, $deviceid);
3542 qemu_drivedel
($vmid, $deviceid);
3543 qemu_deletescsihw
($conf, $vmid, $deviceid);
3545 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3547 qemu_devicedel
($vmid, $deviceid);
3548 qemu_devicedelverify
($vmid, $deviceid);
3549 qemu_netdevdel
($vmid, $deviceid);
3552 die "can't unplug device '$deviceid'\n";
3558 sub qemu_deviceadd
{
3559 my ($vmid, $devicefull) = @_;
3561 $devicefull = "driver=".$devicefull;
3562 my %options = split(/[=,]/, $devicefull);
3564 vm_mon_cmd
($vmid, "device_add" , %options);
3567 sub qemu_devicedel
{
3568 my ($vmid, $deviceid) = @_;
3570 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3573 sub qemu_iothread_add
{
3574 my($vmid, $deviceid, $device) = @_;
3576 if ($device->{iothread
}) {
3577 my $iothreads = vm_iothreads_list
($vmid);
3578 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3582 sub qemu_iothread_del
{
3583 my($conf, $vmid, $deviceid) = @_;
3585 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3586 if ($device->{iothread
}) {
3587 my $iothreads = vm_iothreads_list
($vmid);
3588 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3592 sub qemu_objectadd
{
3593 my($vmid, $objectid, $qomtype) = @_;
3595 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3600 sub qemu_objectdel
{
3601 my($vmid, $objectid) = @_;
3603 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3609 my ($storecfg, $vmid, $device) = @_;
3611 my $drive = print_drive_full
($storecfg, $vmid, $device);
3612 $drive =~ s/\\/\\\\/g;
3613 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3615 # If the command succeeds qemu prints: "OK
"
3616 return 1 if $ret =~ m/OK/s;
3618 die "adding drive failed
: $ret\n";
3622 my($vmid, $deviceid) = @_;
3624 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3627 return 1 if $ret eq "";
3629 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3630 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3632 die "deleting drive
$deviceid failed
: $ret\n";
3635 sub qemu_deviceaddverify {
3636 my ($vmid, $deviceid) = @_;
3638 for (my $i = 0; $i <= 5; $i++) {
3639 my $devices_list = vm_devices_list($vmid);
3640 return 1 if defined($devices_list->{$deviceid});
3644 die "error on hotplug device
'$deviceid'\n";
3648 sub qemu_devicedelverify {
3649 my ($vmid, $deviceid) = @_;
3651 # need to verify that the device is correctly removed as device_del
3652 # is async and empty return is not reliable
3654 for (my $i = 0; $i <= 5; $i++) {
3655 my $devices_list = vm_devices_list($vmid);
3656 return 1 if !defined($devices_list->{$deviceid});
3660 die "error on hot-unplugging device
'$deviceid'\n";
3663 sub qemu_findorcreatescsihw {
3664 my ($storecfg, $conf, $vmid, $device) = @_;
3666 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3668 my $scsihwid="$controller_prefix$controller";
3669 my $devices_list = vm_devices_list($vmid);
3671 if(!defined($devices_list->{$scsihwid})) {
3672 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3678 sub qemu_deletescsihw {
3679 my ($conf, $vmid, $opt) = @_;
3681 my $device = parse_drive($opt, $conf->{$opt});
3683 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3684 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3688 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3690 my $devices_list = vm_devices_list($vmid);
3691 foreach my $opt (keys %{$devices_list}) {
3692 if (PVE::QemuServer::valid_drivename($opt)) {
3693 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3694 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3700 my $scsihwid="scsihw
$controller";
3702 vm_deviceunplug($vmid, $conf, $scsihwid);
3707 sub qemu_add_pci_bridge {
3708 my ($storecfg, $conf, $vmid, $device) = @_;
3714 print_pci_addr($device, $bridges);
3716 while (my ($k, $v) = each %$bridges) {
3719 return 1 if !defined($bridgeid) || $bridgeid < 1;
3721 my $bridge = "pci
.$bridgeid";
3722 my $devices_list = vm_devices_list($vmid);
3724 if (!defined($devices_list->{$bridge})) {
3725 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3731 sub qemu_set_link_status {
3732 my ($vmid, $device, $up) = @_;
3734 vm_mon_cmd($vmid, "set_link
", name => $device,
3735 up => $up ? JSON::true : JSON::false);
3738 sub qemu_netdevadd {
3739 my ($vmid, $conf, $device, $deviceid) = @_;
3741 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid, 1);
3742 my %options = split(/[=,]/, $netdev);
3744 vm_mon_cmd($vmid, "netdev_add
", %options);
3748 sub qemu_netdevdel {
3749 my ($vmid, $deviceid) = @_;
3751 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3754 sub qemu_cpu_hotplug {
3755 my ($vmid, $conf, $vcpus) = @_;
3758 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3759 $sockets = $conf->{sockets} if $conf->{sockets};
3760 my $cores = $conf->{cores} || 1;
3761 my $maxcpus = $sockets * $cores;
3763 $vcpus = $maxcpus if !$vcpus;
3765 die "you can
't add more vcpus than maxcpus\n"
3766 if $vcpus > $maxcpus;
3768 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3769 die "online cpu unplug is not yet possible\n"
3770 if $vcpus < $currentvcpus;
3772 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3773 die "vcpus in running vm is different than configuration\n"
3774 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3776 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3777 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3781 sub qemu_memory_hotplug {
3782 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3784 return $value if !check_running($vmid);
3786 my $memory = $conf->{memory} || $defaults->{memory};
3787 $value = $defaults->{memory} if !$value;
3788 return $value if $value == $memory;
3790 my $static_memory = $STATICMEM;
3791 my $dimm_memory = $memory - $static_memory;
3793 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3794 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3798 $sockets = $conf->{sockets} if $conf->{sockets};
3800 if($value > $memory) {
3802 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3803 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3805 return if $current_size <= $conf->{memory};
3807 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3809 eval { qemu_objectdel($vmid, "mem-
$name"); };
3813 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3815 eval { qemu_objectdel($vmid, "mem-
$name"); };
3818 #update conf after each succesful module hotplug
3819 $conf->{memory} = $current_size;
3820 update_config_nolock($vmid, $conf, 1);
3825 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3826 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3828 return if $current_size >= $conf->{memory};
3829 print "try to unplug memory dimm
$name\n";
3833 eval { qemu_devicedel($vmid, $name) };
3835 my $dimm_list = qemu_dimm_list($vmid);
3836 last if !$dimm_list->{$name};
3837 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3841 #update conf after each succesful module unplug
3842 $conf->{memory} = $current_size;
3844 eval { qemu_objectdel($vmid, "mem-
$name"); };
3845 update_config_nolock($vmid, $conf, 1);
3850 sub qemu_dimm_list {
3853 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3856 foreach my $dimm (@$dimmarray) {
3858 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3859 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3860 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3861 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3862 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3867 sub qemu_block_set_io_throttle {
3868 my ($vmid, $deviceid,
3869 $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr,
3870 $bps_max, $bps_rd_max, $bps_wr_max, $iops_max, $iops_rd_max, $iops_wr_max) = @_;
3872 return if !check_running($vmid) ;
3874 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid,
3876 bps_rd => int($bps_rd),
3877 bps_wr => int($bps_wr),
3879 iops_rd => int($iops_rd),
3880 iops_wr => int($iops_wr),
3881 bps_max => int($bps_max),
3882 bps_rd_max => int($bps_rd_max),
3883 bps_wr_max => int($bps_wr_max),
3884 iops_max => int($iops_max),
3885 iops_rd_max => int($iops_rd_max),
3886 iops_wr_max => int($iops_wr_max)
3891 # old code, only used to shutdown old VM after update
3893 my ($fh, $timeout) = @_;
3895 my $sel = new IO::Select;
3902 while (scalar (@ready = $sel->can_read($timeout))) {
3904 if ($count = $fh->sysread($buf, 8192)) {
3905 if ($buf =~ /^(.*)\(qemu\) $/s) {
3912 if (!defined($count)) {
3919 die "monitor
read timeout
\n" if !scalar(@ready);
3924 # old code, only used to shutdown old VM after update
3925 sub vm_monitor_command {
3926 my ($vmid, $cmdstr, $nocheck) = @_;
3931 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3933 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3935 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3936 die "unable to
connect to VM
$vmid socket - $!\n";
3940 # hack: migrate sometime blocks the monitor (when migrate_downtime
3942 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3943 $timeout = 60*60; # 1 hour
3947 my $data = __read_avail($sock, $timeout);
3949 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3950 die "got unexpected qemu monitor banner
\n";
3953 my $sel = new IO::Select;
3956 if (!scalar(my @ready = $sel->can_write($timeout))) {
3957 die "monitor
write error
- timeout
";
3960 my $fullcmd = "$cmdstr\r";
3962 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3965 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3966 die "monitor
write error
- $!";
3969 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3973 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3974 $timeout = 60*60; # 1 hour
3975 } elsif ($cmdstr =~ m/^(eject|change)/) {
3976 $timeout = 60; # note: cdrom mount command is slow
3978 if ($res = __read_avail($sock, $timeout)) {
3980 my @lines = split("\r?
\n", $res);
3982 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3984 $res = join("\n", @lines);
3992 syslog("err
", "VM
$vmid monitor command failed
- $err");
3999 sub qemu_block_resize {
4000 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
4002 my $running = check_running($vmid);
4004 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
4006 return if !$running;
4008 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
4012 sub qemu_volume_snapshot {
4013 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4015 my $running = check_running($vmid);
4017 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
4018 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
4020 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
4024 sub qemu_volume_snapshot_delete {
4025 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
4027 my $running = check_running($vmid);
4029 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
4031 return if !$running;
4033 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
4036 sub set_migration_caps {
4042 "auto-converge
" => 1,
4044 "x-rdma-pin-all
" => 0,
4049 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
4051 for my $supported_capability (@$supported_capabilities) {
4053 capability => $supported_capability->{capability},
4054 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
4058 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
4061 my $fast_plug_option = {
4070 # hotplug changes in [PENDING]
4071 # $selection hash can be used to only apply specified options, for
4072 # example: { cores => 1 } (only apply changed 'cores')
4073 # $errors ref is used to return error messages
4074 sub vmconfig_hotplug_pending {
4075 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
4077 my $defaults = load_defaults();
4079 # commit values which do not have any impact on running VM first
4080 # Note: those option cannot raise errors, we we do not care about
4081 # $selection and always apply them.
4083 my $add_error = sub {
4084 my ($opt, $msg) = @_;
4085 $errors->{$opt} = "hotplug problem
- $msg";
4089 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4090 if ($fast_plug_option->{$opt}) {
4091 $conf->{$opt} = $conf->{pending}->{$opt};
4092 delete $conf->{pending}->{$opt};
4098 update_config_nolock($vmid, $conf, 1);
4099 $conf = load_config($vmid); # update/reload
4102 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
4104 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4105 while (my ($opt, $force) = each %$pending_delete_hash) {
4106 next if $selection && !$selection->{$opt};
4108 if ($opt eq 'hotplug') {
4109 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
4110 } elsif ($opt eq 'tablet') {
4111 die "skip
\n" if !$hotplug_features->{usb};
4112 if ($defaults->{tablet}) {
4113 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4115 vm_deviceunplug($vmid, $conf, $opt);
4117 } elsif ($opt eq 'vcpus') {
4118 die "skip
\n" if !$hotplug_features->{cpu};
4119 qemu_cpu_hotplug($vmid, $conf, undef);
4120 } elsif ($opt eq 'balloon') {
4121 # enable balloon device is not hotpluggable
4122 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
4123 } elsif ($fast_plug_option->{$opt}) {
4125 } elsif ($opt =~ m/^net(\d+)$/) {
4126 die "skip
\n" if !$hotplug_features->{network};
4127 vm_deviceunplug($vmid, $conf, $opt);
4128 } elsif (valid_drivename($opt)) {
4129 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
4130 vm_deviceunplug($vmid, $conf, $opt);
4131 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4132 } elsif ($opt =~ m/^memory$/) {
4133 die "skip
\n" if !$hotplug_features->{memory};
4134 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
4135 } elsif ($opt eq 'cpuunits') {
4136 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
4137 } elsif ($opt eq 'cpulimit') {
4138 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
4144 &$add_error($opt, $err) if $err ne "skip
\n";
4146 # save new config if hotplug was successful
4147 delete $conf->{$opt};
4148 vmconfig_undelete_pending_option($conf, $opt);
4149 update_config_nolock($vmid, $conf, 1);
4150 $conf = load_config($vmid); # update/reload
4154 foreach my $opt (keys %{$conf->{pending}}) {
4155 next if $selection && !$selection->{$opt};
4156 my $value = $conf->{pending}->{$opt};
4158 if ($opt eq 'hotplug') {
4159 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
4160 } elsif ($opt eq 'tablet') {
4161 die "skip
\n" if !$hotplug_features->{usb};
4163 vm_deviceplug($storecfg, $conf, $vmid, $opt);
4164 } elsif ($value == 0) {
4165 vm_deviceunplug($vmid, $conf, $opt);
4167 } elsif ($opt eq 'vcpus') {
4168 die "skip
\n" if !$hotplug_features->{cpu};
4169 qemu_cpu_hotplug($vmid, $conf, $value);
4170 } elsif ($opt eq 'balloon') {
4171 # enable/disable balloning device is not hotpluggable
4172 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
4173 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
4174 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
4176 # allow manual ballooning if shares is set to zero
4177 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
4178 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
4179 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
4181 } elsif ($opt =~ m/^net(\d+)$/) {
4182 # some changes can be done without hotplug
4183 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
4184 $vmid, $opt, $value);
4185 } elsif (valid_drivename($opt)) {
4186 # some changes can be done without hotplug
4187 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
4188 $vmid, $opt, $value, 1);
4189 } elsif ($opt =~ m/^memory$/) { #dimms
4190 die "skip
\n" if !$hotplug_features->{memory};
4191 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
4192 } elsif ($opt eq 'cpuunits') {
4193 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
4194 } elsif ($opt eq 'cpulimit') {
4195 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
4196 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
4198 die "skip
\n"; # skip non-hot-pluggable options
4202 &$add_error($opt, $err) if $err ne "skip
\n";
4204 # save new config if hotplug was successful
4205 $conf->{$opt} = $value;
4206 delete $conf->{pending}->{$opt};
4207 update_config_nolock($vmid, $conf, 1);
4208 $conf = load_config($vmid); # update/reload
4213 sub try_deallocate_drive {
4214 my ($storecfg, $vmid, $conf, $key, $drive, $rpcenv, $authuser, $force) = @_;
4216 if (($force || $key =~ /^unused/) && !drive_is_cdrom($drive, 1)) {
4217 my $volid = $drive->{file};
4218 if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
4219 my $sid = PVE::Storage::parse_volume_id($volid);
4220 $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
4222 # check if the disk is really unused
4223 die "unable to
delete '$volid' - volume
is still
in use (snapshot?
)\n"
4224 if is_volume_in_use($storecfg, $conf, $key, $volid);
4225 PVE::Storage::vdisk_free($storecfg, $volid);
4228 # If vm is not owner of this disk remove from config
4236 sub vmconfig_delete_or_detach_drive {
4237 my ($vmid, $storecfg, $conf, $opt, $force) = @_;
4239 my $drive = parse_drive($opt, $conf->{$opt});
4241 my $rpcenv = PVE::RPCEnvironment::get();
4242 my $authuser = $rpcenv->get_user();
4245 $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
4246 try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser, $force);
4248 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
4252 sub vmconfig_apply_pending {
4253 my ($vmid, $conf, $storecfg) = @_;
4257 my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
4258 while (my ($opt, $force) = each %$pending_delete_hash) {
4259 die "internal error
" if $opt =~ m/^unused/;
4260 $conf = load_config($vmid); # update/reload
4261 if (!defined($conf->{$opt})) {
4262 vmconfig_undelete_pending_option($conf, $opt);
4263 update_config_nolock($vmid, $conf, 1);
4264 } elsif (valid_drivename($opt)) {
4265 vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
4266 vmconfig_undelete_pending_option($conf, $opt);
4267 delete $conf->{$opt};
4268 update_config_nolock($vmid, $conf, 1);
4270 vmconfig_undelete_pending_option($conf, $opt);
4271 delete $conf->{$opt};
4272 update_config_nolock($vmid, $conf, 1);
4276 $conf = load_config($vmid); # update/reload
4278 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4279 $conf = load_config($vmid); # update/reload
4281 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4282 # skip if nothing changed
4283 } elsif (valid_drivename($opt)) {
4284 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4285 if defined($conf->{$opt});
4286 $conf->{$opt} = $conf->{pending}->{$opt};
4288 $conf->{$opt} = $conf->{pending}->{$opt};
4291 delete $conf->{pending}->{$opt};
4292 update_config_nolock($vmid, $conf, 1);
4296 my $safe_num_ne = sub {
4299 return 0 if !defined($a) && !defined($b);
4300 return 1 if !defined($a);
4301 return 1 if !defined($b);
4306 my $safe_string_ne = sub {
4309 return 0 if !defined($a) && !defined($b);
4310 return 1 if !defined($a);
4311 return 1 if !defined($b);
4316 sub vmconfig_update_net {
4317 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4319 my $newnet = parse_net($value);
4321 if ($conf->{$opt}) {
4322 my $oldnet = parse_net($conf->{$opt});
4324 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4325 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4326 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4327 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4329 # for non online change, we try to hot-unplug
4330 die "skip
\n" if !$hotplug;
4331 vm_deviceunplug($vmid, $conf, $opt);
4334 die "internal error
" if $opt !~ m/net(\d+)/;
4335 my $iface = "tap
${vmid
}i
$1";
4337 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4338 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4341 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4342 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4343 &$safe_num_ne($oldnet->{trunks}, $newnet->{trunks}) ||
4344 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4345 PVE::Network::tap_unplug($iface);
4346 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks});
4349 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4350 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4358 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4364 sub vmconfig_update_disk {
4365 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4367 # fixme: do we need force?
4369 my $drive = parse_drive($opt, $value);
4371 if ($conf->{$opt}) {
4373 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4375 my $media = $drive->{media} || 'disk';
4376 my $oldmedia = $old_drive->{media} || 'disk';
4377 die "unable to change media type
\n" if $media ne $oldmedia;
4379 if (!drive_is_cdrom($old_drive)) {
4381 if ($drive->{file} ne $old_drive->{file}) {
4383 die "skip
\n" if !$hotplug;
4385 # unplug and register as unused
4386 vm_deviceunplug($vmid, $conf, $opt);
4387 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4390 # update existing disk
4392 # skip non hotpluggable value
4393 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4394 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4395 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4396 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4401 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4402 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4403 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4404 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4405 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4406 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4407 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4408 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4409 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4410 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4411 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4412 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4414 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4415 ($drive->{mbps} || 0)*1024*1024,
4416 ($drive->{mbps_rd} || 0)*1024*1024,
4417 ($drive->{mbps_wr} || 0)*1024*1024,
4418 $drive->{iops} || 0,
4419 $drive->{iops_rd} || 0,
4420 $drive->{iops_wr} || 0,
4421 ($drive->{mbps_max} || 0)*1024*1024,
4422 ($drive->{mbps_rd_max} || 0)*1024*1024,
4423 ($drive->{mbps_wr_max} || 0)*1024*1024,
4424 $drive->{iops_max} || 0,
4425 $drive->{iops_rd_max} || 0,
4426 $drive->{iops_wr_max} || 0);
4435 if ($drive->{file} eq 'none') {
4436 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4438 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4439 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4440 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4448 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4450 PVE::Storage::activate_volumes($storecfg, [$drive->{file}]);
4451 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4455 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
4456 $forcemachine, $spice_ticket) = @_;
4458 lock_config($vmid, sub {
4459 my $conf = load_config($vmid, $migratedfrom);
4461 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4463 check_lock($conf) if !$skiplock;
4465 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4467 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4468 vmconfig_apply_pending($vmid, $conf, $storecfg);
4469 $conf = load_config($vmid); # update/reload
4472 my $defaults = load_defaults();
4474 # set environment variable useful inside network script
4475 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4477 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4479 my $migrate_port = 0;
4482 if ($statefile eq 'tcp') {
4483 my $localip = "localhost
";
4484 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4485 my $nodename = PVE::INotify::nodename();
4486 if ($datacenterconf->{migration_unsecure}) {
4487 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4488 $localip = "[$localip]" if Net::IP::ip_is_ipv6($localip);
4490 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4491 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4492 $migrate_uri = "tcp
:${localip
}:${migrate_port
}";
4493 push @$cmd, '-incoming', $migrate_uri;
4496 push @$cmd, '-loadstate', $statefile;
4503 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4504 my $d = parse_hostpci($conf->{"hostpci
$i"});
4506 my $pcidevices = $d->{pciid};
4507 foreach my $pcidevice (@$pcidevices) {
4508 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4510 my $info = pci_device_info("0000:$pciid");
4511 die "IOMMU
not present
\n" if !check_iommu_support();
4512 die "no pci device info
for device
'$pciid'\n" if !$info;
4513 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4514 die "can't
reset pci device
'$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4518 PVE::Storage::activate_volumes($storecfg, $vollist);
4520 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4523 die "start failed
: $err" if $err;
4525 print "migration listens on
$migrate_uri\n" if $migrate_uri;
4527 if ($statefile && $statefile ne 'tcp') {
4528 eval { vm_mon_cmd_nocheck($vmid, "cont
"); };
4532 if ($migratedfrom) {
4535 set_migration_caps($vmid);
4540 print "spice listens on port
$spice_port\n";
4541 if ($spice_ticket) {
4542 vm_mon_cmd_nocheck($vmid, "set_password
", protocol => 'spice', password => $spice_ticket);
4543 vm_mon_cmd_nocheck($vmid, "expire_password
", protocol => 'spice', time => "+30");
4549 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4550 vm_mon_cmd_nocheck($vmid, "balloon
", value => $conf->{balloon}*1024*1024)
4551 if $conf->{balloon};
4554 foreach my $opt (keys %$conf) {
4555 next if $opt !~ m/^net\d+$/;
4556 my $nicconf = parse_net($conf->{$opt});
4557 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4561 vm_mon_cmd_nocheck($vmid, 'qom-set',
4562 path => "machine
/peripheral/balloon0
",
4563 property => "guest-stats-polling-interval
",
4564 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4570 my ($vmid, $execute, %params) = @_;
4572 my $cmd = { execute => $execute, arguments => \%params };
4573 vm_qmp_command($vmid, $cmd);
4576 sub vm_mon_cmd_nocheck {
4577 my ($vmid, $execute, %params) = @_;
4579 my $cmd = { execute => $execute, arguments => \%params };
4580 vm_qmp_command($vmid, $cmd, 1);
4583 sub vm_qmp_command {
4584 my ($vmid, $cmd, $nocheck) = @_;
4589 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4590 $timeout = $cmd->{arguments}->{timeout};
4591 delete $cmd->{arguments}->{timeout};
4595 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
4596 my $sname = qmp_socket($vmid);
4597 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4598 my $qmpclient = PVE::QMPClient->new();
4600 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4601 } elsif (-e "${var_run_tmpdir
}/$vmid.mon
") {
4602 die "can
't execute complex command on old monitor - stop/start your vm to fix the problem\n"
4603 if scalar(%{$cmd->{arguments}});
4604 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4606 die "unable to open monitor socket\n";
4610 syslog("err", "VM $vmid qmp command failed - $err");
4617 sub vm_human_monitor_command {
4618 my ($vmid, $cmdline) = @_;
4623 execute => 'human-monitor-command
',
4624 arguments => { 'command-line
' => $cmdline},
4627 return vm_qmp_command($vmid, $cmd);
4630 sub vm_commandline {
4631 my ($storecfg, $vmid) = @_;
4633 my $conf = load_config($vmid);
4635 my $defaults = load_defaults();
4637 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4639 return join(' ', @$cmd);
4643 my ($vmid, $skiplock) = @_;
4645 lock_config($vmid, sub {
4647 my $conf = load_config($vmid);
4649 check_lock($conf) if !$skiplock;
4651 vm_mon_cmd($vmid, "system_reset");
4655 sub get_vm_volumes {
4659 foreach_volid($conf, sub {
4660 my ($volid, $is_cdrom) = @_;
4662 return if $volid =~ m|^/|;
4664 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4667 push @$vollist, $volid;
4673 sub vm_stop_cleanup {
4674 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4679 my $vollist = get_vm_volumes($conf);
4680 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4683 foreach my $ext (qw(mon qmp pid vnc qga)) {
4684 unlink "/var/run/qemu-server/${vmid}.$ext";
4687 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4689 warn $@ if $@; # avoid errors - just warn
4692 # Note: use $nockeck to skip tests if VM configuration file exists.
4693 # We need that when migration VMs to other nodes (files already moved)
4694 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4696 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4698 $force = 1 if !defined($force) && !$shutdown;
4701 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4702 kill 15, $pid if $pid;
4703 my $conf = load_config
($vmid, $migratedfrom);
4704 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4708 lock_config
($vmid, sub {
4710 my $pid = check_running
($vmid, $nocheck);
4715 $conf = load_config
($vmid);
4716 check_lock
($conf) if !$skiplock;
4717 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4718 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4719 $timeout = $opts->{down
} if $opts->{down
};
4723 $timeout = 60 if !defined($timeout);
4727 if (defined($conf) && $conf->{agent
}) {
4728 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4730 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4733 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4740 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4745 if ($count >= $timeout) {
4747 warn "VM still running - terminating now with SIGTERM\n";
4750 die "VM quit/powerdown failed - got timeout\n";
4753 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4758 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4761 die "VM quit/powerdown failed\n";
4769 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4774 if ($count >= $timeout) {
4775 warn "VM still running - terminating now with SIGKILL\n";
4780 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4785 my ($vmid, $skiplock) = @_;
4787 lock_config
($vmid, sub {
4789 my $conf = load_config
($vmid);
4791 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4793 vm_mon_cmd
($vmid, "stop");
4798 my ($vmid, $skiplock, $nocheck) = @_;
4800 lock_config
($vmid, sub {
4804 my $conf = load_config
($vmid);
4806 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4808 vm_mon_cmd
($vmid, "cont");
4811 vm_mon_cmd_nocheck
($vmid, "cont");
4817 my ($vmid, $skiplock, $key) = @_;
4819 lock_config
($vmid, sub {
4821 my $conf = load_config
($vmid);
4823 # there is no qmp command, so we use the human monitor command
4824 vm_human_monitor_command
($vmid, "sendkey $key");
4829 my ($storecfg, $vmid, $skiplock) = @_;
4831 lock_config
($vmid, sub {
4833 my $conf = load_config
($vmid);
4835 check_lock
($conf) if !$skiplock;
4837 if (!check_running
($vmid)) {
4838 destroy_vm
($storecfg, $vmid);
4840 die "VM $vmid is running - destroy failed\n";
4848 my ($filename, $buf) = @_;
4850 my $fh = IO
::File-
>new($filename, "w");
4851 return undef if !$fh;
4853 my $res = print $fh $buf;
4860 sub pci_device_info
{
4865 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4866 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4868 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4869 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4871 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4872 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4874 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4875 return undef if !defined($product) || $product !~ s/^0x//;
4880 product
=> $product,
4886 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4895 my $name = $dev->{name
};
4897 my $fn = "$pcisysfs/devices/$name/reset";
4899 return file_write
($fn, "1");
4902 sub pci_dev_bind_to_vfio
{
4905 my $name = $dev->{name
};
4907 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4909 if (!-d
$vfio_basedir) {
4910 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4912 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4914 my $testdir = "$vfio_basedir/$name";
4915 return 1 if -d
$testdir;
4917 my $data = "$dev->{vendor} $dev->{product}";
4918 return undef if !file_write
("$vfio_basedir/new_id", $data);
4920 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4921 if (!file_write
($fn, $name)) {
4922 return undef if -f
$fn;
4925 $fn = "$vfio_basedir/bind";
4926 if (! -d
$testdir) {
4927 return undef if !file_write
($fn, $name);
4933 sub pci_dev_group_bind_to_vfio
{
4936 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4938 if (!-d
$vfio_basedir) {
4939 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4941 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4943 # get IOMMU group devices
4944 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4945 my @devs = grep /^0000:/, readdir($D);
4948 foreach my $pciid (@devs) {
4949 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4951 # pci bridges, switches or root ports are not supported
4952 # they have a pci_bus subdirectory so skip them
4953 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4955 my $info = pci_device_info
($1);
4956 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4962 sub print_pci_addr
{
4963 my ($id, $bridges) = @_;
4967 piix3
=> { bus
=> 0, addr
=> 1 },
4968 #addr2 : first videocard
4969 balloon0
=> { bus
=> 0, addr
=> 3 },
4970 watchdog
=> { bus
=> 0, addr
=> 4 },
4971 scsihw0
=> { bus
=> 0, addr
=> 5 },
4972 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4973 scsihw1
=> { bus
=> 0, addr
=> 6 },
4974 ahci0
=> { bus
=> 0, addr
=> 7 },
4975 qga0
=> { bus
=> 0, addr
=> 8 },
4976 spice
=> { bus
=> 0, addr
=> 9 },
4977 virtio0
=> { bus
=> 0, addr
=> 10 },
4978 virtio1
=> { bus
=> 0, addr
=> 11 },
4979 virtio2
=> { bus
=> 0, addr
=> 12 },
4980 virtio3
=> { bus
=> 0, addr
=> 13 },
4981 virtio4
=> { bus
=> 0, addr
=> 14 },
4982 virtio5
=> { bus
=> 0, addr
=> 15 },
4983 hostpci0
=> { bus
=> 0, addr
=> 16 },
4984 hostpci1
=> { bus
=> 0, addr
=> 17 },
4985 net0
=> { bus
=> 0, addr
=> 18 },
4986 net1
=> { bus
=> 0, addr
=> 19 },
4987 net2
=> { bus
=> 0, addr
=> 20 },
4988 net3
=> { bus
=> 0, addr
=> 21 },
4989 net4
=> { bus
=> 0, addr
=> 22 },
4990 net5
=> { bus
=> 0, addr
=> 23 },
4991 vga1
=> { bus
=> 0, addr
=> 24 },
4992 vga2
=> { bus
=> 0, addr
=> 25 },
4993 vga3
=> { bus
=> 0, addr
=> 26 },
4994 hostpci2
=> { bus
=> 0, addr
=> 27 },
4995 hostpci3
=> { bus
=> 0, addr
=> 28 },
4996 #addr29 : usb-host (pve-usb.cfg)
4997 'pci.1' => { bus
=> 0, addr
=> 30 },
4998 'pci.2' => { bus
=> 0, addr
=> 31 },
4999 'net6' => { bus
=> 1, addr
=> 1 },
5000 'net7' => { bus
=> 1, addr
=> 2 },
5001 'net8' => { bus
=> 1, addr
=> 3 },
5002 'net9' => { bus
=> 1, addr
=> 4 },
5003 'net10' => { bus
=> 1, addr
=> 5 },
5004 'net11' => { bus
=> 1, addr
=> 6 },
5005 'net12' => { bus
=> 1, addr
=> 7 },
5006 'net13' => { bus
=> 1, addr
=> 8 },
5007 'net14' => { bus
=> 1, addr
=> 9 },
5008 'net15' => { bus
=> 1, addr
=> 10 },
5009 'net16' => { bus
=> 1, addr
=> 11 },
5010 'net17' => { bus
=> 1, addr
=> 12 },
5011 'net18' => { bus
=> 1, addr
=> 13 },
5012 'net19' => { bus
=> 1, addr
=> 14 },
5013 'net20' => { bus
=> 1, addr
=> 15 },
5014 'net21' => { bus
=> 1, addr
=> 16 },
5015 'net22' => { bus
=> 1, addr
=> 17 },
5016 'net23' => { bus
=> 1, addr
=> 18 },
5017 'net24' => { bus
=> 1, addr
=> 19 },
5018 'net25' => { bus
=> 1, addr
=> 20 },
5019 'net26' => { bus
=> 1, addr
=> 21 },
5020 'net27' => { bus
=> 1, addr
=> 22 },
5021 'net28' => { bus
=> 1, addr
=> 23 },
5022 'net29' => { bus
=> 1, addr
=> 24 },
5023 'net30' => { bus
=> 1, addr
=> 25 },
5024 'net31' => { bus
=> 1, addr
=> 26 },
5025 'virtio6' => { bus
=> 2, addr
=> 1 },
5026 'virtio7' => { bus
=> 2, addr
=> 2 },
5027 'virtio8' => { bus
=> 2, addr
=> 3 },
5028 'virtio9' => { bus
=> 2, addr
=> 4 },
5029 'virtio10' => { bus
=> 2, addr
=> 5 },
5030 'virtio11' => { bus
=> 2, addr
=> 6 },
5031 'virtio12' => { bus
=> 2, addr
=> 7 },
5032 'virtio13' => { bus
=> 2, addr
=> 8 },
5033 'virtio14' => { bus
=> 2, addr
=> 9 },
5034 'virtio15' => { bus
=> 2, addr
=> 10 },
5035 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
5036 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
5037 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
5038 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
5039 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
5040 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
5041 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
5042 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
5043 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
5044 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
5045 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
5046 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
5047 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
5048 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
5049 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
5050 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
5051 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
5052 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
5053 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
5054 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
5055 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
5056 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
5057 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
5058 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
5059 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
5060 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
5061 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
5062 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
5063 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
5064 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
5065 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
5069 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5070 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5071 my $bus = $devices->{$id}->{bus
};
5072 $res = ",bus=pci.$bus,addr=$addr";
5073 $bridges->{$bus} = 1 if $bridges;
5079 sub print_pcie_addr
{
5084 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
5085 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
5086 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
5087 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
5090 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
5091 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
5092 my $bus = $devices->{$id}->{bus
};
5093 $res = ",bus=$bus,addr=$addr";
5099 # vzdump restore implementaion
5101 sub tar_archive_read_firstfile
{
5102 my $archive = shift;
5104 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
5106 # try to detect archive type first
5107 my $pid = open (TMP
, "tar tf '$archive'|") ||
5108 die "unable to open file '$archive'\n";
5109 my $firstfile = <TMP
>;
5113 die "ERROR: archive contaions no data\n" if !$firstfile;
5119 sub tar_restore_cleanup
{
5120 my ($storecfg, $statfile) = @_;
5122 print STDERR
"starting cleanup\n";
5124 if (my $fd = IO
::File-
>new($statfile, "r")) {
5125 while (defined(my $line = <$fd>)) {
5126 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5129 if ($volid =~ m
|^/|) {
5130 unlink $volid || die 'unlink failed\n';
5132 PVE
::Storage
::vdisk_free
($storecfg, $volid);
5134 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5136 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5138 print STDERR
"unable to parse line in statfile - $line";
5145 sub restore_archive
{
5146 my ($archive, $vmid, $user, $opts) = @_;
5148 my $format = $opts->{format
};
5151 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
5152 $format = 'tar' if !$format;
5154 } elsif ($archive =~ m/\.tar$/) {
5155 $format = 'tar' if !$format;
5156 } elsif ($archive =~ m/.tar.lzo$/) {
5157 $format = 'tar' if !$format;
5159 } elsif ($archive =~ m/\.vma$/) {
5160 $format = 'vma' if !$format;
5161 } elsif ($archive =~ m/\.vma\.gz$/) {
5162 $format = 'vma' if !$format;
5164 } elsif ($archive =~ m/\.vma\.lzo$/) {
5165 $format = 'vma' if !$format;
5168 $format = 'vma' if !$format; # default
5171 # try to detect archive format
5172 if ($format eq 'tar') {
5173 return restore_tar_archive
($archive, $vmid, $user, $opts);
5175 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
5179 sub restore_update_config_line
{
5180 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
5182 return if $line =~ m/^\#qmdump\#/;
5183 return if $line =~ m/^\#vzdump\#/;
5184 return if $line =~ m/^lock:/;
5185 return if $line =~ m/^unused\d+:/;
5186 return if $line =~ m/^parent:/;
5187 return if $line =~ m/^template:/; # restored VM is never a template
5189 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
5190 # try to convert old 1.X settings
5191 my ($id, $ind, $ethcfg) = ($1, $2, $3);
5192 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
5193 my ($model, $macaddr) = split(/\=/, $devconfig);
5194 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
5197 bridge
=> "vmbr$ind",
5198 macaddr
=> $macaddr,
5200 my $netstr = print_net
($net);
5202 print $outfd "net$cookie->{netcount}: $netstr\n";
5203 $cookie->{netcount
}++;
5205 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
5206 my ($id, $netstr) = ($1, $2);
5207 my $net = parse_net
($netstr);
5208 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
5209 $netstr = print_net
($net);
5210 print $outfd "$id: $netstr\n";
5211 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
5214 if ($line =~ m/backup=no/) {
5215 print $outfd "#$line";
5216 } elsif ($virtdev && $map->{$virtdev}) {
5217 my $di = parse_drive
($virtdev, $value);
5218 delete $di->{format
}; # format can change on restore
5219 $di->{file
} = $map->{$virtdev};
5220 $value = print_drive
($vmid, $di);
5221 print $outfd "$virtdev: $value\n";
5231 my ($cfg, $vmid) = @_;
5233 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5235 my $volid_hash = {};
5236 foreach my $storeid (keys %$info) {
5237 foreach my $item (@{$info->{$storeid}}) {
5238 next if !($item->{volid
} && $item->{size
});
5239 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5240 $volid_hash->{$item->{volid
}} = $item;
5247 sub is_volume_in_use
{
5248 my ($storecfg, $conf, $skip_drive, $volid) = @_;
5250 my $path = PVE
::Storage
::path
($storecfg, $volid);
5252 my $scan_config = sub {
5253 my ($cref, $snapname) = @_;
5255 foreach my $key (keys %$cref) {
5256 my $value = $cref->{$key};
5257 if (valid_drivename
($key)) {
5258 next if $skip_drive && $key eq $skip_drive;
5259 my $drive = parse_drive
($key, $value);
5260 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5261 return 1 if $volid eq $drive->{file
};
5262 if ($drive->{file
} =~ m!^/!) {
5263 return 1 if $drive->{file
} eq $path;
5265 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5267 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5269 return 1 if $path eq PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5277 return 1 if &$scan_config($conf);
5281 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5282 return 1 if &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5288 sub update_disksize
{
5289 my ($vmid, $conf, $volid_hash) = @_;
5295 # Note: it is allowed to define multiple storages with same path (alias), so
5296 # we need to check both 'volid' and real 'path' (two different volid can point
5297 # to the same path).
5302 foreach my $opt (keys %$conf) {
5303 if (valid_drivename
($opt)) {
5304 my $drive = parse_drive
($opt, $conf->{$opt});
5305 my $volid = $drive->{file
};
5308 $used->{$volid} = 1;
5309 if ($volid_hash->{$volid} &&
5310 (my $path = $volid_hash->{$volid}->{path
})) {
5311 $usedpath->{$path} = 1;
5314 next if drive_is_cdrom
($drive);
5315 next if !$volid_hash->{$volid};
5317 $drive->{size
} = $volid_hash->{$volid}->{size
};
5318 my $new = print_drive
($vmid, $drive);
5319 if ($new ne $conf->{$opt}) {
5321 $conf->{$opt} = $new;
5326 # remove 'unusedX' entry if volume is used
5327 foreach my $opt (keys %$conf) {
5328 next if $opt !~ m/^unused\d+$/;
5329 my $volid = $conf->{$opt};
5330 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5331 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5333 delete $conf->{$opt};
5337 foreach my $volid (sort keys %$volid_hash) {
5338 next if $volid =~ m/vm-$vmid-state-/;
5339 next if $used->{$volid};
5340 my $path = $volid_hash->{$volid}->{path
};
5341 next if !$path; # just to be sure
5342 next if $usedpath->{$path};
5344 add_unused_volume
($conf, $volid);
5345 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5352 my ($vmid, $nolock) = @_;
5354 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5356 my $volid_hash = scan_volids
($cfg, $vmid);
5358 my $updatefn = sub {
5361 my $conf = load_config
($vmid);
5366 foreach my $volid (keys %$volid_hash) {
5367 my $info = $volid_hash->{$volid};
5368 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5371 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5373 update_config_nolock
($vmid, $conf, 1) if $changes;
5376 if (defined($vmid)) {
5380 lock_config
($vmid, $updatefn, $vmid);
5383 my $vmlist = config_list
();
5384 foreach my $vmid (keys %$vmlist) {
5388 lock_config
($vmid, $updatefn, $vmid);
5394 sub restore_vma_archive
{
5395 my ($archive, $vmid, $user, $opts, $comp) = @_;
5397 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5398 my $readfrom = $archive;
5403 my $qarchive = PVE
::Tools
::shellquote
($archive);
5404 if ($comp eq 'gzip') {
5405 $uncomp = "zcat $qarchive|";
5406 } elsif ($comp eq 'lzop') {
5407 $uncomp = "lzop -d -c $qarchive|";
5409 die "unknown compression method '$comp'\n";
5414 my $tmpdir = "/var/tmp/vzdumptmp$$";
5417 # disable interrupts (always do cleanups)
5418 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5419 warn "got interrupt - ignored\n";
5422 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5423 POSIX
::mkfifo
($mapfifo, 0600);
5426 my $openfifo = sub {
5427 open($fifofh, '>', $mapfifo) || die $!;
5430 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5437 my $rpcenv = PVE
::RPCEnvironment
::get
();
5439 my $conffile = config_file
($vmid);
5440 my $tmpfn = "$conffile.$$.tmp";
5442 # Note: $oldconf is undef if VM does not exists
5443 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5445 my $print_devmap = sub {
5446 my $virtdev_hash = {};
5448 my $cfgfn = "$tmpdir/qemu-server.conf";
5450 # we can read the config - that is already extracted
5451 my $fh = IO
::File-
>new($cfgfn, "r") ||
5452 "unable to read qemu-server.conf - $!\n";
5454 my $fwcfgfn = "$tmpdir/qemu-server.fw";
5455 PVE
::Tools
::file_copy
($fwcfgfn, "/etc/pve/firewall/$vmid.fw")
5458 while (defined(my $line = <$fh>)) {
5459 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5460 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5461 die "archive does not contain data for drive '$virtdev'\n"
5462 if !$devinfo->{$devname};
5463 if (defined($opts->{storage
})) {
5464 $storeid = $opts->{storage
} || 'local';
5465 } elsif (!$storeid) {
5468 $format = 'raw' if !$format;
5469 $devinfo->{$devname}->{devname
} = $devname;
5470 $devinfo->{$devname}->{virtdev
} = $virtdev;
5471 $devinfo->{$devname}->{format
} = $format;
5472 $devinfo->{$devname}->{storeid
} = $storeid;
5474 # check permission on storage
5475 my $pool = $opts->{pool
}; # todo: do we need that?
5476 if ($user ne 'root@pam') {
5477 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5480 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5484 foreach my $devname (keys %$devinfo) {
5485 die "found no device mapping information for device '$devname'\n"
5486 if !$devinfo->{$devname}->{virtdev
};
5489 my $cfg = cfs_read_file
('storage.cfg');
5491 # create empty/temp config
5493 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5494 foreach_drive
($oldconf, sub {
5495 my ($ds, $drive) = @_;
5497 return if drive_is_cdrom
($drive);
5499 my $volid = $drive->{file
};
5501 return if !$volid || $volid =~ m
|^/|;
5503 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5504 return if !$path || !$owner || ($owner != $vmid);
5506 # Note: only delete disk we want to restore
5507 # other volumes will become unused
5508 if ($virtdev_hash->{$ds}) {
5509 PVE
::Storage
::vdisk_free
($cfg, $volid);
5515 foreach my $virtdev (sort keys %$virtdev_hash) {
5516 my $d = $virtdev_hash->{$virtdev};
5517 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5518 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5520 # test if requested format is supported
5521 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5522 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5523 $d->{format
} = $defFormat if !$supported;
5525 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5526 $d->{format
}, undef, $alloc_size);
5527 print STDERR
"new volume ID is '$volid'\n";
5528 $d->{volid
} = $volid;
5529 my $path = PVE
::Storage
::path
($cfg, $volid);
5531 PVE
::Storage
::activate_volumes
($cfg,[$volid]);
5533 my $write_zeros = 1;
5534 # fixme: what other storages types initialize volumes with zero?
5535 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5536 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5540 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5542 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5543 $map->{$virtdev} = $volid;
5546 $fh->seek(0, 0) || die "seek failed - $!\n";
5548 my $outfd = new IO
::File
($tmpfn, "w") ||
5549 die "unable to write config for VM $vmid\n";
5551 my $cookie = { netcount
=> 0 };
5552 while (defined(my $line = <$fh>)) {
5553 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5562 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5563 die "interrupted by signal\n";
5565 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5567 $oldtimeout = alarm($timeout);
5574 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5575 my ($dev_id, $size, $devname) = ($1, $2, $3);
5576 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5577 } elsif ($line =~ m/^CTIME: /) {
5578 # we correctly received the vma config, so we can disable
5579 # the timeout now for disk allocation (set to 10 minutes, so
5580 # that we always timeout if something goes wrong)
5583 print $fifofh "done\n";
5584 my $tmp = $oldtimeout || 0;
5585 $oldtimeout = undef;
5591 print "restore vma archive: $cmd\n";
5592 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5596 alarm($oldtimeout) if $oldtimeout;
5599 foreach my $devname (keys %$devinfo) {
5600 my $volid = $devinfo->{$devname}->{volid
};
5601 push @$vollist, $volid if $volid;
5604 my $cfg = cfs_read_file
('storage.cfg');
5605 PVE
::Storage
::deactivate_volumes
($cfg, $vollist);
5613 foreach my $devname (keys %$devinfo) {
5614 my $volid = $devinfo->{$devname}->{volid
};
5617 if ($volid =~ m
|^/|) {
5618 unlink $volid || die 'unlink failed\n';
5620 PVE
::Storage
::vdisk_free
($cfg, $volid);
5622 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5624 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5631 rename($tmpfn, $conffile) ||
5632 die "unable to commit configuration file '$conffile'\n";
5634 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5636 eval { rescan
($vmid, 1); };
5640 sub restore_tar_archive
{
5641 my ($archive, $vmid, $user, $opts) = @_;
5643 if ($archive ne '-') {
5644 my $firstfile = tar_archive_read_firstfile
($archive);
5645 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5646 if $firstfile ne 'qemu-server.conf';
5649 my $storecfg = cfs_read_file
('storage.cfg');
5651 # destroy existing data - keep empty config
5652 my $vmcfgfn = config_file
($vmid);
5653 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5655 my $tocmd = "/usr/lib/qemu-server/qmextract";
5657 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5658 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5659 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5660 $tocmd .= ' --info' if $opts->{info
};
5662 # tar option "xf" does not autodetect compression when read from STDIN,
5663 # so we pipe to zcat
5664 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5665 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5667 my $tmpdir = "/var/tmp/vzdumptmp$$";
5670 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5671 local $ENV{VZDUMP_VMID
} = $vmid;
5672 local $ENV{VZDUMP_USER
} = $user;
5674 my $conffile = config_file
($vmid);
5675 my $tmpfn = "$conffile.$$.tmp";
5677 # disable interrupts (always do cleanups)
5678 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5679 print STDERR
"got interrupt - ignored\n";
5684 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5685 die "interrupted by signal\n";
5688 if ($archive eq '-') {
5689 print "extracting archive from STDIN\n";
5690 run_command
($cmd, input
=> "<&STDIN");
5692 print "extracting archive '$archive'\n";
5696 return if $opts->{info
};
5700 my $statfile = "$tmpdir/qmrestore.stat";
5701 if (my $fd = IO
::File-
>new($statfile, "r")) {
5702 while (defined (my $line = <$fd>)) {
5703 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5704 $map->{$1} = $2 if $1;
5706 print STDERR
"unable to parse line in statfile - $line\n";
5712 my $confsrc = "$tmpdir/qemu-server.conf";
5714 my $srcfd = new IO
::File
($confsrc, "r") ||
5715 die "unable to open file '$confsrc'\n";
5717 my $outfd = new IO
::File
($tmpfn, "w") ||
5718 die "unable to write config for VM $vmid\n";
5720 my $cookie = { netcount
=> 0 };
5721 while (defined (my $line = <$srcfd>)) {
5722 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5734 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5741 rename $tmpfn, $conffile ||
5742 die "unable to commit configuration file '$conffile'\n";
5744 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5746 eval { rescan
($vmid, 1); };
5751 # Internal snapshots
5753 # NOTE: Snapshot create/delete involves several non-atomic
5754 # action, and can take a long time.
5755 # So we try to avoid locking the file and use 'lock' variable
5756 # inside the config file instead.
5758 my $snapshot_copy_config = sub {
5759 my ($source, $dest) = @_;
5761 foreach my $k (keys %$source) {
5762 next if $k eq 'snapshots';
5763 next if $k eq 'snapstate';
5764 next if $k eq 'snaptime';
5765 next if $k eq 'vmstate';
5766 next if $k eq 'lock';
5767 next if $k eq 'digest';
5768 next if $k eq 'description';
5769 next if $k =~ m/^unused\d+$/;
5771 $dest->{$k} = $source->{$k};
5775 my $snapshot_apply_config = sub {
5776 my ($conf, $snap) = @_;
5778 # copy snapshot list
5780 snapshots
=> $conf->{snapshots
},
5783 # keep description and list of unused disks
5784 foreach my $k (keys %$conf) {
5785 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5786 $newconf->{$k} = $conf->{$k};
5789 &$snapshot_copy_config($snap, $newconf);
5794 sub foreach_writable_storage
{
5795 my ($conf, $func) = @_;
5799 foreach my $ds (keys %$conf) {
5800 next if !valid_drivename
($ds);
5802 my $drive = parse_drive
($ds, $conf->{$ds});
5804 next if drive_is_cdrom
($drive);
5806 my $volid = $drive->{file
};
5808 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5809 $sidhash->{$sid} = $sid if $sid;
5812 foreach my $sid (sort keys %$sidhash) {
5817 my $alloc_vmstate_volid = sub {
5818 my ($storecfg, $vmid, $conf, $snapname) = @_;
5820 # Note: we try to be smart when selecting a $target storage
5824 # search shared storage first
5825 foreach_writable_storage
($conf, sub {
5827 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5828 return if !$scfg->{shared
};
5830 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5834 # now search local storage
5835 foreach_writable_storage
($conf, sub {
5837 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5838 return if $scfg->{shared
};
5840 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5844 $target = 'local' if !$target;
5846 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5847 # we abort live save after $conf->{memory}, so we need at max twice that space
5848 my $size = $conf->{memory
}*2 + $driver_state_size;
5850 my $name = "vm-$vmid-state-$snapname";
5851 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5852 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5853 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5858 my $snapshot_prepare = sub {
5859 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5863 my $updatefn = sub {
5865 my $conf = load_config
($vmid);
5867 die "you can't take a snapshot if it's a template\n"
5868 if is_template
($conf);
5872 $conf->{lock} = 'snapshot';
5874 die "snapshot name '$snapname' already used\n"
5875 if defined($conf->{snapshots
}->{$snapname});
5877 my $storecfg = PVE
::Storage
::config
();
5878 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5880 $snap = $conf->{snapshots
}->{$snapname} = {};
5882 if ($save_vmstate && check_running
($vmid)) {
5883 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5886 &$snapshot_copy_config($conf, $snap);
5888 $snap->{snapstate
} = "prepare";
5889 $snap->{snaptime
} = time();
5890 $snap->{description
} = $comment if $comment;
5892 # always overwrite machine if we save vmstate. This makes sure we
5893 # can restore it later using correct machine type
5894 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5896 update_config_nolock
($vmid, $conf, 1);
5899 lock_config
($vmid, $updatefn);
5904 my $snapshot_commit = sub {
5905 my ($vmid, $snapname) = @_;
5907 my $updatefn = sub {
5909 my $conf = load_config
($vmid);
5911 die "missing snapshot lock\n"
5912 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5914 my $has_machine_config = defined($conf->{machine
});
5916 my $snap = $conf->{snapshots
}->{$snapname};
5918 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5920 die "wrong snapshot state\n"
5921 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5923 delete $snap->{snapstate
};
5924 delete $conf->{lock};
5926 my $newconf = &$snapshot_apply_config($conf, $snap);
5928 delete $newconf->{machine
} if !$has_machine_config;
5930 $newconf->{parent
} = $snapname;
5932 update_config_nolock
($vmid, $newconf, 1);
5935 lock_config
($vmid, $updatefn);
5938 sub snapshot_rollback
{
5939 my ($vmid, $snapname) = @_;
5943 my $storecfg = PVE
::Storage
::config
();
5945 my $conf = load_config
($vmid);
5947 my $get_snapshot_config = sub {
5949 die "you can't rollback if vm is a template\n" if is_template
($conf);
5951 my $res = $conf->{snapshots
}->{$snapname};
5953 die "snapshot '$snapname' does not exist\n" if !defined($res);
5958 my $snap = &$get_snapshot_config();
5960 foreach_drive
($snap, sub {
5961 my ($ds, $drive) = @_;
5963 return if drive_is_cdrom
($drive);
5965 my $volid = $drive->{file
};
5967 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5970 my $updatefn = sub {
5972 $conf = load_config
($vmid);
5974 $snap = &$get_snapshot_config();
5976 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5977 if $snap->{snapstate
};
5981 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5984 die "unable to rollback vm $vmid: vm is running\n"
5985 if check_running
($vmid);
5988 $conf->{lock} = 'rollback';
5990 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5991 delete $conf->{lock};
5997 my $has_machine_config = defined($conf->{machine
});
5999 # copy snapshot config to current config
6000 $conf = &$snapshot_apply_config($conf, $snap);
6001 $conf->{parent
} = $snapname;
6003 # Note: old code did not store 'machine', so we try to be smart
6004 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
6005 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
6006 # we remove the 'machine' configuration if not explicitly specified
6007 # in the original config.
6008 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
6011 update_config_nolock
($vmid, $conf, 1);
6013 if (!$prepare && $snap->{vmstate
}) {
6014 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6015 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
6019 lock_config
($vmid, $updatefn);
6021 foreach_drive
($snap, sub {
6022 my ($ds, $drive) = @_;
6024 return if drive_is_cdrom
($drive);
6026 my $volid = $drive->{file
};
6027 my $device = "drive-$ds";
6029 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
6033 lock_config
($vmid, $updatefn);
6036 my $savevm_wait = sub {
6040 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6041 if (!$stat->{status
}) {
6042 die "savevm not active\n";
6043 } elsif ($stat->{status
} eq 'active') {
6046 } elsif ($stat->{status
} eq 'completed') {
6049 die "query-savevm returned status '$stat->{status}'\n";
6054 sub do_snapshots_with_qemu
{
6055 my ($storecfg, $volid) = @_;
6057 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
6059 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}}
6060 && !$storecfg->{ids
}->{$storage_name}->{krbd
}){
6064 if ($volid =~ m/\.(qcow2|qed)$/){
6071 sub snapshot_create
{
6072 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
6074 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
6076 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
6078 my $config = load_config
($vmid);
6080 my $running = check_running
($vmid);
6082 my $freezefs = $running && $config->{agent
};
6083 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
6088 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
6089 warn "guest-fsfreeze-freeze problems - $@" if $@;
6093 # create internal snapshots of all drives
6095 my $storecfg = PVE
::Storage
::config
();
6098 if ($snap->{vmstate
}) {
6099 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
6100 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
6101 &$savevm_wait($vmid);
6103 vm_mon_cmd
($vmid, "savevm-start");
6107 foreach_drive
($snap, sub {
6108 my ($ds, $drive) = @_;
6110 return if drive_is_cdrom
($drive);
6112 my $volid = $drive->{file
};
6113 my $device = "drive-$ds";
6115 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
6116 $drivehash->{$ds} = 1;
6122 eval { vm_mon_cmd
($vmid, "savevm-end") };
6126 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
6127 warn "guest-fsfreeze-thaw problems - $@" if $@;
6130 # savevm-end is async, we need to wait
6132 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
6133 if (!$stat->{bytes
}) {
6136 print "savevm not yet finished\n";
6144 warn "snapshot create failed: starting cleanup\n";
6145 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
6150 &$snapshot_commit($vmid, $snapname);
6153 # Note: $drivehash is only set when called from snapshot_create.
6154 sub snapshot_delete
{
6155 my ($vmid, $snapname, $force, $drivehash) = @_;
6162 my $unlink_parent = sub {
6163 my ($confref, $new_parent) = @_;
6165 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
6167 $confref->{parent
} = $new_parent;
6169 delete $confref->{parent
};
6174 my $updatefn = sub {
6175 my ($remove_drive) = @_;
6177 my $conf = load_config
($vmid);
6181 die "you can't delete a snapshot if vm is a template\n"
6182 if is_template
($conf);
6185 $snap = $conf->{snapshots
}->{$snapname};
6187 die "snapshot '$snapname' does not exist\n" if !defined($snap);
6189 # remove parent refs
6191 &$unlink_parent($conf, $snap->{parent
});
6192 foreach my $sn (keys %{$conf->{snapshots
}}) {
6193 next if $sn eq $snapname;
6194 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
6198 if ($remove_drive) {
6199 if ($remove_drive eq 'vmstate') {
6200 delete $snap->{$remove_drive};
6202 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
6203 my $volid = $drive->{file
};
6204 delete $snap->{$remove_drive};
6205 add_unused_volume
($conf, $volid);
6210 $snap->{snapstate
} = 'delete';
6212 delete $conf->{snapshots
}->{$snapname};
6213 delete $conf->{lock} if $drivehash;
6214 foreach my $volid (@$unused) {
6215 add_unused_volume
($conf, $volid);
6219 update_config_nolock
($vmid, $conf, 1);
6222 lock_config
($vmid, $updatefn);
6224 # now remove vmstate file
6226 my $storecfg = PVE
::Storage
::config
();
6228 if ($snap->{vmstate
}) {
6229 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
6231 die $err if !$force;
6234 # save changes (remove vmstate from snapshot)
6235 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
6238 # now remove all internal snapshots
6239 foreach_drive
($snap, sub {
6240 my ($ds, $drive) = @_;
6242 return if drive_is_cdrom
($drive);
6244 my $volid = $drive->{file
};
6245 my $device = "drive-$ds";
6247 if (!$drivehash || $drivehash->{$ds}) {
6248 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6250 die $err if !$force;
6255 # save changes (remove drive fron snapshot)
6256 lock_config
($vmid, $updatefn, $ds) if !$force;
6257 push @$unused, $volid;
6260 # now cleanup config
6262 lock_config
($vmid, $updatefn);
6266 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6269 foreach_drive
($conf, sub {
6270 my ($ds, $drive) = @_;
6272 return if drive_is_cdrom
($drive);
6273 my $volid = $drive->{file
};
6274 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6277 return $err ?
0 : 1;
6280 sub template_create
{
6281 my ($vmid, $conf, $disk) = @_;
6283 my $storecfg = PVE
::Storage
::config
();
6285 foreach_drive
($conf, sub {
6286 my ($ds, $drive) = @_;
6288 return if drive_is_cdrom
($drive);
6289 return if $disk && $ds ne $disk;
6291 my $volid = $drive->{file
};
6292 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6294 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6295 $drive->{file
} = $voliddst;
6296 $conf->{$ds} = print_drive
($vmid, $drive);
6297 update_config_nolock
($vmid, $conf, 1);
6304 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6307 sub qemu_img_convert
{
6308 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6310 my $storecfg = PVE
::Storage
::config
();
6311 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6312 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6314 if ($src_storeid && $dst_storeid) {
6316 PVE
::Storage
::activate_volumes
($storecfg, [$src_volid], $snapname);
6318 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6319 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6321 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6322 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6324 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6325 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6328 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6329 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6330 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6334 if($line =~ m/\((\S+)\/100\
%\)/){
6336 my $transferred = int($size * $percent / 100);
6337 my $remaining = $size - $transferred;
6339 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6344 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6346 die "copy failed: $err" if $err;
6350 sub qemu_img_format
{
6351 my ($scfg, $volname) = @_;
6353 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6360 sub qemu_drive_mirror
{
6361 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6363 my $storecfg = PVE
::Storage
::config
();
6364 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6366 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6368 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6370 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6372 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6373 $opts->{format
} = $format if $format;
6375 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6378 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6380 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6381 my $stat = @$stats[0];
6382 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6383 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6385 my $busy = $stat->{busy
};
6386 my $ready = $stat->{ready
};
6388 if (my $total = $stat->{len
}) {
6389 my $transferred = $stat->{offset
} || 0;
6390 my $remaining = $total - $transferred;
6391 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6393 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6397 if ($stat->{ready
} eq 'true') {
6399 last if $vmiddst != $vmid;
6401 # try to switch the disk if source and destination are on the same guest
6402 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6404 die $@ if $@ !~ m/cannot be completed/;
6413 my $cancel_job = sub {
6414 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6416 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6417 my $stat = @$stats[0];
6424 eval { &$cancel_job(); };
6425 die "mirroring error: $err";
6428 if ($vmiddst != $vmid) {
6429 # if we clone a disk for a new target vm, we don't switch the disk
6430 &$cancel_job(); # so we call block-job-cancel
6435 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6436 $newvmid, $storage, $format, $full, $newvollist) = @_;
6441 print "create linked clone of drive $drivename ($drive->{file})\n";
6442 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6443 push @$newvollist, $newvolid;
6445 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6446 $storeid = $storage if $storage;
6448 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6450 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6451 $format = qemu_img_format
($scfg, $volname);
6454 # test if requested format is supported - else use default
6455 my $supported = grep { $_ eq $format } @$validFormats;
6456 $format = $defFormat if !$supported;
6458 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6460 print "create full clone of drive $drivename ($drive->{file})\n";
6461 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6462 push @$newvollist, $newvolid;
6464 PVE
::Storage
::activate_volumes
($storecfg, $newvollist);
6466 if (!$running || $snapname) {
6467 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6469 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6473 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6476 $disk->{format
} = undef;
6477 $disk->{file
} = $newvolid;
6478 $disk->{size
} = $size;
6483 # this only works if VM is running
6484 sub get_current_qemu_machine
{
6487 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6488 my $res = vm_qmp_command
($vmid, $cmd);
6490 my ($current, $default);
6491 foreach my $e (@$res) {
6492 $default = $e->{name
} if $e->{'is-default'};
6493 $current = $e->{name
} if $e->{'is-current'};
6496 # fallback to the default machine if current is not supported by qemu
6497 return $current || $default || 'pc';
6500 sub qemu_machine_feature_enabled
{
6501 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6506 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6508 $current_major = $3;
6509 $current_minor = $4;
6511 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6513 $current_major = $1;
6514 $current_minor = $2;
6517 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6522 sub qemu_machine_pxe
{
6523 my ($vmid, $conf, $machine) = @_;
6525 $machine = PVE
::QemuServer
::get_current_qemu_machine
($vmid) if !$machine;
6527 foreach my $opt (keys %$conf) {
6528 next if $opt !~ m/^net(\d+)$/;
6529 my $net = PVE
::QemuServer
::parse_net
($conf->{$opt});
6531 my $romfile = PVE
::QemuServer
::vm_mon_cmd_nocheck
($vmid, 'qom-get', path
=> $opt, property
=> 'romfile');
6532 return $machine.".pxe" if $romfile =~ m/pxe/;
6538 sub qemu_use_old_bios_files
{
6539 my ($machine_type) = @_;
6541 return if !$machine_type;
6543 my $use_old_bios_files = undef;
6545 if ($machine_type =~ m/^(\S+)\.pxe$/) {
6547 $use_old_bios_files = 1;
6549 # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
6550 # load new efi bios files on migration. So this hack is required to allow
6551 # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
6552 # updrading from proxmox-ve-3.X to proxmox-ve 4.0
6553 $use_old_bios_files = !qemu_machine_feature_enabled
($machine_type, undef, 2, 4);
6556 return ($use_old_bios_files, $machine_type);
6563 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6564 my (undef, $id, $function) = @_;
6565 my $res = { id
=> $id, function
=> $function};
6566 push @{$devices->{$id}}, $res;
6572 sub vm_iothreads_list
{
6575 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6578 foreach my $iothread (@$res) {
6579 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6586 my ($conf, $drive) = @_;
6590 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6592 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6598 my $controller = int($drive->{index} / $maxdev);
6599 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6601 return ($maxdev, $controller, $controller_prefix);
6604 # bash completion helper
6606 sub complete_backup_archives
{
6607 my ($cmdname, $pname, $cvalue) = @_;
6609 my $cfg = PVE
::Storage
::config
();
6613 if ($cvalue =~ m/^([^:]+):/) {
6617 my $data = PVE
::Storage
::template_list
($cfg, $storeid, 'backup');
6620 foreach my $id (keys %$data) {
6621 foreach my $item (@{$data->{$id}}) {
6622 next if $item->{format
} !~ m/^vma\.(gz|lzo)$/;
6623 push @$res, $item->{volid
} if defined($item->{volid
});
6630 my $complete_vmid_full = sub {
6633 my $idlist = vmstatus
();
6637 foreach my $id (keys %$idlist) {
6638 my $d = $idlist->{$id};
6639 if (defined($running)) {
6640 next if $d->{template
};
6641 next if $running && $d->{status
} ne 'running';
6642 next if !$running && $d->{status
} eq 'running';
6651 return &$complete_vmid_full();
6654 sub complete_vmid_stopped
{
6655 return &$complete_vmid_full(0);
6658 sub complete_vmid_running
{
6659 return &$complete_vmid_full(1);
6662 sub complete_storage
{
6664 my $cfg = PVE
::Storage
::config
();
6665 my $ids = $cfg->{ids
};
6668 foreach my $sid (keys %$ids) {
6669 next if !PVE
::Storage
::storage_check_enabled
($cfg, $sid, undef, 1);
6670 next if !$ids->{$sid}->{content
}->{images
};