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);
34 my $qemu_snap_storage = {rbd
=> 1, sheepdog
=> 1};
36 my $cpuinfo = PVE
::ProcFSTools
::read_cpuinfo
();
38 # Note about locking: we use flock on the config file protect
39 # against concurent actions.
40 # Aditionaly, we have a 'lock' setting in the config file. This
41 # can be set to 'migrate', 'backup', 'snapshot' or 'rollback'. Most actions are not
42 # allowed when such lock is set. But you can ignore this kind of
43 # lock with the --skiplock flag.
45 cfs_register_file
('/qemu-server/',
49 PVE
::JSONSchema
::register_standard_option
('skiplock', {
50 description
=> "Ignore locks - only root is allowed to use this option.",
55 PVE
::JSONSchema
::register_standard_option
('pve-qm-stateuri', {
56 description
=> "Some command save/restore state from this location.",
62 PVE
::JSONSchema
::register_standard_option
('pve-snapshot-name', {
63 description
=> "The name of the snapshot.",
64 type
=> 'string', format
=> 'pve-configid',
68 #no warnings 'redefine';
71 my ($controller, $vmid, $option, $value) = @_;
73 my $path = "/sys/fs/cgroup/$controller/qemu.slice/$vmid.scope/$option";
74 PVE
::ProcFSTools
::write_proc_entry
($path, $value);
78 my $nodename = PVE
::INotify
::nodename
();
80 mkdir "/etc/pve/nodes/$nodename";
81 my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
84 my $var_run_tmpdir = "/var/run/qemu-server";
85 mkdir $var_run_tmpdir;
87 my $lock_dir = "/var/lock/qemu-server";
90 my $pcisysfs = "/sys/bus/pci";
96 description
=> "Specifies whether a VM will be started during system bootup.",
102 description
=> "Automatic restart after crash (currently ignored).",
107 type
=> 'string', format
=> 'pve-hotplug-features',
108 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'.",
109 default => 'network,disk,usb',
114 description
=> "Allow reboot. If set to '0' the VM exit on reboot.",
120 description
=> "Lock/unlock the VM.",
121 enum
=> [qw(migrate backup snapshot rollback)],
126 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.",
134 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.",
142 description
=> "Amount of RAM for the VM in MB. This is the maximum available memory when you use the balloon device.",
149 description
=> "Amount of target RAM for the VM in MB. Using zero disables the ballon driver.",
155 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",
163 description
=> "Keybord layout for vnc server. Default is read from the datacenter configuration file.",
164 enum
=> PVE
::Tools
::kvmkeymaplist
(),
169 type
=> 'string', format
=> 'dns-name',
170 description
=> "Set a name for the VM. Only used on the configuration web interface.",
175 description
=> "scsi controller model",
176 enum
=> [qw(lsi lsi53c810 virtio-scsi-pci virtio-scsi-single megasas pvscsi)],
182 description
=> "Description for the VM. Only used on the configuration web interface. This is saved as comment inside the configuration file.",
187 enum
=> [qw(other wxp w2k w2k3 w2k8 wvista win7 win8 l24 l26 solaris)],
188 description
=> <<EODESC,
189 Used to enable special optimization/features for specific
192 other => unspecified OS
193 wxp => Microsoft Windows XP
194 w2k => Microsoft Windows 2000
195 w2k3 => Microsoft Windows 2003
196 w2k8 => Microsoft Windows 2008
197 wvista => Microsoft Windows Vista
198 win7 => Microsoft Windows 7
199 win8 => Microsoft Windows 8/2012
200 l24 => Linux 2.4 Kernel
201 l26 => Linux 2.6/3.X Kernel
202 solaris => solaris/opensolaris/openindiania kernel
204 other|l24|l26|solaris ... no special behaviour
205 wxp|w2k|w2k3|w2k8|wvista|win7|win8 ... use --localtime switch
211 description
=> "Boot on floppy (a), hard disk (c), CD-ROM (d), or network (n).",
212 pattern
=> '[acdn]{1,4}',
217 type
=> 'string', format
=> 'pve-qm-bootdisk',
218 description
=> "Enable booting from specified disk.",
219 pattern
=> '(ide|sata|scsi|virtio)\d+',
224 description
=> "The number of CPUs. Please use option -sockets instead.",
231 description
=> "The number of CPU sockets.",
238 description
=> "The number of cores per socket.",
245 description
=> "Enable/disable Numa.",
251 description
=> "Number of hotplugged vcpus.",
258 description
=> "Enable/disable ACPI.",
264 description
=> "Enable/disable Qemu GuestAgent.",
270 description
=> "Enable/disable KVM hardware virtualization.",
276 description
=> "Enable/disable time drift fix.",
282 description
=> "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
287 description
=> "Freeze CPU at startup (use 'c' monitor command to start execution).",
292 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.",
293 enum
=> [qw(std cirrus vmware qxl serial0 serial1 serial2 serial3 qxl2 qxl3 qxl4)],
297 type
=> 'string', format
=> 'pve-qm-watchdog',
298 typetext
=> '[[model=]i6300esb|ib700] [,[action=]reset|shutdown|poweroff|pause|debug|none]',
299 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)",
304 typetext
=> "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
305 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'.",
306 pattern
=> '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
309 startup
=> get_standard_option
('pve-startup-order'),
313 description
=> "Enable/disable Template.",
319 description
=> <<EODESCR,
320 Note: this option is for experts only. It allows you to pass arbitrary arguments to kvm, for example:
322 args: -no-reboot -no-hpet
329 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).",
334 description
=> "Set maximum speed (in MB/s) for migrations. Value 0 is no limit.",
338 migrate_downtime
=> {
341 description
=> "Set maximum tolerated downtime (in seconds) for migrations.",
347 type
=> 'string', format
=> 'pve-qm-drive',
348 typetext
=> 'volume',
349 description
=> "This is an alias for option -ide2",
353 description
=> "Emulated CPU type.",
355 enum
=> [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge IvyBridge Haswell Broadwell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
358 parent
=> get_standard_option
('pve-snapshot-name', {
360 description
=> "Parent snapshot name. This is used internally, and should not be modified.",
364 description
=> "Timestamp for snapshots.",
370 type
=> 'string', format
=> 'pve-volume-id',
371 description
=> "Reference to a volume which stores the VM state. This is used internally for snapshots.",
374 description
=> "Specific the Qemu machine type.",
376 pattern
=> '(pc|pc(-i440fx)?-\d+\.\d+|q35|pc-q35-\d+\.\d+)',
381 description
=> "Specify SMBIOS type 1 fields.",
382 type
=> 'string', format
=> 'pve-qm-smbios1',
383 typetext
=> "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
389 # what about other qemu settings ?
391 #machine => 'string',
404 ##soundhw => 'string',
406 while (my ($k, $v) = each %$confdesc) {
407 PVE
::JSONSchema
::register_standard_option
("pve-qm-$k", $v);
410 my $MAX_IDE_DISKS = 4;
411 my $MAX_SCSI_DISKS = 14;
412 my $MAX_VIRTIO_DISKS = 16;
413 my $MAX_SATA_DISKS = 6;
414 my $MAX_USB_DEVICES = 5;
416 my $MAX_UNUSED_DISKS = 8;
417 my $MAX_HOSTPCI_DEVICES = 4;
418 my $MAX_SERIAL_PORTS = 4;
419 my $MAX_PARALLEL_PORTS = 3;
421 my $MAX_MEM = 4194304;
422 my $STATICMEM = 1024;
426 type
=> 'string', format
=> 'pve-qm-numanode',
427 typetext
=> "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
428 description
=> "numa topology",
430 PVE
::JSONSchema
::register_standard_option
("pve-qm-numanode", $numadesc);
432 for (my $i = 0; $i < $MAX_NUMA; $i++) {
433 $confdesc->{"numa$i"} = $numadesc;
436 my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
437 'ne2k_isa', 'i82551', 'i82557b', 'i82559er', 'vmxnet3',
438 'e1000-82540em', 'e1000-82544gc', 'e1000-82545em'];
439 my $nic_model_list_txt = join(' ', sort @$nic_model_list);
443 type
=> 'string', format
=> 'pve-qm-net',
444 typetext
=> "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>] [,tag=<vlanid>][,firewall=0|1],link_down=0|1]",
445 description
=> <<EODESCR,
446 Specify network devices.
448 MODEL is one of: $nic_model_list_txt
450 XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
451 automatically generated if not specified.
453 The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
455 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'.
457 If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services. The following addresses are used:
463 The DHCP server assign addresses to the guest starting from 10.0.2.15.
467 PVE
::JSONSchema
::register_standard_option
("pve-qm-net", $netdesc);
469 for (my $i = 0; $i < $MAX_NETS; $i++) {
470 $confdesc->{"net$i"} = $netdesc;
477 type
=> 'string', format
=> 'pve-qm-drive',
478 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
479 description
=> "Use volume as IDE hard disk or CD-ROM (n is 0 to " .($MAX_IDE_DISKS -1) . ").",
481 PVE
::JSONSchema
::register_standard_option
("pve-qm-ide", $idedesc);
485 type
=> 'string', format
=> 'pve-qm-drive',
486 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on] [,queues=<nbqueues>]',
487 description
=> "Use volume as SCSI hard disk or CD-ROM (n is 0 to " . ($MAX_SCSI_DISKS - 1) . ").",
489 PVE
::JSONSchema
::register_standard_option
("pve-qm-scsi", $scsidesc);
493 type
=> 'string', format
=> 'pve-qm-drive',
494 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on]',
495 description
=> "Use volume as SATA hard disk or CD-ROM (n is 0 to " . ($MAX_SATA_DISKS - 1). ").",
497 PVE
::JSONSchema
::register_standard_option
("pve-qm-sata", $satadesc);
501 type
=> 'string', format
=> 'pve-qm-drive',
502 typetext
=> '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe|directsync] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads] [,discard=ignore|on] [,iothread=on]',
503 description
=> "Use volume as VIRTIO hard disk (n is 0 to " . ($MAX_VIRTIO_DISKS - 1) . ").",
505 PVE
::JSONSchema
::register_standard_option
("pve-qm-virtio", $virtiodesc);
509 type
=> 'string', format
=> 'pve-qm-usb-device',
510 typetext
=> 'host=HOSTUSBDEVICE|spice',
511 description
=> <<EODESCR,
512 Configure an USB device (n is 0 to 4). This can be used to
513 pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
515 'bus-port(.port)*' (decimal numbers) or
516 'vendor_id:product_id' (hexadeciaml numbers)
518 You can use the 'lsusb -t' command to list existing usb devices.
520 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
522 The value 'spice' can be used to add a usb redirection devices for spice.
526 PVE
::JSONSchema
::register_standard_option
("pve-qm-usb", $usbdesc);
530 type
=> 'string', format
=> 'pve-qm-hostpci',
531 typetext
=> "[host=]HOSTPCIDEVICE [,driver=kvm|vfio] [,rombar=on|off] [,pcie=0|1] [,x-vga=on|off]",
532 description
=> <<EODESCR,
533 Map host pci devices. HOSTPCIDEVICE syntax is:
535 'bus:dev.func' (hexadecimal numbers)
537 You can us the 'lspci' command to list existing pci devices.
539 The 'rombar' option determines whether or not the device's ROM will be visible in the guest's memory map (default is 'on').
541 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
543 Experimental: user reported problems with this option.
546 PVE
::JSONSchema
::register_standard_option
("pve-qm-hostpci", $hostpcidesc);
551 pattern
=> '(/dev/.+|socket)',
552 description
=> <<EODESCR,
553 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).
555 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
557 Experimental: user reported problems with this option.
564 pattern
=> '/dev/parport\d+|/dev/usb/lp\d+',
565 description
=> <<EODESCR,
566 Map host parallel devices (n is 0 to 2).
568 Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
570 Experimental: user reported problems with this option.
574 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
575 $confdesc->{"parallel$i"} = $paralleldesc;
578 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
579 $confdesc->{"serial$i"} = $serialdesc;
582 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
583 $confdesc->{"hostpci$i"} = $hostpcidesc;
586 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++) {
587 $drivename_hash->{"ide$i"} = 1;
588 $confdesc->{"ide$i"} = $idedesc;
591 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++) {
592 $drivename_hash->{"sata$i"} = 1;
593 $confdesc->{"sata$i"} = $satadesc;
596 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++) {
597 $drivename_hash->{"scsi$i"} = 1;
598 $confdesc->{"scsi$i"} = $scsidesc ;
601 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++) {
602 $drivename_hash->{"virtio$i"} = 1;
603 $confdesc->{"virtio$i"} = $virtiodesc;
606 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
607 $confdesc->{"usb$i"} = $usbdesc;
612 type
=> 'string', format
=> 'pve-volume-id',
613 description
=> "Reference to unused volumes.",
616 for (my $i = 0; $i < $MAX_UNUSED_DISKS; $i++) {
617 $confdesc->{"unused$i"} = $unuseddesc;
620 my $kvm_api_version = 0;
624 return $kvm_api_version if $kvm_api_version;
626 my $fh = IO
::File-
>new("</dev/kvm") ||
629 if (my $v = $fh->ioctl(KVM_GET_API_VERSION
(), 0)) {
630 $kvm_api_version = $v;
635 return $kvm_api_version;
638 my $kvm_user_version;
640 sub kvm_user_version
{
642 return $kvm_user_version if $kvm_user_version;
644 $kvm_user_version = 'unknown';
646 my $tmp = `kvm -help 2>/dev/null`;
648 if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+(\.\d+)?)[,\s]/) {
649 $kvm_user_version = $2;
652 return $kvm_user_version;
656 my $kernel_has_vhost_net = -c
'/dev/vhost-net';
659 # order is important - used to autoselect boot disk
660 return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
661 (map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
662 (map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
663 (map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
666 sub valid_drivename
{
669 return defined($drivename_hash->{$dev});
674 return defined($confdesc->{$key});
678 return $nic_model_list;
681 sub os_list_description
{
686 w2k
=> 'Windows 2000',
687 w2k3
=>, 'Windows 2003',
688 w2k8
=> 'Windows 2008',
689 wvista
=> 'Windows Vista',
691 win8
=> 'Windows 8/2012',
701 return $cdrom_path if $cdrom_path;
703 return $cdrom_path = "/dev/cdrom" if -l
"/dev/cdrom";
704 return $cdrom_path = "/dev/cdrom1" if -l
"/dev/cdrom1";
705 return $cdrom_path = "/dev/cdrom2" if -l
"/dev/cdrom2";
709 my ($storecfg, $vmid, $cdrom) = @_;
711 if ($cdrom eq 'cdrom') {
712 return get_cdrom_path
();
713 } elsif ($cdrom eq 'none') {
715 } elsif ($cdrom =~ m
|^/|) {
718 return PVE
::Storage
::path
($storecfg, $cdrom);
722 # try to convert old style file names to volume IDs
723 sub filename_to_volume_id
{
724 my ($vmid, $file, $media) = @_;
726 if (!($file eq 'none' || $file eq 'cdrom' ||
727 $file =~ m
|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
729 return undef if $file =~ m
|/|;
731 if ($media && $media eq 'cdrom') {
732 $file = "local:iso/$file";
734 $file = "local:$vmid/$file";
741 sub verify_media_type
{
742 my ($opt, $vtype, $media) = @_;
747 if ($media eq 'disk') {
749 } elsif ($media eq 'cdrom') {
752 die "internal error";
755 return if ($vtype eq $etype);
757 raise_param_exc
({ $opt => "unexpected media type ($vtype != $etype)" });
760 sub cleanup_drive_path
{
761 my ($opt, $storecfg, $drive) = @_;
763 # try to convert filesystem paths to volume IDs
765 if (($drive->{file
} !~ m/^(cdrom|none)$/) &&
766 ($drive->{file
} !~ m
|^/dev/.+|) &&
767 ($drive->{file
} !~ m/^([^:]+):(.+)$/) &&
768 ($drive->{file
} !~ m/^\d+$/)) {
769 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($storecfg, $drive->{file
});
770 raise_param_exc
({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
771 $drive->{media
} = 'cdrom' if !$drive->{media
} && $vtype eq 'iso';
772 verify_media_type
($opt, $vtype, $drive->{media
});
773 $drive->{file
} = $volid;
776 $drive->{media
} = 'cdrom' if !$drive->{media
} && $drive->{file
} =~ m/^(cdrom|none)$/;
779 sub create_conf_nolock
{
780 my ($vmid, $settings) = @_;
782 my $filename = config_file
($vmid);
784 die "configuration file '$filename' already exists\n" if -f
$filename;
786 my $defaults = load_defaults
();
788 $settings->{name
} = "vm$vmid" if !$settings->{name
};
789 $settings->{memory
} = $defaults->{memory
} if !$settings->{memory
};
792 foreach my $opt (keys %$settings) {
793 next if !$confdesc->{$opt};
795 my $value = $settings->{$opt};
798 $data .= "$opt: $value\n";
801 PVE
::Tools
::file_set_contents
($filename, $data);
804 sub parse_hotplug_features
{
809 return $res if $data eq '0';
811 $data = $confdesc->{hotplug
}->{default} if $data eq '1';
813 foreach my $feature (PVE
::Tools
::split_list
($data)) {
814 if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
817 warn "ignoring unknown hotplug feature '$feature'\n";
823 PVE
::JSONSchema
::register_format
('pve-hotplug-features', \
&pve_verify_hotplug_features
);
824 sub pve_verify_hotplug_features
{
825 my ($value, $noerr) = @_;
827 return $value if parse_hotplug_features
($value);
829 return undef if $noerr;
831 die "unable to parse hotplug option\n";
834 my $parse_size = sub {
837 return undef if $value !~ m/^(\d+(\.\d+)?)([KMG])?$/;
838 my ($size, $unit) = ($1, $3);
841 $size = $size * 1024;
842 } elsif ($unit eq 'M') {
843 $size = $size * 1024 * 1024;
844 } elsif ($unit eq 'G') {
845 $size = $size * 1024 * 1024 * 1024;
851 my $format_size = sub {
856 my $kb = int($size/1024);
857 return $size if $kb*1024 != $size;
859 my $mb = int($kb/1024);
860 return "${kb}K" if $mb*1024 != $kb;
862 my $gb = int($mb/1024);
863 return "${mb}M" if $gb*1024 != $mb;
868 # ideX = [volume=]volume-id[,media=d][,cyls=c,heads=h,secs=s[,trans=t]]
869 # [,snapshot=on|off][,cache=on|off][,format=f][,backup=yes|no]
870 # [,rerror=ignore|report|stop][,werror=enospc|ignore|report|stop]
871 # [,aio=native|threads][,discard=ignore|on][,iothread=on]
874 my ($key, $data) = @_;
878 # $key may be undefined - used to verify JSON parameters
879 if (!defined($key)) {
880 $res->{interface
} = 'unknown'; # should not harm when used to verify parameters
882 } elsif ($key =~ m/^([^\d]+)(\d+)$/) {
883 $res->{interface
} = $1;
889 foreach my $p (split (/,/, $data)) {
890 next if $p =~ m/^\s*$/;
892 if ($p =~ m/^(file|volume|cyls|heads|secs|trans|media|snapshot|cache|format|rerror|werror|backup|aio|bps|mbps|mbps_max|bps_rd|mbps_rd|mbps_rd_max|bps_wr|mbps_wr|mbps_wr_max|iops|iops_max|iops_rd|iops_rd_max|iops_wr|iops_wr_max|size|discard|iothread|queues)=(.+)$/) {
893 my ($k, $v) = ($1, $2);
895 $k = 'file' if $k eq 'volume';
897 return undef if defined $res->{$k};
899 if ($k eq 'bps' || $k eq 'bps_rd' || $k eq 'bps_wr') {
900 return undef if !$v || $v !~ m/^\d+/;
902 $v = sprintf("%.3f", $v / (1024*1024));
906 if (!$res->{file
} && $p !~ m/=/) {
914 return undef if !$res->{file
};
916 return undef if $res->{cache
} &&
917 $res->{cache
} !~ m/^(off|none|writethrough|writeback|unsafe|directsync)$/;
918 return undef if $res->{snapshot
} && $res->{snapshot
} !~ m/^(on|off)$/;
919 return undef if $res->{cyls
} && $res->{cyls
} !~ m/^\d+$/;
920 return undef if $res->{heads
} && $res->{heads
} !~ m/^\d+$/;
921 return undef if $res->{secs
} && $res->{secs
} !~ m/^\d+$/;
922 return undef if $res->{media
} && $res->{media
} !~ m/^(disk|cdrom)$/;
923 return undef if $res->{trans
} && $res->{trans
} !~ m/^(none|lba|auto)$/;
924 return undef if $res->{format
} && $res->{format
} !~ m/^(raw|cow|qcow|qed|qcow2|vmdk|cloop)$/;
925 return undef if $res->{rerror
} && $res->{rerror
} !~ m/^(ignore|report|stop)$/;
926 return undef if $res->{werror
} && $res->{werror
} !~ m/^(enospc|ignore|report|stop)$/;
927 return undef if $res->{backup
} && $res->{backup
} !~ m/^(yes|no)$/;
928 return undef if $res->{aio
} && $res->{aio
} !~ m/^(native|threads)$/;
929 return undef if $res->{discard
} && $res->{discard
} !~ m/^(ignore|on)$/;
930 return undef if $res->{iothread
} && $res->{iothread
} !~ m/^(on)$/;
931 return undef if $res->{queues
} && ($res->{queues
} !~ m/^\d+$/ || $res->{queues
} < 2);
933 return undef if $res->{mbps_rd
} && $res->{mbps
};
934 return undef if $res->{mbps_wr
} && $res->{mbps
};
936 return undef if $res->{mbps
} && $res->{mbps
} !~ m/^\d+(\.\d+)?$/;
937 return undef if $res->{mbps_max
} && $res->{mbps_max
} !~ m/^\d+(\.\d+)?$/;
938 return undef if $res->{mbps_rd
} && $res->{mbps_rd
} !~ m/^\d+(\.\d+)?$/;
939 return undef if $res->{mbps_rd_max
} && $res->{mbps_rd_max
} !~ m/^\d+(\.\d+)?$/;
940 return undef if $res->{mbps_wr
} && $res->{mbps_wr
} !~ m/^\d+(\.\d+)?$/;
941 return undef if $res->{mbps_wr_max
} && $res->{mbps_wr_max
} !~ m/^\d+(\.\d+)?$/;
943 return undef if $res->{iops_rd
} && $res->{iops
};
944 return undef if $res->{iops_wr
} && $res->{iops
};
947 return undef if $res->{iops
} && $res->{iops
} !~ m/^\d+$/;
948 return undef if $res->{iops_max
} && $res->{iops_max
} !~ m/^\d+$/;
949 return undef if $res->{iops_rd
} && $res->{iops_rd
} !~ m/^\d+$/;
950 return undef if $res->{iops_rd_max
} && $res->{iops_rd_max
} !~ m/^\d+$/;
951 return undef if $res->{iops_wr
} && $res->{iops_wr
} !~ m/^\d+$/;
952 return undef if $res->{iops_wr_max
} && $res->{iops_wr_max
} !~ m/^\d+$/;
956 return undef if !defined($res->{size
} = &$parse_size($res->{size
}));
959 if ($res->{media
} && ($res->{media
} eq 'cdrom')) {
960 return undef if $res->{snapshot
} || $res->{trans
} || $res->{format
};
961 return undef if $res->{heads
} || $res->{secs
} || $res->{cyls
};
962 return undef if $res->{interface
} eq 'virtio';
965 # rerror does not work with scsi drives
966 if ($res->{rerror
}) {
967 return undef if $res->{interface
} eq 'scsi';
973 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);
976 my ($vmid, $drive) = @_;
979 foreach my $o (@qemu_drive_options, 'mbps', 'mbps_rd', 'mbps_wr', 'mbps_max', 'mbps_rd_max', 'mbps_wr_max', 'backup', 'iothread', 'queues') {
980 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
983 if ($drive->{size
}) {
984 $opts .= ",size=" . &$format_size($drive->{size
});
987 return "$drive->{file}$opts";
991 my($fh, $noerr) = @_;
994 my $SG_GET_VERSION_NUM = 0x2282;
996 my $versionbuf = "\x00" x
8;
997 my $ret = ioctl($fh, $SG_GET_VERSION_NUM, $versionbuf);
999 die "scsi ioctl SG_GET_VERSION_NUM failoed - $!\n" if !$noerr;
1002 my $version = unpack("I", $versionbuf);
1003 if ($version < 30000) {
1004 die "scsi generic interface too old\n" if !$noerr;
1008 my $buf = "\x00" x
36;
1009 my $sensebuf = "\x00" x
8;
1010 my $cmd = pack("C x3 C x1", 0x12, 36);
1012 # see /usr/include/scsi/sg.h
1013 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";
1015 my $packet = pack($sg_io_hdr_t, ord('S'), -3, length($cmd),
1016 length($sensebuf), 0, length($buf), $buf,
1017 $cmd, $sensebuf, 6000);
1019 $ret = ioctl($fh, $SG_IO, $packet);
1021 die "scsi ioctl SG_IO failed - $!\n" if !$noerr;
1025 my @res = unpack($sg_io_hdr_t, $packet);
1026 if ($res[17] || $res[18]) {
1027 die "scsi ioctl SG_IO status error - $!\n" if !$noerr;
1032 (my $byte0, my $byte1, $res->{vendor
},
1033 $res->{product
}, $res->{revision
}) = unpack("C C x6 A8 A16 A4", $buf);
1035 $res->{removable
} = $byte1 & 128 ?
1 : 0;
1036 $res->{type
} = $byte0 & 31;
1044 my $fh = IO
::File-
>new("+<$path") || return undef;
1045 my $res = scsi_inquiry
($fh, 1);
1051 sub machine_type_is_q35
{
1054 return $conf->{machine
} && ($conf->{machine
} =~ m/q35/) ?
1 : 0;
1057 sub print_tabletdevice_full
{
1060 my $q35 = machine_type_is_q35
($conf);
1062 # we use uhci for old VMs because tablet driver was buggy in older qemu
1063 my $usbbus = $q35 ?
"ehci" : "uhci";
1065 return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
1068 sub print_drivedevice_full
{
1069 my ($storecfg, $conf, $vmid, $drive, $bridges) = @_;
1074 if ($drive->{interface
} eq 'virtio') {
1075 my $pciaddr = print_pci_addr
("$drive->{interface}$drive->{index}", $bridges);
1076 $device = "virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}$pciaddr";
1077 $device .= ",iothread=iothread-$drive->{interface}$drive->{index}" if $drive->{iothread
};
1078 } elsif ($drive->{interface
} eq 'scsi') {
1080 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
1081 my $unit = $drive->{index} % $maxdev;
1082 my $devicetype = 'hd';
1084 if (drive_is_cdrom
($drive)) {
1087 if ($drive->{file
} =~ m
|^/|) {
1088 $path = $drive->{file
};
1090 $path = PVE
::Storage
::path
($storecfg, $drive->{file
});
1093 if($path =~ m/^iscsi\:\/\
//){
1094 $devicetype = 'generic';
1096 if (my $info = path_is_scsi
($path)) {
1097 if ($info->{type
} == 0) {
1098 $devicetype = 'block';
1099 } elsif ($info->{type
} == 1) { # tape
1100 $devicetype = 'generic';
1106 if (!$conf->{scsihw
} || ($conf->{scsihw
} =~ m/^lsi/)){
1107 $device = "scsi-$devicetype,bus=$controller_prefix$controller.0,scsi-id=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1109 $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}";
1112 } elsif ($drive->{interface
} eq 'ide'){
1114 my $controller = int($drive->{index} / $maxdev);
1115 my $unit = $drive->{index} % $maxdev;
1116 my $devicetype = ($drive->{media
} && $drive->{media
} eq 'cdrom') ?
"cd" : "hd";
1118 $device = "ide-$devicetype,bus=ide.$controller,unit=$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1119 } elsif ($drive->{interface
} eq 'sata'){
1120 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
1121 my $unit = $drive->{index} % $MAX_SATA_DISKS;
1122 $device = "ide-drive,bus=ahci$controller.$unit,drive=drive-$drive->{interface}$drive->{index},id=$drive->{interface}$drive->{index}";
1123 } elsif ($drive->{interface
} eq 'usb') {
1125 # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
1127 die "unsupported interface type";
1130 $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex
};
1135 sub get_initiator_name
{
1138 my $fh = IO
::File-
>new('/etc/iscsi/initiatorname.iscsi') || return undef;
1139 while (defined(my $line = <$fh>)) {
1140 next if $line !~ m/^\s*InitiatorName\s*=\s*([\.\-:\w]+)/;
1149 sub print_drive_full
{
1150 my ($storecfg, $vmid, $drive) = @_;
1153 my $volid = $drive->{file
};
1156 if (drive_is_cdrom
($drive)) {
1157 $path = get_iso_path
($storecfg, $vmid, $volid);
1159 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
1161 $path = PVE
::Storage
::path
($storecfg, $volid);
1162 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
1163 $format = qemu_img_format
($scfg, $volname);
1170 foreach my $o (@qemu_drive_options) {
1171 next if $o eq 'bootindex';
1172 $opts .= ",$o=$drive->{$o}" if $drive->{$o};
1175 $opts .= ",format=$format" if $format && !$drive->{format
};
1177 foreach my $o (qw(bps bps_rd bps_wr)) {
1178 my $v = $drive->{"m$o"};
1179 $opts .= ",$o=" . int($v*1024*1024) if $v;
1182 my $cache_direct = 0;
1184 if (my $cache = $drive->{cache
}) {
1185 $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
1186 } elsif (!drive_is_cdrom
($drive)) {
1187 $opts .= ",cache=none";
1191 # aio native works only with O_DIRECT
1192 if (!$drive->{aio
}) {
1194 $opts .= ",aio=native";
1196 $opts .= ",aio=threads";
1200 my $detectzeroes = $drive->{discard
} ?
"unmap" : "on";
1201 $opts .= ",detect-zeroes=$detectzeroes" if !drive_is_cdrom
($drive);
1203 my $pathinfo = $path ?
"file=$path," : '';
1205 return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
1208 sub print_netdevice_full
{
1209 my ($vmid, $conf, $net, $netid, $bridges) = @_;
1211 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
1213 my $device = $net->{model
};
1214 if ($net->{model
} eq 'virtio') {
1215 $device = 'virtio-net-pci';
1218 my $pciaddr = print_pci_addr
("$netid", $bridges);
1219 my $tmpstr = "$device,mac=$net->{macaddr},netdev=$netid$pciaddr,id=$netid";
1220 if ($net->{queues
} && $net->{queues
} > 1 && $net->{model
} eq 'virtio'){
1221 #Consider we have N queues, the number of vectors needed is 2*N + 2 (plus one config interrupt and control vq)
1222 my $vectors = $net->{queues
} * 2 + 2;
1223 $tmpstr .= ",vectors=$vectors,mq=on";
1225 $tmpstr .= ",bootindex=$net->{bootindex}" if $net->{bootindex
} ;
1229 sub print_netdev_full
{
1230 my ($vmid, $conf, $net, $netid) = @_;
1233 if ($netid =~ m/^net(\d+)$/) {
1237 die "got strange net id '$i'\n" if $i >= ${MAX_NETS
};
1239 my $ifname = "tap${vmid}i$i";
1241 # kvm uses TUNSETIFF ioctl, and that limits ifname length
1242 die "interface name '$ifname' is too long (max 15 character)\n"
1243 if length($ifname) >= 16;
1245 my $vhostparam = '';
1246 $vhostparam = ',vhost=on' if $kernel_has_vhost_net && $net->{model
} eq 'virtio';
1248 my $vmname = $conf->{name
} || "vm$vmid";
1252 if ($net->{bridge
}) {
1253 $netdev = "type=tap,id=$netid,ifname=${ifname},script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown$vhostparam";
1255 $netdev = "type=user,id=$netid,hostname=$vmname";
1258 $netdev .= ",queues=$net->{queues}" if ($net->{queues
} && $net->{model
} eq 'virtio');
1263 sub drive_is_cdrom
{
1266 return $drive && $drive->{media
} && ($drive->{media
} eq 'cdrom');
1275 foreach my $kvp (split(/,/, $data)) {
1277 if ($kvp =~ m/^memory=(\S+)$/) {
1278 $res->{memory
} = $1;
1279 } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
1280 $res->{policy
} = $1;
1281 } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
1282 $res->{cpus
}->{start
} = $1;
1283 $res->{cpus
}->{end
} = $3;
1284 } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
1285 $res->{hostnodes
}->{start
} = $1;
1286 $res->{hostnodes
}->{end
} = $3;
1298 return undef if !$value;
1301 my @list = split(/,/, $value);
1305 foreach my $kv (@list) {
1307 if ($kv =~ m/^(host=)?([a-f0-9]{2}:[a-f0-9]{2})(\.([a-f0-9]))?$/) {
1310 push @{$res->{pciid
}}, { id
=> $2 , function
=> $4};
1313 my $pcidevices = lspci
($2);
1314 $res->{pciid
} = $pcidevices->{$2};
1316 } elsif ($kv =~ m/^driver=(kvm|vfio)$/) {
1317 $res->{driver
} = $1;
1318 } elsif ($kv =~ m/^rombar=(on|off)$/) {
1319 $res->{rombar
} = $1;
1320 } elsif ($kv =~ m/^x-vga=(on|off)$/) {
1321 $res->{'x-vga'} = $1;
1322 } elsif ($kv =~ m/^pcie=(\d+)$/) {
1323 $res->{pcie
} = 1 if $1 == 1;
1325 warn "unknown hostpci setting '$kv'\n";
1329 return undef if !$found;
1334 # netX: e1000=XX:XX:XX:XX:XX:XX,bridge=vmbr0,rate=<mbps>
1340 foreach my $kvp (split(/,/, $data)) {
1342 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) {
1344 my $mac = defined($3) ?
uc($3) : PVE
::Tools
::random_ether_addr
();
1345 $res->{model
} = $model;
1346 $res->{macaddr
} = $mac;
1347 } elsif ($kvp =~ m/^bridge=(\S+)$/) {
1348 $res->{bridge
} = $1;
1349 } elsif ($kvp =~ m/^queues=(\d+)$/) {
1350 $res->{queues
} = $1;
1351 } elsif ($kvp =~ m/^rate=(\d+(\.\d+)?)$/) {
1353 } elsif ($kvp =~ m/^tag=(\d+)$/) {
1355 } elsif ($kvp =~ m/^firewall=([01])$/) {
1356 $res->{firewall
} = $1;
1357 } elsif ($kvp =~ m/^link_down=([01])$/) {
1358 $res->{link_down
} = $1;
1365 return undef if !$res->{model
};
1373 my $res = "$net->{model}";
1374 $res .= "=$net->{macaddr}" if $net->{macaddr
};
1375 $res .= ",bridge=$net->{bridge}" if $net->{bridge
};
1376 $res .= ",rate=$net->{rate}" if $net->{rate
};
1377 $res .= ",tag=$net->{tag}" if $net->{tag
};
1378 $res .= ",firewall=1" if $net->{firewall
};
1379 $res .= ",link_down=1" if $net->{link_down
};
1380 $res .= ",queues=$net->{queues}" if $net->{queues
};
1385 sub add_random_macs
{
1386 my ($settings) = @_;
1388 foreach my $opt (keys %$settings) {
1389 next if $opt !~ m/^net(\d+)$/;
1390 my $net = parse_net
($settings->{$opt});
1392 $settings->{$opt} = print_net
($net);
1396 sub add_unused_volume
{
1397 my ($config, $volid) = @_;
1400 for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
1401 my $test = "unused$ind";
1402 if (my $vid = $config->{$test}) {
1403 return if $vid eq $volid; # do not add duplicates
1409 die "To many unused volume - please delete them first.\n" if !$key;
1411 $config->{$key} = $volid;
1416 sub vm_is_volid_owner
{
1417 my ($storecfg, $vmid, $volid) = @_;
1419 if ($volid !~ m
|^/|) {
1421 eval { ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid); };
1422 if ($owner && ($owner == $vmid)) {
1430 sub vmconfig_delete_pending_option
{
1431 my ($conf, $key) = @_;
1433 delete $conf->{pending
}->{$key};
1434 my $pending_delete_hash = { $key => 1 };
1435 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1436 $pending_delete_hash->{$opt} = 1;
1438 $conf->{pending
}->{delete} = join(',', keys %$pending_delete_hash);
1441 sub vmconfig_undelete_pending_option
{
1442 my ($conf, $key) = @_;
1444 my $pending_delete_hash = {};
1445 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1446 $pending_delete_hash->{$opt} = 1;
1448 delete $pending_delete_hash->{$key};
1450 my @keylist = keys %$pending_delete_hash;
1451 if (scalar(@keylist)) {
1452 $conf->{pending
}->{delete} = join(',', @keylist);
1454 delete $conf->{pending
}->{delete};
1458 sub vmconfig_register_unused_drive
{
1459 my ($storecfg, $vmid, $conf, $drive) = @_;
1461 if (!drive_is_cdrom
($drive)) {
1462 my $volid = $drive->{file
};
1463 if (vm_is_volid_owner
($storecfg, $vmid, $volid)) {
1464 add_unused_volume
($conf, $volid, $vmid);
1469 sub vmconfig_cleanup_pending
{
1472 # remove pending changes when nothing changed
1474 foreach my $opt (keys %{$conf->{pending
}}) {
1475 if (defined($conf->{$opt}) && ($conf->{pending
}->{$opt} eq $conf->{$opt})) {
1477 delete $conf->{pending
}->{$opt};
1481 # remove delete if option is not set
1482 my $pending_delete_hash = {};
1483 foreach my $opt (PVE
::Tools
::split_list
($conf->{pending
}->{delete})) {
1484 if (defined($conf->{$opt})) {
1485 $pending_delete_hash->{$opt} = 1;
1491 my @keylist = keys %$pending_delete_hash;
1492 if (scalar(@keylist)) {
1493 $conf->{pending
}->{delete} = join(',', @keylist);
1495 delete $conf->{pending
}->{delete};
1501 my $valid_smbios1_options = {
1502 manufacturer
=> '\S+',
1506 uuid
=> '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
1511 # smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
1517 foreach my $kvp (split(/,/, $data)) {
1518 return undef if $kvp !~ m/^(\S+)=(.+)$/;
1519 my ($k, $v) = split(/=/, $kvp);
1520 return undef if !defined($k) || !defined($v);
1521 return undef if !$valid_smbios1_options->{$k};
1522 return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
1533 foreach my $k (keys %$smbios1) {
1534 next if !defined($smbios1->{$k});
1535 next if !$valid_smbios1_options->{$k};
1536 $data .= ',' if $data;
1537 $data .= "$k=$smbios1->{$k}";
1542 PVE
::JSONSchema
::register_format
('pve-qm-smbios1', \
&verify_smbios1
);
1543 sub verify_smbios1
{
1544 my ($value, $noerr) = @_;
1546 return $value if parse_smbios1
($value);
1548 return undef if $noerr;
1550 die "unable to parse smbios (type 1) options\n";
1553 PVE
::JSONSchema
::register_format
('pve-qm-bootdisk', \
&verify_bootdisk
);
1554 sub verify_bootdisk
{
1555 my ($value, $noerr) = @_;
1557 return $value if valid_drivename
($value);
1559 return undef if $noerr;
1561 die "invalid boot disk '$value'\n";
1564 PVE
::JSONSchema
::register_format
('pve-qm-numanode', \
&verify_numa
);
1566 my ($value, $noerr) = @_;
1568 return $value if parse_numa
($value);
1570 return undef if $noerr;
1572 die "unable to parse numa options\n";
1575 PVE
::JSONSchema
::register_format
('pve-qm-net', \
&verify_net
);
1577 my ($value, $noerr) = @_;
1579 return $value if parse_net
($value);
1581 return undef if $noerr;
1583 die "unable to parse network options\n";
1586 PVE
::JSONSchema
::register_format
('pve-qm-drive', \
&verify_drive
);
1588 my ($value, $noerr) = @_;
1590 return $value if parse_drive
(undef, $value);
1592 return undef if $noerr;
1594 die "unable to parse drive options\n";
1597 PVE
::JSONSchema
::register_format
('pve-qm-hostpci', \
&verify_hostpci
);
1598 sub verify_hostpci
{
1599 my ($value, $noerr) = @_;
1601 return $value if parse_hostpci
($value);
1603 return undef if $noerr;
1605 die "unable to parse pci id\n";
1608 PVE
::JSONSchema
::register_format
('pve-qm-watchdog', \
&verify_watchdog
);
1609 sub verify_watchdog
{
1610 my ($value, $noerr) = @_;
1612 return $value if parse_watchdog
($value);
1614 return undef if $noerr;
1616 die "unable to parse watchdog options\n";
1619 sub parse_watchdog
{
1622 return undef if !$value;
1626 foreach my $p (split(/,/, $value)) {
1627 next if $p =~ m/^\s*$/;
1629 if ($p =~ m/^(model=)?(i6300esb|ib700)$/) {
1631 } elsif ($p =~ m/^(action=)?(reset|shutdown|poweroff|pause|debug|none)$/) {
1632 $res->{action
} = $2;
1641 sub parse_usb_device
{
1644 return undef if !$value;
1646 my @dl = split(/,/, $value);
1650 foreach my $v (@dl) {
1651 if ($v =~ m/^host=(0x)?([0-9A-Fa-f]{4}):(0x)?([0-9A-Fa-f]{4})$/) {
1653 $res->{vendorid
} = $2;
1654 $res->{productid
} = $4;
1655 } elsif ($v =~ m/^host=(\d+)\-(\d+(\.\d+)*)$/) {
1657 $res->{hostbus
} = $1;
1658 $res->{hostport
} = $2;
1659 } elsif ($v =~ m/^spice$/) {
1666 return undef if !$found;
1671 PVE
::JSONSchema
::register_format
('pve-qm-usb-device', \
&verify_usb_device
);
1672 sub verify_usb_device
{
1673 my ($value, $noerr) = @_;
1675 return $value if parse_usb_device
($value);
1677 return undef if $noerr;
1679 die "unable to parse usb device\n";
1682 # add JSON properties for create and set function
1683 sub json_config_properties
{
1686 foreach my $opt (keys %$confdesc) {
1687 next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate';
1688 $prop->{$opt} = $confdesc->{$opt};
1695 my ($key, $value) = @_;
1697 die "unknown setting '$key'\n" if !$confdesc->{$key};
1699 my $type = $confdesc->{$key}->{type
};
1701 if (!defined($value)) {
1702 die "got undefined value\n";
1705 if ($value =~ m/[\n\r]/) {
1706 die "property contains a line feed\n";
1709 if ($type eq 'boolean') {
1710 return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
1711 return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
1712 die "type check ('boolean') failed - got '$value'\n";
1713 } elsif ($type eq 'integer') {
1714 return int($1) if $value =~ m/^(\d+)$/;
1715 die "type check ('integer') failed - got '$value'\n";
1716 } elsif ($type eq 'number') {
1717 return $value if $value =~ m/^(\d+)(\.\d+)?$/;
1718 die "type check ('number') failed - got '$value'\n";
1719 } elsif ($type eq 'string') {
1720 if (my $fmt = $confdesc->{$key}->{format
}) {
1721 if ($fmt eq 'pve-qm-drive') {
1722 # special case - we need to pass $key to parse_drive()
1723 my $drive = parse_drive
($key, $value);
1724 return $value if $drive;
1725 die "unable to parse drive options\n";
1727 PVE
::JSONSchema
::check_format
($fmt, $value);
1730 $value =~ s/^\"(.*)\"$/$1/;
1733 die "internal error"
1737 sub lock_config_full
{
1738 my ($vmid, $timeout, $code, @param) = @_;
1740 my $filename = config_file_lock
($vmid);
1742 my $res = lock_file
($filename, $timeout, $code, @param);
1749 sub lock_config_mode
{
1750 my ($vmid, $timeout, $shared, $code, @param) = @_;
1752 my $filename = config_file_lock
($vmid);
1754 my $res = lock_file_full
($filename, $timeout, $shared, $code, @param);
1762 my ($vmid, $code, @param) = @_;
1764 return lock_config_full
($vmid, 10, $code, @param);
1767 sub cfs_config_path
{
1768 my ($vmid, $node) = @_;
1770 $node = $nodename if !$node;
1771 return "nodes/$node/qemu-server/$vmid.conf";
1774 sub check_iommu_support
{
1775 #fixme : need to check IOMMU support
1776 #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
1784 my ($vmid, $node) = @_;
1786 my $cfspath = cfs_config_path
($vmid, $node);
1787 return "/etc/pve/$cfspath";
1790 sub config_file_lock
{
1793 return "$lock_dir/lock-$vmid.conf";
1799 my $conf = config_file
($vmid);
1800 utime undef, undef, $conf;
1804 my ($storecfg, $vmid, $keep_empty_config) = @_;
1806 my $conffile = config_file
($vmid);
1808 my $conf = load_config
($vmid);
1812 # only remove disks owned by this VM
1813 foreach_drive
($conf, sub {
1814 my ($ds, $drive) = @_;
1816 return if drive_is_cdrom
($drive);
1818 my $volid = $drive->{file
};
1820 return if !$volid || $volid =~ m
|^/|;
1822 my ($path, $owner) = PVE
::Storage
::path
($storecfg, $volid);
1823 return if !$path || !$owner || ($owner != $vmid);
1825 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1828 if ($keep_empty_config) {
1829 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
1834 # also remove unused disk
1836 my $dl = PVE
::Storage
::vdisk_list
($storecfg, undef, $vmid);
1839 PVE
::Storage
::foreach_volid
($dl, sub {
1840 my ($volid, $sid, $volname, $d) = @_;
1841 PVE
::Storage
::vdisk_free
($storecfg, $volid);
1851 my ($vmid, $node) = @_;
1853 my $cfspath = cfs_config_path
($vmid, $node);
1855 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath);
1857 die "no such VM ('$vmid')\n" if !defined($conf);
1862 sub parse_vm_config
{
1863 my ($filename, $raw) = @_;
1865 return undef if !defined($raw);
1868 digest
=> Digest
::SHA
::sha1_hex
($raw),
1873 $filename =~ m
|/qemu-server/(\d
+)\
.conf
$|
1874 || die "got strange filename '$filename'";
1882 my @lines = split(/\n/, $raw);
1883 foreach my $line (@lines) {
1884 next if $line =~ m/^\s*$/;
1886 if ($line =~ m/^\[PENDING\]\s*$/i) {
1887 $section = 'pending';
1888 $conf->{description
} = $descr if $descr;
1890 $conf = $res->{$section} = {};
1893 } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
1895 $conf->{description
} = $descr if $descr;
1897 $conf = $res->{snapshots
}->{$section} = {};
1901 if ($line =~ m/^\#(.*)\s*$/) {
1902 $descr .= PVE
::Tools
::decode_text
($1) . "\n";
1906 if ($line =~ m/^(description):\s*(.*\S)\s*$/) {
1907 $descr .= PVE
::Tools
::decode_text
($2);
1908 } elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
1909 $conf->{snapstate
} = $1;
1910 } elsif ($line =~ m/^(args):\s*(.*\S)\s*$/) {
1913 $conf->{$key} = $value;
1914 } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
1916 if ($section eq 'pending') {
1917 $conf->{delete} = $value; # we parse this later
1919 warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
1921 } elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
1924 eval { $value = check_type
($key, $value); };
1926 warn "vm $vmid - unable to parse value of '$key' - $@";
1928 my $fmt = $confdesc->{$key}->{format
};
1929 if ($fmt && $fmt eq 'pve-qm-drive') {
1930 my $v = parse_drive
($key, $value);
1931 if (my $volid = filename_to_volume_id
($vmid, $v->{file
}, $v->{media
})) {
1932 $v->{file
} = $volid;
1933 $value = print_drive
($vmid, $v);
1935 warn "vm $vmid - unable to parse value of '$key'\n";
1940 if ($key eq 'cdrom') {
1941 $conf->{ide2
} = $value;
1943 $conf->{$key} = $value;
1949 $conf->{description
} = $descr if $descr;
1951 delete $res->{snapstate
}; # just to be sure
1956 sub write_vm_config
{
1957 my ($filename, $conf) = @_;
1959 delete $conf->{snapstate
}; # just to be sure
1961 if ($conf->{cdrom
}) {
1962 die "option ide2 conflicts with cdrom\n" if $conf->{ide2
};
1963 $conf->{ide2
} = $conf->{cdrom
};
1964 delete $conf->{cdrom
};
1967 # we do not use 'smp' any longer
1968 if ($conf->{sockets
}) {
1969 delete $conf->{smp
};
1970 } elsif ($conf->{smp
}) {
1971 $conf->{sockets
} = $conf->{smp
};
1972 delete $conf->{cores
};
1973 delete $conf->{smp
};
1976 my $used_volids = {};
1978 my $cleanup_config = sub {
1979 my ($cref, $pending, $snapname) = @_;
1981 foreach my $key (keys %$cref) {
1982 next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
1983 $key eq 'snapstate' || $key eq 'pending';
1984 my $value = $cref->{$key};
1985 if ($key eq 'delete') {
1986 die "propertry 'delete' is only allowed in [PENDING]\n"
1988 # fixme: check syntax?
1991 eval { $value = check_type
($key, $value); };
1992 die "unable to parse value of '$key' - $@" if $@;
1994 $cref->{$key} = $value;
1996 if (!$snapname && valid_drivename
($key)) {
1997 my $drive = parse_drive
($key, $value);
1998 $used_volids->{$drive->{file
}} = 1 if $drive && $drive->{file
};
2003 &$cleanup_config($conf);
2005 &$cleanup_config($conf->{pending
}, 1);
2007 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2008 die "internal error" if $snapname eq 'pending';
2009 &$cleanup_config($conf->{snapshots
}->{$snapname}, undef, $snapname);
2012 # remove 'unusedX' settings if we re-add a volume
2013 foreach my $key (keys %$conf) {
2014 my $value = $conf->{$key};
2015 if ($key =~ m/^unused/ && $used_volids->{$value}) {
2016 delete $conf->{$key};
2020 my $generate_raw_config = sub {
2025 # add description as comment to top of file
2026 my $descr = $conf->{description
} || '';
2027 foreach my $cl (split(/\n/, $descr)) {
2028 $raw .= '#' . PVE
::Tools
::encode_text
($cl) . "\n";
2031 foreach my $key (sort keys %$conf) {
2032 next if $key eq 'digest' || $key eq 'description' || $key eq 'pending' || $key eq 'snapshots';
2033 $raw .= "$key: $conf->{$key}\n";
2038 my $raw = &$generate_raw_config($conf);
2040 if (scalar(keys %{$conf->{pending
}})){
2041 $raw .= "\n[PENDING]\n";
2042 $raw .= &$generate_raw_config($conf->{pending
});
2045 foreach my $snapname (sort keys %{$conf->{snapshots
}}) {
2046 $raw .= "\n[$snapname]\n";
2047 $raw .= &$generate_raw_config($conf->{snapshots
}->{$snapname});
2053 sub update_config_nolock
{
2054 my ($vmid, $conf, $skiplock) = @_;
2056 check_lock
($conf) if !$skiplock;
2058 my $cfspath = cfs_config_path
($vmid);
2060 PVE
::Cluster
::cfs_write_file
($cfspath, $conf);
2064 my ($vmid, $conf, $skiplock) = @_;
2066 lock_config
($vmid, &update_config_nolock
, $conf, $skiplock);
2073 # we use static defaults from our JSON schema configuration
2074 foreach my $key (keys %$confdesc) {
2075 if (defined(my $default = $confdesc->{$key}->{default})) {
2076 $res->{$key} = $default;
2080 my $conf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
2081 $res->{keyboard
} = $conf->{keyboard
} if $conf->{keyboard
};
2087 my $vmlist = PVE
::Cluster
::get_vmlist
();
2089 return $res if !$vmlist || !$vmlist->{ids
};
2090 my $ids = $vmlist->{ids
};
2092 foreach my $vmid (keys %$ids) {
2093 my $d = $ids->{$vmid};
2094 next if !$d->{node
} || $d->{node
} ne $nodename;
2095 next if !$d->{type
} || $d->{type
} ne 'qemu';
2096 $res->{$vmid}->{exists} = 1;
2101 # test if VM uses local resources (to prevent migration)
2102 sub check_local_resources
{
2103 my ($conf, $noerr) = @_;
2107 $loc_res = 1 if $conf->{hostusb
}; # old syntax
2108 $loc_res = 1 if $conf->{hostpci
}; # old syntax
2110 foreach my $k (keys %$conf) {
2111 next if $k =~ m/^usb/ && ($conf->{$k} eq 'spice');
2112 $loc_res = 1 if $k =~ m/^(usb|hostpci|serial|parallel)\d+$/;
2115 die "VM uses local resources\n" if $loc_res && !$noerr;
2120 # check if used storages are available on all nodes (use by migrate)
2121 sub check_storage_availability
{
2122 my ($storecfg, $conf, $node) = @_;
2124 foreach_drive
($conf, sub {
2125 my ($ds, $drive) = @_;
2127 my $volid = $drive->{file
};
2130 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2133 # check if storage is available on both nodes
2134 my $scfg = PVE
::Storage
::storage_check_node
($storecfg, $sid);
2135 PVE
::Storage
::storage_check_node
($storecfg, $sid, $node);
2139 # list nodes where all VM images are available (used by has_feature API)
2141 my ($conf, $storecfg) = @_;
2143 my $nodelist = PVE
::Cluster
::get_nodelist
();
2144 my $nodehash = { map { $_ => 1 } @$nodelist };
2145 my $nodename = PVE
::INotify
::nodename
();
2147 foreach_drive
($conf, sub {
2148 my ($ds, $drive) = @_;
2150 my $volid = $drive->{file
};
2153 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
2155 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
2156 if ($scfg->{disable
}) {
2158 } elsif (my $avail = $scfg->{nodes
}) {
2159 foreach my $node (keys %$nodehash) {
2160 delete $nodehash->{$node} if !$avail->{$node};
2162 } elsif (!$scfg->{shared
}) {
2163 foreach my $node (keys %$nodehash) {
2164 delete $nodehash->{$node} if $node ne $nodename
2176 die "VM is locked ($conf->{lock})\n" if $conf->{lock};
2180 my ($pidfile, $pid) = @_;
2182 my $fh = IO
::File-
>new("/proc/$pid/cmdline", "r");
2186 return undef if !$line;
2187 my @param = split(/\0/, $line);
2189 my $cmd = $param[0];
2190 return if !$cmd || ($cmd !~ m
|kvm
$| && $cmd !~ m
|qemu-system-x86_64
$|);
2192 for (my $i = 0; $i < scalar (@param); $i++) {
2195 if (($p eq '-pidfile') || ($p eq '--pidfile')) {
2196 my $p = $param[$i+1];
2197 return 1 if $p && ($p eq $pidfile);
2206 my ($vmid, $nocheck, $node) = @_;
2208 my $filename = config_file
($vmid, $node);
2210 die "unable to find configuration file for VM $vmid - no such machine\n"
2211 if !$nocheck && ! -f
$filename;
2213 my $pidfile = pidfile_name
($vmid);
2215 if (my $fd = IO
::File-
>new("<$pidfile")) {
2220 my $mtime = $st->mtime;
2221 if ($mtime > time()) {
2222 warn "file '$filename' modified in future\n";
2225 if ($line =~ m/^(\d+)$/) {
2227 if (check_cmdline
($pidfile, $pid)) {
2228 if (my $pinfo = PVE
::ProcFSTools
::check_process_running
($pid)) {
2240 my $vzlist = config_list
();
2242 my $fd = IO
::Dir-
>new($var_run_tmpdir) || return $vzlist;
2244 while (defined(my $de = $fd->read)) {
2245 next if $de !~ m/^(\d+)\.pid$/;
2247 next if !defined($vzlist->{$vmid});
2248 if (my $pid = check_running
($vmid)) {
2249 $vzlist->{$vmid}->{pid
} = $pid;
2257 my ($storecfg, $conf) = @_;
2259 my $bootdisk = $conf->{bootdisk
};
2260 return undef if !$bootdisk;
2261 return undef if !valid_drivename
($bootdisk);
2263 return undef if !$conf->{$bootdisk};
2265 my $drive = parse_drive
($bootdisk, $conf->{$bootdisk});
2266 return undef if !defined($drive);
2268 return undef if drive_is_cdrom
($drive);
2270 my $volid = $drive->{file
};
2271 return undef if !$volid;
2273 return $drive->{size
};
2276 my $last_proc_pid_stat;
2278 # get VM status information
2279 # This must be fast and should not block ($full == false)
2280 # We only query KVM using QMP if $full == true (this can be slow)
2282 my ($opt_vmid, $full) = @_;
2286 my $storecfg = PVE
::Storage
::config
();
2288 my $list = vzlist
();
2289 my ($uptime) = PVE
::ProcFSTools
::read_proc_uptime
(1);
2291 my $cpucount = $cpuinfo->{cpus
} || 1;
2293 foreach my $vmid (keys %$list) {
2294 next if $opt_vmid && ($vmid ne $opt_vmid);
2296 my $cfspath = cfs_config_path
($vmid);
2297 my $conf = PVE
::Cluster
::cfs_read_file
($cfspath) || {};
2300 $d->{pid
} = $list->{$vmid}->{pid
};
2302 # fixme: better status?
2303 $d->{status
} = $list->{$vmid}->{pid
} ?
'running' : 'stopped';
2305 my $size = disksize
($storecfg, $conf);
2306 if (defined($size)) {
2307 $d->{disk
} = 0; # no info available
2308 $d->{maxdisk
} = $size;
2314 $d->{cpus
} = ($conf->{sockets
} || 1) * ($conf->{cores
} || 1);
2315 $d->{cpus
} = $cpucount if $d->{cpus
} > $cpucount;
2316 $d->{cpus
} = $conf->{vcpus
} if $conf->{vcpus
};
2318 $d->{name
} = $conf->{name
} || "VM $vmid";
2319 $d->{maxmem
} = $conf->{memory
} ?
$conf->{memory
}*(1024*1024) : 0;
2321 if ($conf->{balloon
}) {
2322 $d->{balloon_min
} = $conf->{balloon
}*(1024*1024);
2323 $d->{shares
} = defined($conf->{shares
}) ?
$conf->{shares
} : 1000;
2334 $d->{diskwrite
} = 0;
2336 $d->{template
} = is_template
($conf);
2341 my $netdev = PVE
::ProcFSTools
::read_proc_net_dev
();
2342 foreach my $dev (keys %$netdev) {
2343 next if $dev !~ m/^tap([1-9]\d*)i/;
2345 my $d = $res->{$vmid};
2348 $d->{netout
} += $netdev->{$dev}->{receive
};
2349 $d->{netin
} += $netdev->{$dev}->{transmit
};
2352 $d->{nics
}->{$dev}->{netout
} = $netdev->{$dev}->{receive
};
2353 $d->{nics
}->{$dev}->{netin
} = $netdev->{$dev}->{transmit
};
2358 my $ctime = gettimeofday
;
2360 foreach my $vmid (keys %$list) {
2362 my $d = $res->{$vmid};
2363 my $pid = $d->{pid
};
2366 my $pstat = PVE
::ProcFSTools
::read_proc_pid_stat
($pid);
2367 next if !$pstat; # not running
2369 my $used = $pstat->{utime} + $pstat->{stime
};
2371 $d->{uptime
} = int(($uptime - $pstat->{starttime
})/$cpuinfo->{user_hz
});
2373 if ($pstat->{vsize
}) {
2374 $d->{mem
} = int(($pstat->{rss
}/$pstat->{vsize
})*$d->{maxmem
});
2377 my $old = $last_proc_pid_stat->{$pid};
2379 $last_proc_pid_stat->{$pid} = {
2387 my $dtime = ($ctime - $old->{time}) * $cpucount * $cpuinfo->{user_hz
};
2389 if ($dtime > 1000) {
2390 my $dutime = $used - $old->{used
};
2392 $d->{cpu
} = (($dutime/$dtime)* $cpucount) / $d->{cpus
};
2393 $last_proc_pid_stat->{$pid} = {
2399 $d->{cpu
} = $old->{cpu
};
2403 return $res if !$full;
2405 my $qmpclient = PVE
::QMPClient-
>new();
2407 my $ballooncb = sub {
2408 my ($vmid, $resp) = @_;
2410 my $info = $resp->{'return'};
2411 return if !$info->{max_mem
};
2413 my $d = $res->{$vmid};
2415 # use memory assigned to VM
2416 $d->{maxmem
} = $info->{max_mem
};
2417 $d->{balloon
} = $info->{actual
};
2419 if (defined($info->{total_mem
}) && defined($info->{free_mem
})) {
2420 $d->{mem
} = $info->{total_mem
} - $info->{free_mem
};
2421 $d->{freemem
} = $info->{free_mem
};
2424 $d->{ballooninfo
} = $info;
2427 my $blockstatscb = sub {
2428 my ($vmid, $resp) = @_;
2429 my $data = $resp->{'return'} || [];
2430 my $totalrdbytes = 0;
2431 my $totalwrbytes = 0;
2433 for my $blockstat (@$data) {
2434 $totalrdbytes = $totalrdbytes + $blockstat->{stats
}->{rd_bytes
};
2435 $totalwrbytes = $totalwrbytes + $blockstat->{stats
}->{wr_bytes
};
2437 $blockstat->{device
} =~ s/drive-//;
2438 $res->{$vmid}->{blockstat
}->{$blockstat->{device
}} = $blockstat->{stats
};
2440 $res->{$vmid}->{diskread
} = $totalrdbytes;
2441 $res->{$vmid}->{diskwrite
} = $totalwrbytes;
2444 my $statuscb = sub {
2445 my ($vmid, $resp) = @_;
2447 $qmpclient->queue_cmd($vmid, $blockstatscb, 'query-blockstats');
2448 # this fails if ballon driver is not loaded, so this must be
2449 # the last commnand (following command are aborted if this fails).
2450 $qmpclient->queue_cmd($vmid, $ballooncb, 'query-balloon');
2452 my $status = 'unknown';
2453 if (!defined($status = $resp->{'return'}->{status
})) {
2454 warn "unable to get VM status\n";
2458 $res->{$vmid}->{qmpstatus
} = $resp->{'return'}->{status
};
2461 foreach my $vmid (keys %$list) {
2462 next if $opt_vmid && ($vmid ne $opt_vmid);
2463 next if !$res->{$vmid}->{pid
}; # not running
2464 $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
2467 $qmpclient->queue_execute(undef, 1);
2469 foreach my $vmid (keys %$list) {
2470 next if $opt_vmid && ($vmid ne $opt_vmid);
2471 $res->{$vmid}->{qmpstatus
} = $res->{$vmid}->{status
} if !$res->{$vmid}->{qmpstatus
};
2478 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2481 my $current_size = 1024;
2482 my $dimm_size = 512;
2483 return if $current_size == $memory;
2485 for (my $j = 0; $j < 8; $j++) {
2486 for (my $i = 0; $i < 32; $i++) {
2487 my $name = "dimm${dimm_id}";
2489 my $numanode = $i % $sockets;
2490 $current_size += $dimm_size;
2491 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2492 return $current_size if $current_size >= $memory;
2498 sub foreach_reverse_dimm
{
2499 my ($conf, $vmid, $memory, $sockets, $func) = @_;
2502 my $current_size = 4177920;
2503 my $dimm_size = 65536;
2504 return if $current_size == $memory;
2506 for (my $j = 0; $j < 8; $j++) {
2507 for (my $i = 0; $i < 32; $i++) {
2508 my $name = "dimm${dimm_id}";
2510 my $numanode = $i % $sockets;
2511 $current_size -= $dimm_size;
2512 &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory);
2513 return $current_size if $current_size <= $memory;
2520 my ($conf, $func) = @_;
2522 foreach my $ds (keys %$conf) {
2523 next if !valid_drivename
($ds);
2525 my $drive = parse_drive
($ds, $conf->{$ds});
2528 &$func($ds, $drive);
2533 my ($conf, $func) = @_;
2537 my $test_volid = sub {
2538 my ($volid, $is_cdrom) = @_;
2542 $volhash->{$volid} = $is_cdrom || 0;
2545 foreach_drive
($conf, sub {
2546 my ($ds, $drive) = @_;
2547 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2550 foreach my $snapname (keys %{$conf->{snapshots
}}) {
2551 my $snap = $conf->{snapshots
}->{$snapname};
2552 &$test_volid($snap->{vmstate
}, 0);
2553 foreach_drive
($snap, sub {
2554 my ($ds, $drive) = @_;
2555 &$test_volid($drive->{file
}, drive_is_cdrom
($drive));
2559 foreach my $volid (keys %$volhash) {
2560 &$func($volid, $volhash->{$volid});
2564 sub vga_conf_has_spice
{
2567 return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
2572 sub config_to_command
{
2573 my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
2576 my $globalFlags = [];
2577 my $machineFlags = [];
2583 my $kvmver = kvm_user_version
();
2584 my $vernum = 0; # unknown
2585 if ($kvmver =~ m/^(\d+)\.(\d+)$/) {
2586 $vernum = $1*1000000+$2*1000;
2587 } elsif ($kvmver =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
2588 $vernum = $1*1000000+$2*1000+$3;
2591 die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
2593 my $have_ovz = -f
'/proc/vz/vestat';
2595 my $q35 = machine_type_is_q35
($conf);
2596 my $hotplug_features = parse_hotplug_features
(defined($conf->{hotplug
}) ?
$conf->{hotplug
} : '1');
2597 my $machine_type = $forcemachine || $conf->{machine
};
2599 my $cpuunits = defined($conf->{cpuunits
}) ?
2600 $conf->{cpuunits
} : $defaults->{cpuunits
};
2602 push @$cmd, '/usr/bin/systemd-run';
2603 push @$cmd, '--scope';
2604 push @$cmd, '--slice', "qemu";
2605 push @$cmd, '--unit', $vmid;
2606 push @$cmd, '-p', "CPUShares=$cpuunits";
2607 if ($conf->{cpulimit
}) {
2608 my $cpulimit = int($conf->{cpulimit
} * 100);
2609 push @$cmd, '-p', "CPUQuota=$cpulimit\%";
2612 push @$cmd, '/usr/bin/kvm';
2614 push @$cmd, '-id', $vmid;
2618 my $qmpsocket = qmp_socket
($vmid);
2619 push @$cmd, '-chardev', "socket,id=qmp,path=$qmpsocket,server,nowait";
2620 push @$cmd, '-mon', "chardev=qmp,mode=control";
2622 my $socket = vnc_socket
($vmid);
2623 push @$cmd, '-vnc', "unix:$socket,x509,password";
2625 push @$cmd, '-pidfile' , pidfile_name
($vmid);
2627 push @$cmd, '-daemonize';
2629 if ($conf->{smbios1
}) {
2630 push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
2634 # the q35 chipset support native usb2, so we enable usb controller
2635 # by default for this machine type
2636 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-q35.cfg';
2638 $pciaddr = print_pci_addr
("piix3", $bridges);
2639 push @$devices, '-device', "piix3-usb-uhci,id=uhci$pciaddr.0x2";
2642 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2643 next if !$conf->{"usb$i"};
2646 # include usb device config
2647 push @$devices, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg' if $use_usb2;
2650 my $vga = $conf->{vga
};
2652 my $qxlnum = vga_conf_has_spice
($vga);
2653 $vga = 'qxl' if $qxlnum;
2656 if ($conf->{ostype
} && ($conf->{ostype
} eq 'win8' ||
2657 $conf->{ostype
} eq 'win7' ||
2658 $conf->{ostype
} eq 'w2k8')) {
2665 # enable absolute mouse coordinates (needed by vnc)
2667 if (defined($conf->{tablet
})) {
2668 $tablet = $conf->{tablet
};
2670 $tablet = $defaults->{tablet
};
2671 $tablet = 0 if $qxlnum; # disable for spice because it is not needed
2672 $tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
2675 push @$devices, '-device', print_tabletdevice_full
($conf) if $tablet;
2678 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
2679 my $d = parse_hostpci
($conf->{"hostpci$i"});
2682 my $pcie = $d->{pcie
};
2684 die "q35 machine model is not enabled" if !$q35;
2685 $pciaddr = print_pcie_addr
("hostpci$i");
2687 $pciaddr = print_pci_addr
("hostpci$i", $bridges);
2690 my $rombar = $d->{rombar
} && $d->{rombar
} eq 'off' ?
",rombar=0" : "";
2691 my $driver = $d->{driver
} && $d->{driver
} eq 'vfio' ?
"vfio-pci" : "pci-assign";
2692 my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ?
",x-vga=on" : "";
2693 if ($xvga && $xvga ne '') {
2694 push @$cpuFlags, 'kvm=off';
2697 $driver = "vfio-pci" if $xvga ne '';
2698 my $pcidevices = $d->{pciid
};
2699 my $multifunction = 1 if @$pcidevices > 1;
2702 foreach my $pcidevice (@$pcidevices) {
2704 my $id = "hostpci$i";
2705 $id .= ".$j" if $multifunction;
2706 my $addr = $pciaddr;
2707 $addr .= ".$j" if $multifunction;
2708 my $devicestr = "$driver,host=$pcidevice->{id}.$pcidevice->{function},id=$id$addr";
2711 $devicestr .= "$rombar$xvga";
2712 $devicestr .= ",multifunction=on" if $multifunction;
2715 push @$devices, '-device', $devicestr;
2721 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
2722 my $d = parse_usb_device
($conf->{"usb$i"});
2724 if ($d->{vendorid
} && $d->{productid
}) {
2725 push @$devices, '-device', "usb-host,vendorid=0x$d->{vendorid},productid=0x$d->{productid}";
2726 } elsif (defined($d->{hostbus
}) && defined($d->{hostport
})) {
2727 push @$devices, '-device', "usb-host,hostbus=$d->{hostbus},hostport=$d->{hostport}";
2728 } elsif ($d->{spice
}) {
2729 # usb redir support for spice
2730 push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
2731 push @$devices, '-device', "usb-redir,chardev=usbredirchardev$i,id=usbredirdev$i,bus=ehci.0";
2736 for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
2737 if (my $path = $conf->{"serial$i"}) {
2738 if ($path eq 'socket') {
2739 my $socket = "/var/run/qemu-server/${vmid}.serial$i";
2740 push @$devices, '-chardev', "socket,id=serial$i,path=$socket,server,nowait";
2741 push @$devices, '-device', "isa-serial,chardev=serial$i";
2743 die "no such serial device\n" if ! -c
$path;
2744 push @$devices, '-chardev', "tty,id=serial$i,path=$path";
2745 push @$devices, '-device', "isa-serial,chardev=serial$i";
2751 for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
2752 if (my $path = $conf->{"parallel$i"}) {
2753 die "no such parallel device\n" if ! -c
$path;
2754 my $devtype = $path =~ m!^/dev/usb/lp! ?
'tty' : 'parport';
2755 push @$devices, '-chardev', "$devtype,id=parallel$i,path=$path";
2756 push @$devices, '-device', "isa-parallel,chardev=parallel$i";
2760 my $vmname = $conf->{name
} || "vm$vmid";
2762 push @$cmd, '-name', $vmname;
2765 $sockets = $conf->{smp
} if $conf->{smp
}; # old style - no longer iused
2766 $sockets = $conf->{sockets
} if $conf->{sockets
};
2768 my $cores = $conf->{cores
} || 1;
2770 my $maxcpus = $sockets * $cores;
2772 my $vcpus = $conf->{vcpus
} ?
$conf->{vcpus
} : $maxcpus;
2774 my $allowed_vcpus = $cpuinfo->{cpus
};
2776 die "MAX $maxcpus vcpus allowed per VM on this node\n"
2777 if ($allowed_vcpus < $maxcpus);
2779 push @$cmd, '-smp', "$vcpus,sockets=$sockets,cores=$cores,maxcpus=$maxcpus";
2781 push @$cmd, '-nodefaults';
2783 my $bootorder = $conf->{boot
} || $confdesc->{boot
}->{default};
2785 my $bootindex_hash = {};
2787 foreach my $o (split(//, $bootorder)) {
2788 $bootindex_hash->{$o} = $i*100;
2792 push @$cmd, '-boot', "menu=on,strict=on,reboot-timeout=1000";
2794 push @$cmd, '-no-acpi' if defined($conf->{acpi
}) && $conf->{acpi
} == 0;
2796 push @$cmd, '-no-reboot' if defined($conf->{reboot
}) && $conf->{reboot
} == 0;
2798 push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
2801 my $tdf = defined($conf->{tdf
}) ?
$conf->{tdf
} : $defaults->{tdf
};
2803 my $nokvm = defined($conf->{kvm
}) && $conf->{kvm
} == 0 ?
1 : 0;
2804 my $useLocaltime = $conf->{localtime};
2806 if (my $ost = $conf->{ostype
}) {
2807 # other, wxp, w2k, w2k3, w2k8, wvista, win7, win8, l24, l26, solaris
2809 if ($ost =~ m/^w/) { # windows
2810 $useLocaltime = 1 if !defined($conf->{localtime});
2812 # use time drift fix when acpi is enabled
2813 if (!(defined($conf->{acpi
}) && $conf->{acpi
} == 0)) {
2814 $tdf = 1 if !defined($conf->{tdf
});
2818 if ($ost eq 'win7' || $ost eq 'win8' || $ost eq 'w2k8' ||
2820 push @$globalFlags, 'kvm-pit.lost_tick_policy=discard';
2821 push @$cmd, '-no-hpet';
2822 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2823 push @$cpuFlags , 'hv_spinlocks=0x1fff' if !$nokvm;
2824 push @$cpuFlags , 'hv_vapic' if !$nokvm;
2825 push @$cpuFlags , 'hv_time' if !$nokvm;
2828 push @$cpuFlags , 'hv_spinlocks=0xffff' if !$nokvm;
2832 if ($ost eq 'win7' || $ost eq 'win8') {
2833 push @$cpuFlags , 'hv_relaxed' if !$nokvm;
2837 push @$rtcFlags, 'driftfix=slew' if $tdf;
2840 push @$machineFlags, 'accel=tcg';
2842 die "No accelerator found!\n" if !$cpuinfo->{hvm
};
2845 if ($machine_type) {
2846 push @$machineFlags, "type=${machine_type}";
2849 if ($conf->{startdate
}) {
2850 push @$rtcFlags, "base=$conf->{startdate}";
2851 } elsif ($useLocaltime) {
2852 push @$rtcFlags, 'base=localtime';
2855 my $cpu = $nokvm ?
"qemu64" : "kvm64";
2856 $cpu = $conf->{cpu
} if $conf->{cpu
};
2858 push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64';
2860 push @$cpuFlags , '+x2apic' if !$nokvm && $conf->{ostype
} ne 'solaris';
2862 push @$cpuFlags , '-x2apic' if $conf->{ostype
} eq 'solaris';
2864 push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
2866 push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
2868 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
2870 push @$cpuFlags , '+kvm_pv_unhalt' if !$nokvm;
2871 push @$cpuFlags , '+kvm_pv_eoi' if !$nokvm;
2874 push @$cpuFlags, 'enforce' if $cpu ne 'host' && !$nokvm;
2876 $cpu .= "," . join(',', @$cpuFlags) if scalar(@$cpuFlags);
2878 push @$cmd, '-cpu', $cpu;
2880 my $memory = $conf->{memory
} || $defaults->{memory
};
2881 my $static_memory = 0;
2882 my $dimm_memory = 0;
2884 if ($hotplug_features->{memory
}) {
2885 die "Numa need to be enabled for memory hotplug\n" if !$conf->{numa
};
2886 die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM;
2887 $static_memory = $STATICMEM;
2888 die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory);
2889 $dimm_memory = $memory - $static_memory;
2890 push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M";
2894 $static_memory = $memory;
2895 push @$cmd, '-m', $static_memory;
2898 if ($conf->{numa
}) {
2900 my $numa_totalmemory = undef;
2901 for (my $i = 0; $i < $MAX_NUMA; $i++) {
2902 next if !$conf->{"numa$i"};
2903 my $numa = parse_numa
($conf->{"numa$i"});
2906 die "missing numa node$i memory value\n" if !$numa->{memory
};
2907 my $numa_memory = $numa->{memory
};
2908 $numa_totalmemory += $numa_memory;
2909 my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
2912 my $cpus_start = $numa->{cpus
}->{start
};
2913 die "missing numa node$i cpus\n" if !defined($cpus_start);
2914 my $cpus_end = $numa->{cpus
}->{end
} if defined($numa->{cpus
}->{end
});
2915 my $cpus = $cpus_start;
2916 if (defined($cpus_end)) {
2917 $cpus .= "-$cpus_end";
2918 die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
2922 my $hostnodes_start = $numa->{hostnodes
}->{start
};
2923 if (defined($hostnodes_start)) {
2924 my $hostnodes_end = $numa->{hostnodes
}->{end
} if defined($numa->{hostnodes
}->{end
});
2925 my $hostnodes = $hostnodes_start;
2926 if (defined($hostnodes_end)) {
2927 $hostnodes .= "-$hostnodes_end";
2928 die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
2931 my $hostnodes_end_range = defined($hostnodes_end) ?
$hostnodes_end : $hostnodes_start;
2932 for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
2933 die "host numa node$i don't exist\n" if ! -d
"/sys/devices/system/node/node$i/";
2937 my $policy = $numa->{policy
};
2938 die "you need to define a policy for hostnode $hostnodes\n" if !$policy;
2939 $numa_object .= ",host-nodes=$hostnodes,policy=$policy";
2942 push @$cmd, '-object', $numa_object;
2943 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2946 die "total memory for NUMA nodes must be equal to vm static memory\n"
2947 if $numa_totalmemory && $numa_totalmemory != $static_memory;
2949 #if no custom tology, we split memory and cores across numa nodes
2950 if(!$numa_totalmemory) {
2952 my $numa_memory = ($static_memory / $sockets) . "M";
2954 for (my $i = 0; $i < $sockets; $i++) {
2956 my $cpustart = ($cores * $i);
2957 my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1;
2958 my $cpus = $cpustart;
2959 $cpus .= "-$cpuend" if $cpuend;
2961 push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i";
2962 push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i";
2967 if ($hotplug_features->{memory
}) {
2968 foreach_dimm
($conf, $vmid, $memory, $sockets, sub {
2969 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
2970 push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M";
2971 push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode";
2973 #if dimm_memory is not aligned to dimm map
2974 if($current_size > $memory) {
2975 $conf->{memory
} = $current_size;
2976 update_config_nolock
($vmid, $conf, 1);
2981 push @$cmd, '-S' if $conf->{freeze
};
2983 # set keyboard layout
2984 my $kb = $conf->{keyboard
} || $defaults->{keyboard
};
2985 push @$cmd, '-k', $kb if $kb;
2988 #my $soundhw = $conf->{soundhw} || $defaults->{soundhw};
2989 #push @$cmd, '-soundhw', 'es1370';
2990 #push @$cmd, '-soundhw', $soundhw if $soundhw;
2992 if($conf->{agent
}) {
2993 my $qgasocket = qmp_socket
($vmid, 1);
2994 my $pciaddr = print_pci_addr
("qga0", $bridges);
2995 push @$devices, '-chardev', "socket,path=$qgasocket,server,nowait,id=qga0";
2996 push @$devices, '-device', "virtio-serial,id=qga0$pciaddr";
2997 push @$devices, '-device', 'virtserialport,chardev=qga0,name=org.qemu.guest_agent.0';
3004 if ($conf->{ostype
} && $conf->{ostype
} =~ m/^w/){
3005 for(my $i = 1; $i < $qxlnum; $i++){
3006 my $pciaddr = print_pci_addr
("vga$i", $bridges);
3007 push @$cmd, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
3010 # assume other OS works like Linux
3011 push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
3012 push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
3016 my $pciaddr = print_pci_addr
("spice", $bridges);
3018 my $nodename = PVE
::INotify
::nodename
();
3019 my $pfamily = PVE
::Tools
::get_host_address_family
($nodename);
3020 $spice_port = PVE
::Tools
::next_spice_port
($pfamily);
3022 push @$devices, '-spice', "tls-port=${spice_port},addr=localhost,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
3024 push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
3025 push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
3026 push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
3029 # enable balloon by default, unless explicitly disabled
3030 if (!defined($conf->{balloon
}) || $conf->{balloon
}) {
3031 $pciaddr = print_pci_addr
("balloon0", $bridges);
3032 push @$devices, '-device', "virtio-balloon-pci,id=balloon0$pciaddr";
3035 if ($conf->{watchdog
}) {
3036 my $wdopts = parse_watchdog
($conf->{watchdog
});
3037 $pciaddr = print_pci_addr
("watchdog", $bridges);
3038 my $watchdog = $wdopts->{model
} || 'i6300esb';
3039 push @$devices, '-device', "$watchdog$pciaddr";
3040 push @$devices, '-watchdog-action', $wdopts->{action
} if $wdopts->{action
};
3044 my $scsicontroller = {};
3045 my $ahcicontroller = {};
3046 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : $defaults->{scsihw
};
3048 # Add iscsi initiator name if available
3049 if (my $initiator = get_initiator_name
()) {
3050 push @$devices, '-iscsi', "initiator-name=$initiator";
3053 foreach_drive
($conf, sub {
3054 my ($ds, $drive) = @_;
3056 if (PVE
::Storage
::parse_volume_id
($drive->{file
}, 1)) {
3057 push @$vollist, $drive->{file
};
3060 $use_virtio = 1 if $ds =~ m/^virtio/;
3062 if (drive_is_cdrom
($drive)) {
3063 if ($bootindex_hash->{d
}) {
3064 $drive->{bootindex
} = $bootindex_hash->{d
};
3065 $bootindex_hash->{d
} += 1;
3068 if ($bootindex_hash->{c
}) {
3069 $drive->{bootindex
} = $bootindex_hash->{c
} if $conf->{bootdisk
} && ($conf->{bootdisk
} eq $ds);
3070 $bootindex_hash->{c
} += 1;
3074 if($drive->{interface
} eq 'virtio'){
3075 push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread
};
3078 if ($drive->{interface
} eq 'scsi') {
3080 my ($maxdev, $controller, $controller_prefix) = scsihw_infos
($conf, $drive);
3082 $pciaddr = print_pci_addr
("$controller_prefix$controller", $bridges);
3083 my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ?
"virtio-scsi-pci" : $scsihw;
3086 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{iothread
}){
3087 $iothread .= ",iothread=iothread-$controller_prefix$controller";
3088 push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
3092 if($conf->{scsihw
} && $conf->{scsihw
} eq "virtio-scsi-single" && $drive->{queues
}){
3093 $queues = ",num_queues=$drive->{queues}";
3096 push @$devices, '-device', "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues" if !$scsicontroller->{$controller};
3097 $scsicontroller->{$controller}=1;
3100 if ($drive->{interface
} eq 'sata') {
3101 my $controller = int($drive->{index} / $MAX_SATA_DISKS);
3102 $pciaddr = print_pci_addr
("ahci$controller", $bridges);
3103 push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr" if !$ahcicontroller->{$controller};
3104 $ahcicontroller->{$controller}=1;
3107 my $drive_cmd = print_drive_full
($storecfg, $vmid, $drive);
3108 push @$devices, '-drive',$drive_cmd;
3109 push @$devices, '-device', print_drivedevice_full
($storecfg, $conf, $vmid, $drive, $bridges);
3112 for (my $i = 0; $i < $MAX_NETS; $i++) {
3113 next if !$conf->{"net$i"};
3114 my $d = parse_net
($conf->{"net$i"});
3117 $use_virtio = 1 if $d->{model
} eq 'virtio';
3119 if ($bootindex_hash->{n
}) {
3120 $d->{bootindex
} = $bootindex_hash->{n
};
3121 $bootindex_hash->{n
} += 1;
3124 my $netdevfull = print_netdev_full
($vmid,$conf,$d,"net$i");
3125 push @$devices, '-netdev', $netdevfull;
3127 my $netdevicefull = print_netdevice_full
($vmid,$conf,$d,"net$i",$bridges);
3128 push @$devices, '-device', $netdevicefull;
3133 if (qemu_machine_feature_enabled
($machine_type, $kvmver, 2, 3)) {
3138 $bridges->{3} = 1 if $scsihw =~ m/^virtio-scsi-single/;
3140 while (my ($k, $v) = each %$bridges) {
3141 $pciaddr = print_pci_addr
("pci.$k");
3142 unshift @$devices, '-device', "pci-bridge,id=pci.$k,chassis_nr=$k$pciaddr" if $k > 0;
3147 if ($conf->{args
}) {
3148 my $aa = PVE
::Tools
::split_args
($conf->{args
});
3152 push @$cmd, @$devices;
3153 push @$cmd, '-rtc', join(',', @$rtcFlags)
3154 if scalar(@$rtcFlags);
3155 push @$cmd, '-machine', join(',', @$machineFlags)
3156 if scalar(@$machineFlags);
3157 push @$cmd, '-global', join(',', @$globalFlags)
3158 if scalar(@$globalFlags);
3160 return wantarray ?
($cmd, $vollist, $spice_port) : $cmd;
3165 return "${var_run_tmpdir}/$vmid.vnc";
3171 my $res = vm_mon_cmd
($vmid, 'query-spice');
3173 return $res->{'tls-port'} || $res->{'port'} || die "no spice port\n";
3177 my ($vmid, $qga) = @_;
3178 my $sockettype = $qga ?
'qga' : 'qmp';
3179 return "${var_run_tmpdir}/$vmid.$sockettype";
3184 return "${var_run_tmpdir}/$vmid.pid";
3187 sub vm_devices_list
{
3190 my $res = vm_mon_cmd
($vmid, 'query-pci');
3192 foreach my $pcibus (@$res) {
3193 foreach my $device (@{$pcibus->{devices
}}) {
3194 next if !$device->{'qdev_id'};
3195 if ($device->{'pci_bridge'}) {
3196 $devices->{$device->{'qdev_id'}} = 1;
3197 foreach my $bridge_device (@{$device->{'pci_bridge'}->{devices
}}) {
3198 next if !$bridge_device->{'qdev_id'};
3199 $devices->{$bridge_device->{'qdev_id'}} = 1;
3200 $devices->{$device->{'qdev_id'}}++;
3203 $devices->{$device->{'qdev_id'}} = 1;
3208 my $resblock = vm_mon_cmd
($vmid, 'query-block');
3209 foreach my $block (@$resblock) {
3210 if($block->{device
} =~ m/^drive-(\S+)/){
3215 my $resmice = vm_mon_cmd
($vmid, 'query-mice');
3216 foreach my $mice (@$resmice) {
3217 if ($mice->{name
} eq 'QEMU HID Tablet') {
3218 $devices->{tablet
} = 1;
3227 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
3229 my $q35 = machine_type_is_q35
($conf);
3231 my $devices_list = vm_devices_list
($vmid);
3232 return 1 if defined($devices_list->{$deviceid});
3234 qemu_add_pci_bridge
($storecfg, $conf, $vmid, $deviceid); # add PCI bridge if we need it for the device
3236 if ($deviceid eq 'tablet') {
3238 qemu_deviceadd
($vmid, print_tabletdevice_full
($conf));
3240 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3242 qemu_iothread_add
($vmid, $deviceid, $device);
3244 qemu_driveadd
($storecfg, $vmid, $device);
3245 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3247 qemu_deviceadd
($vmid, $devicefull);
3248 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3250 eval { qemu_drivedel
($vmid, $deviceid); };
3255 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3258 my $scsihw = defined($conf->{scsihw
}) ?
$conf->{scsihw
} : "lsi";
3259 my $pciaddr = print_pci_addr
($deviceid);
3260 my $scsihw_type = $scsihw eq 'virtio-scsi-single' ?
"virtio-scsi-pci" : $scsihw;
3262 my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
3264 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread
}) {
3265 qemu_iothread_add
($vmid, $deviceid, $device);
3266 $devicefull .= ",iothread=iothread-$deviceid";
3269 if($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues
}) {
3270 $devicefull .= ",num_queues=$device->{queues}";
3273 qemu_deviceadd
($vmid, $devicefull);
3274 qemu_deviceaddverify
($vmid, $deviceid);
3276 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3278 qemu_findorcreatescsihw
($storecfg,$conf, $vmid, $device);
3279 qemu_driveadd
($storecfg, $vmid, $device);
3281 my $devicefull = print_drivedevice_full
($storecfg, $conf, $vmid, $device);
3282 eval { qemu_deviceadd
($vmid, $devicefull); };
3284 eval { qemu_drivedel
($vmid, $deviceid); };
3289 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3291 return undef if !qemu_netdevadd
($vmid, $conf, $device, $deviceid);
3292 my $netdevicefull = print_netdevice_full
($vmid, $conf, $device, $deviceid);
3293 qemu_deviceadd
($vmid, $netdevicefull);
3294 eval { qemu_deviceaddverify
($vmid, $deviceid); };
3296 eval { qemu_netdevdel
($vmid, $deviceid); };
3301 } elsif (!$q35 && $deviceid =~ m/^(pci\.)(\d+)$/) {
3304 my $pciaddr = print_pci_addr
($deviceid);
3305 my $devicefull = "pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr";
3307 qemu_deviceadd
($vmid, $devicefull);
3308 qemu_deviceaddverify
($vmid, $deviceid);
3311 die "can't hotplug device '$deviceid'\n";
3317 # fixme: this should raise exceptions on error!
3318 sub vm_deviceunplug
{
3319 my ($vmid, $conf, $deviceid) = @_;
3321 my $devices_list = vm_devices_list
($vmid);
3322 return 1 if !defined($devices_list->{$deviceid});
3324 die "can't unplug bootdisk" if $conf->{bootdisk
} && $conf->{bootdisk
} eq $deviceid;
3326 if ($deviceid eq 'tablet') {
3328 qemu_devicedel
($vmid, $deviceid);
3330 } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
3332 qemu_devicedel
($vmid, $deviceid);
3333 qemu_devicedelverify
($vmid, $deviceid);
3334 qemu_drivedel
($vmid, $deviceid);
3335 qemu_iothread_del
($conf, $vmid, $deviceid);
3337 } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
3339 qemu_devicedel
($vmid, $deviceid);
3340 qemu_devicedelverify
($vmid, $deviceid);
3341 qemu_iothread_del
($conf, $vmid, $deviceid);
3343 } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
3345 #qemu 2.3 segfault on drive_del with virtioscsi + iothread
3346 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3347 die "virtioscsi with iothread is not hot-unplugglable currently" if $device->{iothread
};
3349 qemu_devicedel
($vmid, $deviceid);
3350 qemu_drivedel
($vmid, $deviceid);
3351 qemu_deletescsihw
($conf, $vmid, $deviceid);
3353 } elsif ($deviceid =~ m/^(net)(\d+)$/) {
3355 qemu_devicedel
($vmid, $deviceid);
3356 qemu_devicedelverify
($vmid, $deviceid);
3357 qemu_netdevdel
($vmid, $deviceid);
3360 die "can't unplug device '$deviceid'\n";
3366 sub qemu_deviceadd
{
3367 my ($vmid, $devicefull) = @_;
3369 $devicefull = "driver=".$devicefull;
3370 my %options = split(/[=,]/, $devicefull);
3372 vm_mon_cmd
($vmid, "device_add" , %options);
3375 sub qemu_devicedel
{
3376 my ($vmid, $deviceid) = @_;
3378 my $ret = vm_mon_cmd
($vmid, "device_del", id
=> $deviceid);
3381 sub qemu_iothread_add
{
3382 my($vmid, $deviceid, $device) = @_;
3384 if ($device->{iothread
}) {
3385 my $iothreads = vm_iothreads_list
($vmid);
3386 qemu_objectadd
($vmid, "iothread-$deviceid", "iothread") if !$iothreads->{"iothread-$deviceid"};
3390 sub qemu_iothread_del
{
3391 my($conf, $vmid, $deviceid) = @_;
3393 my $device = parse_drive
($deviceid, $conf->{$deviceid});
3394 if ($device->{iothread
}) {
3395 my $iothreads = vm_iothreads_list
($vmid);
3396 qemu_objectdel
($vmid, "iothread-$deviceid") if $iothreads->{"iothread-$deviceid"};
3400 sub qemu_objectadd
{
3401 my($vmid, $objectid, $qomtype) = @_;
3403 vm_mon_cmd
($vmid, "object-add", id
=> $objectid, "qom-type" => $qomtype);
3408 sub qemu_objectdel
{
3409 my($vmid, $objectid) = @_;
3411 vm_mon_cmd
($vmid, "object-del", id
=> $objectid);
3417 my ($storecfg, $vmid, $device) = @_;
3419 my $drive = print_drive_full
($storecfg, $vmid, $device);
3420 $drive =~ s/\\/\\\\/g;
3421 my $ret = vm_human_monitor_command
($vmid, "drive_add auto \"$drive\"");
3423 # If the command succeeds qemu prints: "OK
"
3424 return 1 if $ret =~ m/OK/s;
3426 die "adding drive failed
: $ret\n";
3430 my($vmid, $deviceid) = @_;
3432 my $ret = vm_human_monitor_command($vmid, "drive_del drive-
$deviceid");
3435 return 1 if $ret eq "";
3437 # NB: device not found errors mean the drive was auto-deleted and we ignore the error
3438 return 1 if $ret =~ m/Device \'.*?\' not found/s;
3440 die "deleting drive
$deviceid failed
: $ret\n";
3443 sub qemu_deviceaddverify {
3444 my ($vmid, $deviceid) = @_;
3446 for (my $i = 0; $i <= 5; $i++) {
3447 my $devices_list = vm_devices_list($vmid);
3448 return 1 if defined($devices_list->{$deviceid});
3452 die "error on hotplug device
'$deviceid'\n";
3456 sub qemu_devicedelverify {
3457 my ($vmid, $deviceid) = @_;
3459 # need to verify that the device is correctly removed as device_del
3460 # is async and empty return is not reliable
3462 for (my $i = 0; $i <= 5; $i++) {
3463 my $devices_list = vm_devices_list($vmid);
3464 return 1 if !defined($devices_list->{$deviceid});
3468 die "error on hot-unplugging device
'$deviceid'\n";
3471 sub qemu_findorcreatescsihw {
3472 my ($storecfg, $conf, $vmid, $device) = @_;
3474 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3476 my $scsihwid="$controller_prefix$controller";
3477 my $devices_list = vm_devices_list($vmid);
3479 if(!defined($devices_list->{$scsihwid})) {
3480 vm_deviceplug($storecfg, $conf, $vmid, $scsihwid, $device);
3486 sub qemu_deletescsihw {
3487 my ($conf, $vmid, $opt) = @_;
3489 my $device = parse_drive($opt, $conf->{$opt});
3491 if ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
3492 vm_deviceunplug($vmid, $conf, "virtioscsi
$device->{index}");
3496 my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $device);
3498 my $devices_list = vm_devices_list($vmid);
3499 foreach my $opt (keys %{$devices_list}) {
3500 if (PVE::QemuServer::valid_drivename($opt)) {
3501 my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
3502 if($drive->{interface} eq 'scsi' && $drive->{index} < (($maxdev-1)*($controller+1))) {
3508 my $scsihwid="scsihw
$controller";
3510 vm_deviceunplug($vmid, $conf, $scsihwid);
3515 sub qemu_add_pci_bridge {
3516 my ($storecfg, $conf, $vmid, $device) = @_;
3522 print_pci_addr($device, $bridges);
3524 while (my ($k, $v) = each %$bridges) {
3527 return 1 if !defined($bridgeid) || $bridgeid < 1;
3529 my $bridge = "pci
.$bridgeid";
3530 my $devices_list = vm_devices_list($vmid);
3532 if (!defined($devices_list->{$bridge})) {
3533 vm_deviceplug($storecfg, $conf, $vmid, $bridge);
3539 sub qemu_set_link_status {
3540 my ($vmid, $device, $up) = @_;
3542 vm_mon_cmd($vmid, "set_link
", name => $device,
3543 up => $up ? JSON::true : JSON::false);
3546 sub qemu_netdevadd {
3547 my ($vmid, $conf, $device, $deviceid) = @_;
3549 my $netdev = print_netdev_full($vmid, $conf, $device, $deviceid);
3550 my %options = split(/[=,]/, $netdev);
3552 vm_mon_cmd($vmid, "netdev_add
", %options);
3556 sub qemu_netdevdel {
3557 my ($vmid, $deviceid) = @_;
3559 vm_mon_cmd($vmid, "netdev_del
", id => $deviceid);
3562 sub qemu_cpu_hotplug {
3563 my ($vmid, $conf, $vcpus) = @_;
3566 $sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
3567 $sockets = $conf->{sockets} if $conf->{sockets};
3568 my $cores = $conf->{cores} || 1;
3569 my $maxcpus = $sockets * $cores;
3571 $vcpus = $maxcpus if !$vcpus;
3573 die "you can
't add more vcpus than maxcpus\n"
3574 if $vcpus > $maxcpus;
3576 my $currentvcpus = $conf->{vcpus} || $maxcpus;
3577 die "online cpu unplug is not yet possible\n"
3578 if $vcpus < $currentvcpus;
3580 my $currentrunningvcpus = vm_mon_cmd($vmid, "query-cpus");
3581 die "vcpus in running vm is different than configuration\n"
3582 if scalar(@{$currentrunningvcpus}) != $currentvcpus;
3584 for (my $i = $currentvcpus; $i < $vcpus; $i++) {
3585 vm_mon_cmd($vmid, "cpu-add", id => int($i));
3589 sub qemu_memory_hotplug {
3590 my ($vmid, $conf, $defaults, $opt, $value) = @_;
3592 return $value if !check_running($vmid);
3594 my $memory = $conf->{memory} || $defaults->{memory};
3595 $value = $defaults->{memory} if !$value;
3596 return $value if $value == $memory;
3598 my $static_memory = $STATICMEM;
3599 my $dimm_memory = $memory - $static_memory;
3601 die "memory can't be lower than
$static_memory MB
" if $value < $static_memory;
3602 die "you cannot add more memory than
$MAX_MEM MB
!\n" if $memory > $MAX_MEM;
3606 $sockets = $conf->{sockets} if $conf->{sockets};
3608 if($value > $memory) {
3610 foreach_dimm($conf, $vmid, $value, $sockets, sub {
3611 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3613 return if $current_size <= $conf->{memory};
3615 eval { vm_mon_cmd($vmid, "object-add
", 'qom-type' => "memory-backend-ram
", id => "mem-
$name", props => { size => int($dimm_size*1024*1024) } ) };
3617 eval { qemu_objectdel($vmid, "mem-
$name"); };
3621 eval { vm_mon_cmd($vmid, "device_add
", driver => "pc-dimm
", id => "$name", memdev => "mem-
$name", node => $numanode) };
3623 eval { qemu_objectdel($vmid, "mem-
$name"); };
3626 #update conf after each succesful module hotplug
3627 $conf->{memory} = $current_size;
3628 update_config_nolock($vmid, $conf, 1);
3633 foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
3634 my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_;
3636 return if $current_size >= $conf->{memory};
3637 print "try to unplug memory dimm
$name\n";
3641 eval { qemu_devicedel($vmid, $name) };
3643 my $dimm_list = qemu_dimm_list($vmid);
3644 last if !$dimm_list->{$name};
3645 raise_param_exc({ $name => "error unplug memory module
" }) if $retry > 5;
3649 #update conf after each succesful module unplug
3650 $conf->{memory} = $current_size;
3652 eval { qemu_objectdel($vmid, "mem-
$name"); };
3653 update_config_nolock($vmid, $conf, 1);
3658 sub qemu_dimm_list {
3661 my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices
");
3664 foreach my $dimm (@$dimmarray) {
3666 $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
3667 $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
3668 $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
3669 $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
3670 $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
3675 sub qemu_block_set_io_throttle {
3676 my ($vmid, $deviceid, $bps, $bps_rd, $bps_wr, $iops, $iops_rd, $iops_wr) = @_;
3678 return if !check_running($vmid) ;
3680 vm_mon_cmd($vmid, "block_set_io_throttle
", device => $deviceid, bps => int($bps), bps_rd => int($bps_rd), bps_wr => int($bps_wr), iops => int($iops), iops_rd => int($iops_rd), iops_wr => int($iops_wr));
3684 # old code, only used to shutdown old VM after update
3686 my ($fh, $timeout) = @_;
3688 my $sel = new IO::Select;
3695 while (scalar (@ready = $sel->can_read($timeout))) {
3697 if ($count = $fh->sysread($buf, 8192)) {
3698 if ($buf =~ /^(.*)\(qemu\) $/s) {
3705 if (!defined($count)) {
3712 die "monitor
read timeout
\n" if !scalar(@ready);
3717 # old code, only used to shutdown old VM after update
3718 sub vm_monitor_command {
3719 my ($vmid, $cmdstr, $nocheck) = @_;
3724 die "VM
$vmid not running
\n" if !check_running($vmid, $nocheck);
3726 my $sname = "${var_run_tmpdir
}/$vmid.mon
";
3728 my $sock = IO::Socket::UNIX->new( Peer => $sname ) ||
3729 die "unable to
connect to VM
$vmid socket - $!\n";
3733 # hack: migrate sometime blocks the monitor (when migrate_downtime
3735 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3736 $timeout = 60*60; # 1 hour
3740 my $data = __read_avail($sock, $timeout);
3742 if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
3743 die "got unexpected qemu monitor banner
\n";
3746 my $sel = new IO::Select;
3749 if (!scalar(my @ready = $sel->can_write($timeout))) {
3750 die "monitor
write error
- timeout
";
3753 my $fullcmd = "$cmdstr\r";
3755 # syslog('info', "VM
$vmid monitor command
: $cmdstr");
3758 if (!($b = $sock->syswrite($fullcmd)) || ($b != length($fullcmd))) {
3759 die "monitor
write error
- $!";
3762 return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
3766 if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
3767 $timeout = 60*60; # 1 hour
3768 } elsif ($cmdstr =~ m/^(eject|change)/) {
3769 $timeout = 60; # note: cdrom mount command is slow
3771 if ($res = __read_avail($sock, $timeout)) {
3773 my @lines = split("\r?
\n", $res);
3775 shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
3777 $res = join("\n", @lines);
3785 syslog("err
", "VM
$vmid monitor command failed
- $err");
3792 sub qemu_block_resize {
3793 my ($vmid, $deviceid, $storecfg, $volid, $size) = @_;
3795 my $running = check_running($vmid);
3797 return if !PVE::Storage::volume_resize($storecfg, $volid, $size, $running);
3799 return if !$running;
3801 vm_mon_cmd($vmid, "block_resize
", device => $deviceid, size => int($size));
3805 sub qemu_volume_snapshot {
3806 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3808 my $running = check_running($vmid);
3810 if ($running && do_snapshots_with_qemu($storecfg, $volid)){
3811 vm_mon_cmd($vmid, "snapshot-drive
", device => $deviceid, name => $snap);
3813 PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
3817 sub qemu_volume_snapshot_delete {
3818 my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
3820 my $running = check_running($vmid);
3822 return if !PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, $running);
3824 return if !$running;
3826 vm_mon_cmd($vmid, "delete-drive-snapshot
", device => $deviceid, name => $snap);
3829 sub set_migration_caps {
3835 "auto-converge
" => 1,
3837 "x-rdma-pin-all
" => 0,
3841 my $supported_capabilities = vm_mon_cmd_nocheck($vmid, "query-migrate-capabilities
");
3843 for my $supported_capability (@$supported_capabilities) {
3845 capability => $supported_capability->{capability},
3846 state => $enabled_cap->{$supported_capability->{capability}} ? JSON::true : JSON::false,
3850 vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities
", capabilities => $cap_ref);
3853 my $fast_plug_option = {
3861 # hotplug changes in [PENDING]
3862 # $selection hash can be used to only apply specified options, for
3863 # example: { cores => 1 } (only apply changed 'cores')
3864 # $errors ref is used to return error messages
3865 sub vmconfig_hotplug_pending {
3866 my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
3868 my $defaults = load_defaults();
3870 # commit values which do not have any impact on running VM first
3871 # Note: those option cannot raise errors, we we do not care about
3872 # $selection and always apply them.
3874 my $add_error = sub {
3875 my ($opt, $msg) = @_;
3876 $errors->{$opt} = "hotplug problem
- $msg";
3880 foreach my $opt (keys %{$conf->{pending}}) { # add/change
3881 if ($fast_plug_option->{$opt}) {
3882 $conf->{$opt} = $conf->{pending}->{$opt};
3883 delete $conf->{pending}->{$opt};
3889 update_config_nolock($vmid, $conf, 1);
3890 $conf = load_config($vmid); # update/reload
3893 my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
3895 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
3896 foreach my $opt (@delete) {
3897 next if $selection && !$selection->{$opt};
3899 if ($opt eq 'hotplug') {
3900 die "skip
\n" if ($conf->{hotplug} =~ /memory/);
3901 } elsif ($opt eq 'tablet') {
3902 die "skip
\n" if !$hotplug_features->{usb};
3903 if ($defaults->{tablet}) {
3904 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3906 vm_deviceunplug($vmid, $conf, $opt);
3908 } elsif ($opt eq 'vcpus') {
3909 die "skip
\n" if !$hotplug_features->{cpu};
3910 qemu_cpu_hotplug($vmid, $conf, undef);
3911 } elsif ($opt eq 'balloon') {
3912 # enable balloon device is not hotpluggable
3913 die "skip
\n" if !defined($conf->{balloon}) || $conf->{balloon};
3914 } elsif ($fast_plug_option->{$opt}) {
3916 } elsif ($opt =~ m/^net(\d+)$/) {
3917 die "skip
\n" if !$hotplug_features->{network};
3918 vm_deviceunplug($vmid, $conf, $opt);
3919 } elsif (valid_drivename($opt)) {
3920 die "skip
\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
3921 vm_deviceunplug($vmid, $conf, $opt);
3922 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
3923 } elsif ($opt =~ m/^memory$/) {
3924 die "skip
\n" if !$hotplug_features->{memory};
3925 qemu_memory_hotplug($vmid, $conf, $defaults, $opt);
3926 } elsif ($opt eq 'cpuunits') {
3927 cgroups_write("cpu
", $vmid, "cpu
.shares
", $defaults->{cpuunits});
3928 } elsif ($opt eq 'cpulimit') {
3929 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", -1);
3935 &$add_error($opt, $err) if $err ne "skip
\n";
3937 # save new config if hotplug was successful
3938 delete $conf->{$opt};
3939 vmconfig_undelete_pending_option($conf, $opt);
3940 update_config_nolock($vmid, $conf, 1);
3941 $conf = load_config($vmid); # update/reload
3945 foreach my $opt (keys %{$conf->{pending}}) {
3946 next if $selection && !$selection->{$opt};
3947 my $value = $conf->{pending}->{$opt};
3949 if ($opt eq 'hotplug') {
3950 die "skip
\n" if ($value =~ /memory/) || ($value !~ /memory/ && $conf->{hotplug} =~ /memory/);
3951 } elsif ($opt eq 'tablet') {
3952 die "skip
\n" if !$hotplug_features->{usb};
3954 vm_deviceplug($storecfg, $conf, $vmid, $opt);
3955 } elsif ($value == 0) {
3956 vm_deviceunplug($vmid, $conf, $opt);
3958 } elsif ($opt eq 'vcpus') {
3959 die "skip
\n" if !$hotplug_features->{cpu};
3960 qemu_cpu_hotplug($vmid, $conf, $value);
3961 } elsif ($opt eq 'balloon') {
3962 # enable/disable balloning device is not hotpluggable
3963 my $old_balloon_enabled = !!(!defined($conf->{balloon}) || $conf->{balloon});
3964 my $new_balloon_enabled = !!(!defined($conf->{pending}->{balloon}) || $conf->{pending}->{balloon});
3965 die "skip
\n" if $old_balloon_enabled != $new_balloon_enabled;
3967 # allow manual ballooning if shares is set to zero
3968 if ((defined($conf->{shares}) && ($conf->{shares} == 0))) {
3969 my $balloon = $conf->{pending}->{balloon} || $conf->{memory} || $defaults->{memory};
3970 vm_mon_cmd($vmid, "balloon
", value => $balloon*1024*1024);
3972 } elsif ($opt =~ m/^net(\d+)$/) {
3973 # some changes can be done without hotplug
3974 vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
3975 $vmid, $opt, $value);
3976 } elsif (valid_drivename($opt)) {
3977 # some changes can be done without hotplug
3978 vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
3979 $vmid, $opt, $value, 1);
3980 } elsif ($opt =~ m/^memory$/) { #dimms
3981 die "skip
\n" if !$hotplug_features->{memory};
3982 $value = qemu_memory_hotplug($vmid, $conf, $defaults, $opt, $value);
3983 } elsif ($opt eq 'cpuunits') {
3984 cgroups_write("cpu
", $vmid, "cpu
.shares
", $conf->{pending}->{$opt});
3985 } elsif ($opt eq 'cpulimit') {
3986 my $cpulimit = $conf->{pending}->{$opt} == 0 ? -1 : int($conf->{pending}->{$opt} * 100000);
3987 cgroups_write("cpu
", $vmid, "cpu
.cfs_quota_us
", $cpulimit);
3989 die "skip
\n"; # skip non-hot-pluggable options
3993 &$add_error($opt, $err) if $err ne "skip
\n";
3995 # save new config if hotplug was successful
3996 $conf->{$opt} = $value;
3997 delete $conf->{pending}->{$opt};
3998 update_config_nolock($vmid, $conf, 1);
3999 $conf = load_config($vmid); # update/reload
4004 sub vmconfig_apply_pending {
4005 my ($vmid, $conf, $storecfg) = @_;
4009 my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
4010 foreach my $opt (@delete) { # delete
4011 die "internal error
" if $opt =~ m/^unused/;
4012 $conf = load_config($vmid); # update/reload
4013 if (!defined($conf->{$opt})) {
4014 vmconfig_undelete_pending_option($conf, $opt);
4015 update_config_nolock($vmid, $conf, 1);
4016 } elsif (valid_drivename($opt)) {
4017 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
4018 vmconfig_undelete_pending_option($conf, $opt);
4019 delete $conf->{$opt};
4020 update_config_nolock($vmid, $conf, 1);
4022 vmconfig_undelete_pending_option($conf, $opt);
4023 delete $conf->{$opt};
4024 update_config_nolock($vmid, $conf, 1);
4028 $conf = load_config($vmid); # update/reload
4030 foreach my $opt (keys %{$conf->{pending}}) { # add/change
4031 $conf = load_config($vmid); # update/reload
4033 if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
4034 # skip if nothing changed
4035 } elsif (valid_drivename($opt)) {
4036 vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
4037 if defined($conf->{$opt});
4038 $conf->{$opt} = $conf->{pending}->{$opt};
4040 $conf->{$opt} = $conf->{pending}->{$opt};
4043 delete $conf->{pending}->{$opt};
4044 update_config_nolock($vmid, $conf, 1);
4048 my $safe_num_ne = sub {
4051 return 0 if !defined($a) && !defined($b);
4052 return 1 if !defined($a);
4053 return 1 if !defined($b);
4058 my $safe_string_ne = sub {
4061 return 0 if !defined($a) && !defined($b);
4062 return 1 if !defined($a);
4063 return 1 if !defined($b);
4068 sub vmconfig_update_net {
4069 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value) = @_;
4071 my $newnet = parse_net($value);
4073 if ($conf->{$opt}) {
4074 my $oldnet = parse_net($conf->{$opt});
4076 if (&$safe_string_ne($oldnet->{model}, $newnet->{model}) ||
4077 &$safe_string_ne($oldnet->{macaddr}, $newnet->{macaddr}) ||
4078 &$safe_num_ne($oldnet->{queues}, $newnet->{queues}) ||
4079 !($newnet->{bridge} && $oldnet->{bridge})) { # bridge/nat mode change
4081 # for non online change, we try to hot-unplug
4082 die "skip
\n" if !$hotplug;
4083 vm_deviceunplug($vmid, $conf, $opt);
4086 die "internal error
" if $opt !~ m/net(\d+)/;
4087 my $iface = "tap
${vmid
}i
$1";
4089 if (&$safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
4090 PVE::Network::tap_rate_limit($iface, $newnet->{rate});
4093 if (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
4094 &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
4095 &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
4096 PVE::Network::tap_unplug($iface);
4097 PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
4100 if (&$safe_string_ne($oldnet->{link_down}, $newnet->{link_down})) {
4101 qemu_set_link_status($vmid, $opt, !$newnet->{link_down});
4109 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
4115 sub vmconfig_update_disk {
4116 my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $force) = @_;
4118 # fixme: do we need force?
4120 my $drive = parse_drive($opt, $value);
4122 if ($conf->{$opt}) {
4124 if (my $old_drive = parse_drive($opt, $conf->{$opt})) {
4126 my $media = $drive->{media} || 'disk';
4127 my $oldmedia = $old_drive->{media} || 'disk';
4128 die "unable to change media type
\n" if $media ne $oldmedia;
4130 if (!drive_is_cdrom($old_drive)) {
4132 if ($drive->{file} ne $old_drive->{file}) {
4134 die "skip
\n" if !$hotplug;
4136 # unplug and register as unused
4137 vm_deviceunplug($vmid, $conf, $opt);
4138 vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive)
4141 # update existing disk
4143 # skip non hotpluggable value
4144 if (&$safe_num_ne($drive->{discard}, $old_drive->{discard}) ||
4145 &$safe_string_ne($drive->{iothread}, $old_drive->{iothread}) ||
4146 &$safe_string_ne($drive->{queues}, $old_drive->{queues}) ||
4147 &$safe_string_ne($drive->{cache}, $old_drive->{cache})) {
4152 if (&$safe_num_ne($drive->{mbps}, $old_drive->{mbps}) ||
4153 &$safe_num_ne($drive->{mbps_rd}, $old_drive->{mbps_rd}) ||
4154 &$safe_num_ne($drive->{mbps_wr}, $old_drive->{mbps_wr}) ||
4155 &$safe_num_ne($drive->{iops}, $old_drive->{iops}) ||
4156 &$safe_num_ne($drive->{iops_rd}, $old_drive->{iops_rd}) ||
4157 &$safe_num_ne($drive->{iops_wr}, $old_drive->{iops_wr}) ||
4158 &$safe_num_ne($drive->{mbps_max}, $old_drive->{mbps_max}) ||
4159 &$safe_num_ne($drive->{mbps_rd_max}, $old_drive->{mbps_rd_max}) ||
4160 &$safe_num_ne($drive->{mbps_wr_max}, $old_drive->{mbps_wr_max}) ||
4161 &$safe_num_ne($drive->{iops_max}, $old_drive->{iops_max}) ||
4162 &$safe_num_ne($drive->{iops_rd_max}, $old_drive->{iops_rd_max}) ||
4163 &$safe_num_ne($drive->{iops_wr_max}, $old_drive->{iops_wr_max})) {
4165 qemu_block_set_io_throttle($vmid,"drive-
$opt",
4166 ($drive->{mbps} || 0)*1024*1024,
4167 ($drive->{mbps_rd} || 0)*1024*1024,
4168 ($drive->{mbps_wr} || 0)*1024*1024,
4169 $drive->{iops} || 0,
4170 $drive->{iops_rd} || 0,
4171 $drive->{iops_wr} || 0,
4172 ($drive->{mbps_max} || 0)*1024*1024,
4173 ($drive->{mbps_rd_max} || 0)*1024*1024,
4174 ($drive->{mbps_wr_max} || 0)*1024*1024,
4175 $drive->{iops_max} || 0,
4176 $drive->{iops_rd_max} || 0,
4177 $drive->{iops_wr_max} || 0);
4186 if ($drive->{file} eq 'none') {
4187 vm_mon_cmd($vmid, "eject
",force => JSON::true,device => "drive-
$opt");
4189 my $path = get_iso_path($storecfg, $vmid, $drive->{file});
4190 vm_mon_cmd($vmid, "eject
", force => JSON::true,device => "drive-
$opt"); # force eject if locked
4191 vm_mon_cmd($vmid, "change
", device => "drive-
$opt",target => "$path") if $path;
4199 die "skip
\n" if !$hotplug || $opt =~ m/(ide|sata)(\d+)/;
4201 vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive);
4205 my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
4207 lock_config($vmid, sub {
4208 my $conf = load_config($vmid, $migratedfrom);
4210 die "you can
't start a vm if it's a template
\n" if is_template($conf);
4212 check_lock($conf) if !$skiplock;
4214 die "VM
$vmid already running
\n" if check_running($vmid, undef, $migratedfrom);
4216 if (!$statefile && scalar(keys %{$conf->{pending}})) {
4217 vmconfig_apply_pending($vmid, $conf, $storecfg);
4218 $conf = load_config($vmid); # update/reload
4221 my $defaults = load_defaults();
4223 # set environment variable useful inside network script
4224 $ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
4226 my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
4228 my $migrate_port = 0;
4231 if ($statefile eq 'tcp') {
4232 my $localip = "localhost
";
4233 my $datacenterconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
4234 my $nodename = PVE::INotify::nodename();
4235 if ($datacenterconf->{migration_unsecure}) {
4236 $localip = PVE::Cluster::remote_node_ip($nodename, 1);
4238 my $pfamily = PVE::Tools::get_host_address_family($nodename);
4239 $migrate_port = PVE::Tools::next_migrate_port($pfamily);
4240 $migrate_uri = "tcp
:[${localip
}]:${migrate_port
}";
4241 push @$cmd, '-incoming', $migrate_uri;
4244 push @$cmd, '-loadstate', $statefile;
4251 for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
4252 my $d = parse_hostpci($conf->{"hostpci
$i"});
4254 my $pcidevices = $d->{pciid};
4255 foreach my $pcidevice (@$pcidevices) {
4256 my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
4258 my $info = pci_device_info("0000:$pciid");
4259 die "IOMMU
not present
\n" if !check_iommu_support();
4260 die "no pci device info
for device
'$pciid'\n" if !$info;
4262 if ($d->{driver} && $d->{driver} eq "vfio
") {
4263 die "can
't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
4265 die "can't unbind
/bind to stub pci device
'$pciid'\n" if !pci_dev_bind_to_stub($info);
4268 die "can
't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
4272 PVE::Storage::activate_volumes($storecfg, $vollist);
4274 eval { run_command($cmd, timeout => $statefile ? undef : 30,
4277 die "start failed: $err" if $err;
4279 print "migration listens on $migrate_uri\n" if $migrate_uri;
4281 if ($statefile && $statefile ne 'tcp
') {
4282 eval { vm_mon_cmd_nocheck($vmid, "cont"); };
4286 if ($migratedfrom) {
4289 set_migration_caps($vmid);
4294 print "spice listens on port $spice_port\n";
4295 if ($spice_ticket) {
4296 vm_mon_cmd_nocheck($vmid, "set_password", protocol => 'spice
', password => $spice_ticket);
4297 vm_mon_cmd_nocheck($vmid, "expire_password", protocol => 'spice
', time => "+30");
4303 if (!$statefile && (!defined($conf->{balloon}) || $conf->{balloon})) {
4304 vm_mon_cmd_nocheck($vmid, "balloon", value => $conf->{balloon}*1024*1024)
4305 if $conf->{balloon};
4308 foreach my $opt (keys %$conf) {
4309 next if $opt !~ m/^net\d+$/;
4310 my $nicconf = parse_net($conf->{$opt});
4311 qemu_set_link_status($vmid, $opt, 0) if $nicconf->{link_down};
4315 vm_mon_cmd_nocheck($vmid, 'qom-set
',
4316 path => "machine/peripheral/balloon0",
4317 property => "guest-stats-polling-interval",
4318 value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
4324 my ($vmid, $execute, %params) = @_;
4326 my $cmd = { execute => $execute, arguments => \%params };
4327 vm_qmp_command($vmid, $cmd);
4330 sub vm_mon_cmd_nocheck {
4331 my ($vmid, $execute, %params) = @_;
4333 my $cmd = { execute => $execute, arguments => \%params };
4334 vm_qmp_command($vmid, $cmd, 1);
4337 sub vm_qmp_command {
4338 my ($vmid, $cmd, $nocheck) = @_;
4343 if ($cmd->{arguments} && $cmd->{arguments}->{timeout}) {
4344 $timeout = $cmd->{arguments}->{timeout};
4345 delete $cmd->{arguments}->{timeout};
4349 die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
4350 my $sname = qmp_socket($vmid);
4351 if (-e $sname) { # test if VM is reasonambe new and supports qmp/qga
4352 my $qmpclient = PVE::QMPClient->new();
4354 $res = $qmpclient->cmd($vmid, $cmd, $timeout);
4355 } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
4356 die "can't execute complex command on old monitor
- stop
/start your vm to fix the problem
\n"
4357 if scalar(%{$cmd->{arguments}});
4358 vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
4360 die "unable to
open monitor
socket\n";
4364 syslog("err
", "VM
$vmid qmp command failed
- $err");
4371 sub vm_human_monitor_command {
4372 my ($vmid, $cmdline) = @_;
4377 execute => 'human-monitor-command',
4378 arguments => { 'command-line' => $cmdline},
4381 return vm_qmp_command($vmid, $cmd);
4384 sub vm_commandline {
4385 my ($storecfg, $vmid) = @_;
4387 my $conf = load_config($vmid);
4389 my $defaults = load_defaults();
4391 my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults);
4393 return join(' ', @$cmd);
4397 my ($vmid, $skiplock) = @_;
4399 lock_config($vmid, sub {
4401 my $conf = load_config($vmid);
4403 check_lock($conf) if !$skiplock;
4405 vm_mon_cmd($vmid, "system_reset
");
4409 sub get_vm_volumes {
4413 foreach_volid($conf, sub {
4414 my ($volid, $is_cdrom) = @_;
4416 return if $volid =~ m|^/|;
4418 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
4421 push @$vollist, $volid;
4427 sub vm_stop_cleanup {
4428 my ($storecfg, $vmid, $conf, $keepActive, $apply_pending_changes) = @_;
4433 my $vollist = get_vm_volumes($conf);
4434 PVE::Storage::deactivate_volumes($storecfg, $vollist);
4437 foreach my $ext (qw(mon qmp pid vnc qga)) {
4438 unlink "/var/run/qemu-server/${vmid}.$ext";
4441 vmconfig_apply_pending
($vmid, $conf, $storecfg) if $apply_pending_changes;
4443 warn $@ if $@; # avoid errors - just warn
4446 # Note: use $nockeck to skip tests if VM configuration file exists.
4447 # We need that when migration VMs to other nodes (files already moved)
4448 # Note: we set $keepActive in vzdump stop mode - volumes need to stay active
4450 my ($storecfg, $vmid, $skiplock, $nocheck, $timeout, $shutdown, $force, $keepActive, $migratedfrom) = @_;
4452 $force = 1 if !defined($force) && !$shutdown;
4455 my $pid = check_running
($vmid, $nocheck, $migratedfrom);
4456 kill 15, $pid if $pid;
4457 my $conf = load_config
($vmid, $migratedfrom);
4458 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 0);
4462 lock_config
($vmid, sub {
4464 my $pid = check_running
($vmid, $nocheck);
4469 $conf = load_config
($vmid);
4470 check_lock
($conf) if !$skiplock;
4471 if (!defined($timeout) && $shutdown && $conf->{startup
}) {
4472 my $opts = PVE
::JSONSchema
::pve_parse_startup_order
($conf->{startup
});
4473 $timeout = $opts->{down
} if $opts->{down
};
4477 $timeout = 60 if !defined($timeout);
4481 if (defined($conf) && $conf->{agent
}) {
4482 vm_qmp_command
($vmid, { execute
=> "guest-shutdown" }, $nocheck);
4484 vm_qmp_command
($vmid, { execute
=> "system_powerdown" }, $nocheck);
4487 vm_qmp_command
($vmid, { execute
=> "quit" }, $nocheck);
4494 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4499 if ($count >= $timeout) {
4501 warn "VM still running - terminating now with SIGTERM\n";
4504 die "VM quit/powerdown failed - got timeout\n";
4507 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4512 warn "VM quit/powerdown failed - terminating now with SIGTERM\n";
4515 die "VM quit/powerdown failed\n";
4523 while (($count < $timeout) && check_running
($vmid, $nocheck)) {
4528 if ($count >= $timeout) {
4529 warn "VM still running - terminating now with SIGKILL\n";
4534 vm_stop_cleanup
($storecfg, $vmid, $conf, $keepActive, 1) if $conf;
4539 my ($vmid, $skiplock) = @_;
4541 lock_config
($vmid, sub {
4543 my $conf = load_config
($vmid);
4545 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4547 vm_mon_cmd
($vmid, "stop");
4552 my ($vmid, $skiplock) = @_;
4554 lock_config
($vmid, sub {
4556 my $conf = load_config
($vmid);
4558 check_lock
($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
4560 vm_mon_cmd
($vmid, "cont");
4565 my ($vmid, $skiplock, $key) = @_;
4567 lock_config
($vmid, sub {
4569 my $conf = load_config
($vmid);
4571 # there is no qmp command, so we use the human monitor command
4572 vm_human_monitor_command
($vmid, "sendkey $key");
4577 my ($storecfg, $vmid, $skiplock) = @_;
4579 lock_config
($vmid, sub {
4581 my $conf = load_config
($vmid);
4583 check_lock
($conf) if !$skiplock;
4585 if (!check_running
($vmid)) {
4586 destroy_vm
($storecfg, $vmid);
4588 die "VM $vmid is running - destroy failed\n";
4596 my ($filename, $buf) = @_;
4598 my $fh = IO
::File-
>new($filename, "w");
4599 return undef if !$fh;
4601 my $res = print $fh $buf;
4608 sub pci_device_info
{
4613 return undef if $name !~ m/^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\.([a-f0-9])$/;
4614 my ($domain, $bus, $slot, $func) = ($1, $2, $3, $4);
4616 my $irq = file_read_firstline
("$pcisysfs/devices/$name/irq");
4617 return undef if !defined($irq) || $irq !~ m/^\d+$/;
4619 my $vendor = file_read_firstline
("$pcisysfs/devices/$name/vendor");
4620 return undef if !defined($vendor) || $vendor !~ s/^0x//;
4622 my $product = file_read_firstline
("$pcisysfs/devices/$name/device");
4623 return undef if !defined($product) || $product !~ s/^0x//;
4628 product
=> $product,
4634 has_fl_reset
=> -f
"$pcisysfs/devices/$name/reset" || 0,
4643 my $name = $dev->{name
};
4645 my $fn = "$pcisysfs/devices/$name/reset";
4647 return file_write
($fn, "1");
4650 sub pci_dev_bind_to_stub
{
4653 my $name = $dev->{name
};
4655 my $testdir = "$pcisysfs/drivers/pci-stub/$name";
4656 return 1 if -d
$testdir;
4658 my $data = "$dev->{vendor} $dev->{product}";
4659 return undef if !file_write
("$pcisysfs/drivers/pci-stub/new_id", $data);
4661 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4662 if (!file_write
($fn, $name)) {
4663 return undef if -f
$fn;
4666 $fn = "$pcisysfs/drivers/pci-stub/bind";
4667 if (! -d
$testdir) {
4668 return undef if !file_write
($fn, $name);
4674 sub pci_dev_bind_to_vfio
{
4677 my $name = $dev->{name
};
4679 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4681 if (!-d
$vfio_basedir) {
4682 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4684 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4686 my $testdir = "$vfio_basedir/$name";
4687 return 1 if -d
$testdir;
4689 my $data = "$dev->{vendor} $dev->{product}";
4690 return undef if !file_write
("$vfio_basedir/new_id", $data);
4692 my $fn = "$pcisysfs/devices/$name/driver/unbind";
4693 if (!file_write
($fn, $name)) {
4694 return undef if -f
$fn;
4697 $fn = "$vfio_basedir/bind";
4698 if (! -d
$testdir) {
4699 return undef if !file_write
($fn, $name);
4705 sub pci_dev_group_bind_to_vfio
{
4708 my $vfio_basedir = "$pcisysfs/drivers/vfio-pci";
4710 if (!-d
$vfio_basedir) {
4711 system("/sbin/modprobe vfio-pci >/dev/null 2>/dev/null");
4713 die "Cannot find vfio-pci module!\n" if !-d
$vfio_basedir;
4715 # get IOMMU group devices
4716 opendir(my $D, "$pcisysfs/devices/0000:$pciid/iommu_group/devices/") || die "Cannot open iommu_group: $!\n";
4717 my @devs = grep /^0000:/, readdir($D);
4720 foreach my $pciid (@devs) {
4721 $pciid =~ m/^([:\.\da-f]+)$/ or die "PCI ID $pciid not valid!\n";
4723 # pci bridges, switches or root ports are not supported
4724 # they have a pci_bus subdirectory so skip them
4725 next if (-e
"$pcisysfs/devices/$pciid/pci_bus");
4727 my $info = pci_device_info
($1);
4728 pci_dev_bind_to_vfio
($info) || die "Cannot bind $pciid to vfio\n";
4734 sub print_pci_addr
{
4735 my ($id, $bridges) = @_;
4739 piix3
=> { bus
=> 0, addr
=> 1 },
4740 #addr2 : first videocard
4741 balloon0
=> { bus
=> 0, addr
=> 3 },
4742 watchdog
=> { bus
=> 0, addr
=> 4 },
4743 scsihw0
=> { bus
=> 0, addr
=> 5 },
4744 'pci.3' => { bus
=> 0, addr
=> 5 }, #can also be used for virtio-scsi-single bridge
4745 scsihw1
=> { bus
=> 0, addr
=> 6 },
4746 ahci0
=> { bus
=> 0, addr
=> 7 },
4747 qga0
=> { bus
=> 0, addr
=> 8 },
4748 spice
=> { bus
=> 0, addr
=> 9 },
4749 virtio0
=> { bus
=> 0, addr
=> 10 },
4750 virtio1
=> { bus
=> 0, addr
=> 11 },
4751 virtio2
=> { bus
=> 0, addr
=> 12 },
4752 virtio3
=> { bus
=> 0, addr
=> 13 },
4753 virtio4
=> { bus
=> 0, addr
=> 14 },
4754 virtio5
=> { bus
=> 0, addr
=> 15 },
4755 hostpci0
=> { bus
=> 0, addr
=> 16 },
4756 hostpci1
=> { bus
=> 0, addr
=> 17 },
4757 net0
=> { bus
=> 0, addr
=> 18 },
4758 net1
=> { bus
=> 0, addr
=> 19 },
4759 net2
=> { bus
=> 0, addr
=> 20 },
4760 net3
=> { bus
=> 0, addr
=> 21 },
4761 net4
=> { bus
=> 0, addr
=> 22 },
4762 net5
=> { bus
=> 0, addr
=> 23 },
4763 vga1
=> { bus
=> 0, addr
=> 24 },
4764 vga2
=> { bus
=> 0, addr
=> 25 },
4765 vga3
=> { bus
=> 0, addr
=> 26 },
4766 hostpci2
=> { bus
=> 0, addr
=> 27 },
4767 hostpci3
=> { bus
=> 0, addr
=> 28 },
4768 #addr29 : usb-host (pve-usb.cfg)
4769 'pci.1' => { bus
=> 0, addr
=> 30 },
4770 'pci.2' => { bus
=> 0, addr
=> 31 },
4771 'net6' => { bus
=> 1, addr
=> 1 },
4772 'net7' => { bus
=> 1, addr
=> 2 },
4773 'net8' => { bus
=> 1, addr
=> 3 },
4774 'net9' => { bus
=> 1, addr
=> 4 },
4775 'net10' => { bus
=> 1, addr
=> 5 },
4776 'net11' => { bus
=> 1, addr
=> 6 },
4777 'net12' => { bus
=> 1, addr
=> 7 },
4778 'net13' => { bus
=> 1, addr
=> 8 },
4779 'net14' => { bus
=> 1, addr
=> 9 },
4780 'net15' => { bus
=> 1, addr
=> 10 },
4781 'net16' => { bus
=> 1, addr
=> 11 },
4782 'net17' => { bus
=> 1, addr
=> 12 },
4783 'net18' => { bus
=> 1, addr
=> 13 },
4784 'net19' => { bus
=> 1, addr
=> 14 },
4785 'net20' => { bus
=> 1, addr
=> 15 },
4786 'net21' => { bus
=> 1, addr
=> 16 },
4787 'net22' => { bus
=> 1, addr
=> 17 },
4788 'net23' => { bus
=> 1, addr
=> 18 },
4789 'net24' => { bus
=> 1, addr
=> 19 },
4790 'net25' => { bus
=> 1, addr
=> 20 },
4791 'net26' => { bus
=> 1, addr
=> 21 },
4792 'net27' => { bus
=> 1, addr
=> 22 },
4793 'net28' => { bus
=> 1, addr
=> 23 },
4794 'net29' => { bus
=> 1, addr
=> 24 },
4795 'net30' => { bus
=> 1, addr
=> 25 },
4796 'net31' => { bus
=> 1, addr
=> 26 },
4797 'virtio6' => { bus
=> 2, addr
=> 1 },
4798 'virtio7' => { bus
=> 2, addr
=> 2 },
4799 'virtio8' => { bus
=> 2, addr
=> 3 },
4800 'virtio9' => { bus
=> 2, addr
=> 4 },
4801 'virtio10' => { bus
=> 2, addr
=> 5 },
4802 'virtio11' => { bus
=> 2, addr
=> 6 },
4803 'virtio12' => { bus
=> 2, addr
=> 7 },
4804 'virtio13' => { bus
=> 2, addr
=> 8 },
4805 'virtio14' => { bus
=> 2, addr
=> 9 },
4806 'virtio15' => { bus
=> 2, addr
=> 10 },
4807 'virtioscsi0' => { bus
=> 3, addr
=> 1 },
4808 'virtioscsi1' => { bus
=> 3, addr
=> 2 },
4809 'virtioscsi2' => { bus
=> 3, addr
=> 3 },
4810 'virtioscsi3' => { bus
=> 3, addr
=> 4 },
4811 'virtioscsi4' => { bus
=> 3, addr
=> 5 },
4812 'virtioscsi5' => { bus
=> 3, addr
=> 6 },
4813 'virtioscsi6' => { bus
=> 3, addr
=> 7 },
4814 'virtioscsi7' => { bus
=> 3, addr
=> 8 },
4815 'virtioscsi8' => { bus
=> 3, addr
=> 9 },
4816 'virtioscsi9' => { bus
=> 3, addr
=> 10 },
4817 'virtioscsi10' => { bus
=> 3, addr
=> 11 },
4818 'virtioscsi11' => { bus
=> 3, addr
=> 12 },
4819 'virtioscsi12' => { bus
=> 3, addr
=> 13 },
4820 'virtioscsi13' => { bus
=> 3, addr
=> 14 },
4821 'virtioscsi14' => { bus
=> 3, addr
=> 15 },
4822 'virtioscsi15' => { bus
=> 3, addr
=> 16 },
4823 'virtioscsi16' => { bus
=> 3, addr
=> 17 },
4824 'virtioscsi17' => { bus
=> 3, addr
=> 18 },
4825 'virtioscsi18' => { bus
=> 3, addr
=> 19 },
4826 'virtioscsi19' => { bus
=> 3, addr
=> 20 },
4827 'virtioscsi20' => { bus
=> 3, addr
=> 21 },
4828 'virtioscsi21' => { bus
=> 3, addr
=> 22 },
4829 'virtioscsi22' => { bus
=> 3, addr
=> 23 },
4830 'virtioscsi23' => { bus
=> 3, addr
=> 24 },
4831 'virtioscsi24' => { bus
=> 3, addr
=> 25 },
4832 'virtioscsi25' => { bus
=> 3, addr
=> 26 },
4833 'virtioscsi26' => { bus
=> 3, addr
=> 27 },
4834 'virtioscsi27' => { bus
=> 3, addr
=> 28 },
4835 'virtioscsi28' => { bus
=> 3, addr
=> 29 },
4836 'virtioscsi29' => { bus
=> 3, addr
=> 30 },
4837 'virtioscsi30' => { bus
=> 3, addr
=> 31 },
4841 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4842 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4843 my $bus = $devices->{$id}->{bus
};
4844 $res = ",bus=pci.$bus,addr=$addr";
4845 $bridges->{$bus} = 1 if $bridges;
4851 sub print_pcie_addr
{
4856 hostpci0
=> { bus
=> "ich9-pcie-port-1", addr
=> 0 },
4857 hostpci1
=> { bus
=> "ich9-pcie-port-2", addr
=> 0 },
4858 hostpci2
=> { bus
=> "ich9-pcie-port-3", addr
=> 0 },
4859 hostpci3
=> { bus
=> "ich9-pcie-port-4", addr
=> 0 },
4862 if (defined($devices->{$id}->{bus
}) && defined($devices->{$id}->{addr
})) {
4863 my $addr = sprintf("0x%x", $devices->{$id}->{addr
});
4864 my $bus = $devices->{$id}->{bus
};
4865 $res = ",bus=$bus,addr=$addr";
4871 # vzdump restore implementaion
4873 sub tar_archive_read_firstfile
{
4874 my $archive = shift;
4876 die "ERROR: file '$archive' does not exist\n" if ! -f
$archive;
4878 # try to detect archive type first
4879 my $pid = open (TMP
, "tar tf '$archive'|") ||
4880 die "unable to open file '$archive'\n";
4881 my $firstfile = <TMP
>;
4885 die "ERROR: archive contaions no data\n" if !$firstfile;
4891 sub tar_restore_cleanup
{
4892 my ($storecfg, $statfile) = @_;
4894 print STDERR
"starting cleanup\n";
4896 if (my $fd = IO
::File-
>new($statfile, "r")) {
4897 while (defined(my $line = <$fd>)) {
4898 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
4901 if ($volid =~ m
|^/|) {
4902 unlink $volid || die 'unlink failed\n';
4904 PVE
::Storage
::vdisk_free
($storecfg, $volid);
4906 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
4908 print STDERR
"unable to cleanup '$volid' - $@" if $@;
4910 print STDERR
"unable to parse line in statfile - $line";
4917 sub restore_archive
{
4918 my ($archive, $vmid, $user, $opts) = @_;
4920 my $format = $opts->{format
};
4923 if ($archive =~ m/\.tgz$/ || $archive =~ m/\.tar\.gz$/) {
4924 $format = 'tar' if !$format;
4926 } elsif ($archive =~ m/\.tar$/) {
4927 $format = 'tar' if !$format;
4928 } elsif ($archive =~ m/.tar.lzo$/) {
4929 $format = 'tar' if !$format;
4931 } elsif ($archive =~ m/\.vma$/) {
4932 $format = 'vma' if !$format;
4933 } elsif ($archive =~ m/\.vma\.gz$/) {
4934 $format = 'vma' if !$format;
4936 } elsif ($archive =~ m/\.vma\.lzo$/) {
4937 $format = 'vma' if !$format;
4940 $format = 'vma' if !$format; # default
4943 # try to detect archive format
4944 if ($format eq 'tar') {
4945 return restore_tar_archive
($archive, $vmid, $user, $opts);
4947 return restore_vma_archive
($archive, $vmid, $user, $opts, $comp);
4951 sub restore_update_config_line
{
4952 my ($outfd, $cookie, $vmid, $map, $line, $unique) = @_;
4954 return if $line =~ m/^\#qmdump\#/;
4955 return if $line =~ m/^\#vzdump\#/;
4956 return if $line =~ m/^lock:/;
4957 return if $line =~ m/^unused\d+:/;
4958 return if $line =~ m/^parent:/;
4959 return if $line =~ m/^template:/; # restored VM is never a template
4961 if (($line =~ m/^(vlan(\d+)):\s*(\S+)\s*$/)) {
4962 # try to convert old 1.X settings
4963 my ($id, $ind, $ethcfg) = ($1, $2, $3);
4964 foreach my $devconfig (PVE
::Tools
::split_list
($ethcfg)) {
4965 my ($model, $macaddr) = split(/\=/, $devconfig);
4966 $macaddr = PVE
::Tools
::random_ether_addr
() if !$macaddr || $unique;
4969 bridge
=> "vmbr$ind",
4970 macaddr
=> $macaddr,
4972 my $netstr = print_net
($net);
4974 print $outfd "net$cookie->{netcount}: $netstr\n";
4975 $cookie->{netcount
}++;
4977 } elsif (($line =~ m/^(net\d+):\s*(\S+)\s*$/) && $unique) {
4978 my ($id, $netstr) = ($1, $2);
4979 my $net = parse_net
($netstr);
4980 $net->{macaddr
} = PVE
::Tools
::random_ether_addr
() if $net->{macaddr
};
4981 $netstr = print_net
($net);
4982 print $outfd "$id: $netstr\n";
4983 } elsif ($line =~ m/^((ide|scsi|virtio|sata)\d+):\s*(\S+)\s*$/) {
4986 if ($line =~ m/backup=no/) {
4987 print $outfd "#$line";
4988 } elsif ($virtdev && $map->{$virtdev}) {
4989 my $di = parse_drive
($virtdev, $value);
4990 delete $di->{format
}; # format can change on restore
4991 $di->{file
} = $map->{$virtdev};
4992 $value = print_drive
($vmid, $di);
4993 print $outfd "$virtdev: $value\n";
5003 my ($cfg, $vmid) = @_;
5005 my $info = PVE
::Storage
::vdisk_list
($cfg, undef, $vmid);
5007 my $volid_hash = {};
5008 foreach my $storeid (keys %$info) {
5009 foreach my $item (@{$info->{$storeid}}) {
5010 next if !($item->{volid
} && $item->{size
});
5011 $item->{path
} = PVE
::Storage
::path
($cfg, $item->{volid
});
5012 $volid_hash->{$item->{volid
}} = $item;
5019 sub get_used_paths
{
5020 my ($vmid, $storecfg, $conf, $scan_snapshots, $skip_drive) = @_;
5024 my $scan_config = sub {
5025 my ($cref, $snapname) = @_;
5027 foreach my $key (keys %$cref) {
5028 my $value = $cref->{$key};
5029 if (valid_drivename
($key)) {
5030 next if $skip_drive && $key eq $skip_drive;
5031 my $drive = parse_drive
($key, $value);
5032 next if !$drive || !$drive->{file
} || drive_is_cdrom
($drive);
5033 if ($drive->{file
} =~ m!^/!) {
5034 $used_path->{$drive->{file
}}++; # = 1;
5036 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
}, 1);
5038 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid, 1);
5040 my $path = PVE
::Storage
::path
($storecfg, $drive->{file
}, $snapname);
5041 $used_path->{$path}++; # = 1;
5047 &$scan_config($conf);
5051 if ($scan_snapshots) {
5052 foreach my $snapname (keys %{$conf->{snapshots
}}) {
5053 &$scan_config($conf->{snapshots
}->{$snapname}, $snapname);
5060 sub update_disksize
{
5061 my ($vmid, $conf, $volid_hash) = @_;
5067 # Note: it is allowed to define multiple storages with same path (alias), so
5068 # we need to check both 'volid' and real 'path' (two different volid can point
5069 # to the same path).
5074 foreach my $opt (keys %$conf) {
5075 if (valid_drivename
($opt)) {
5076 my $drive = parse_drive
($opt, $conf->{$opt});
5077 my $volid = $drive->{file
};
5080 $used->{$volid} = 1;
5081 if ($volid_hash->{$volid} &&
5082 (my $path = $volid_hash->{$volid}->{path
})) {
5083 $usedpath->{$path} = 1;
5086 next if drive_is_cdrom
($drive);
5087 next if !$volid_hash->{$volid};
5089 $drive->{size
} = $volid_hash->{$volid}->{size
};
5090 my $new = print_drive
($vmid, $drive);
5091 if ($new ne $conf->{$opt}) {
5093 $conf->{$opt} = $new;
5098 # remove 'unusedX' entry if volume is used
5099 foreach my $opt (keys %$conf) {
5100 next if $opt !~ m/^unused\d+$/;
5101 my $volid = $conf->{$opt};
5102 my $path = $volid_hash->{$volid}->{path
} if $volid_hash->{$volid};
5103 if ($used->{$volid} || ($path && $usedpath->{$path})) {
5105 delete $conf->{$opt};
5109 foreach my $volid (sort keys %$volid_hash) {
5110 next if $volid =~ m/vm-$vmid-state-/;
5111 next if $used->{$volid};
5112 my $path = $volid_hash->{$volid}->{path
};
5113 next if !$path; # just to be sure
5114 next if $usedpath->{$path};
5116 add_unused_volume
($conf, $volid);
5117 $usedpath->{$path} = 1; # avoid to add more than once (aliases)
5124 my ($vmid, $nolock) = @_;
5126 my $cfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
5128 my $volid_hash = scan_volids
($cfg, $vmid);
5130 my $updatefn = sub {
5133 my $conf = load_config
($vmid);
5138 foreach my $volid (keys %$volid_hash) {
5139 my $info = $volid_hash->{$volid};
5140 $vm_volids->{$volid} = $info if $info->{vmid
} && $info->{vmid
} == $vmid;
5143 my $changes = update_disksize
($vmid, $conf, $vm_volids);
5145 update_config_nolock
($vmid, $conf, 1) if $changes;
5148 if (defined($vmid)) {
5152 lock_config
($vmid, $updatefn, $vmid);
5155 my $vmlist = config_list
();
5156 foreach my $vmid (keys %$vmlist) {
5160 lock_config
($vmid, $updatefn, $vmid);
5166 sub restore_vma_archive
{
5167 my ($archive, $vmid, $user, $opts, $comp) = @_;
5169 my $input = $archive eq '-' ?
"<&STDIN" : undef;
5170 my $readfrom = $archive;
5175 my $qarchive = PVE
::Tools
::shellquote
($archive);
5176 if ($comp eq 'gzip') {
5177 $uncomp = "zcat $qarchive|";
5178 } elsif ($comp eq 'lzop') {
5179 $uncomp = "lzop -d -c $qarchive|";
5181 die "unknown compression method '$comp'\n";
5186 my $tmpdir = "/var/tmp/vzdumptmp$$";
5189 # disable interrupts (always do cleanups)
5190 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5191 warn "got interrupt - ignored\n";
5194 my $mapfifo = "/var/tmp/vzdumptmp$$.fifo";
5195 POSIX
::mkfifo
($mapfifo, 0600);
5198 my $openfifo = sub {
5199 open($fifofh, '>', $mapfifo) || die $!;
5202 my $cmd = "${uncomp}vma extract -v -r $mapfifo $readfrom $tmpdir";
5209 my $rpcenv = PVE
::RPCEnvironment
::get
();
5211 my $conffile = config_file
($vmid);
5212 my $tmpfn = "$conffile.$$.tmp";
5214 # Note: $oldconf is undef if VM does not exists
5215 my $oldconf = PVE
::Cluster
::cfs_read_file
(cfs_config_path
($vmid));
5217 my $print_devmap = sub {
5218 my $virtdev_hash = {};
5220 my $cfgfn = "$tmpdir/qemu-server.conf";
5222 # we can read the config - that is already extracted
5223 my $fh = IO
::File-
>new($cfgfn, "r") ||
5224 "unable to read qemu-server.conf - $!\n";
5226 while (defined(my $line = <$fh>)) {
5227 if ($line =~ m/^\#qmdump\#map:(\S+):(\S+):(\S*):(\S*):$/) {
5228 my ($virtdev, $devname, $storeid, $format) = ($1, $2, $3, $4);
5229 die "archive does not contain data for drive '$virtdev'\n"
5230 if !$devinfo->{$devname};
5231 if (defined($opts->{storage
})) {
5232 $storeid = $opts->{storage
} || 'local';
5233 } elsif (!$storeid) {
5236 $format = 'raw' if !$format;
5237 $devinfo->{$devname}->{devname
} = $devname;
5238 $devinfo->{$devname}->{virtdev
} = $virtdev;
5239 $devinfo->{$devname}->{format
} = $format;
5240 $devinfo->{$devname}->{storeid
} = $storeid;
5242 # check permission on storage
5243 my $pool = $opts->{pool
}; # todo: do we need that?
5244 if ($user ne 'root@pam') {
5245 $rpcenv->check($user, "/storage/$storeid", ['Datastore.AllocateSpace']);
5248 $virtdev_hash->{$virtdev} = $devinfo->{$devname};
5252 foreach my $devname (keys %$devinfo) {
5253 die "found no device mapping information for device '$devname'\n"
5254 if !$devinfo->{$devname}->{virtdev
};
5257 my $cfg = cfs_read_file
('storage.cfg');
5259 # create empty/temp config
5261 PVE
::Tools
::file_set_contents
($conffile, "memory: 128\n");
5262 foreach_drive
($oldconf, sub {
5263 my ($ds, $drive) = @_;
5265 return if drive_is_cdrom
($drive);
5267 my $volid = $drive->{file
};
5269 return if !$volid || $volid =~ m
|^/|;
5271 my ($path, $owner) = PVE
::Storage
::path
($cfg, $volid);
5272 return if !$path || !$owner || ($owner != $vmid);
5274 # Note: only delete disk we want to restore
5275 # other volumes will become unused
5276 if ($virtdev_hash->{$ds}) {
5277 PVE
::Storage
::vdisk_free
($cfg, $volid);
5283 foreach my $virtdev (sort keys %$virtdev_hash) {
5284 my $d = $virtdev_hash->{$virtdev};
5285 my $alloc_size = int(($d->{size
} + 1024 - 1)/1024);
5286 my $scfg = PVE
::Storage
::storage_config
($cfg, $d->{storeid
});
5288 # test if requested format is supported
5289 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($cfg, $d->{storeid
});
5290 my $supported = grep { $_ eq $d->{format
} } @$validFormats;
5291 $d->{format
} = $defFormat if !$supported;
5293 my $volid = PVE
::Storage
::vdisk_alloc
($cfg, $d->{storeid
}, $vmid,
5294 $d->{format
}, undef, $alloc_size);
5295 print STDERR
"new volume ID is '$volid'\n";
5296 $d->{volid
} = $volid;
5297 my $path = PVE
::Storage
::path
($cfg, $volid);
5299 my $write_zeros = 1;
5300 # fixme: what other storages types initialize volumes with zero?
5301 if ($scfg->{type
} eq 'dir' || $scfg->{type
} eq 'nfs' || $scfg->{type
} eq 'glusterfs' ||
5302 $scfg->{type
} eq 'sheepdog' || $scfg->{type
} eq 'rbd') {
5306 print $fifofh "${write_zeros}:$d->{devname}=$path\n";
5308 print "map '$d->{devname}' to '$path' (write zeros = ${write_zeros})\n";
5309 $map->{$virtdev} = $volid;
5312 $fh->seek(0, 0) || die "seek failed - $!\n";
5314 my $outfd = new IO
::File
($tmpfn, "w") ||
5315 die "unable to write config for VM $vmid\n";
5317 my $cookie = { netcount
=> 0 };
5318 while (defined(my $line = <$fh>)) {
5319 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5328 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5329 die "interrupted by signal\n";
5331 local $SIG{ALRM
} = sub { die "got timeout\n"; };
5333 $oldtimeout = alarm($timeout);
5340 if ($line =~ m/^DEV:\sdev_id=(\d+)\ssize:\s(\d+)\sdevname:\s(\S+)$/) {
5341 my ($dev_id, $size, $devname) = ($1, $2, $3);
5342 $devinfo->{$devname} = { size
=> $size, dev_id
=> $dev_id };
5343 } elsif ($line =~ m/^CTIME: /) {
5344 # we correctly received the vma config, so we can disable
5345 # the timeout now for disk allocation (set to 10 minutes, so
5346 # that we always timeout if something goes wrong)
5349 print $fifofh "done\n";
5350 my $tmp = $oldtimeout || 0;
5351 $oldtimeout = undef;
5357 print "restore vma archive: $cmd\n";
5358 run_command
($cmd, input
=> $input, outfunc
=> $parser, afterfork
=> $openfifo);
5362 alarm($oldtimeout) if $oldtimeout;
5370 my $cfg = cfs_read_file
('storage.cfg');
5371 foreach my $devname (keys %$devinfo) {
5372 my $volid = $devinfo->{$devname}->{volid
};
5375 if ($volid =~ m
|^/|) {
5376 unlink $volid || die 'unlink failed\n';
5378 PVE
::Storage
::vdisk_free
($cfg, $volid);
5380 print STDERR
"temporary volume '$volid' sucessfuly removed\n";
5382 print STDERR
"unable to cleanup '$volid' - $@" if $@;
5389 rename($tmpfn, $conffile) ||
5390 die "unable to commit configuration file '$conffile'\n";
5392 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5394 eval { rescan
($vmid, 1); };
5398 sub restore_tar_archive
{
5399 my ($archive, $vmid, $user, $opts) = @_;
5401 if ($archive ne '-') {
5402 my $firstfile = tar_archive_read_firstfile
($archive);
5403 die "ERROR: file '$archive' dos not lock like a QemuServer vzdump backup\n"
5404 if $firstfile ne 'qemu-server.conf';
5407 my $storecfg = cfs_read_file
('storage.cfg');
5409 # destroy existing data - keep empty config
5410 my $vmcfgfn = config_file
($vmid);
5411 destroy_vm
($storecfg, $vmid, 1) if -f
$vmcfgfn;
5413 my $tocmd = "/usr/lib/qemu-server/qmextract";
5415 $tocmd .= " --storage " . PVE
::Tools
::shellquote
($opts->{storage
}) if $opts->{storage
};
5416 $tocmd .= " --pool " . PVE
::Tools
::shellquote
($opts->{pool
}) if $opts->{pool
};
5417 $tocmd .= ' --prealloc' if $opts->{prealloc
};
5418 $tocmd .= ' --info' if $opts->{info
};
5420 # tar option "xf" does not autodetect compression when read from STDIN,
5421 # so we pipe to zcat
5422 my $cmd = "zcat -f|tar xf " . PVE
::Tools
::shellquote
($archive) . " " .
5423 PVE
::Tools
::shellquote
("--to-command=$tocmd");
5425 my $tmpdir = "/var/tmp/vzdumptmp$$";
5428 local $ENV{VZDUMP_TMPDIR
} = $tmpdir;
5429 local $ENV{VZDUMP_VMID
} = $vmid;
5430 local $ENV{VZDUMP_USER
} = $user;
5432 my $conffile = config_file
($vmid);
5433 my $tmpfn = "$conffile.$$.tmp";
5435 # disable interrupts (always do cleanups)
5436 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = sub {
5437 print STDERR
"got interrupt - ignored\n";
5442 local $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = $SIG{HUP
} = $SIG{PIPE
} = sub {
5443 die "interrupted by signal\n";
5446 if ($archive eq '-') {
5447 print "extracting archive from STDIN\n";
5448 run_command
($cmd, input
=> "<&STDIN");
5450 print "extracting archive '$archive'\n";
5454 return if $opts->{info
};
5458 my $statfile = "$tmpdir/qmrestore.stat";
5459 if (my $fd = IO
::File-
>new($statfile, "r")) {
5460 while (defined (my $line = <$fd>)) {
5461 if ($line =~ m/vzdump:([^\s:]*):(\S+)$/) {
5462 $map->{$1} = $2 if $1;
5464 print STDERR
"unable to parse line in statfile - $line\n";
5470 my $confsrc = "$tmpdir/qemu-server.conf";
5472 my $srcfd = new IO
::File
($confsrc, "r") ||
5473 die "unable to open file '$confsrc'\n";
5475 my $outfd = new IO
::File
($tmpfn, "w") ||
5476 die "unable to write config for VM $vmid\n";
5478 my $cookie = { netcount
=> 0 };
5479 while (defined (my $line = <$srcfd>)) {
5480 restore_update_config_line
($outfd, $cookie, $vmid, $map, $line, $opts->{unique
});
5492 tar_restore_cleanup
($storecfg, "$tmpdir/qmrestore.stat") if !$opts->{info
};
5499 rename $tmpfn, $conffile ||
5500 die "unable to commit configuration file '$conffile'\n";
5502 PVE
::Cluster
::cfs_update
(); # make sure we read new file
5504 eval { rescan
($vmid, 1); };
5509 # Internal snapshots
5511 # NOTE: Snapshot create/delete involves several non-atomic
5512 # action, and can take a long time.
5513 # So we try to avoid locking the file and use 'lock' variable
5514 # inside the config file instead.
5516 my $snapshot_copy_config = sub {
5517 my ($source, $dest) = @_;
5519 foreach my $k (keys %$source) {
5520 next if $k eq 'snapshots';
5521 next if $k eq 'snapstate';
5522 next if $k eq 'snaptime';
5523 next if $k eq 'vmstate';
5524 next if $k eq 'lock';
5525 next if $k eq 'digest';
5526 next if $k eq 'description';
5527 next if $k =~ m/^unused\d+$/;
5529 $dest->{$k} = $source->{$k};
5533 my $snapshot_apply_config = sub {
5534 my ($conf, $snap) = @_;
5536 # copy snapshot list
5538 snapshots
=> $conf->{snapshots
},
5541 # keep description and list of unused disks
5542 foreach my $k (keys %$conf) {
5543 next if !($k =~ m/^unused\d+$/ || $k eq 'description');
5544 $newconf->{$k} = $conf->{$k};
5547 &$snapshot_copy_config($snap, $newconf);
5552 sub foreach_writable_storage
{
5553 my ($conf, $func) = @_;
5557 foreach my $ds (keys %$conf) {
5558 next if !valid_drivename
($ds);
5560 my $drive = parse_drive
($ds, $conf->{$ds});
5562 next if drive_is_cdrom
($drive);
5564 my $volid = $drive->{file
};
5566 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
5567 $sidhash->{$sid} = $sid if $sid;
5570 foreach my $sid (sort keys %$sidhash) {
5575 my $alloc_vmstate_volid = sub {
5576 my ($storecfg, $vmid, $conf, $snapname) = @_;
5578 # Note: we try to be smart when selecting a $target storage
5582 # search shared storage first
5583 foreach_writable_storage
($conf, sub {
5585 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5586 return if !$scfg->{shared
};
5588 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage
5592 # now search local storage
5593 foreach_writable_storage
($conf, sub {
5595 my $scfg = PVE
::Storage
::storage_config
($storecfg, $sid);
5596 return if $scfg->{shared
};
5598 $target = $sid if !$target || $scfg->{path
}; # prefer file based storage;
5602 $target = 'local' if !$target;
5604 my $driver_state_size = 500; # assume 32MB is enough to safe all driver state;
5605 # we abort live save after $conf->{memory}, so we need at max twice that space
5606 my $size = $conf->{memory
}*2 + $driver_state_size;
5608 my $name = "vm-$vmid-state-$snapname";
5609 my $scfg = PVE
::Storage
::storage_config
($storecfg, $target);
5610 $name .= ".raw" if $scfg->{path
}; # add filename extension for file base storage
5611 my $volid = PVE
::Storage
::vdisk_alloc
($storecfg, $target, $vmid, 'raw', $name, $size*1024);
5616 my $snapshot_prepare = sub {
5617 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5621 my $updatefn = sub {
5623 my $conf = load_config
($vmid);
5625 die "you can't take a snapshot if it's a template\n"
5626 if is_template
($conf);
5630 $conf->{lock} = 'snapshot';
5632 die "snapshot name '$snapname' already used\n"
5633 if defined($conf->{snapshots
}->{$snapname});
5635 my $storecfg = PVE
::Storage
::config
();
5636 die "snapshot feature is not available" if !has_feature
('snapshot', $conf, $storecfg);
5638 $snap = $conf->{snapshots
}->{$snapname} = {};
5640 if ($save_vmstate && check_running
($vmid)) {
5641 $snap->{vmstate
} = &$alloc_vmstate_volid($storecfg, $vmid, $conf, $snapname);
5644 &$snapshot_copy_config($conf, $snap);
5646 $snap->{snapstate
} = "prepare";
5647 $snap->{snaptime
} = time();
5648 $snap->{description
} = $comment if $comment;
5650 # always overwrite machine if we save vmstate. This makes sure we
5651 # can restore it later using correct machine type
5652 $snap->{machine
} = get_current_qemu_machine
($vmid) if $snap->{vmstate
};
5654 update_config_nolock
($vmid, $conf, 1);
5657 lock_config
($vmid, $updatefn);
5662 my $snapshot_commit = sub {
5663 my ($vmid, $snapname) = @_;
5665 my $updatefn = sub {
5667 my $conf = load_config
($vmid);
5669 die "missing snapshot lock\n"
5670 if !($conf->{lock} && $conf->{lock} eq 'snapshot');
5672 my $has_machine_config = defined($conf->{machine
});
5674 my $snap = $conf->{snapshots
}->{$snapname};
5676 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5678 die "wrong snapshot state\n"
5679 if !($snap->{snapstate
} && $snap->{snapstate
} eq "prepare");
5681 delete $snap->{snapstate
};
5682 delete $conf->{lock};
5684 my $newconf = &$snapshot_apply_config($conf, $snap);
5686 delete $newconf->{machine
} if !$has_machine_config;
5688 $newconf->{parent
} = $snapname;
5690 update_config_nolock
($vmid, $newconf, 1);
5693 lock_config
($vmid, $updatefn);
5696 sub snapshot_rollback
{
5697 my ($vmid, $snapname) = @_;
5701 my $storecfg = PVE
::Storage
::config
();
5703 my $conf = load_config
($vmid);
5705 my $get_snapshot_config = sub {
5707 die "you can't rollback if vm is a template\n" if is_template
($conf);
5709 my $res = $conf->{snapshots
}->{$snapname};
5711 die "snapshot '$snapname' does not exist\n" if !defined($res);
5716 my $snap = &$get_snapshot_config();
5718 foreach_drive
($snap, sub {
5719 my ($ds, $drive) = @_;
5721 return if drive_is_cdrom
($drive);
5723 my $volid = $drive->{file
};
5725 PVE
::Storage
::volume_rollback_is_possible
($storecfg, $volid, $snapname);
5728 my $updatefn = sub {
5730 $conf = load_config
($vmid);
5732 $snap = &$get_snapshot_config();
5734 die "unable to rollback to incomplete snapshot (snapstate = $snap->{snapstate})\n"
5735 if $snap->{snapstate
};
5739 vm_stop
($storecfg, $vmid, undef, undef, 5, undef, undef);
5742 die "unable to rollback vm $vmid: vm is running\n"
5743 if check_running
($vmid);
5746 $conf->{lock} = 'rollback';
5748 die "got wrong lock\n" if !($conf->{lock} && $conf->{lock} eq 'rollback');
5749 delete $conf->{lock};
5755 my $has_machine_config = defined($conf->{machine
});
5757 # copy snapshot config to current config
5758 $conf = &$snapshot_apply_config($conf, $snap);
5759 $conf->{parent
} = $snapname;
5761 # Note: old code did not store 'machine', so we try to be smart
5762 # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
5763 $forcemachine = $conf->{machine
} || 'pc-i440fx-1.4';
5764 # we remove the 'machine' configuration if not explicitly specified
5765 # in the original config.
5766 delete $conf->{machine
} if $snap->{vmstate
} && !$has_machine_config;
5769 update_config_nolock
($vmid, $conf, 1);
5771 if (!$prepare && $snap->{vmstate
}) {
5772 my $statefile = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5773 vm_start
($storecfg, $vmid, $statefile, undef, undef, undef, $forcemachine);
5777 lock_config
($vmid, $updatefn);
5779 foreach_drive
($snap, sub {
5780 my ($ds, $drive) = @_;
5782 return if drive_is_cdrom
($drive);
5784 my $volid = $drive->{file
};
5785 my $device = "drive-$ds";
5787 PVE
::Storage
::volume_snapshot_rollback
($storecfg, $volid, $snapname);
5791 lock_config
($vmid, $updatefn);
5794 my $savevm_wait = sub {
5798 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5799 if (!$stat->{status
}) {
5800 die "savevm not active\n";
5801 } elsif ($stat->{status
} eq 'active') {
5804 } elsif ($stat->{status
} eq 'completed') {
5807 die "query-savevm returned status '$stat->{status}'\n";
5812 sub do_snapshots_with_qemu
{
5813 my ($storecfg, $volid) = @_;
5815 my $storage_name = PVE
::Storage
::parse_volume_id
($volid);
5817 if ($qemu_snap_storage->{$storecfg->{ids
}->{$storage_name}->{type
}} ){
5821 if ($volid =~ m/\.(qcow2|qed)$/){
5828 sub snapshot_create
{
5829 my ($vmid, $snapname, $save_vmstate, $comment) = @_;
5831 my $snap = &$snapshot_prepare($vmid, $snapname, $save_vmstate, $comment);
5833 $save_vmstate = 0 if !$snap->{vmstate
}; # vm is not running
5835 my $config = load_config
($vmid);
5837 my $running = check_running
($vmid);
5839 my $freezefs = $running && $config->{agent
};
5840 $freezefs = 0 if $snap->{vmstate
}; # not needed if we save RAM
5845 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-freeze"); };
5846 warn "guest-fsfreeze-freeze problems - $@" if $@;
5850 # create internal snapshots of all drives
5852 my $storecfg = PVE
::Storage
::config
();
5855 if ($snap->{vmstate
}) {
5856 my $path = PVE
::Storage
::path
($storecfg, $snap->{vmstate
});
5857 vm_mon_cmd
($vmid, "savevm-start", statefile
=> $path);
5858 &$savevm_wait($vmid);
5860 vm_mon_cmd
($vmid, "savevm-start");
5864 foreach_drive
($snap, sub {
5865 my ($ds, $drive) = @_;
5867 return if drive_is_cdrom
($drive);
5869 my $volid = $drive->{file
};
5870 my $device = "drive-$ds";
5872 qemu_volume_snapshot
($vmid, $device, $storecfg, $volid, $snapname);
5873 $drivehash->{$ds} = 1;
5879 eval { vm_mon_cmd
($vmid, "savevm-end") };
5883 eval { vm_mon_cmd
($vmid, "guest-fsfreeze-thaw"); };
5884 warn "guest-fsfreeze-thaw problems - $@" if $@;
5887 # savevm-end is async, we need to wait
5889 my $stat = vm_mon_cmd_nocheck
($vmid, "query-savevm");
5890 if (!$stat->{bytes
}) {
5893 print "savevm not yet finished\n";
5901 warn "snapshot create failed: starting cleanup\n";
5902 eval { snapshot_delete
($vmid, $snapname, 0, $drivehash); };
5907 &$snapshot_commit($vmid, $snapname);
5910 # Note: $drivehash is only set when called from snapshot_create.
5911 sub snapshot_delete
{
5912 my ($vmid, $snapname, $force, $drivehash) = @_;
5919 my $unlink_parent = sub {
5920 my ($confref, $new_parent) = @_;
5922 if ($confref->{parent
} && $confref->{parent
} eq $snapname) {
5924 $confref->{parent
} = $new_parent;
5926 delete $confref->{parent
};
5931 my $updatefn = sub {
5932 my ($remove_drive) = @_;
5934 my $conf = load_config
($vmid);
5938 die "you can't delete a snapshot if vm is a template\n"
5939 if is_template
($conf);
5942 $snap = $conf->{snapshots
}->{$snapname};
5944 die "snapshot '$snapname' does not exist\n" if !defined($snap);
5946 # remove parent refs
5948 &$unlink_parent($conf, $snap->{parent
});
5949 foreach my $sn (keys %{$conf->{snapshots
}}) {
5950 next if $sn eq $snapname;
5951 &$unlink_parent($conf->{snapshots
}->{$sn}, $snap->{parent
});
5955 if ($remove_drive) {
5956 if ($remove_drive eq 'vmstate') {
5957 delete $snap->{$remove_drive};
5959 my $drive = parse_drive
($remove_drive, $snap->{$remove_drive});
5960 my $volid = $drive->{file
};
5961 delete $snap->{$remove_drive};
5962 add_unused_volume
($conf, $volid);
5967 $snap->{snapstate
} = 'delete';
5969 delete $conf->{snapshots
}->{$snapname};
5970 delete $conf->{lock} if $drivehash;
5971 foreach my $volid (@$unused) {
5972 add_unused_volume
($conf, $volid);
5976 update_config_nolock
($vmid, $conf, 1);
5979 lock_config
($vmid, $updatefn);
5981 # now remove vmstate file
5983 my $storecfg = PVE
::Storage
::config
();
5985 if ($snap->{vmstate
}) {
5986 eval { PVE
::Storage
::vdisk_free
($storecfg, $snap->{vmstate
}); };
5988 die $err if !$force;
5991 # save changes (remove vmstate from snapshot)
5992 lock_config
($vmid, $updatefn, 'vmstate') if !$force;
5995 # now remove all internal snapshots
5996 foreach_drive
($snap, sub {
5997 my ($ds, $drive) = @_;
5999 return if drive_is_cdrom
($drive);
6001 my $volid = $drive->{file
};
6002 my $device = "drive-$ds";
6004 if (!$drivehash || $drivehash->{$ds}) {
6005 eval { qemu_volume_snapshot_delete
($vmid, $device, $storecfg, $volid, $snapname); };
6007 die $err if !$force;
6012 # save changes (remove drive fron snapshot)
6013 lock_config
($vmid, $updatefn, $ds) if !$force;
6014 push @$unused, $volid;
6017 # now cleanup config
6019 lock_config
($vmid, $updatefn);
6023 my ($feature, $conf, $storecfg, $snapname, $running) = @_;
6026 foreach_drive
($conf, sub {
6027 my ($ds, $drive) = @_;
6029 return if drive_is_cdrom
($drive);
6030 my $volid = $drive->{file
};
6031 $err = 1 if !PVE
::Storage
::volume_has_feature
($storecfg, $feature, $volid, $snapname, $running);
6034 return $err ?
0 : 1;
6037 sub template_create
{
6038 my ($vmid, $conf, $disk) = @_;
6040 my $storecfg = PVE
::Storage
::config
();
6042 foreach_drive
($conf, sub {
6043 my ($ds, $drive) = @_;
6045 return if drive_is_cdrom
($drive);
6046 return if $disk && $ds ne $disk;
6048 my $volid = $drive->{file
};
6049 return if !PVE
::Storage
::volume_has_feature
($storecfg, 'template', $volid);
6051 my $voliddst = PVE
::Storage
::vdisk_create_base
($storecfg, $volid);
6052 $drive->{file
} = $voliddst;
6053 $conf->{$ds} = print_drive
($vmid, $drive);
6054 update_config_nolock
($vmid, $conf, 1);
6061 return 1 if defined $conf->{template
} && $conf->{template
} == 1;
6064 sub qemu_img_convert
{
6065 my ($src_volid, $dst_volid, $size, $snapname) = @_;
6067 my $storecfg = PVE
::Storage
::config
();
6068 my ($src_storeid, $src_volname) = PVE
::Storage
::parse_volume_id
($src_volid, 1);
6069 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid, 1);
6071 if ($src_storeid && $dst_storeid) {
6072 my $src_scfg = PVE
::Storage
::storage_config
($storecfg, $src_storeid);
6073 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6075 my $src_format = qemu_img_format
($src_scfg, $src_volname);
6076 my $dst_format = qemu_img_format
($dst_scfg, $dst_volname);
6078 my $src_path = PVE
::Storage
::path
($storecfg, $src_volid, $snapname);
6079 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6082 push @$cmd, '/usr/bin/qemu-img', 'convert', '-t', 'writeback', '-p', '-n';
6083 push @$cmd, '-s', $snapname if($snapname && $src_format eq "qcow2");
6084 push @$cmd, '-f', $src_format, '-O', $dst_format, $src_path, $dst_path;
6088 if($line =~ m/\((\S+)\/100\
%\)/){
6090 my $transferred = int($size * $percent / 100);
6091 my $remaining = $size - $transferred;
6093 print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
6098 eval { run_command
($cmd, timeout
=> undef, outfunc
=> $parser); };
6100 die "copy failed: $err" if $err;
6104 sub qemu_img_format
{
6105 my ($scfg, $volname) = @_;
6107 if ($scfg->{path
} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) {
6114 sub qemu_drive_mirror
{
6115 my ($vmid, $drive, $dst_volid, $vmiddst) = @_;
6117 my $storecfg = PVE
::Storage
::config
();
6118 my ($dst_storeid, $dst_volname) = PVE
::Storage
::parse_volume_id
($dst_volid);
6120 my $dst_scfg = PVE
::Storage
::storage_config
($storecfg, $dst_storeid);
6122 my $format = qemu_img_format
($dst_scfg, $dst_volname);
6124 my $dst_path = PVE
::Storage
::path
($storecfg, $dst_volid);
6126 my $opts = { timeout
=> 10, device
=> "drive-$drive", mode
=> "existing", sync
=> "full", target
=> $dst_path };
6127 $opts->{format
} = $format if $format;
6129 print "drive mirror is starting (scanning bitmap) : this step can take some minutes/hours, depend of disk size and storage speed\n";
6132 vm_mon_cmd
($vmid, "drive-mirror", %$opts);
6134 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6135 my $stat = @$stats[0];
6136 die "mirroring job seem to have die. Maybe do you have bad sectors?" if !$stat;
6137 die "error job is not mirroring" if $stat->{type
} ne "mirror";
6139 my $busy = $stat->{busy
};
6140 my $ready = $stat->{ready
};
6142 if (my $total = $stat->{len
}) {
6143 my $transferred = $stat->{offset
} || 0;
6144 my $remaining = $total - $transferred;
6145 my $percent = sprintf "%.2f", ($transferred * 100 / $total);
6147 print "transferred: $transferred bytes remaining: $remaining bytes total: $total bytes progression: $percent % busy: $busy ready: $ready \n";
6151 if ($stat->{ready
} eq 'true') {
6153 last if $vmiddst != $vmid;
6155 # try to switch the disk if source and destination are on the same guest
6156 eval { vm_mon_cmd
($vmid, "block-job-complete", device
=> "drive-$drive") };
6158 die $@ if $@ !~ m/cannot be completed/;
6167 my $cancel_job = sub {
6168 vm_mon_cmd
($vmid, "block-job-cancel", device
=> "drive-$drive");
6170 my $stats = vm_mon_cmd
($vmid, "query-block-jobs");
6171 my $stat = @$stats[0];
6178 eval { &$cancel_job(); };
6179 die "mirroring error: $err";
6182 if ($vmiddst != $vmid) {
6183 # if we clone a disk for a new target vm, we don't switch the disk
6184 &$cancel_job(); # so we call block-job-cancel
6189 my ($storecfg, $vmid, $running, $drivename, $drive, $snapname,
6190 $newvmid, $storage, $format, $full, $newvollist) = @_;
6195 print "create linked clone of drive $drivename ($drive->{file})\n";
6196 $newvolid = PVE
::Storage
::vdisk_clone
($storecfg, $drive->{file
}, $newvmid, $snapname);
6197 push @$newvollist, $newvolid;
6199 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($drive->{file
});
6200 $storeid = $storage if $storage;
6202 my ($defFormat, $validFormats) = PVE
::Storage
::storage_default_format
($storecfg, $storeid);
6204 my $scfg = PVE
::Storage
::storage_config
($storecfg, $storeid);
6205 $format = qemu_img_format
($scfg, $volname);
6208 # test if requested format is supported - else use default
6209 my $supported = grep { $_ eq $format } @$validFormats;
6210 $format = $defFormat if !$supported;
6212 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $drive->{file
}, 3);
6214 print "create full clone of drive $drivename ($drive->{file})\n";
6215 $newvolid = PVE
::Storage
::vdisk_alloc
($storecfg, $storeid, $newvmid, $format, undef, ($size/1024));
6216 push @$newvollist, $newvolid;
6218 if (!$running || $snapname) {
6219 qemu_img_convert
($drive->{file
}, $newvolid, $size, $snapname);
6221 qemu_drive_mirror
($vmid, $drivename, $newvolid, $newvmid);
6225 my ($size) = PVE
::Storage
::volume_size_info
($storecfg, $newvolid, 3);
6228 $disk->{format
} = undef;
6229 $disk->{file
} = $newvolid;
6230 $disk->{size
} = $size;
6235 # this only works if VM is running
6236 sub get_current_qemu_machine
{
6239 my $cmd = { execute
=> 'query-machines', arguments
=> {} };
6240 my $res = vm_qmp_command
($vmid, $cmd);
6242 my ($current, $default);
6243 foreach my $e (@$res) {
6244 $default = $e->{name
} if $e->{'is-default'};
6245 $current = $e->{name
} if $e->{'is-current'};
6248 # fallback to the default machine if current is not supported by qemu
6249 return $current || $default || 'pc';
6252 sub qemu_machine_feature_enabled
{
6253 my ($machine, $kvmver, $version_major, $version_minor) = @_;
6258 if ($machine && $machine =~ m/^(pc(-i440fx|-q35)?-(\d+)\.(\d+))/) {
6260 $current_major = $3;
6261 $current_minor = $4;
6263 } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
6265 $current_major = $1;
6266 $current_minor = $2;
6269 return 1 if $current_major >= $version_major && $current_minor >= $version_minor;
6278 dir_glob_foreach
("$pcisysfs/devices", '[a-f0-9]{4}:([a-f0-9]{2}:[a-f0-9]{2})\.([0-9])', sub {
6279 my (undef, $id, $function) = @_;
6280 my $res = { id
=> $id, function
=> $function};
6281 push @{$devices->{$id}}, $res;
6287 sub vm_iothreads_list
{
6290 my $res = vm_mon_cmd
($vmid, 'query-iothreads');
6293 foreach my $iothread (@$res) {
6294 $iothreads->{ $iothread->{id
} } = $iothread->{"thread-id"};
6301 my ($conf, $drive) = @_;
6305 if ($conf->{scsihw
} && ($conf->{scsihw
} =~ m/^lsi/)) {
6307 } elsif ($conf->{scsihw
} && ($conf->{scsihw
} eq 'virtio-scsi-single')) {
6313 my $controller = int($drive->{index} / $maxdev);
6314 my $controller_prefix = ($conf->{scsihw
} && $conf->{scsihw
} eq 'virtio-scsi-single') ?
"virtioscsi" : "scsihw";
6316 return ($maxdev, $controller, $controller_prefix);